diff options
Diffstat (limited to 'src/VBox')
152 files changed, 2379 insertions, 674 deletions
diff --git a/src/VBox/Additions/common/VBoxGuest/VBoxGuest-linux.c b/src/VBox/Additions/common/VBoxGuest/VBoxGuest-linux.c index 538a0bc4..499ad791 100644 --- a/src/VBox/Additions/common/VBoxGuest/VBoxGuest-linux.c +++ b/src/VBox/Additions/common/VBoxGuest/VBoxGuest-linux.c @@ -79,6 +79,7 @@ #include <iprt/string.h> #include <VBox/err.h> #include <VBox/log.h> +#include <VBox/VBoxLnxModInline.h> /********************************************************************************************************************************* @@ -661,6 +662,10 @@ static int __init vgdrvLinuxModInit(void) PRTLOGGER pRelLogger; int rc; + /* Check if modue loading was disabled. */ + if (!vbox_mod_should_load()) + return -EINVAL; + /* * Initialize IPRT first. */ @@ -1361,8 +1366,7 @@ static int vgdrvLinuxParamLogGrpSet(const char *pszValue, CONST_4_15 struct kern RTLogGroupSettings(pLogger, pszValue); } else if (pParam->name[0] != 'd') - strlcpy(&g_szLogGrp[0], pszValue, sizeof(g_szLogGrp)); - + RTStrCopy(&g_szLogGrp[0], sizeof(g_szLogGrp), pszValue); return 0; } @@ -1387,7 +1391,7 @@ static int vgdrvLinuxParamLogFlagsSet(const char *pszValue, CONST_4_15 struct ke RTLogFlags(pLogger, pszValue); } else if (pParam->name[0] != 'd') - strlcpy(&g_szLogFlags[0], pszValue, sizeof(g_szLogFlags)); + RTStrCopy(&g_szLogFlags[0], sizeof(g_szLogFlags), pszValue); return 0; } @@ -1412,7 +1416,7 @@ static int vgdrvLinuxParamLogDstSet(const char *pszValue, CONST_4_15 struct kern RTLogDestinations(pLogger, pszValue); } else if (pParam->name[0] != 'd') - strlcpy(&g_szLogDst[0], pszValue, sizeof(g_szLogDst)); + RTStrCopy(&g_szLogDst[0], sizeof(g_szLogDst), pszValue); return 0; } diff --git a/src/VBox/Additions/common/VBoxGuest/lib/VBoxGuestR3LibRuntimeXF86.cpp b/src/VBox/Additions/common/VBoxGuest/lib/VBoxGuestR3LibRuntimeXF86.cpp index 8a9d15c0..899cb903 100644 --- a/src/VBox/Additions/common/VBoxGuest/lib/VBoxGuestR3LibRuntimeXF86.cpp +++ b/src/VBox/Additions/common/VBoxGuest/lib/VBoxGuestR3LibRuntimeXF86.cpp @@ -46,6 +46,9 @@ #if defined(VBOX_VBGLR3_XFREE86) extern "C" { # define XFree86LOADER +# if RT_GNUC_PREREQ(13,0) /* cmath gets dragged in and the c++/13/cmath header is allergic to -ffreestanding. */ +# define _GLIBCXX_INCLUDE_NEXT_C_HEADERS +# endif # include <xf86_ansic.h> # undef size_t } diff --git a/src/VBox/Additions/common/VBoxGuest/linux/files_vboxguest b/src/VBox/Additions/common/VBoxGuest/linux/files_vboxguest index 5df520b6..4e7e5f59 100755 --- a/src/VBox/Additions/common/VBoxGuest/linux/files_vboxguest +++ b/src/VBox/Additions/common/VBoxGuest/linux/files_vboxguest @@ -95,6 +95,7 @@ FILES_VBOXGUEST_NOBIN=" \ ${PATH_ROOT}/include/VBox/VBoxGuestLib.h=>include/VBox/VBoxGuestLib.h \ ${PATH_ROOT}/include/VBox/VBoxGuestMangling.h=>include/VBox/VBoxGuestMangling.h \ ${PATH_ROOT}/include/VBox/version.h=>include/VBox/version.h \ + ${PATH_ROOT}/include/VBox/VBoxLnxModInline.h=>VBox/VBoxLnxModInline.h \ ${PATH_ROOT}/include/VBox/HostServices/GuestPropertySvc.h=>include/VBox/HostServices/GuestPropertySvc.h \ ${PATH_ROOT}/include/VBox/vmm/cpuidcall.h=>include/VBox/vmm/cpuidcall.h \ ${PATH_ROOT}/src/VBox/Additions/common/VBoxGuest/VBoxGuest.cpp=>VBoxGuest-common.c \ diff --git a/src/VBox/Additions/linux/drm/files_vboxvideo_drv b/src/VBox/Additions/linux/drm/files_vboxvideo_drv index 04092484..46fdf366 100755 --- a/src/VBox/Additions/linux/drm/files_vboxvideo_drv +++ b/src/VBox/Additions/linux/drm/files_vboxvideo_drv @@ -38,6 +38,7 @@ FILES_VBOXVIDEO_DRM_NOBIN=" \ ${PATH_ROOT}/include/VBox/Graphics/HGSMIDefs.h=>hgsmi_defs.h \ ${PATH_ROOT}/include/VBox/Graphics/VBoxVideoErr.h=>vbox_err.h \ ${PATH_ROOT}/include/VBox/Graphics/VBoxVideoVBE.h=>vboxvideo_vbe.h \ + ${PATH_ROOT}/include/VBox/VBoxLnxModInline.h=>VBox/VBoxLnxModInline.h \ ${PATH_ROOT}/src/VBox/Additions/common/VBoxVideo/HGSMIBase.cpp=>hgsmi_base.c \ ${PATH_ROOT}/src/VBox/Additions/common/VBoxVideo/Modesetting.cpp=>modesetting.c \ ${PATH_ROOT}/src/VBox/Additions/common/VBoxVideo/VBVABase.cpp=>vbva_base.c \ diff --git a/src/VBox/Additions/linux/drm/vbox_drv.c b/src/VBox/Additions/linux/drm/vbox_drv.c index 3e4cbc60..7d2561dd 100644 --- a/src/VBox/Additions/linux/drm/vbox_drv.c +++ b/src/VBox/Additions/linux/drm/vbox_drv.c @@ -63,6 +63,8 @@ # define VBOX_VIDEO_NOMODESET() 0 #endif /* !CONFIG_VGA_CONSOLE */ +#include <VBox/VBoxLnxModInline.h> + static int vbox_modeset = -1; MODULE_PARM_DESC(modeset, "Disable/Enable modesetting"); @@ -413,6 +415,10 @@ static struct drm_driver driver = { static int __init vbox_init(void) { + /* Check if modue loading was disabled. */ + if (!vbox_mod_should_load()) + return -EINVAL; + printk("vboxvideo: loading version " VBOX_VERSION_STRING " r" __stringify(VBOX_SVN_REV) "\n"); if (VBOX_VIDEO_NOMODESET()) { diff --git a/src/VBox/Additions/linux/drm/vbox_drv.h b/src/VBox/Additions/linux/drm/vbox_drv.h index 8eb9f83e..aaaef937 100644 --- a/src/VBox/Additions/linux/drm/vbox_drv.h +++ b/src/VBox/Additions/linux/drm/vbox_drv.h @@ -538,9 +538,7 @@ int vbox_gem_prime_mmap(struct drm_gem_object *obj, int vbox_irq_init(struct vbox_private *vbox); void vbox_irq_fini(struct vbox_private *vbox); void vbox_report_hotplug(struct vbox_private *vbox); -#if RTLNX_VER_MAX(5,15,0) && !RTLNX_RHEL_MAJ_PREREQ(9,1) && !RTLNX_SUSE_MAJ_PREREQ(15,5) irqreturn_t vbox_irq_handler(int irq, void *arg); -#endif /* vbox_hgsmi.c */ void *hgsmi_buffer_alloc(struct gen_pool *guest_pool, size_t size, diff --git a/src/VBox/Additions/linux/drm/vbox_ttm.c b/src/VBox/Additions/linux/drm/vbox_ttm.c index d020aa3f..d5c64ceb 100644 --- a/src/VBox/Additions/linux/drm/vbox_ttm.c +++ b/src/VBox/Additions/linux/drm/vbox_ttm.c @@ -532,10 +532,15 @@ void vbox_ttm_placement(struct vbox_bo *bo, u32 mem_type) #endif bo->placement.placement = bo->placements; +#if RTLNX_VER_MAX(6,9,0) bo->placement.busy_placement = bo->placements; +#endif if (mem_type & VBOX_MEM_TYPE_VRAM) { -#if RTLNX_VER_MIN(5,11,0) || RTLNX_RHEL_RANGE(8,5, 8,99) +#if RTLNX_VER_MIN(6,9,0) + bo->placements[c].mem_type = TTM_PL_VRAM; + PLACEMENT_FLAGS(bo->placements[c++]) = TTM_PL_FLAG_DESIRED; +#elif RTLNX_VER_MIN(5,11,0) || RTLNX_RHEL_RANGE(8,5, 8,99) bo->placements[c].mem_type = TTM_PL_VRAM; PLACEMENT_FLAGS(bo->placements[c++]) = 0; #elif RTLNX_VER_MIN(5,10,0) @@ -548,7 +553,11 @@ void vbox_ttm_placement(struct vbox_bo *bo, u32 mem_type) #endif } if (mem_type & VBOX_MEM_TYPE_SYSTEM) { -#if RTLNX_VER_MIN(5,11,0) || RTLNX_RHEL_RANGE(8,5, 8,99) + +#if RTLNX_VER_MIN(6,9,0) + bo->placements[c].mem_type = TTM_PL_SYSTEM; + PLACEMENT_FLAGS(bo->placements[c++]) = TTM_PL_FLAG_DESIRED; +#elif RTLNX_VER_MIN(5,11,0) || RTLNX_RHEL_RANGE(8,5, 8,99) bo->placements[c].mem_type = TTM_PL_SYSTEM; PLACEMENT_FLAGS(bo->placements[c++]) = 0; #elif RTLNX_VER_MIN(5,10,0) @@ -561,7 +570,10 @@ void vbox_ttm_placement(struct vbox_bo *bo, u32 mem_type) #endif } if (!c) { -#if RTLNX_VER_MIN(5,11,0) || RTLNX_RHEL_RANGE(8,5, 8,99) +#if RTLNX_VER_MIN(6,9,0) + bo->placements[c].mem_type = TTM_PL_SYSTEM; + PLACEMENT_FLAGS(bo->placements[c++]) = TTM_PL_FLAG_DESIRED; +#elif RTLNX_VER_MIN(5,11,0) || RTLNX_RHEL_RANGE(8,5, 8,99) bo->placements[c].mem_type = TTM_PL_SYSTEM; PLACEMENT_FLAGS(bo->placements[c++]) = 0; #elif RTLNX_VER_MIN(5,10,0) @@ -575,7 +587,9 @@ void vbox_ttm_placement(struct vbox_bo *bo, u32 mem_type) } bo->placement.num_placement = c; +#if RTLNX_VER_MAX(6,9,0) bo->placement.num_busy_placement = c; +#endif #if RTLNX_VER_MIN(3,18,0) || RTLNX_RHEL_MAJ_PREREQ(7,2) for (i = 0; i < c; ++i) { diff --git a/src/VBox/Additions/linux/sharedfolders/files_vboxsf b/src/VBox/Additions/linux/sharedfolders/files_vboxsf index 8187ad33..4de23b09 100755 --- a/src/VBox/Additions/linux/sharedfolders/files_vboxsf +++ b/src/VBox/Additions/linux/sharedfolders/files_vboxsf @@ -72,6 +72,7 @@ FILES_VBOXSF_NOBIN=" \ ${PATH_ROOT}/include/VBox/VBoxGuestMangling.h=>include/VBox/VBoxGuestMangling.h \ ${PATH_ROOT}/include/VBox/VMMDev.h=>include/VBox/VMMDev.h \ ${PATH_ROOT}/include/VBox/VMMDevCoreTypes.h=>include/VBox/VMMDevCoreTypes.h \ + ${PATH_ROOT}/include/VBox/VBoxLnxModInline.h=>VBox/VBoxLnxModInline.h \ ${PATH_ROOT}/src/VBox/Additions/common/VBoxGuest/lib/VBoxGuestR0LibInternal.h=>VBoxGuestR0LibInternal.h \ ${PATH_ROOT}/src/VBox/Additions/common/VBoxGuest/lib/VBoxGuestR0LibGenericRequest.cpp=>VBoxGuestR0LibGenericRequest.c \ ${PATH_ROOT}/src/VBox/Additions/common/VBoxGuest/lib/VBoxGuestR0LibHGCM.cpp=>VBoxGuestR0LibHGCM.c \ diff --git a/src/VBox/Additions/linux/sharedfolders/regops.c b/src/VBox/Additions/linux/sharedfolders/regops.c index ca604090..d98add74 100644 --- a/src/VBox/Additions/linux/sharedfolders/regops.c +++ b/src/VBox/Additions/linux/sharedfolders/regops.c @@ -2535,7 +2535,11 @@ static ssize_t vbsf_reg_read_iter_locking(struct kiocb *kio, struct iov_iter *it if (rc == 0) { size_t iPage = cPages; while (iPage-- > 0) - pReq->PgLst.aPages[iPage] = page_to_phys(papPages[iPage]); + { + RTGCPHYS64 * paDstPages = pReq->PgLst.aPages; + paDstPages[iPage] = page_to_phys(papPages[iPage]); + } + pReq->PgLst.offFirstPage = (uint16_t)offPage0; AssertStmt(cbChunk <= cbToRead, cbChunk = cbToRead); } else { @@ -2749,7 +2753,10 @@ static ssize_t vbsf_reg_write_iter_locking(struct kiocb *kio, struct iov_iter *i if (rc == 0) { size_t iPage = cPages; while (iPage-- > 0) - pReq->PgLst.aPages[iPage] = page_to_phys(papPages[iPage]); + { + RTGCPHYS64 * paDstPages = pReq->PgLst.aPages; + paDstPages[iPage] = page_to_phys(papPages[iPage]); + } pReq->PgLst.offFirstPage = (uint16_t)offPage0; AssertStmt(cbChunk <= cbToWrite, cbChunk = cbToWrite); } else { @@ -3505,7 +3512,7 @@ static struct vm_operations_struct const g_LoggingVmOpsTemplate = { }; /** file_operations::mmap wrapper for logging purposes. */ -extern int vbsf_reg_mmap(struct file *file, struct vm_area_struct *vma) +static int vbsf_reg_mmap(struct file *file, struct vm_area_struct *vma) { int rc; SFLOGFLOW(("vbsf_reg_mmap: file=%p vma=%p\n", file, vma)); @@ -3786,14 +3793,14 @@ static inline void vbsf_write_begin_warn(loff_t pos, unsigned len, unsigned flag } # if RTLNX_VER_MIN(5,19,0) || RTLNX_RHEL_RANGE(9,3, 9,99) -int vbsf_write_begin(struct file *file, struct address_space *mapping, loff_t pos, +static int vbsf_write_begin(struct file *file, struct address_space *mapping, loff_t pos, unsigned len, struct page **pagep, void **fsdata) { vbsf_write_begin_warn(pos, len, 0); return simple_write_begin(file, mapping, pos, len, pagep, fsdata); } # else -int vbsf_write_begin(struct file *file, struct address_space *mapping, loff_t pos, +static int vbsf_write_begin(struct file *file, struct address_space *mapping, loff_t pos, unsigned len, unsigned flags, struct page **pagep, void **fsdata) { vbsf_write_begin_warn(pos, len, flags); diff --git a/src/VBox/Additions/linux/sharedfolders/utils.c b/src/VBox/Additions/linux/sharedfolders/utils.c index b75997a8..7c1fba95 100644 --- a/src/VBox/Additions/linux/sharedfolders/utils.c +++ b/src/VBox/Additions/linux/sharedfolders/utils.c @@ -190,10 +190,11 @@ int vbsf_nls_to_shflstring(struct vbsf_super_info *pSuperInfo, const char *pszNl if (cchNls + 1 < _64K) { pString = (PSHFLSTRING)kmalloc(SHFLSTRING_HEADER_SIZE + cchNls + 1, GFP_KERNEL); if (pString) { + char *pchDst = pString->String.ach; pString->u16Length = (uint16_t)cchNls; pString->u16Size = (uint16_t)(cchNls + 1); - RT_BCOPY_UNFORTIFIED(pString->String.ach, pszNls, cchNls); - pString->String.ach[cchNls] = '\0'; + RT_BCOPY_UNFORTIFIED(pchDst, pszNls, cchNls); + pchDst[cchNls] = '\0'; rc = 0; } else { Log(("vbsf_nls_to_shflstring: failed to allocate %u bytes\n", SHFLSTRING_HEADER_SIZE + cchNls + 1)); diff --git a/src/VBox/Additions/linux/sharedfolders/vfsmod.c b/src/VBox/Additions/linux/sharedfolders/vfsmod.c index 18324fe1..0c5c77af 100644 --- a/src/VBox/Additions/linux/sharedfolders/vfsmod.c +++ b/src/VBox/Additions/linux/sharedfolders/vfsmod.c @@ -63,6 +63,7 @@ #elif RTLNX_VER_MIN(2,6,0) # include <linux/parser.h> #endif +#include <VBox/VBoxLnxModInline.h> /********************************************************************************************************************************* @@ -1408,7 +1409,7 @@ static int vbsf_parse_param(struct fs_context *fc, struct fs_parameter *param) switch (opt) { case Opt_iocharset: case Opt_nls: - strlcpy(info->nls_name, param->string, sizeof(info->nls_name)); + RTStrCopy(info->nls_name, sizeof(info->nls_name), param->string); break; case Opt_uid: info->uid = result.uint_32; @@ -1469,7 +1470,7 @@ static int vbsf_parse_param(struct fs_context *fc, struct fs_parameter *param) printk(KERN_WARNING "vboxsf: cache mode (%u) is out of range, using default instead.\n", result.uint_32); break; case Opt_tag: - strlcpy(info->szTag, param->string, sizeof(info->szTag)); + RTStrCopy(info->szTag, sizeof(info->szTag), param->string); break; default: return invalf(fc, "Invalid mount option: '%s'", param->key); @@ -1528,7 +1529,7 @@ static int vbsf_get_tree(struct fs_context *fc) } /* fc->source (the shared folder name) is set after vbsf_init_fs_ctx() */ - strlcpy(info->name, fc->source, sizeof(info->name)); + RTStrCopy(info->name, sizeof(info->name), fc->source); # if RTLNX_VER_MAX(5,3,0) return vfs_get_super(fc, vfs_get_independent_super, vbsf_read_super_aux); @@ -1621,6 +1622,10 @@ static int __init init(void) int rc; SFLOGFLOW(("vboxsf: init\n")); + /* Check if modue loading was disabled. */ + if (!vbox_mod_should_load()) + return -EINVAL; + /* * Must be paranoid about the vbsf_mount_info_new size. */ diff --git a/src/VBox/Devices/Audio/AudioMixer.cpp b/src/VBox/Devices/Audio/AudioMixer.cpp index 90d86063..899154eb 100644 --- a/src/VBox/Devices/Audio/AudioMixer.cpp +++ b/src/VBox/Devices/Audio/AudioMixer.cpp @@ -2011,6 +2011,9 @@ uint64_t AudioMixerSinkTransferFromCircBuf(PAUDMIXSINK pSink, PRTCIRCBUF pCircBu Assert(pSink->enmDir == PDMAUDIODIR_OUT); RT_NOREF(idStream); + int rc = RTCritSectEnter(&pSink->CritSect); + AssertRCReturn(rc, rc); + /* * Figure how much that we can push down. */ @@ -2022,7 +2025,8 @@ uint64_t AudioMixerSinkTransferFromCircBuf(PAUDMIXSINK pSink, PRTCIRCBUF pCircBu Log3Func(("idStream=%u: cbSinkWritable=%#RX32 cbCircBufReadable=%#RX32 -> cbToTransfer=%#RX32 @%#RX64\n", idStream, cbSinkWritable, cbCircBufReadable, cbToTransfer, offStream)); - AssertMsg(!(pSink->fStatus & AUDMIXSINK_STS_DRAINING) || cbCircBufReadable == pSink->cbDmaLeftToDrain, + /* Note: There now can be more data in the DMA buffer than initially announced. See @bugref{10354}. */ + AssertMsg(!(pSink->fStatus & AUDMIXSINK_STS_DRAINING) || cbCircBufReadable >= pSink->cbDmaLeftToDrain, ("cbCircBufReadable=%#x cbDmaLeftToDrain=%#x\n", cbCircBufReadable, pSink->cbDmaLeftToDrain)); /* @@ -2080,6 +2084,11 @@ uint64_t AudioMixerSinkTransferFromCircBuf(PAUDMIXSINK pSink, PRTCIRCBUF pCircBu else Assert(cbToTransfer2 == 0); + Log3Func(("idStream=%u: cbCircBufUsed=%RX32 left\n", idStream, (uint32_t)RTCircBufUsed(pCircBuf))); + + RTCritSectLeave(&pSink->CritSect); + + LogFlowFuncLeave(); return offStream; } diff --git a/src/VBox/Devices/Audio/DevHdaStream.cpp b/src/VBox/Devices/Audio/DevHdaStream.cpp index aa6b0535..9bb27a4a 100644 --- a/src/VBox/Devices/Audio/DevHdaStream.cpp +++ b/src/VBox/Devices/Audio/DevHdaStream.cpp @@ -797,18 +797,6 @@ int hdaR3StreamSetUp(PPDMDEVINS pDevIns, PHDASTATE pThis, PHDASTREAM pStreamShar * Set up internal ring buffer. */ - /* (Re-)Allocate the stream's internal DMA buffer, - * based on the timing *and* PCM properties we just got above. */ - if (pStreamR3->State.pCircBuf) - { - RTCircBufDestroy(pStreamR3->State.pCircBuf); - pStreamR3->State.pCircBuf = NULL; - pStreamR3->State.StatDmaBufSize = 0; - pStreamR3->State.StatDmaBufUsed = 0; - } - pStreamShared->State.offWrite = 0; - pStreamShared->State.offRead = 0; - /* * The default internal ring buffer size must be: * @@ -857,16 +845,37 @@ int hdaR3StreamSetUp(PPDMDEVINS pDevIns, PHDASTATE pThis, PHDASTREAM pStreamShar rc = VERR_INVALID_PARAMETER); if (RT_SUCCESS(rc)) { - rc = RTCircBufCreate(&pStreamR3->State.pCircBuf, cbCircBuf); - if (RT_SUCCESS(rc)) + /** + * Note: Only re-create the DMA buffer if the size actually has changed. + * + * Otherwise do *not* reset the stream's circular buffer here, as the audio mixer still relies on + * previously announced DMA data (via AudioMixerSinkDrainAndStop()) and processes it asynchronously. + * Resetting the buffer here will cause a race condition. See @bugref{10354}. */ + if (pStreamR3->State.StatDmaBufSize != cbCircBuf) { - pStreamR3->State.StatDmaBufSize = cbCircBuf; + /* (Re-)Allocate the stream's internal DMA buffer, + * based on the timing *and* PCM properties we just got above. */ + if (pStreamR3->State.pCircBuf) + { + RTCircBufDestroy(pStreamR3->State.pCircBuf); + pStreamR3->State.pCircBuf = NULL; + pStreamR3->State.StatDmaBufSize = 0; + pStreamR3->State.StatDmaBufUsed = 0; + } + pStreamShared->State.offWrite = 0; + pStreamShared->State.offRead = 0; - /* - * Forward the timer frequency hint to TM as well for better accuracy on - * systems w/o preemption timers (also good for 'info timers'). - */ - PDMDevHlpTimerSetFrequencyHint(pDevIns, pStreamShared->hTimer, uTransferHz); + rc = RTCircBufCreate(&pStreamR3->State.pCircBuf, cbCircBuf); + if (RT_SUCCESS(rc)) + { + pStreamR3->State.StatDmaBufSize = cbCircBuf; + + /* + * Forward the timer frequency hint to TM as well for better accuracy on + * systems w/o preemption timers (also good for 'info timers'). + */ + PDMDevHlpTimerSetFrequencyHint(pDevIns, pStreamShared->hTimer, uTransferHz); + } } } @@ -1003,10 +1012,9 @@ void hdaR3StreamReset(PHDASTATE pThis, PHDASTATER3 pThisCC, PHDASTREAM pStreamSh pStreamShared->State.idxScheduleLoop = 0; pStreamShared->State.fInputPreBuffered = false; - if (pStreamR3->State.pCircBuf) - RTCircBufReset(pStreamR3->State.pCircBuf); - pStreamShared->State.offWrite = 0; - pStreamShared->State.offRead = 0; + /* Note: Do *not* reset the stream's circular buffer here, as the audio mixer still relies on + * previously announced DMA data (via AudioMixerSinkDrainAndStop()) and processes it asynchronously. + * Resetting the buffer here will cause a race condition. See @bugref{10354}. */ /* Report that we're done resetting this stream. */ HDA_STREAM_REG(pThis, CTL, uSD) = 0; @@ -1041,6 +1049,8 @@ int hdaR3StreamEnable(PHDASTATE pThis, PHDASTREAM pStreamShared, PHDASTREAMR3 pS PAUDMIXSINK const pSink = pStreamR3->pMixSink ? pStreamR3->pMixSink->pMixSink : NULL; if (pSink) { + AudioMixerSinkLock(pSink); + if (fEnable) { if (pStreamR3->State.pAioRegSink != pSink) @@ -1060,6 +1070,8 @@ int hdaR3StreamEnable(PHDASTATE pThis, PHDASTREAM pStreamShared, PHDASTREAMR3 pS else rc = AudioMixerSinkDrainAndStop(pSink, pStreamR3->State.pCircBuf ? (uint32_t)RTCircBufUsed(pStreamR3->State.pCircBuf) : 0); + + AudioMixerSinkUnlock(pSink); } if ( RT_SUCCESS(rc) && fEnable diff --git a/src/VBox/Devices/Audio/DevIchAc97.cpp b/src/VBox/Devices/Audio/DevIchAc97.cpp index 97743372..969e12db 100644 --- a/src/VBox/Devices/Audio/DevIchAc97.cpp +++ b/src/VBox/Devices/Audio/DevIchAc97.cpp @@ -1730,8 +1730,9 @@ static void ichac97R3StreamReset(PAC97STATE pThis, PAC97STREAM pStream, PAC97STR LogFunc(("[SD%RU8]\n", pStream->u8SD)); - if (pStreamCC->State.pCircBuf) - RTCircBufReset(pStreamCC->State.pCircBuf); + /* Note: Do *not* reset the stream's circular buffer here, as the audio mixer still relies on + * previously announced DMA data (via AudioMixerSinkDrainAndStop()) and processes it asynchronously. + * Resetting the buffer here will cause a race condition. See @bugref{10354}. */ pStream->Regs.bdbar = 0; pStream->Regs.civ = 0; @@ -2198,7 +2199,11 @@ static int ichac97R3StreamSetUp(PPDMDEVINS pDevIns, PAC97STATE pThis, PAC97STATE */ if ( pStreamCC->State.pCircBuf && RTCircBufSize(pStreamCC->State.pCircBuf) == cbCircBuf) - RTCircBufReset(pStreamCC->State.pCircBuf); + { + /* Note: Do *not* reset the stream's circular buffer here, as the audio mixer still relies on + * previously announced DMA data (via AudioMixerSinkDrainAndStop()) and processes it asynchronously. + * Resetting the buffer here will cause a race condition. See @bugref{10354}. */ + } else { if (pStreamCC->State.pCircBuf) diff --git a/src/VBox/Devices/Audio/DevSB16.cpp b/src/VBox/Devices/Audio/DevSB16.cpp index a405f311..7df081e7 100644 --- a/src/VBox/Devices/Audio/DevSB16.cpp +++ b/src/VBox/Devices/Audio/DevSB16.cpp @@ -110,6 +110,8 @@ typedef struct SB16STATE *PSB16STATE; */ typedef struct SB16STREAMSTATE { + /** Critical section for this stream. */ + RTCRITSECT CritSect; /** Flag indicating whether this stream is in enabled state or not. */ bool fEnabled; /** Set if we've registered the asynchronous update job. */ @@ -335,6 +337,8 @@ static int sb16StreamEnable(PSB16STATE pThis, PSB16STREAM pStream, bool fEnable static void sb16StreamReset(PSB16STATE pThis, PSB16STREAM pStream); static int sb16StreamOpen(PPDMDEVINS pDevIns, PSB16STATE pThis, PSB16STREAM pStream); static void sb16StreamClose(PPDMDEVINS pDevIns, PSB16STATE pThis, PSB16STREAM pStream); +DECLINLINE(void) sb16StreamLock(PSB16STREAM pStream); +DECLINLINE(void) sb16StreamUnlock(PSB16STREAM pStream); DECLINLINE(PAUDMIXSINK) sb16StreamIndexToSink(PSB16STATE pThis, uint8_t uIdx); static void sb16StreamTransferScheduleNext(PSB16STATE pThis, PSB16STREAM pStream, uint32_t cSamples); static int sb16StreamDoDmaOutput(PSB16STATE pThis, PSB16STREAM pStream, int uDmaChan, uint32_t offDma, uint32_t cbDma, uint32_t cbToRead, uint32_t *pcbRead); @@ -1923,6 +1927,20 @@ static void sb16RemoveDrv(PPDMDEVINS pDevIns, PSB16STATE pThis, PSB16DRIVER pDrv * Stream handling * *********************************************************************************************************************************/ +/** + * Reads DMA output data into the internal DMA buffer. + * + * @returns VBox status code. + * @param pThis The SB16 state. + * @param pStream The SB16 stream to read DMA output data from. + * @param uDmaChan DMA channel to read from. + * @param offDma DMA offset (in bytes) to start reading from. + * @param cbDma DMA area size in bytes. + * @param cbToRead How much bytes to read in total. + * @param pcbRead Where to return the DMA bytes read. + * + * @thread EMT + */ static int sb16StreamDoDmaOutput(PSB16STATE pThis, PSB16STREAM pStream, int uDmaChan, uint32_t offDma, uint32_t cbDma, uint32_t cbToRead, uint32_t *pcbRead) { @@ -1930,6 +1948,8 @@ static int sb16StreamDoDmaOutput(PSB16STATE pThis, PSB16STREAM pStream, int uDma //Assert(cbToRead <= cbFree); /** @todo Add statistics for overflows. */ cbToRead = RT_MIN(cbToRead, cbFree); + sb16StreamLock(pStream); + uint32_t cbReadTotal = 0; while (cbToRead) { @@ -1948,6 +1968,8 @@ static int sb16StreamDoDmaOutput(PSB16STATE pThis, PSB16STREAM pStream, int uDma if (cbReadTotal > 0) break; *pcbRead = 0; + + sb16StreamUnlock(pStream); return rc; } @@ -1956,8 +1978,12 @@ static int sb16StreamDoDmaOutput(PSB16STATE pThis, PSB16STREAM pStream, int uDma else AudioHlpFileWrite(pStream->Dbg.Runtime.pFileDMA, pv, cbRead); + Log3Func(("Writing %#RX32 bytes to DMA buffer\n", cbRead)); + RTCircBufReleaseWriteBlock(pStream->State.pCircBuf, cbRead); + Log3Func(("Now %#RX32 bytes in buffer\n", RTCircBufUsed(pStream->State.pCircBuf))); + Assert(cbToRead >= cbRead); pStream->State.offWrite += cbRead; offDma = (offDma + cbRead) % cbDma; @@ -1970,6 +1996,9 @@ static int sb16StreamDoDmaOutput(PSB16STATE pThis, PSB16STREAM pStream, int uDma /* Update buffer stats. */ pStream->State.StatDmaBufUsed = (uint32_t)RTCircBufUsed(pStream->State.pCircBuf); + Log3Func(("[SD%RU8] cbCircBufUsed=%#RX64\n", pStream->uIdx, RTCircBufUsed(pStream->State.pCircBuf))); + + sb16StreamUnlock(pStream); return VINF_SUCCESS; } @@ -2011,8 +2040,19 @@ static int sb16StreamEnable(PSB16STATE pThis, PSB16STREAM pStream, bool fEnable, } else { - rc = AudioMixerSinkDrainAndStop(pSink, pStream->State.pCircBuf ? (uint32_t)RTCircBufUsed(pStream->State.pCircBuf) : 0); + /* We need to lock the stream here in order to synchronize the amount of bytes we have to drain + * here with the mixer's async I/O thread. See @bugref{10354}. */ + sb16StreamLock(pStream); + + uint32_t const cbToDrain = pStream->State.pCircBuf ? (uint32_t)RTCircBufUsed(pStream->State.pCircBuf) : 0; + Log3Func(("cbToDrain=%#RX32\n", cbToDrain)); + + sb16StreamUnlock(pStream); + + rc = AudioMixerSinkDrainAndStop(pSink, cbToDrain); AssertRCReturn(rc, rc); + + } pStream->State.fEnabled = fEnable; @@ -2068,6 +2108,9 @@ static int sb16StreamCreate(PSB16STATE pThis, PSB16STREAM pStream, uint8_t uIdx) { LogFlowFuncEnter(); + int rc = RTCritSectInit(&pStream->State.CritSect); + AssertRCReturn(rc, rc); + pStream->Dbg.Runtime.fEnabled = pThis->Dbg.fEnabled; if (RT_LIKELY(!pStream->Dbg.Runtime.fEnabled)) @@ -2111,6 +2154,9 @@ static int sb16StreamDestroy(PPDMDEVINS pDevIns, PSB16STATE pThis, PSB16STREAM p pStream->State.fRegisteredAsyncUpdateJob = false; } + int rc2 = RTCritSectDelete(&pStream->State.CritSect); + AssertRC(rc2); + if (pStream->State.pCircBuf) { RTCircBufDestroy(pStream->State.pCircBuf); @@ -2177,6 +2223,28 @@ static void sb16StreamReset(PSB16STATE pThis, PSB16STREAM pStream) } /** + * Locks a SB16 stream for serialized access. + * + * @param pStream The SB16 stream to lock. + */ +DECLINLINE(void) sb16StreamLock(PSB16STREAM pStream) +{ + int rc2 = RTCritSectEnter(&pStream->State.CritSect); + AssertRC(rc2); +} + +/** + * Unlocks a formerly locked SB16 stream. + * + * @param pStream The SB16 stream to unlock. + */ +DECLINLINE(void) sb16StreamUnlock(PSB16STREAM pStream) +{ + int rc2 = RTCritSectLeave(&pStream->State.CritSect); + AssertRC(rc2); +} + +/** * Opens a SB16 stream with its current mixer settings. * * @returns VBox status code. @@ -2209,47 +2277,59 @@ static int sb16StreamOpen(PPDMDEVINS pDevIns, PSB16STATE pThis, PSB16STREAM pStr PDMAudioPropsChannels(&pStream->Cfg.Props), pStream->Cfg.Props.fSigned ? "S" : "U", PDMAudioPropsSampleBits(&pStream->Cfg.Props))); - /* (Re-)create the stream's internal ring buffer. */ - if (pStream->State.pCircBuf) - { - RTCircBufDestroy(pStream->State.pCircBuf); - pStream->State.pCircBuf = NULL; - } - /** @todo r=bird: two DMA periods is probably too little. */ const uint32_t cbCircBuf = PDMAudioPropsMilliToBytes(&pStream->Cfg.Props, (RT_MS_1SEC / pStream->uTimerHz) * 2 /* Use double buffering here */); + int rc = VINF_SUCCESS; - int rc = RTCircBufCreate(&pStream->State.pCircBuf, cbCircBuf); - AssertRCReturn(rc, rc); - pStream->State.StatDmaBufSize = (uint32_t)RTCircBufSize(pStream->State.pCircBuf); + /** + * Note: Only re-create the DMA buffer if the size actually has changed. + * + * Otherwise do *not* reset the stream's circular buffer here, as the audio mixer still relies on + * previously announced DMA data (via AudioMixerSinkDrainAndStop()) and processes it asynchronously. + * Resetting the buffer here will cause a race condition. See @bugref{10354}. */ + if (pStream->State.StatDmaBufSize != cbCircBuf) + { + Log3Func(("Re-creating ring buffer (%#RX32 -> %#RX32)\n", pStream->State.StatDmaBufSize, cbCircBuf)); - /* Set scheduling hint. */ - pStream->Cfg.Device.cMsSchedulingHint = RT_MS_1SEC / RT_MIN(pStream->uTimerHz, 1); + /* (Re-)create the stream's internal ring buffer. */ + if (pStream->State.pCircBuf) + { + RTCircBufDestroy(pStream->State.pCircBuf); + pStream->State.pCircBuf = NULL; + } - PAUDMIXSINK pMixerSink = sb16StreamIndexToSink(pThis, pStream->uIdx); - AssertPtrReturn(pMixerSink, VERR_INVALID_POINTER); + rc = RTCircBufCreate(&pStream->State.pCircBuf, cbCircBuf); + AssertRCReturn(rc, rc); + pStream->State.StatDmaBufSize = (uint32_t)RTCircBufSize(pStream->State.pCircBuf); - sb16RemoveDrvStreams(pDevIns, pThis, - sb16StreamIndexToSink(pThis, pStream->uIdx), pStream->Cfg.enmDir, pStream->Cfg.enmPath); + /* Set scheduling hint. */ + pStream->Cfg.Device.cMsSchedulingHint = RT_MS_1SEC / RT_MIN(pStream->uTimerHz, 1); - rc = sb16AddDrvStreams(pDevIns, pThis, pMixerSink, &pStream->Cfg); - if (RT_SUCCESS(rc)) - { - if (RT_LIKELY(!pStream->Dbg.Runtime.fEnabled)) - { /* likely */ } - else + PAUDMIXSINK pMixerSink = sb16StreamIndexToSink(pThis, pStream->uIdx); + AssertPtrReturn(pMixerSink, VERR_INVALID_POINTER); + + sb16RemoveDrvStreams(pDevIns, pThis, + sb16StreamIndexToSink(pThis, pStream->uIdx), pStream->Cfg.enmDir, pStream->Cfg.enmPath); + + rc = sb16AddDrvStreams(pDevIns, pThis, pMixerSink, &pStream->Cfg); + if (RT_SUCCESS(rc)) { - /* Make sure to close + delete a former debug file, as the PCM format has changed (e.g. U8 -> S16). */ - if (AudioHlpFileIsOpen(pStream->Dbg.Runtime.pFileDMA)) + if (RT_LIKELY(!pStream->Dbg.Runtime.fEnabled)) + { /* likely */ } + else { - AudioHlpFileClose(pStream->Dbg.Runtime.pFileDMA); - AudioHlpFileDelete(pStream->Dbg.Runtime.pFileDMA); - } + /* Make sure to close + delete a former debug file, as the PCM format has changed (e.g. U8 -> S16). */ + if (AudioHlpFileIsOpen(pStream->Dbg.Runtime.pFileDMA)) + { + AudioHlpFileClose(pStream->Dbg.Runtime.pFileDMA); + AudioHlpFileDelete(pStream->Dbg.Runtime.pFileDMA); + } - int rc2 = AudioHlpFileOpen(pStream->Dbg.Runtime.pFileDMA, AUDIOHLPFILE_DEFAULT_OPEN_FLAGS, - &pStream->Cfg.Props); - AssertRC(rc2); + int rc2 = AudioHlpFileOpen(pStream->Dbg.Runtime.pFileDMA, AUDIOHLPFILE_DEFAULT_OPEN_FLAGS, + &pStream->Cfg.Props); + AssertRC(rc2); + } } } @@ -2302,11 +2382,18 @@ static void sb16StreamTransferScheduleNext(PSB16STATE pThis, PSB16STREAM pStream * * @param pStream The SB16 stream. * @param pSink The mixer sink to push to. + * + * @thread MixAIO-n + * + * @note Takes the stream's lock. */ static void sb16StreamPushToMixer(PSB16STREAM pStream, PAUDMIXSINK pSink) { + sb16StreamLock(pStream); + #ifdef LOG_ENABLED uint64_t const offReadOld = pStream->State.offRead; + Log3Func(("[SD%RU8] cbCircBufUsed=%#RX64\n", pStream->uIdx, RTCircBufUsed(pStream->State.pCircBuf))); #endif pStream->State.offRead = AudioMixerSinkTransferFromCircBuf(pSink, pStream->State.pCircBuf, @@ -2315,11 +2402,13 @@ static void sb16StreamPushToMixer(PSB16STREAM pStream, PAUDMIXSINK pSink) /** @todo pStream->Dbg.Runtime.fEnabled ? pStream->Dbg.Runtime.pFileStream :*/ NULL); - Log3Func(("[SD%RU8] transferred=%#RX64 bytes -> @%#RX64\n", pStream->uIdx, - pStream->State.offRead - offReadOld, pStream->State.offRead)); + Log3Func(("[SD%RU8] transferred=%#RX64 bytes -> @%#RX64 (cbCircBufUsed=%#RX64)\n", pStream->uIdx, + pStream->State.offRead - offReadOld, pStream->State.offRead, RTCircBufUsed(pStream->State.pCircBuf))); /* Update buffer stats. */ pStream->State.StatDmaBufUsed = (uint32_t)RTCircBufUsed(pStream->State.pCircBuf); + + sb16StreamUnlock(pStream); } @@ -2327,8 +2416,10 @@ static void sb16StreamPushToMixer(PSB16STREAM pStream, PAUDMIXSINK pSink) * @callback_method_impl{FNAUDMIXSINKUPDATE} * * For output streams this moves data from the internal DMA buffer (in which - * ichac97R3StreamUpdateDma put it), thru the mixer and to the various backend + * sb16StreamDoDmaOutput put it), thru the mixer and to the various backend * audio devices. + * + * @thread MixAIO-n */ static DECLCALLBACK(void) sb16StreamUpdateAsyncIoJob(PPDMDEVINS pDevIns, PAUDMIXSINK pSink, void *pvUser) { diff --git a/src/VBox/Devices/Bus/DevPciIch9.cpp b/src/VBox/Devices/Bus/DevPciIch9.cpp index 7e2b49a7..2bd89e9b 100644 --- a/src/VBox/Devices/Bus/DevPciIch9.cpp +++ b/src/VBox/Devices/Bus/DevPciIch9.cpp @@ -730,6 +730,7 @@ static DECLCALLBACK(VBOXSTRICTRC) ich9pciMcfgMMIORead(PPDMDEVINS pDevIns, void * break; default: ASSERT_GUEST_MSG_FAILED(("cb=%u off=%RGp\n", cb, off)); /** @todo how the heck should this work? Split it, right? */ + rcStrict = VINF_IOM_MMIO_UNUSED_00; break; } } diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Scripts/GetUtcDateTime.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Scripts/GetUtcDateTime.py index c23a3a10..c23a3a10 100644..100755 --- a/src/VBox/Devices/EFI/Firmware/BaseTools/Scripts/GetUtcDateTime.py +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Scripts/GetUtcDateTime.py diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Scripts/PackageDocumentTools/plugins/EdkPlugins/basemodel/doxygen.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Scripts/PackageDocumentTools/plugins/EdkPlugins/basemodel/doxygen.py index b3198d5b..b3198d5b 100644..100755 --- a/src/VBox/Devices/EFI/Firmware/BaseTools/Scripts/PackageDocumentTools/plugins/EdkPlugins/basemodel/doxygen.py +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Scripts/PackageDocumentTools/plugins/EdkPlugins/basemodel/doxygen.py diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Common/BuildToolError.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Common/BuildToolError.py index c0a3269b..c0a3269b 100644..100755 --- a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Common/BuildToolError.py +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/Common/BuildToolError.py diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/CommonDataClass/Exceptions.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/CommonDataClass/Exceptions.py index c0b5e460..c0b5e460 100644..100755 --- a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/CommonDataClass/Exceptions.py +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/CommonDataClass/Exceptions.py diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Logger/ToolError.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Logger/ToolError.py index f4cf1989..f4cf1989 100644..100755 --- a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Logger/ToolError.py +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/Logger/ToolError.py diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/UnitTest/InfBinarySectionTest.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/UnitTest/InfBinarySectionTest.py index 7f000648..7f000648 100755..100644 --- a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/UnitTest/InfBinarySectionTest.py +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/UPT/UnitTest/InfBinarySectionTest.py diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/tests/Split/test_split.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/tests/Split/test_split.py index 4e19e636..4e19e636 100644..100755 --- a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/tests/Split/test_split.py +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/Python/tests/Split/test_split.py diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Tests/CToolsTests.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Tests/CToolsTests.py index e5e20f41..e5e20f41 100644..100755 --- a/src/VBox/Devices/EFI/Firmware/BaseTools/Tests/CToolsTests.py +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Tests/CToolsTests.py diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Tests/CheckPythonSyntax.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Tests/CheckPythonSyntax.py index 29ed80b4..29ed80b4 100644..100755 --- a/src/VBox/Devices/EFI/Firmware/BaseTools/Tests/CheckPythonSyntax.py +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Tests/CheckPythonSyntax.py diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Tests/PythonTest.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Tests/PythonTest.py index afe58534..afe58534 100644..100755 --- a/src/VBox/Devices/EFI/Firmware/BaseTools/Tests/PythonTest.py +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Tests/PythonTest.py diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Tests/PythonToolsTests.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Tests/PythonToolsTests.py index a287f3a3..a287f3a3 100644..100755 --- a/src/VBox/Devices/EFI/Firmware/BaseTools/Tests/PythonToolsTests.py +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Tests/PythonToolsTests.py diff --git a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/OpensslLib/process_files.pl b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/OpensslLib/process_files.pl index 5b0749fa..5b0749fa 100644..100755 --- a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/OpensslLib/process_files.pl +++ b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/OpensslLib/process_files.pl diff --git a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/Tests/test_yaml.py b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/Tests/test_yaml.py index a71073ba..a71073ba 100644..100755 --- a/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/Tests/test_yaml.py +++ b/src/VBox/Devices/EFI/Firmware/IntelFsp2Pkg/Tools/Tests/test_yaml.py diff --git a/src/VBox/Devices/EFI/FirmwareBin/VBoxEFI32.fd b/src/VBox/Devices/EFI/FirmwareBin/VBoxEFI32.fd Binary files differindex 4e0d4b76..2c689d9b 100644 --- a/src/VBox/Devices/EFI/FirmwareBin/VBoxEFI32.fd +++ b/src/VBox/Devices/EFI/FirmwareBin/VBoxEFI32.fd diff --git a/src/VBox/Devices/EFI/FirmwareBin/VBoxEFI64.fd b/src/VBox/Devices/EFI/FirmwareBin/VBoxEFI64.fd Binary files differindex 07cc531c..e586a195 100644 --- a/src/VBox/Devices/EFI/FirmwareBin/VBoxEFI64.fd +++ b/src/VBox/Devices/EFI/FirmwareBin/VBoxEFI64.fd diff --git a/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative286.asm b/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative286.asm index d805833f..0b83b579 100644 --- a/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative286.asm +++ b/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative286.asm @@ -8281,7 +8281,7 @@ vesa_pm_end: ; 0xc4754 LB 0x1 section _DATA progbits vstart=0x4780 align=1 ; size=0x374d class=DATA group=DGROUP ; disGetNextSymbol 0xc4780 LB 0x374d -> off=0x0 cb=000000000000002f uValue=00000000000c0000 '_msg_vga_init' _msg_vga_init: ; 0xc4780 LB 0x2f - db 'Oracle VM VirtualBox Version 7.0.14 VGA BIOS', 00dh, 00ah, 000h + db 'Oracle VM VirtualBox Version 7.0.16 VGA BIOS', 00dh, 00ah, 000h ; disGetNextSymbol 0xc47af LB 0x371e -> off=0x0 cb=0000000000000080 uValue=00000000000c002f 'vga_modes' vga_modes: ; 0xc47af LB 0x80 db 000h, 000h, 000h, 004h, 000h, 0b8h, 0ffh, 002h, 001h, 000h, 000h, 004h, 000h, 0b8h, 0ffh, 002h @@ -9212,7 +9212,7 @@ _vbebios_product_name: ; 0xc7e34 LB 0x21 db 'Oracle VM VirtualBox VBE Adapter', 000h ; disGetNextSymbol 0xc7e55 LB 0x78 -> off=0x0 cb=0000000000000024 uValue=00000000000c36d5 '_vbebios_product_revision' _vbebios_product_revision: ; 0xc7e55 LB 0x24 - db 'Oracle VM VirtualBox Version 7.0.14', 000h + db 'Oracle VM VirtualBox Version 7.0.16', 000h ; disGetNextSymbol 0xc7e79 LB 0x54 -> off=0x0 cb=000000000000002b uValue=00000000000c36f9 '_vbebios_info_string' _vbebios_info_string: ; 0xc7e79 LB 0x2b db 'VirtualBox VBE Display Adapter enabled', 00dh, 00ah, 00dh, 00ah, 000h @@ -9247,4 +9247,4 @@ section CONST2 progbits vstart=0x7ece align=1 ; size=0x0 class=DATA group=DGROUP db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h - db 000h, 0e2h + db 000h, 0deh diff --git a/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative286.md5sum b/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative286.md5sum index 2f608321..9d6aad04 100644 --- a/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative286.md5sum +++ b/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative286.md5sum @@ -1 +1 @@ -9431df94586df05b1873d86a27b77eb5 *VBoxVgaBios286.rom +852353ec31d0749de1c385e91ab27511 *VBoxVgaBios286.rom diff --git a/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative386.asm b/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative386.asm index 9b6c7100..12ea3360 100644 --- a/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative386.asm +++ b/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative386.asm @@ -7735,7 +7735,7 @@ vesa_pm_end: ; 0xc4754 LB 0x1 section _DATA progbits vstart=0x4780 align=1 ; size=0x374d class=DATA group=DGROUP ; disGetNextSymbol 0xc4780 LB 0x374d -> off=0x0 cb=000000000000002f uValue=00000000000c0000 '_msg_vga_init' _msg_vga_init: ; 0xc4780 LB 0x2f - db 'Oracle VM VirtualBox Version 7.0.14 VGA BIOS', 00dh, 00ah, 000h + db 'Oracle VM VirtualBox Version 7.0.16 VGA BIOS', 00dh, 00ah, 000h ; disGetNextSymbol 0xc47af LB 0x371e -> off=0x0 cb=0000000000000080 uValue=00000000000c002f 'vga_modes' vga_modes: ; 0xc47af LB 0x80 db 000h, 000h, 000h, 004h, 000h, 0b8h, 0ffh, 002h, 001h, 000h, 000h, 004h, 000h, 0b8h, 0ffh, 002h @@ -8666,7 +8666,7 @@ _vbebios_product_name: ; 0xc7e34 LB 0x21 db 'Oracle VM VirtualBox VBE Adapter', 000h ; disGetNextSymbol 0xc7e55 LB 0x78 -> off=0x0 cb=0000000000000024 uValue=00000000000c36d5 '_vbebios_product_revision' _vbebios_product_revision: ; 0xc7e55 LB 0x24 - db 'Oracle VM VirtualBox Version 7.0.14', 000h + db 'Oracle VM VirtualBox Version 7.0.16', 000h ; disGetNextSymbol 0xc7e79 LB 0x54 -> off=0x0 cb=000000000000002b uValue=00000000000c36f9 '_vbebios_info_string' _vbebios_info_string: ; 0xc7e79 LB 0x2b db 'VirtualBox VBE Display Adapter enabled', 00dh, 00ah, 00dh, 00ah, 000h @@ -8701,4 +8701,4 @@ section CONST2 progbits vstart=0x7ece align=1 ; size=0x0 class=DATA group=DGROUP db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h - db 000h, 057h + db 000h, 053h diff --git a/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative386.md5sum b/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative386.md5sum index d0e0691d..5bbcac9e 100644 --- a/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative386.md5sum +++ b/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative386.md5sum @@ -1 +1 @@ -a0e84ee6aab110901a8d59aa1451cfd2 *VBoxVgaBios386.rom +5fd5574a01aad6139078230edb9b0545 *VBoxVgaBios386.rom diff --git a/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative8086.asm b/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative8086.asm index 89fd1abc..695ce11f 100644 --- a/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative8086.asm +++ b/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative8086.asm @@ -8439,7 +8439,7 @@ vesa_pm_end: ; 0xc4754 LB 0x1 section _DATA progbits vstart=0x4780 align=1 ; size=0x374d class=DATA group=DGROUP ; disGetNextSymbol 0xc4780 LB 0x374d -> off=0x0 cb=000000000000002f uValue=00000000000c0000 '_msg_vga_init' _msg_vga_init: ; 0xc4780 LB 0x2f - db 'Oracle VM VirtualBox Version 7.0.14 VGA BIOS', 00dh, 00ah, 000h + db 'Oracle VM VirtualBox Version 7.0.16 VGA BIOS', 00dh, 00ah, 000h ; disGetNextSymbol 0xc47af LB 0x371e -> off=0x0 cb=0000000000000080 uValue=00000000000c002f 'vga_modes' vga_modes: ; 0xc47af LB 0x80 db 000h, 000h, 000h, 004h, 000h, 0b8h, 0ffh, 002h, 001h, 000h, 000h, 004h, 000h, 0b8h, 0ffh, 002h @@ -9370,7 +9370,7 @@ _vbebios_product_name: ; 0xc7e34 LB 0x21 db 'Oracle VM VirtualBox VBE Adapter', 000h ; disGetNextSymbol 0xc7e55 LB 0x78 -> off=0x0 cb=0000000000000024 uValue=00000000000c36d5 '_vbebios_product_revision' _vbebios_product_revision: ; 0xc7e55 LB 0x24 - db 'Oracle VM VirtualBox Version 7.0.14', 000h + db 'Oracle VM VirtualBox Version 7.0.16', 000h ; disGetNextSymbol 0xc7e79 LB 0x54 -> off=0x0 cb=000000000000002b uValue=00000000000c36f9 '_vbebios_info_string' _vbebios_info_string: ; 0xc7e79 LB 0x2b db 'VirtualBox VBE Display Adapter enabled', 00dh, 00ah, 00dh, 00ah, 000h @@ -9405,4 +9405,4 @@ section CONST2 progbits vstart=0x7ece align=1 ; size=0x0 class=DATA group=DGROUP db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h db 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h, 000h - db 000h, 021h + db 000h, 01dh diff --git a/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative8086.md5sum b/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative8086.md5sum index 437a4099..d19f9c05 100644 --- a/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative8086.md5sum +++ b/src/VBox/Devices/Graphics/BIOS/VBoxVgaBiosAlternative8086.md5sum @@ -1 +1 @@ -fe9decb70cbd4b2ae6fa11107ac955ae *VBoxVgaBios8086.rom +4d5fd4aad75f5b2295caecb11ca646b2 *VBoxVgaBios8086.rom diff --git a/src/VBox/Devices/Graphics/DevVGA-SVGA3d-dx-dx11.cpp b/src/VBox/Devices/Graphics/DevVGA-SVGA3d-dx-dx11.cpp index 9802b570..58aa8562 100644 --- a/src/VBox/Devices/Graphics/DevVGA-SVGA3d-dx-dx11.cpp +++ b/src/VBox/Devices/Graphics/DevVGA-SVGA3d-dx-dx11.cpp @@ -7902,7 +7902,14 @@ static DECLCALLBACK(int) vmsvga3dBackDXClearDepthStencilView(PVGASTATECC pThisCC int rc = dxDefineDepthStencilView(pThisCC, pDXContext, depthStencilViewId, pEntry); AssertRCReturn(rc, rc); } - pDevice->pImmediateContext->ClearDepthStencilView(pDXView->u.pDepthStencilView, flags, depth, stencil); + + UINT ClearFlags = 0; + if (flags & SVGA3D_CLEAR_DEPTH) + ClearFlags |= D3D11_CLEAR_DEPTH; + if (flags & SVGA3D_CLEAR_STENCIL) + ClearFlags |= D3D11_CLEAR_STENCIL; + + pDevice->pImmediateContext->ClearDepthStencilView(pDXView->u.pDepthStencilView, ClearFlags, depth, stencil); return VINF_SUCCESS; } diff --git a/src/VBox/Devices/Graphics/DevVGA.cpp b/src/VBox/Devices/Graphics/DevVGA.cpp index a2ce3b39..e1060783 100644 --- a/src/VBox/Devices/Graphics/DevVGA.cpp +++ b/src/VBox/Devices/Graphics/DevVGA.cpp @@ -387,9 +387,9 @@ DECLINLINE(bool) vgaR3IsDirty(PVGASTATE pThis, RTGCPHYS offVRAM) */ DECLINLINE(void) vgaR3ResetDirty(PVGASTATE pThis, RTGCPHYS offVRAMStart, RTGCPHYS offVRAMEnd) { - Assert(offVRAMStart < pThis->vram_size); - Assert(offVRAMEnd <= pThis->vram_size); - Assert(offVRAMStart < offVRAMEnd); + AssertReturnVoid(offVRAMStart < pThis->vram_size); + AssertReturnVoid(offVRAMEnd <= pThis->vram_size); + AssertReturnVoid(offVRAMStart < offVRAMEnd); ASMBitClearRange(&pThis->bmDirtyBitmap[0], offVRAMStart >> GUEST_PAGE_SHIFT, offVRAMEnd >> GUEST_PAGE_SHIFT); } @@ -962,9 +962,9 @@ static void recalculate_data(PVGASTATE pThis) offStart += offX >> 1; else offStart += offX * ((cBPP + 7) >> 3); - offStart >>= 2; + pThis->vbe_line_offset = RT_MIN(cbLinePitch, pThis->vram_size); - pThis->vbe_start_addr = RT_MIN(offStart, pThis->vram_size); + pThis->vbe_start_addr = RT_MIN(offStart, pThis->vram_size) >> 2; /* The VBE_DISPI_INDEX_VIRT_HEIGHT is used to prevent setting resolution bigger than * the VRAM size permits. It is used instead of VBE_DISPI_INDEX_YRES *only* in case @@ -985,10 +985,14 @@ static VBOXSTRICTRC vbe_ioport_write_data(PPDMDEVINS pDevIns, PVGASTATE pThis, P uint32_t max_bank; RT_NOREF(pThisCC, addr); - if (pThis->vbe_index <= VBE_DISPI_INDEX_NB) { + uint16_t const idxVbe = pThis->vbe_index; + if (idxVbe <= VBE_DISPI_INDEX_NB) + { + RT_UNTRUSTED_VALIDATED_FENCE(); + bool fRecalculate = false; - Log(("VBE: write index=0x%x val=0x%x\n", pThis->vbe_index, val)); - switch(pThis->vbe_index) { + Log(("VBE: write index=0x%x val=0x%x\n", idxVbe, val)); + switch(idxVbe) { case VBE_DISPI_INDEX_ID: if (val == VBE_DISPI_ID0 || val == VBE_DISPI_ID1 || @@ -1003,27 +1007,27 @@ static VBOXSTRICTRC vbe_ioport_write_data(PPDMDEVINS pDevIns, PVGASTATE pThis, P # endif val == VBE_DISPI_ID_CFG) { - pThis->vbe_regs[pThis->vbe_index] = val; + pThis->vbe_regs[VBE_DISPI_INDEX_ID] = val; } break; case VBE_DISPI_INDEX_XRES: if (val <= VBE_DISPI_MAX_XRES) { - pThis->vbe_regs[pThis->vbe_index] = val; + pThis->vbe_regs[VBE_DISPI_INDEX_XRES] = val; pThis->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] = val; fRecalculate = true; } break; case VBE_DISPI_INDEX_YRES: if (val <= VBE_DISPI_MAX_YRES) - pThis->vbe_regs[pThis->vbe_index] = val; + pThis->vbe_regs[VBE_DISPI_INDEX_YRES] = val; break; case VBE_DISPI_INDEX_BPP: if (val == 0) val = 8; if (val == 4 || val == 8 || val == 15 || val == 16 || val == 24 || val == 32) { - pThis->vbe_regs[pThis->vbe_index] = val; + pThis->vbe_regs[VBE_DISPI_INDEX_BPP] = val; fRecalculate = true; } break; @@ -1039,7 +1043,7 @@ static VBOXSTRICTRC vbe_ioport_write_data(PPDMDEVINS pDevIns, PVGASTATE pThis, P val &= 0xff; if (val > max_bank) val = max_bank; - pThis->vbe_regs[pThis->vbe_index] = val; + pThis->vbe_regs[VBE_DISPI_INDEX_BANK] = val; pThis->bank_offset = (val << 16); # ifndef IN_RC @@ -1143,7 +1147,7 @@ static VBOXSTRICTRC vbe_ioport_write_data(PPDMDEVINS pDevIns, PVGASTATE pThis, P */ pThis->bank_offset = 0; } - pThis->vbe_regs[pThis->vbe_index] = val; + pThis->vbe_regs[VBE_DISPI_INDEX_ENABLE] = val; /* * LFB video mode is either disabled or changed. Notify the display * and reset VBVA. @@ -1167,7 +1171,7 @@ static VBOXSTRICTRC vbe_ioport_write_data(PPDMDEVINS pDevIns, PVGASTATE pThis, P case VBE_DISPI_INDEX_X_OFFSET: case VBE_DISPI_INDEX_Y_OFFSET: { - pThis->vbe_regs[pThis->vbe_index] = val; + pThis->vbe_regs[idxVbe] = val; fRecalculate = true; } break; @@ -1185,7 +1189,7 @@ static VBOXSTRICTRC vbe_ioport_write_data(PPDMDEVINS pDevIns, PVGASTATE pThis, P # endif /* IN_RING3 */ break; case VBE_DISPI_INDEX_CFG: - pThis->vbe_regs[pThis->vbe_index] = val; + pThis->vbe_regs[VBE_DISPI_INDEX_CFG] = val; break; default: break; diff --git a/src/VBox/Devices/Input/testcase/tstUsbMouse.cpp b/src/VBox/Devices/Input/testcase/tstUsbMouse.cpp index 1b411583..32ed14a8 100644 --- a/src/VBox/Devices/Input/testcase/tstUsbMouse.cpp +++ b/src/VBox/Devices/Input/testcase/tstUsbMouse.cpp @@ -100,6 +100,23 @@ static DECLCALLBACK(int) tstDriverAttach(PPDMUSBINS pUsbIns, RTUINT iLun, PPDMIB } +/** @interface_method_impl{PDMUSBHLP,pfnTimerCreate} */ +static DECLCALLBACK(int) tstTimerCreate(PPDMUSBINS pUsbIns, TMCLOCK enmClock, PFNTMTIMERUSB pfnCallback, void *pvUser, + uint32_t fFlags, const char *pszDesc, PTMTIMERHANDLE phTimer) +{ + RT_NOREF7(pUsbIns, enmClock, pfnCallback, pvUser, fFlags, pszDesc, phTimer); + return VINF_SUCCESS; +} + + +/** @interface_method_impl{PDMUSBHLP,pfnTimerCreate} */ +static DECLCALLBACK(int) tstTimerDestroy(PPDMUSBINS pUsbIns, TMTIMERHANDLE hTimer) +{ + RT_NOREF2(pUsbIns, hTimer); + return VINF_SUCCESS; +} + + /** * @interface_method_impl{PDMIBASE,pfnQueryInterface} */ @@ -393,6 +410,8 @@ int main() g_tstUsbHlp.u32Version = PDM_USBHLP_VERSION; g_tstUsbHlp.pfnVMSetErrorV = tstVMSetErrorV; g_tstUsbHlp.pfnDriverAttach = tstDriverAttach; + g_tstUsbHlp.pfnTimerCreate = tstTimerCreate; + g_tstUsbHlp.pfnTimerDestroy = tstTimerDestroy; g_tstUsbHlp.pfnCFGMValidateConfig = CFGMR3ValidateConfig; g_tstUsbHlp.pfnCFGMQueryStringDef = CFGMR3QueryStringDef; g_tstUsbHlp.pfnCFGMQueryU8Def = CFGMR3QueryU8Def; diff --git a/src/VBox/Devices/Network/DevPCNet.cpp b/src/VBox/Devices/Network/DevPCNet.cpp index 49140775..10dbcd27 100644 --- a/src/VBox/Devices/Network/DevPCNet.cpp +++ b/src/VBox/Devices/Network/DevPCNet.cpp @@ -3813,7 +3813,9 @@ static DECLCALLBACK(VBOXSTRICTRC) pcnetR3MmioRead(PPDMDEVINS pDevIns, void *pvUs case 2: rc = pcnetR3MmioReadU16(pDevIns, pThis, pThisCC, off, (uint16_t *)pv); break; case 4: rc = pcnetR3MmioReadU32(pDevIns, pThis, pThisCC, off, (uint32_t *)pv); break; default: + memset(pv, 0, cb); rc = PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, "pcnetR3MmioRead: unsupported op size: address=%RGp cb=%u\n", off, cb); + break; } STAM_PROFILE_ADV_STOP(&pThis->CTX_SUFF_Z(StatMMIORead), a); } diff --git a/src/VBox/Devices/Network/SrvIntNetR0.cpp b/src/VBox/Devices/Network/SrvIntNetR0.cpp index 1a2b055d..728cd25a 100644 --- a/src/VBox/Devices/Network/SrvIntNetR0.cpp +++ b/src/VBox/Devices/Network/SrvIntNetR0.cpp @@ -4104,9 +4104,16 @@ INTNETR0DECL(int) IntNetR0IfSend(INTNETIFHANDLE hIf, PSUPDRVSESSION pSession) * Process the send buffer. */ INTNETSWDECISION enmSwDecision = INTNETSWDECISION_BROADCAST; - INTNETSG Sg; /** @todo this will have to be changed if we're going to use async sending - * with buffer sharing for some OS or service. Darwin copies everything so - * I won't bother allocating and managing SGs right now. Sorry. */ + + /** @todo this will have to be changed if we're going to use async sending + * with buffer sharing for some OS or service. Darwin copies everything so + * I won't bother allocating and managing SGs right now. Sorry. */ + union + { + uint8_t abBuf[sizeof(INTNETSG) + sizeof(INTNETSEG)]; + INTNETSG SG; + } u; + PINTNETHDR pHdr; while ((pHdr = IntNetRingGetNextFrameToRead(&pIf->pIntBuf->Send)) != NULL) { @@ -4115,10 +4122,10 @@ INTNETR0DECL(int) IntNetR0IfSend(INTNETIFHANDLE hIf, PSUPDRVSESSION pSession) { /* Send regular frame. */ void *pvCurFrame = IntNetHdrGetFramePtr(pHdr, pIf->pIntBuf); - IntNetSgInitTemp(&Sg, pvCurFrame, pHdr->cbFrame); + IntNetSgInitTemp(&u.SG, pvCurFrame, pHdr->cbFrame); if (pNetwork->fFlags & INTNET_OPEN_FLAGS_SHARED_MAC_ON_WIRE) - intnetR0IfSnoopAddr(pIf, (uint8_t *)pvCurFrame, pHdr->cbFrame, false /*fGso*/, (uint16_t *)&Sg.fFlags); - enmSwDecision = intnetR0NetworkSend(pNetwork, pIf, 0 /*fSrc*/, &Sg, pDstTab); + intnetR0IfSnoopAddr(pIf, (uint8_t *)pvCurFrame, pHdr->cbFrame, false /*fGso*/, (uint16_t *)&u.SG.fFlags); + enmSwDecision = intnetR0NetworkSend(pNetwork, pIf, 0 /*fSrc*/, &u.SG, pDstTab); } else if (u8Type == INTNETHDR_TYPE_GSO) { @@ -4128,10 +4135,10 @@ INTNETR0DECL(int) IntNetR0IfSend(INTNETIFHANDLE hIf, PSUPDRVSESSION pSession) if (RT_LIKELY(PDMNetGsoIsValid(pGso, pHdr->cbFrame, cbFrame))) { void *pvCurFrame = pGso + 1; - IntNetSgInitTempGso(&Sg, pvCurFrame, cbFrame, pGso); + IntNetSgInitTempGso(&u.SG, pvCurFrame, cbFrame, pGso); if (pNetwork->fFlags & INTNET_OPEN_FLAGS_SHARED_MAC_ON_WIRE) - intnetR0IfSnoopAddr(pIf, (uint8_t *)pvCurFrame, cbFrame, true /*fGso*/, (uint16_t *)&Sg.fFlags); - enmSwDecision = intnetR0NetworkSend(pNetwork, pIf, 0 /*fSrc*/, &Sg, pDstTab); + intnetR0IfSnoopAddr(pIf, (uint8_t *)pvCurFrame, cbFrame, true /*fGso*/, (uint16_t *)&u.SG.fFlags); + enmSwDecision = intnetR0NetworkSend(pNetwork, pIf, 0 /*fSrc*/, &u.SG, pDstTab); } else { diff --git a/src/VBox/Devices/Network/testcase/tstIntNetR0.cpp b/src/VBox/Devices/Network/testcase/tstIntNetR0.cpp index 5cb94894..515f2065 100644 --- a/src/VBox/Devices/Network/testcase/tstIntNetR0.cpp +++ b/src/VBox/Devices/Network/testcase/tstIntNetR0.cpp @@ -203,9 +203,13 @@ INTNETR3DECL(int) SUPR0MemFree(PSUPDRVSESSION pSession, RTHCUINTPTR uPtr) static int tstIntNetSendBuf(PINTNETRINGBUF pRingBuf, INTNETIFHANDLE hIf, PSUPDRVSESSION pSession, void const *pvBuf, size_t cbBuf) { - INTNETSG Sg; - IntNetSgInitTemp(&Sg, (void *)pvBuf, (uint32_t)cbBuf); - int rc = intnetR0RingWriteFrame(pRingBuf, &Sg, NULL); + union + { + uint8_t abBuf[sizeof(INTNETSG) + sizeof(INTNETSEG)]; + INTNETSG SG; + } u; + IntNetSgInitTemp(&u.SG, (void *)pvBuf, (uint32_t)cbBuf); + int rc = intnetR0RingWriteFrame(pRingBuf, &u.SG, NULL); if (RT_SUCCESS(rc)) rc = IntNetR0IfSend(hIf, pSession); return rc; @@ -269,9 +273,13 @@ static DECLCALLBACK(int) SendThread(RTTHREAD hThreadSelf, void *pvArg) : iFrame % 1519 + sizeof(RTMAC) * 2 + sizeof(unsigned); pHdr->iFrame = iFrame; - INTNETSG Sg; - IntNetSgInitTemp(&Sg, abBuf, cb); - RTTEST_CHECK_RC_OK(g_hTest, rc = intnetR0RingWriteFrame(&pArgs->pBuf->Send, &Sg, NULL)); + union + { + uint8_t abBuf[sizeof(INTNETSG) + sizeof(INTNETSEG)]; + INTNETSG SG; + } u; + IntNetSgInitTemp(&u.SG, abBuf, cb); + RTTEST_CHECK_RC_OK(g_hTest, rc = intnetR0RingWriteFrame(&pArgs->pBuf->Send, &u.SG, NULL)); if (RT_SUCCESS(rc)) RTTEST_CHECK_RC_OK(g_hTest, rc = IntNetR0IfSend(pArgs->hIf, g_pSession)); if (RT_FAILURE(rc) && ++cErrors > 64) diff --git a/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative286.asm b/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative286.asm index 050ae0c2..5b6da227 100644 --- a/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative286.asm +++ b/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative286.asm @@ -1621,7 +1621,7 @@ section CONST progbits vstart=0xf0 align=1 ; size=0xcda class=DATA group=DGROUP section CONST2 progbits vstart=0xdca align=1 ; size=0x3fa class=DATA group=DGROUP ; disGetNextSymbol 0xf0dca LB 0x3fa -> off=0x0 cb=0000000000000012 uValue=00000000000f0dca 'bios_cvs_version_string' bios_cvs_version_string: ; 0xf0dca LB 0x12 - db 'VirtualBox 7.0.14', 000h + db 'VirtualBox 7.0.16', 000h ; disGetNextSymbol 0xf0ddc LB 0x3e8 -> off=0x0 cb=0000000000000008 uValue=00000000000f0ddc '_bios_prefix_string' _bios_prefix_string: ; 0xf0ddc LB 0x8 db 'BIOS: ', 000h, 000h @@ -19429,4 +19429,4 @@ biosorg_check_before_or_at_0FFEEh: ; 0xfff80 LB 0x70 cpu_reset: ; 0xffff0 LB 0x10 jmp far 0f000h:0e05bh ; ea 5b e0 00 f0 ; 0xffff0 orgs.asm:2114 ; disGetNextSymbol 0xffff5 LB 0xb -> off=0xb cb=0000000000000000 uValue=0000000000100000 '_dummy_addr_0x100000' - db 030h, 036h, 02fh, 032h, 033h, 02fh, 039h, 039h, 000h, 0fch, 0d8h + db 030h, 036h, 02fh, 032h, 033h, 02fh, 039h, 039h, 000h, 0fch, 0d6h diff --git a/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative286.md5sum b/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative286.md5sum index 90f623ca..556bdbe3 100644 --- a/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative286.md5sum +++ b/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative286.md5sum @@ -1 +1 @@ -21db2300f54bae35aef5b24839864806 *VBoxPcBios286.rom +574c2c72048d5a5c9c079fbf47683b0f *VBoxPcBios286.rom diff --git a/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative386.asm b/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative386.asm index 2b0294cc..a3231d00 100644 --- a/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative386.asm +++ b/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative386.asm @@ -1566,7 +1566,7 @@ section CONST progbits vstart=0xf0 align=1 ; size=0xd14 class=DATA group=DGROUP section CONST2 progbits vstart=0xe04 align=1 ; size=0x3fa class=DATA group=DGROUP ; disGetNextSymbol 0xf0e04 LB 0x3fa -> off=0x0 cb=0000000000000012 uValue=00000000000f0e04 'bios_cvs_version_string' bios_cvs_version_string: ; 0xf0e04 LB 0x12 - db 'VirtualBox 7.0.14', 000h + db 'VirtualBox 7.0.16', 000h ; disGetNextSymbol 0xf0e16 LB 0x3e8 -> off=0x0 cb=0000000000000008 uValue=00000000000f0e16 '_bios_prefix_string' _bios_prefix_string: ; 0xf0e16 LB 0x8 db 'BIOS: ', 000h, 000h @@ -19195,4 +19195,4 @@ biosorg_check_before_or_at_0FFEEh: ; 0xfff80 LB 0x70 cpu_reset: ; 0xffff0 LB 0x10 jmp far 0f000h:0e05bh ; ea 5b e0 00 f0 ; 0xffff0 orgs.asm:2114 ; disGetNextSymbol 0xffff5 LB 0xb -> off=0xb cb=0000000000000000 uValue=0000000000100000 '_dummy_addr_0x100000' - db 030h, 036h, 02fh, 032h, 033h, 02fh, 039h, 039h, 000h, 0fch, 036h + db 030h, 036h, 02fh, 032h, 033h, 02fh, 039h, 039h, 000h, 0fch, 034h diff --git a/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative386.md5sum b/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative386.md5sum index 0ff07b1e..80cc8e0a 100644 --- a/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative386.md5sum +++ b/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative386.md5sum @@ -1 +1 @@ -b0137ac614de33e88bea424380fe32be *VBoxPcBios386.rom +951bc82dd1a8482863248e9157928f1b *VBoxPcBios386.rom diff --git a/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative8086.asm b/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative8086.asm index 263b9f5c..92665f77 100644 --- a/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative8086.asm +++ b/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative8086.asm @@ -1621,7 +1621,7 @@ section CONST progbits vstart=0xf0 align=1 ; size=0xcda class=DATA group=DGROUP section CONST2 progbits vstart=0xdca align=1 ; size=0x3fa class=DATA group=DGROUP ; disGetNextSymbol 0xf0dca LB 0x3fa -> off=0x0 cb=0000000000000012 uValue=00000000000f0dca 'bios_cvs_version_string' bios_cvs_version_string: ; 0xf0dca LB 0x12 - db 'VirtualBox 7.0.14', 000h + db 'VirtualBox 7.0.16', 000h ; disGetNextSymbol 0xf0ddc LB 0x3e8 -> off=0x0 cb=0000000000000008 uValue=00000000000f0ddc '_bios_prefix_string' _bios_prefix_string: ; 0xf0ddc LB 0x8 db 'BIOS: ', 000h, 000h @@ -19906,4 +19906,4 @@ biosorg_check_before_or_at_0FFEEh: ; 0xfff80 LB 0x70 cpu_reset: ; 0xffff0 LB 0x10 jmp far 0f000h:0e05bh ; ea 5b e0 00 f0 ; 0xffff0 orgs.asm:2114 ; disGetNextSymbol 0xffff5 LB 0xb -> off=0xb cb=0000000000000000 uValue=0000000000100000 '_dummy_addr_0x100000' - db 030h, 036h, 02fh, 032h, 033h, 02fh, 039h, 039h, 000h, 0fbh, 0bdh + db 030h, 036h, 02fh, 032h, 033h, 02fh, 039h, 039h, 000h, 0fbh, 0bbh diff --git a/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative8086.md5sum b/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative8086.md5sum index 7746ce56..95f06271 100644 --- a/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative8086.md5sum +++ b/src/VBox/Devices/PC/BIOS/VBoxBiosAlternative8086.md5sum @@ -1 +1 @@ -341856987bd565a025d1f9896927c8a6 *VBoxPcBios8086.rom +0704d20fb86b2ca3eba57b2ca2f9e135 *VBoxPcBios8086.rom diff --git a/src/VBox/Devices/Serial/DevOxPcie958.cpp b/src/VBox/Devices/Serial/DevOxPcie958.cpp index e9cccd0b..1cfb2dd1 100644 --- a/src/VBox/Devices/Serial/DevOxPcie958.cpp +++ b/src/VBox/Devices/Serial/DevOxPcie958.cpp @@ -247,10 +247,23 @@ static VBOXSTRICTRC ox958UartRegRead(PPDMDEVINS pDevIns, PDEVOX958 pThis, POX958 if (offUartReg >= OX958_REG_UART_DMA_REGION_OFFSET) { /* Access to the DMA registers. */ - rc = VINF_SUCCESS; + rc = VINF_IOM_MMIO_UNUSED_00; /** @todo Misses implementation, just pretend there is nothing there yet. */ } else /* Access UART registers. */ - rc = uartRegRead(pDevIns, &pUart->UartCore, &pUartCC->UartCore, offUartReg, (uint32_t *)pv, cb); + { + AssertReturn(cb == 1, VINF_IOM_MMIO_UNUSED_00); + + uint32_t u32 = 0; + rc = uartRegRead(pDevIns, &pUart->UartCore, &pUartCC->UartCore, offUartReg, &u32, 1); + Assert(rc == VINF_SUCCESS || rc == VINF_IOM_R3_IOPORT_READ); + + if (rc == VINF_SUCCESS) + *(uint8_t *)pv = (uint8_t)u32; + else if (rc == VERR_IOM_IOPORT_UNUSED) + rc = VINF_IOM_MMIO_UNUSED_00; + else if (rc == VINF_IOM_R3_IOPORT_READ) + rc = VINF_IOM_R3_MMIO_READ; + } return rc; } @@ -280,7 +293,15 @@ static VBOXSTRICTRC ox958UartRegWrite(PPDMDEVINS pDevIns, PDEVOX958 pThis, POX95 rc = VINF_SUCCESS; } else /* Access UART registers. */ - rc = uartRegWrite(pDevIns, &pUart->UartCore, &pUartCC->UartCore, offUartReg, *(const uint32_t *)pv, cb); + { + AssertReturn(cb == 1, VINF_SUCCESS); + + rc = uartRegWrite(pDevIns, &pUart->UartCore, &pUartCC->UartCore, offUartReg, *(const uint8_t *)pv, 1); + Assert(rc == VINF_SUCCESS || rc == VINF_IOM_R3_IOPORT_WRITE); + + if (rc == VINF_IOM_R3_IOPORT_WRITE) + rc = VINF_IOM_R3_MMIO_WRITE; + } return rc; } @@ -319,8 +340,8 @@ static DECLCALLBACK(VBOXSTRICTRC) ox958MmioRead(PPDMDEVINS pDevIns, void *pvUser if (off < OX958_REG_UART_REGION_OFFSET) { + AssertReturn(cb == 4, VINF_IOM_MMIO_UNUSED_00); uint32_t *pu32 = (uint32_t *)pv; - Assert(cb == 4); switch ((uint32_t)off) { @@ -360,8 +381,6 @@ static DECLCALLBACK(VBOXSTRICTRC) ox958MmioRead(PPDMDEVINS pDevIns, void *pvUser POX958UART pUart = &pThis->aUarts[iUart]; POX958UARTCC pUartCC = &pThisCC->aUarts[iUart]; rc = ox958UartRegRead(pDevIns, pThis, pUart, pUartCC, offUartReg, pv, cb); - if (rc == VINF_IOM_R3_IOPORT_READ) - rc = VINF_IOM_R3_MMIO_READ; } else rc = VINF_IOM_MMIO_UNUSED_00; @@ -383,8 +402,8 @@ static DECLCALLBACK(VBOXSTRICTRC) ox958MmioWrite(PPDMDEVINS pDevIns, void *pvUse if (off < OX958_REG_UART_REGION_OFFSET) { + AssertReturn(cb == 4, VINF_SUCCESS); const uint32_t u32 = *(const uint32_t *)pv; - Assert(cb == 4); switch ((uint32_t)off) { @@ -420,8 +439,6 @@ static DECLCALLBACK(VBOXSTRICTRC) ox958MmioWrite(PPDMDEVINS pDevIns, void *pvUse POX958UART pUart = &pThis->aUarts[iUart]; POX958UARTCC pUartCC = &pThisCC->aUarts[iUart]; rc = ox958UartRegWrite(pDevIns, pThis, pUart, pUartCC, offUartReg, pv, cb); - if (rc == VINF_IOM_R3_IOPORT_WRITE) - rc = VINF_IOM_R3_MMIO_WRITE; } } diff --git a/src/VBox/Devices/Storage/DevAHCI.cpp b/src/VBox/Devices/Storage/DevAHCI.cpp index 199dc04f..f77f5c28 100644 --- a/src/VBox/Devices/Storage/DevAHCI.cpp +++ b/src/VBox/Devices/Storage/DevAHCI.cpp @@ -1912,7 +1912,7 @@ static VBOXSTRICTRC PortInvalid_r(PPDMDEVINS pDevIns, PAHCI pThis, PAHCIPORT pAh { RT_NOREF(pDevIns, pThis, pAhciPort, iReg, pu32Value); ahciLog(("%s: Read denied!!! iReg=%u\n", __FUNCTION__, iReg)); - return VINF_SUCCESS; + return VINF_IOM_MMIO_UNUSED_00; } /** @@ -2356,10 +2356,10 @@ ahciLegacyFakeWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t static DECLCALLBACK(VBOXSTRICTRC) ahciLegacyFakeRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t *pu32, unsigned cb) { - /** @todo we should set *pu32 to something. */ - RT_NOREF(pDevIns, pvUser, offPort, pu32, cb); + *pu32 = 0; + RT_NOREF(pDevIns, pvUser, offPort, cb); ASSERT_GUEST_MSG_FAILED(("Should not happen\n")); - return VINF_SUCCESS; + return VERR_IOM_IOPORT_UNUSED; } diff --git a/src/VBox/Devices/Storage/DevBusLogic.cpp b/src/VBox/Devices/Storage/DevBusLogic.cpp index a5cf9f9a..21f59250 100644 --- a/src/VBox/Devices/Storage/DevBusLogic.cpp +++ b/src/VBox/Devices/Storage/DevBusLogic.cpp @@ -979,10 +979,12 @@ typedef struct ESCMD unsigned char uReserved2 : 3; /** Length of the SCSI CDB. */ uint8_t cbCDB; - /** The SCSI CDB. (A CDB can be 12 bytes long.) */ - uint8_t abCDB[12]; + /** The SCSI CDB. (A CDB from our BIOS can be up to 16 bytes long + * which works with our emulation even though the original BusLogic HBA + * supports only 12 byte CDBs). */ + uint8_t abCDB[16]; } ESCMD, *PESCMD; -AssertCompileSize(ESCMD, 24); +AssertCompileSize(ESCMD, 28); /** * Task state for a CCB request. @@ -3161,7 +3163,8 @@ static int buslogicR3DeviceSCSIRequestSetup(PPDMDEVINS pDevIns, PBUSLOGIC pThis, blPhysReadMeta(pDevIns, pThis, GCPhysAddrCCB, &CCBGuest, sizeof(CCB32)); uTargetIdCCB = pThis->fMbxIs24Bit ? CCBGuest.o.uTargetId : CCBGuest.n.uTargetId; - if (RT_LIKELY(uTargetIdCCB < RT_ELEMENTS(pThisCC->aDeviceStates))) + if ( RT_LIKELY(uTargetIdCCB < RT_ELEMENTS(pThisCC->aDeviceStates)) + && CCBGuest.c.cbCDB <= RT_ELEMENTS(CCBGuest.c.abCDB)) { PBUSLOGICDEVICE pTgtDev = &pThisCC->aDeviceStates[uTargetIdCCB]; @@ -3378,7 +3381,7 @@ static void buslogicR3ProcessBiosReq(PPDMDEVINS pDevIns, PBUSLOGIC pThis, PBUSLO PESCMD pCmd = (PESCMD)pThis->aCommandBuffer; if (RT_LIKELY( pCmd->uTargetId < RT_ELEMENTS(pThisCC->aDeviceStates) - && pCmd->cbCDB <= 16)) + && pCmd->cbCDB <= RT_ELEMENTS(pCmd->abCDB))) { PBUSLOGICDEVICE pTgtDev = &pThisCC->aDeviceStates[pCmd->uTargetId]; diff --git a/src/VBox/Devices/Storage/DevLsiLogicSCSI.cpp b/src/VBox/Devices/Storage/DevLsiLogicSCSI.cpp index b089f3c4..626f531d 100644 --- a/src/VBox/Devices/Storage/DevLsiLogicSCSI.cpp +++ b/src/VBox/Devices/Storage/DevLsiLogicSCSI.cpp @@ -2295,7 +2295,8 @@ static int lsilogicR3ProcessSCSIIORequest(PPDMDEVINS pDevIns, PLSILOGICSCSI pThi { PLSILOGICDEVICE pTgtDev = &pThisCC->paDeviceStates[pGuestReq->SCSIIO.u8TargetID]; - if (pTgtDev->pDrvBase) + if ( pTgtDev->pDrvBase + && pGuestReq->SCSIIO.u8CDBLength <= RT_ELEMENTS(pGuestReq->SCSIIO.au8CDB)) { /* Allocate and prepare a new request. */ PDMMEDIAEXIOREQ hIoReq; @@ -2364,12 +2365,12 @@ static int lsilogicR3ProcessSCSIIORequest(PPDMDEVINS pDevIns, PLSILOGICSCSI pThi if (g_cLogged++ < MAX_REL_LOG_ERRORS) { - LogRel(("LsiLogic#%d: %d/%d (Bus/Target) doesn't exist\n", pDevIns->iInstance, - pGuestReq->SCSIIO.u8TargetID, pGuestReq->SCSIIO.u8Bus)); + LogRel(("LsiLogic#%d: %d/%d/%d (Bus/Target/CDBLength) doesn't exist\n", pDevIns->iInstance, + pGuestReq->SCSIIO.u8TargetID, pGuestReq->SCSIIO.u8Bus, pGuestReq->SCSIIO.u8CDBLength)); /* Log the CDB too */ LogRel(("LsiLogic#%d: Guest issued CDB {%#x", pDevIns->iInstance, pGuestReq->SCSIIO.au8CDB[0])); - for (unsigned i = 1; i < pGuestReq->SCSIIO.u8CDBLength; i++) + for (unsigned i = 1; i < RT_MIN(pGuestReq->SCSIIO.u8CDBLength, RT_ELEMENTS(pGuestReq->SCSIIO.au8CDB)); i++) LogRel((", %#x", pGuestReq->SCSIIO.au8CDB[i])); LogRel(("}\n")); } diff --git a/src/VBox/Devices/Storage/VSCSI/VSCSIDevice.cpp b/src/VBox/Devices/Storage/VSCSI/VSCSIDevice.cpp index a2864b84..2b8a9a07 100644 --- a/src/VBox/Devices/Storage/VSCSI/VSCSIDevice.cpp +++ b/src/VBox/Devices/Storage/VSCSI/VSCSIDevice.cpp @@ -67,6 +67,13 @@ static bool vscsiDeviceReqProcess(PVSCSIDEVICEINT pVScsiDevice, PVSCSIREQINT pVS { bool fProcessed = true; + if (!pVScsiReq->cbCDB) + { + *prcReq = vscsiReqSenseErrorSet(&pVScsiDevice->VScsiSense, pVScsiReq, SCSI_SENSE_ILLEGAL_REQUEST, + SCSI_ASC_ILLEGAL_OPCODE, 0x00); + return true; + } + switch (pVScsiReq->pbCDB[0]) { case SCSI_INQUIRY: @@ -92,6 +99,13 @@ static bool vscsiDeviceReqProcess(PVSCSIDEVICEINT pVScsiDevice, PVSCSIREQINT pVS } case SCSI_REPORT_LUNS: { + if (pVScsiReq->cbCDB < 10) + { + *prcReq = vscsiReqSenseErrorSet(&pVScsiDevice->VScsiSense, pVScsiReq, SCSI_SENSE_ILLEGAL_REQUEST, + SCSI_ASC_ILLEGAL_OPCODE, 0x00); + break; + } + /* * If allocation length is less than 16 bytes SPC compliant devices have * to return an error. @@ -127,6 +141,13 @@ static bool vscsiDeviceReqProcess(PVSCSIDEVICEINT pVScsiDevice, PVSCSIREQINT pVS } case SCSI_REQUEST_SENSE: { + if (pVScsiReq->cbCDB < 5) + { + *prcReq = vscsiReqSenseErrorSet(&pVScsiDevice->VScsiSense, pVScsiReq, SCSI_SENSE_ILLEGAL_REQUEST, + SCSI_ASC_ILLEGAL_OPCODE, 0x00); + break; + } + vscsiReqSetXferDir(pVScsiReq, VSCSIXFERDIR_T2I); vscsiReqSetXferSize(pVScsiReq, pVScsiReq->pbCDB[4]); @@ -140,6 +161,13 @@ static bool vscsiDeviceReqProcess(PVSCSIDEVICEINT pVScsiDevice, PVSCSIREQINT pVS #if 0 case SCSI_MAINTENANCE_IN: { + if (pVScsiReq->cbCDB < 8) + { + *prcReq = vscsiLunReqSenseErrorSet(pVScsiLun, pVScsiReq, SCSI_SENSE_ILLEGAL_REQUEST, + SCSI_ASC_ILLEGAL_OPCODE, 0x00); + break; + } + if (pVScsiReq->pbCDB[1] == SCSI_MAINTENANCE_IN_REPORT_SUPP_OPC) { /* @@ -374,7 +402,26 @@ VBOXDDU_DECL(int) VSCSIDeviceReqEnqueue(VSCSIDEVICE hVScsiDevice, VSCSIREQ hVScs if (vscsiDeviceLunIsPresent(pVScsiDevice, pVScsiReq->iLun)) { PVSCSILUNINT pVScsiLun = pVScsiDevice->papVScsiLun[pVScsiReq->iLun]; - rc = pVScsiLun->pVScsiLunDesc->pfnVScsiLunReqProcess(pVScsiLun, pVScsiReq); + PVSCSILUNDESC pVScsiLunDesc = pVScsiLun->pVScsiLunDesc; + uint8_t const bOpc = pVScsiReq->pbCDB[0]; + uint8_t const cbCdbMin = pVScsiLunDesc->pacbCdbOpc[bOpc]; + + /* Fail if the opcode is not supported or the CDB is too short. */ + if ( cbCdbMin != VSCSI_LUN_CDB_SZ_INVALID + && pVScsiReq->cbCDB >= cbCdbMin) + rc = pVScsiLunDesc->pfnVScsiLunReqProcess(pVScsiLun, pVScsiReq); + else + { + /* + * CDB length is smaller than what the LUN expects, respond with an + * ILLEGAL OPCODE error. + */ + vscsiLunReqSenseErrorSet(pVScsiLun, pVScsiReq, SCSI_SENSE_ILLEGAL_REQUEST, + SCSI_ASC_ILLEGAL_OPCODE, 0x00); + + vscsiDeviceReqComplete(pVScsiDevice, pVScsiReq, + SCSI_STATUS_CHECK_CONDITION, false, VINF_SUCCESS); + } } else { diff --git a/src/VBox/Devices/Storage/VSCSI/VSCSIInternal.h b/src/VBox/Devices/Storage/VSCSI/VSCSIInternal.h index 71924d1d..b4af0cb5 100644 --- a/src/VBox/Devices/Storage/VSCSI/VSCSIInternal.h +++ b/src/VBox/Devices/Storage/VSCSI/VSCSIInternal.h @@ -241,6 +241,25 @@ typedef const VSCSILUNSUPOPC *PCVSCSILUNSUPOPC; { a_u8Opc, a_u16SvcAction, VSCSI_LUN_SUP_OPC_SVC_ACTION_REQUIRED, a_pszOpc, a_cbCdb, a_pbCdbUsage, 0, 0, 0} /** @} */ +/** @name Helper macros to specify a range of not supported CDB opcodes for the entries pointed + * to by VSCSILUNDESC::pacbCdbOpc. + * @{ */ +#define VSCSI_LUN_CDB_SZ_INVALID 0 +#define VSCSI_LUN_CDB_SZ_INVALID_X2 \ + VSCSI_LUN_CDB_SZ_INVALID, \ + VSCSI_LUN_CDB_SZ_INVALID +#define VSCSI_LUN_CDB_SZ_INVALID_X4 \ + VSCSI_LUN_CDB_SZ_INVALID_X2, \ + VSCSI_LUN_CDB_SZ_INVALID_X2 +#define VSCSI_LUN_CDB_SZ_INVALID_X8 \ + VSCSI_LUN_CDB_SZ_INVALID_X4, \ + VSCSI_LUN_CDB_SZ_INVALID_X4 +#define VSCSI_LUN_CDB_SZ_INVALID_X16 \ + VSCSI_LUN_CDB_SZ_INVALID_X8, \ + VSCSI_LUN_CDB_SZ_INVALID_X8 +/** @} */ + + /** * Virtual SCSI LUN descriptor. */ @@ -252,6 +271,9 @@ typedef struct VSCSILUNDESC const char *pcszDescName; /** LUN type size */ size_t cbLun; + /** Pointer to the array holding the CDB length indexed by the opcode. + * A 0 entry means opcode not supported (CDB must be at least 1 byte big). */ + const uint8_t *pacbCdbOpc; /** Number of entries in the supported operation codes array. */ uint32_t cSupOpcInfo; /** Pointer to the array of supported operation codes for the diff --git a/src/VBox/Devices/Storage/VSCSI/VSCSILunMmc.cpp b/src/VBox/Devices/Storage/VSCSI/VSCSILunMmc.cpp index 66d76e22..24fc6a33 100644 --- a/src/VBox/Devices/Storage/VSCSI/VSCSILunMmc.cpp +++ b/src/VBox/Devices/Storage/VSCSI/VSCSILunMmc.cpp @@ -1770,6 +1770,115 @@ static DECLCALLBACK(int) vscsiLunMmcMediumRemoved(PVSCSILUNINT pVScsiLun) } +/** + * The supported operation codes for the MMC LUN type. + * + * @note This gives the minimum size required by our implementation + * which may be smaller than what the spec defines (for example + * we do not access the control byte at the end). + */ +static uint8_t s_acbCdbOpc[] = +{ + 1, /**< 0x00 TEST UNIT READY */ + VSCSI_LUN_CDB_SZ_INVALID, /**< 0x01 Invalid */ + VSCSI_LUN_CDB_SZ_INVALID_X2, /**< 0x02 - 0x03 Invalid */ + VSCSI_LUN_CDB_SZ_INVALID_X4, /**< 0x04 - 0x07 Invalid */ + 5, /**< 0x08 READ (6) */ + VSCSI_LUN_CDB_SZ_INVALID, /**< 0x09 Invalid */ + VSCSI_LUN_CDB_SZ_INVALID_X2, /**< 0x0a - 0x0b Invalid */ + VSCSI_LUN_CDB_SZ_INVALID_X4, /**< 0x0c - 0x0f Invalid */ + + VSCSI_LUN_CDB_SZ_INVALID_X2, /**< 0x10 - 0x11 Invalid */ + 5, /**< 0x12 INQUIRY */ + VSCSI_LUN_CDB_SZ_INVALID, /**< 0x13 Invalid */ + VSCSI_LUN_CDB_SZ_INVALID, /**< 0x14 Invalid */ + 5, /**< 0x15 MODE SELECT (6) */ + VSCSI_LUN_CDB_SZ_INVALID_X2, /**< 0x16 - 0x17 Invalid */ + VSCSI_LUN_CDB_SZ_INVALID_X2, /**< 0x18 - 0x19 Invalid */ + 5, /**< 0x1a MODE SENSE (6) */ + 5, /**< 0x1b START STOP UNIT */ + VSCSI_LUN_CDB_SZ_INVALID_X2, /**< 0x1c - 0x1d Invalid */ + 5, /**< 0x1e PREVENT ALLOW MEDIUM REMOVAL */ + VSCSI_LUN_CDB_SZ_INVALID, /**< 0x1f Invalid */ + + VSCSI_LUN_CDB_SZ_INVALID_X4, /**< 0x20 - 0x23 Invalid */ + VSCSI_LUN_CDB_SZ_INVALID, /**< 0x24 Invalid */ + 1, /**< 0x25 READ CAPACITY */ + VSCSI_LUN_CDB_SZ_INVALID_X2, /**< 0x26 - 0x27 Invalid */ + 9, /**< 0x28 READ (10) */ + VSCSI_LUN_CDB_SZ_INVALID_X2, /**< 0x29 - 0x2a Invalid */ + 6, /**< 0x2b SEEK (10) */ + VSCSI_LUN_CDB_SZ_INVALID_X2, /**< 0x2c - 0x2d Invalid */ + VSCSI_LUN_CDB_SZ_INVALID, /**< 0x2e Invalid */ + 5, /**< 0x2f VERIFY (10) */ + + VSCSI_LUN_CDB_SZ_INVALID_X8, /**< 0x30 - 0x37 Invalid */ + VSCSI_LUN_CDB_SZ_INVALID_X4, /**< 0x38 - 0x3b Invalid */ + 8, /**< 0x3c READ BUFFER */ + VSCSI_LUN_CDB_SZ_INVALID, /**< 0x3d Invalid */ + VSCSI_LUN_CDB_SZ_INVALID_X2, /**< 0x3e - 0x3f Invalid */ + + VSCSI_LUN_CDB_SZ_INVALID_X2, /**< 0x40 - 0x41 Invalid */ + VSCSI_LUN_CDB_SZ_INVALID, /**< 0x42 Invalid */ + 9, /**< 0x43 READ TOC PMA ATIP */ + VSCSI_LUN_CDB_SZ_INVALID_X2, /**< 0x44 - 0x45 Invalid */ + 9, /**< 0x46 GET CONFIGURATION */ + VSCSI_LUN_CDB_SZ_INVALID, /**< 0x47 Invalid */ + VSCSI_LUN_CDB_SZ_INVALID_X2, /**< 0x48 - 0x49 Invalid */ + 9, /**< 0x4a GET EVENT STATUS NOTIFICATION */ + VSCSI_LUN_CDB_SZ_INVALID, /**< 0x4b Invalid */ + VSCSI_LUN_CDB_SZ_INVALID, /**< 0x4c Invalid */ + 9, /**< 0x4d LOG SENSE */ + VSCSI_LUN_CDB_SZ_INVALID_X2, /**< 0x4e - 0x4f Invalid */ + + VSCSI_LUN_CDB_SZ_INVALID, /**< 0x50 Invalid */ + 9, /**< 0x51 READ DISC INFORMATION */ + 9, /**< 0x52 READ TRACK INFORMATION */ + VSCSI_LUN_CDB_SZ_INVALID, /**< 0x53 Invalid */ + VSCSI_LUN_CDB_SZ_INVALID_X4, /**< 0x54 - 0x57 Invalid */ + VSCSI_LUN_CDB_SZ_INVALID_X2, /**< 0x58 - 0x59 Invalid */ + 9, /**< 0x5a MODE SENSE (10) */ + VSCSI_LUN_CDB_SZ_INVALID, /**< 0x5b Invalid */ + VSCSI_LUN_CDB_SZ_INVALID_X4, /**< 0x5c - 0x5f Invalid */ + + VSCSI_LUN_CDB_SZ_INVALID_X16, /**< 0x60 - 0x6f Invalid */ + VSCSI_LUN_CDB_SZ_INVALID_X16, /**< 0x70 - 0x7f Invalid */ + + VSCSI_LUN_CDB_SZ_INVALID_X8, /**< 0x80 - 0x87 Invalid */ + 14, /**< 0x88 READ (16) */ + VSCSI_LUN_CDB_SZ_INVALID, /**< 0x89 Invalid */ + VSCSI_LUN_CDB_SZ_INVALID_X2, /**< 0x8a - 0x8b Invalid */ + VSCSI_LUN_CDB_SZ_INVALID_X4, /**< 0x8c - 0x8f Invalid */ + + VSCSI_LUN_CDB_SZ_INVALID_X8, /**< 0x90 - 0x97 Invalid */ + VSCSI_LUN_CDB_SZ_INVALID_X4, /**< 0x98 - 0x9b Invalid */ + VSCSI_LUN_CDB_SZ_INVALID_X2, /**< 0x9c - 0x9d Invalid */ + 2, /**< 0x9e SERVICE ACTION IN (16) (at least 2). */ + VSCSI_LUN_CDB_SZ_INVALID, /**< 0x9f Invalid */ + + VSCSI_LUN_CDB_SZ_INVALID_X8, /**< 0xa0 - 0xa7 Invalid */ + 10, /**< 0xa8 READ (12) */ + VSCSI_LUN_CDB_SZ_INVALID, /**< 0xa9 Invalid */ + VSCSI_LUN_CDB_SZ_INVALID_X2, /**< 0xaa - 0xab Invalid */ + VSCSI_LUN_CDB_SZ_INVALID, /**< 0xac Invalid */ + 10, /**< 0xad READ DVD STRUCTURE */ + VSCSI_LUN_CDB_SZ_INVALID_X2, /**< 0xae - 0xaf Invalid */ + + VSCSI_LUN_CDB_SZ_INVALID_X8, /**< 0xb0 - 0xb7 Invalid */ + VSCSI_LUN_CDB_SZ_INVALID_X4, /**< 0xb8 - 0xbb Invalid */ + VSCSI_LUN_CDB_SZ_INVALID, /**< 0xbc Invalid */ + 10, /**< 0xbd MECHANISM STATUS */ + 10, /**< 0xbe READ CD */ + VSCSI_LUN_CDB_SZ_INVALID, /**< 0xbf Invalid */ + + VSCSI_LUN_CDB_SZ_INVALID_X16, /**< 0xc0 - 0xcf Invalid */ + VSCSI_LUN_CDB_SZ_INVALID_X16, /**< 0xd0 - 0xdf Invalid */ + VSCSI_LUN_CDB_SZ_INVALID_X16, /**< 0xe0 - 0xef Invalid */ + VSCSI_LUN_CDB_SZ_INVALID_X16 /**< 0xf0 - 0xff Invalid */ +}; +AssertCompileSize(s_acbCdbOpc, 256 * sizeof(uint8_t)); + + VSCSILUNDESC g_VScsiLunTypeMmc = { /** enmLunType */ @@ -1778,6 +1887,8 @@ VSCSILUNDESC g_VScsiLunTypeMmc = "MMC", /** cbLun */ sizeof(VSCSILUNMMC), + /** pacbCdbOpc */ + &s_acbCdbOpc[0], /** cSupOpcInfo */ 0, /** paSupOpcInfo */ diff --git a/src/VBox/Devices/Storage/VSCSI/VSCSILunSbc.cpp b/src/VBox/Devices/Storage/VSCSI/VSCSILunSbc.cpp index 3769c4f6..3fb5436e 100644 --- a/src/VBox/Devices/Storage/VSCSI/VSCSILunSbc.cpp +++ b/src/VBox/Devices/Storage/VSCSI/VSCSILunSbc.cpp @@ -230,30 +230,35 @@ static DECLCALLBACK(int) vscsiLunSbcReqProcess(PVSCSILUNINT pVScsiLun, PVSCSIREQ SCSI_ASC_INV_FIELD_IN_CMD_PACKET, 0x00); else { - SCSIINQUIRYDATA ScsiInquiryReply; + if (pVScsiReq->cbCDB >= 5) + { + SCSIINQUIRYDATA ScsiInquiryReply; - vscsiReqSetXferSize(pVScsiReq, RT_MIN(sizeof(SCSIINQUIRYDATA), scsiBE2H_U16(&pVScsiReq->pbCDB[3]))); - memset(&ScsiInquiryReply, 0, sizeof(ScsiInquiryReply)); + vscsiReqSetXferSize(pVScsiReq, RT_MIN(sizeof(SCSIINQUIRYDATA), scsiBE2H_U16(&pVScsiReq->pbCDB[3]))); + memset(&ScsiInquiryReply, 0, sizeof(ScsiInquiryReply)); - ScsiInquiryReply.cbAdditional = 31; - ScsiInquiryReply.u5PeripheralDeviceType = SCSI_INQUIRY_DATA_PERIPHERAL_DEVICE_TYPE_DIRECT_ACCESS; - ScsiInquiryReply.u3PeripheralQualifier = SCSI_INQUIRY_DATA_PERIPHERAL_QUALIFIER_CONNECTED; - ScsiInquiryReply.u3AnsiVersion = 0x05; /* SPC-4 compliant */ - ScsiInquiryReply.fCmdQue = 1; /* Command queuing supported. */ - ScsiInquiryReply.fWBus16 = 1; + ScsiInquiryReply.cbAdditional = 31; + ScsiInquiryReply.u5PeripheralDeviceType = SCSI_INQUIRY_DATA_PERIPHERAL_DEVICE_TYPE_DIRECT_ACCESS; + ScsiInquiryReply.u3PeripheralQualifier = SCSI_INQUIRY_DATA_PERIPHERAL_QUALIFIER_CONNECTED; + ScsiInquiryReply.u3AnsiVersion = 0x05; /* SPC-4 compliant */ + ScsiInquiryReply.fCmdQue = 1; /* Command queuing supported. */ + ScsiInquiryReply.fWBus16 = 1; - const char *pszVendorId = "VBOX"; - const char *pszProductId = "HARDDISK"; - const char *pszProductLevel = "1.0"; - int rcTmp = vscsiLunQueryInqStrings(pVScsiLun, &pszVendorId, &pszProductId, &pszProductLevel); - Assert(RT_SUCCESS(rcTmp) || rcTmp == VERR_NOT_FOUND); RT_NOREF(rcTmp); + const char *pszVendorId = "VBOX"; + const char *pszProductId = "HARDDISK"; + const char *pszProductLevel = "1.0"; + int rcTmp = vscsiLunQueryInqStrings(pVScsiLun, &pszVendorId, &pszProductId, &pszProductLevel); + Assert(RT_SUCCESS(rcTmp) || rcTmp == VERR_NOT_FOUND); RT_NOREF(rcTmp); - scsiPadStrS(ScsiInquiryReply.achVendorId, pszVendorId, 8); - scsiPadStrS(ScsiInquiryReply.achProductId, pszProductId, 16); - scsiPadStrS(ScsiInquiryReply.achProductLevel, pszProductLevel, 4); + scsiPadStrS(ScsiInquiryReply.achVendorId, pszVendorId, 8); + scsiPadStrS(ScsiInquiryReply.achProductId, pszProductId, 16); + scsiPadStrS(ScsiInquiryReply.achProductLevel, pszProductLevel, 4); - RTSgBufCopyFromBuf(&pVScsiReq->SgBuf, (uint8_t *)&ScsiInquiryReply, sizeof(SCSIINQUIRYDATA)); - rcReq = vscsiLunReqSenseOkSet(pVScsiLun, pVScsiReq); + RTSgBufCopyFromBuf(&pVScsiReq->SgBuf, (uint8_t *)&ScsiInquiryReply, sizeof(SCSIINQUIRYDATA)); + rcReq = vscsiLunReqSenseOkSet(pVScsiLun, pVScsiReq); + } + else + rcReq = vscsiLunReqSenseErrorSet(pVScsiLun, pVScsiReq, SCSI_SENSE_ILLEGAL_REQUEST, SCSI_ASC_INVALID_MESSAGE, 0x00); } break; } @@ -419,7 +424,7 @@ static DECLCALLBACK(int) vscsiLunSbcReqProcess(PVSCSILUNINT pVScsiLun, PVSCSIREQ uint8_t uDataMode = pVScsiReq->pbCDB[1] & 0x1f; vscsiReqSetXferDir(pVScsiReq, VSCSIXFERDIR_T2I); - vscsiReqSetXferSize(pVScsiReq, scsiBE2H_U16(&pVScsiReq->pbCDB[6])); + vscsiReqSetXferSize(pVScsiReq, scsiBE2H_U24(&pVScsiReq->pbCDB[6])); switch (uDataMode) { @@ -627,6 +632,92 @@ static DECLCALLBACK(int) vscsiLunSbcReqProcess(PVSCSILUNINT pVScsiLun, PVSCSIREQ return rc; } + +/** + * The supported operation codes for the SBC LUN type. + * + * @note This gives the minimum size required by our implementation + * which may be smaller than what the spec defines (for example + * we do not access the control byte at the end). + */ +static uint8_t s_acbCdbOpc[] = +{ + VSCSI_LUN_CDB_SZ_INVALID_X8, /**< 0x00 - 0x07 Invalid */ + 5, /**< 0x08 READ (6) */ + VSCSI_LUN_CDB_SZ_INVALID, /**< 0x09 Invalid */ + 5, /**< 0x0a WRITE (6) */ + VSCSI_LUN_CDB_SZ_INVALID, /**< 0x0b Invalid */ + VSCSI_LUN_CDB_SZ_INVALID_X4, /**< 0x0c - 0x0f Invalid */ + + VSCSI_LUN_CDB_SZ_INVALID_X2, /**< 0x10 - 0x11 Invalid */ + 3, /**< 0x12 INQUIRY (at least 3) */ + VSCSI_LUN_CDB_SZ_INVALID_X2, /**< 0x13 - 0x14 Invalid */ + 5, /**< 0x15 MODE SELECT (6) */ + VSCSI_LUN_CDB_SZ_INVALID_X4, /**< 0x16 - 0x19 Invalid */ + 5, /**< 0x1a MODE SENSE (6) */ + 1, /**< 0x1b START STOP UNIT */ + VSCSI_LUN_CDB_SZ_INVALID_X4, /**< 0x1c - 0x1f Invalid */ + + VSCSI_LUN_CDB_SZ_INVALID_X4, /**< 0x20 - 0x23 Invalid */ + VSCSI_LUN_CDB_SZ_INVALID, /**< 0x24 Invalid */ + 1, /**< 0x25 READ CAPACITY */ + VSCSI_LUN_CDB_SZ_INVALID_X2, /**< 0x26 - 0x27 Invalid */ + 9, /**< 0x28 READ (10) */ + VSCSI_LUN_CDB_SZ_INVALID, /**< 0x29 Invalid */ + 9, /**< 0x2a WRITE (10) */ + VSCSI_LUN_CDB_SZ_INVALID_X4, /**< 0x2b - 0x2e Invalid */ + 1, /**< 0x2f VERIFY (10) */ + + VSCSI_LUN_CDB_SZ_INVALID_X4, /**< 0x30 - 0x33 Invalid */ + VSCSI_LUN_CDB_SZ_INVALID, /**< 0x34 Invalid */ + 1, /**< 0x35 SYNCHRONIZE CACHE */ + VSCSI_LUN_CDB_SZ_INVALID_X4, /**< 0x36 - 0x39 Invalid */ + VSCSI_LUN_CDB_SZ_INVALID_X2, /**< 0x3a - 0x3b Invalid */ + 8, /**< 0x3c READ BUFFER */ + VSCSI_LUN_CDB_SZ_INVALID, /**< 0x3d Invalid */ + VSCSI_LUN_CDB_SZ_INVALID_X2, /**< 0x3e - 0x3f Invalid */ + + VSCSI_LUN_CDB_SZ_INVALID_X2, /**< 0x40 - 0x41 Invalid */ + 9, /**< 0x42 UNMAP */ + VSCSI_LUN_CDB_SZ_INVALID, /**< 0x43 Invalid */ + VSCSI_LUN_CDB_SZ_INVALID_X8, /**< 0x44 - 0x4b Invalid */ + VSCSI_LUN_CDB_SZ_INVALID, /**< 0x4c Invalid */ + 9, /**< 0x4d LOG SENSE */ + VSCSI_LUN_CDB_SZ_INVALID_X2, /**< 0x4e - 0x4f Invalid */ + + VSCSI_LUN_CDB_SZ_INVALID_X16, /**< 0x50 - 0x5f Invalid */ + VSCSI_LUN_CDB_SZ_INVALID_X16, /**< 0x60 - 0x6f Invalid */ + VSCSI_LUN_CDB_SZ_INVALID_X16, /**< 0x70 - 0x7f Invalid */ + + VSCSI_LUN_CDB_SZ_INVALID_X8, /**< 0x80 - 0x87 Invalid */ + 14, /**< 0x88 READ (16) */ + VSCSI_LUN_CDB_SZ_INVALID, /**< 0x89 Invalid */ + 14, /**< 0x8a WRITE (16) */ + VSCSI_LUN_CDB_SZ_INVALID, /**< 0x8b Invalid */ + VSCSI_LUN_CDB_SZ_INVALID_X4, /**< 0x8c - 0x8f Invalid */ + + VSCSI_LUN_CDB_SZ_INVALID_X8, /**< 0x90 - 0x97 Invalid */ + VSCSI_LUN_CDB_SZ_INVALID_X4, /**< 0x98 - 0x9b Invalid */ + VSCSI_LUN_CDB_SZ_INVALID_X2, /**< 0x9c - 0x9d Invalid */ + 2, /**< 0x9e SERVICE ACTION IN (16) (at least 2). */ + VSCSI_LUN_CDB_SZ_INVALID, /**< 0x9f Invalid */ + + VSCSI_LUN_CDB_SZ_INVALID_X8, /**< 0xa0 - 0xa7 Invalid */ + 10, /**< 0xa8 READ (12) */ + VSCSI_LUN_CDB_SZ_INVALID, /**< 0xa9 Invalid */ + 10, /**< 0xaa WRITE (12) */ + VSCSI_LUN_CDB_SZ_INVALID, /**< 0xab Invalid */ + VSCSI_LUN_CDB_SZ_INVALID_X4, /**< 0xac - 0xaf Invalid */ + + VSCSI_LUN_CDB_SZ_INVALID_X16, /**< 0xb0 - 0xbf Invalid */ + VSCSI_LUN_CDB_SZ_INVALID_X16, /**< 0xc0 - 0xcf Invalid */ + VSCSI_LUN_CDB_SZ_INVALID_X16, /**< 0xd0 - 0xdf Invalid */ + VSCSI_LUN_CDB_SZ_INVALID_X16, /**< 0xe0 - 0xef Invalid */ + VSCSI_LUN_CDB_SZ_INVALID_X16 /**< 0xf0 - 0xff Invalid */ +}; +AssertCompileSize(s_acbCdbOpc, 256 * sizeof(uint8_t)); + + VSCSILUNDESC g_VScsiLunTypeSbc = { /** enmLunType */ @@ -635,6 +726,8 @@ VSCSILUNDESC g_VScsiLunTypeSbc = "SBC", /** cbLun */ sizeof(VSCSILUNSBC), + /** pacbCdbOpc */ + &s_acbCdbOpc[0], /** cSupOpcInfo */ 0, /** paSupOpcInfo */ diff --git a/src/VBox/Devices/Storage/VSCSI/VSCSILunSsc.cpp b/src/VBox/Devices/Storage/VSCSI/VSCSILunSsc.cpp index 4c659a2d..a190ff65 100644 --- a/src/VBox/Devices/Storage/VSCSI/VSCSILunSsc.cpp +++ b/src/VBox/Devices/Storage/VSCSI/VSCSILunSsc.cpp @@ -450,6 +450,8 @@ VSCSILUNDESC g_VScsiLunTypeSsc = "SSC", /** cbLun */ sizeof(VSCSILUNSSC), + /** pacbCdbOpc */ + NULL, /** cSupOpcInfo */ 0, /** paSupOpcInfo */ diff --git a/src/VBox/Devices/USB/DevEHCI.cpp b/src/VBox/Devices/USB/DevEHCI.cpp index ade53208..1ca85af3 100644 --- a/src/VBox/Devices/USB/DevEHCI.cpp +++ b/src/VBox/Devices/USB/DevEHCI.cpp @@ -1623,7 +1623,7 @@ DECLINLINE(void) ehciR3DumpQTD(PPDMDEVINS pDevIns, RTGCPHYS GCPhysHead, bool fLi if (GCPhys == ((RTGCPHYS)qtd.Next.Pointer << EHCI_TD_PTR_SHIFT)) break; /* detect if list item is self-cycled. */ - GCPhys = qtd.Next.Pointer << EHCI_TD_PTR_SHIFT; + GCPhys = (RTGCPHYS)qtd.Next.Pointer << EHCI_TD_PTR_SHIFT; if (GCPhys == GCPhysHead) break; @@ -1659,7 +1659,7 @@ DECLINLINE(void) ehciR3DumpQTD(PPDMDEVINS pDevIns, RTGCPHYS GCPhysHead, bool fLi if (GCPhys == ((RTGCPHYS)qtd.AltNext.Pointer << EHCI_TD_PTR_SHIFT)) break; /* detect if list item is self-cycled. */ - GCPhys = qtd.AltNext.Pointer << EHCI_TD_PTR_SHIFT; + GCPhys = (RTGCPHYS)qtd.AltNext.Pointer << EHCI_TD_PTR_SHIFT; if (GCPhys == GCPhysHead) break; @@ -1701,8 +1701,8 @@ DECLINLINE(void) ehciR3DumpQH(PPDMDEVINS pDevIns, RTGCPHYS GCPhysHead, bool fLis ((RTGCPHYS)qhd.CurrQTD.Pointer << EHCI_TD_PTR_SHIFT), ((RTGCPHYS)qhd.Overlay.OrgQTD.Next.Pointer << EHCI_TD_PTR_SHIFT), qhd.Overlay.OrgQTD.Next.Terminate, ((RTGCPHYS)qhd.Overlay.OrgQTD.AltNext.Pointer << EHCI_TD_PTR_SHIFT), qhd.Overlay.OrgQTD.AltNext.Terminate)); - ehciR3DumpSingleQTD(qhd.CurrQTD.Pointer << EHCI_TD_PTR_SHIFT, &qhd.Overlay.OrgQTD, ""); - ehciR3DumpQTD(pDevIns, qhd.Overlay.OrgQTD.Next.Pointer << EHCI_TD_PTR_SHIFT, true); + ehciR3DumpSingleQTD((RTGCPHYS)qhd.CurrQTD.Pointer << EHCI_TD_PTR_SHIFT, &qhd.Overlay.OrgQTD, ""); + ehciR3DumpQTD(pDevIns, (RTGCPHYS)qhd.Overlay.OrgQTD.Next.Pointer << EHCI_TD_PTR_SHIFT, true); Assert(qhd.Next.Pointer || qhd.Next.Terminate); if ( !fList @@ -1727,7 +1727,7 @@ DECLINLINE(void) ehciR3DumpQH(PPDMDEVINS pDevIns, RTGCPHYS GCPhysHead, bool fLis if (GCPhys == ((RTGCPHYS)ptr.Pointer << EHCI_TD_PTR_SHIFT)) break; /* Looping on itself. Bad guest! */ - GCPhys = ptr.Pointer << EHCI_TD_PTR_SHIFT; + GCPhys = (RTGCPHYS)ptr.Pointer << EHCI_TD_PTR_SHIFT; if (GCPhys == GCPhysHead) break; /* break the loop */ @@ -1767,7 +1767,7 @@ DECLINLINE(void) ehciR3DumpITD(PPDMDEVINS pDevIns, RTGCPHYS GCPhysHead, bool fLi if (pItd->Transaction[i].Active) { Log2(("T%d Len=%x Offset=%x PG=%d IOC=%d Buffer=%x\n", i, pItd->Transaction[i].Length, pItd->Transaction[i].Offset, pItd->Transaction[i].PG, pItd->Transaction[i].IOC, - pItd->Buffer.Buffer[pItd->Transaction[i].PG].Pointer << EHCI_BUFFER_PTR_SHIFT)); + (RTGCPHYS)pItd->Buffer.Buffer[pItd->Transaction[i].PG].Pointer << EHCI_BUFFER_PTR_SHIFT)); } } Assert(pItd->Next.Pointer || pItd->Next.Terminate); @@ -1784,7 +1784,7 @@ DECLINLINE(void) ehciR3DumpITD(PPDMDEVINS pDevIns, RTGCPHYS GCPhysHead, bool fLi } /* next */ - GCPhys = pItd->Next.Pointer << EHCI_TD_PTR_SHIFT; + GCPhys = (RTGCPHYS)pItd->Next.Pointer << EHCI_TD_PTR_SHIFT; } } @@ -2325,7 +2325,7 @@ static void ehciR3RhXferCompleteITD(PPDMDEVINS pDevIns, PEHCI pThis, PEHCICC pTh if ((pg + 1) >= EHCI_NUM_ITD_PAGES) LogRelMax(10, ("EHCI: Crossing to undefined page %d in iTD at %RGp on completion.\n", pg + 1, pUrb->paTds[0].TdAddr)); - GCPhysBuf = pItd->Buffer.Buffer[pg + 1].Pointer << EHCI_BUFFER_PTR_SHIFT; + GCPhysBuf = (RTGCPHYS)pItd->Buffer.Buffer[pg + 1].Pointer << EHCI_BUFFER_PTR_SHIFT; ehciPhysWrite(pDevIns, GCPhysBuf, pb + cb1, cb2); } else @@ -2409,7 +2409,7 @@ static void ehciR3RhXferCompleteQH(PPDMDEVINS pDevIns, PEHCI pThis, PEHCICC pThi AssertMsg(pUrb->paTds[0].TdAddr == ((RTGCPHYS)qhd.CurrQTD.Pointer << EHCI_TD_PTR_SHIFT), ("Out of order completion %RGp != %RGp Endpoint=%#x\n", pUrb->paTds[0].TdAddr, ((RTGCPHYS)qhd.CurrQTD.Pointer << EHCI_TD_PTR_SHIFT), pUrb->EndPt)); - ehciR3ReadQTD(pDevIns, qhd.CurrQTD.Pointer << EHCI_TD_PTR_SHIFT, &qtd); + ehciR3ReadQTD(pDevIns, (RTGCPHYS)qhd.CurrQTD.Pointer << EHCI_TD_PTR_SHIFT, &qtd); /* * Check that the URB hasn't been canceled and then try unlink the TDs. @@ -2460,7 +2460,7 @@ static void ehciR3RhXferCompleteQH(PPDMDEVINS pDevIns, PEHCI pThis, PEHCICC pThi RTGCPHYS GCPhysBuf; unsigned cbCurTransfer; - GCPhysBuf = qtd.Buffer.Buffer[i].Pointer << EHCI_BUFFER_PTR_SHIFT; + GCPhysBuf = (RTGCPHYS)qtd.Buffer.Buffer[i].Pointer << EHCI_BUFFER_PTR_SHIFT; if (i == 0) GCPhysBuf += qtd.Buffer.Offset.Offset; @@ -2600,7 +2600,7 @@ static bool ehciR3RhXferErrorQH(PPDMDEVINS pDevIns, PEHCICC pThisCC, PVUSBURB pU /* Read the whole QHD & QTD */ ehciR3ReadQHD(pDevIns, pUrb->pHci->EdAddr, &qhd); Assert(pUrb->paTds[0].TdAddr == ((RTGCPHYS)qhd.CurrQTD.Pointer << EHCI_TD_PTR_SHIFT)); - ehciR3ReadQTD(pDevIns, qhd.CurrQTD.Pointer << EHCI_TD_PTR_SHIFT, &qtd); + ehciR3ReadQTD(pDevIns, (RTGCPHYS)qhd.CurrQTD.Pointer << EHCI_TD_PTR_SHIFT, &qtd); /* * Check if the TDs still are valid. @@ -2737,7 +2737,7 @@ static bool ehciR3SubmitQTD(PPDMDEVINS pDevIns, PEHCI pThis, PEHCICC pThisCC, RT RTGCPHYS GCPhysBuf; unsigned cbCurTransfer; - GCPhysBuf = pQtd->Buffer.Buffer[i].Pointer << EHCI_BUFFER_PTR_SHIFT; + GCPhysBuf = (RTGCPHYS)pQtd->Buffer.Buffer[i].Pointer << EHCI_BUFFER_PTR_SHIFT; if (i == 0) GCPhysBuf += pQtd->Buffer.Offset.Offset; @@ -2862,7 +2862,7 @@ static bool ehciR3SubmitITD(PPDMDEVINS pDevIns, PEHCI pThis, PEHCICC pThisCC, { const unsigned pg = pItd->Transaction[i].PG; - GCPhysBuf = pItd->Buffer.Buffer[pg].Pointer << EHCI_BUFFER_PTR_SHIFT; + GCPhysBuf = (RTGCPHYS)pItd->Buffer.Buffer[pg].Pointer << EHCI_BUFFER_PTR_SHIFT; GCPhysBuf += pItd->Transaction[i].Offset; /* If the transfer would cross page boundary, use the next sequential PG pointer @@ -2877,7 +2877,7 @@ static bool ehciR3SubmitITD(PPDMDEVINS pDevIns, PEHCI pThis, PEHCICC pThisCC, if ((pg + 1) >= EHCI_NUM_ITD_PAGES) LogRelMax(10, ("EHCI: Crossing to undefined page %d in iTD at %RGp on submit.\n", pg + 1, pUrb->paTds[0].TdAddr)); - GCPhysBuf = pItd->Buffer.Buffer[pg + 1].Pointer << EHCI_BUFFER_PTR_SHIFT; + GCPhysBuf = (RTGCPHYS)pItd->Buffer.Buffer[pg + 1].Pointer << EHCI_BUFFER_PTR_SHIFT; ehciPhysRead(pDevIns, GCPhysBuf, &pUrb->abData[curOffset + cb1], cb2); } else @@ -3024,7 +3024,7 @@ static void ehciR3QHUpdateOverlay(PPDMDEVINS pDevIns, PEHCI pThis, PEHCICC pThis if (!pQhd->Overlay.OrgQTD.Next.Terminate) { EHCI_QTD qtdNext; - RTGCPHYS GCPhysNextQTD = pQhd->Overlay.OrgQTD.Next.Pointer << EHCI_TD_PTR_SHIFT; + RTGCPHYS GCPhysNextQTD = (RTGCPHYS)pQhd->Overlay.OrgQTD.Next.Pointer << EHCI_TD_PTR_SHIFT; if (ehciR3IsTdInFlight(pThisCC, GCPhysNextQTD)) { @@ -3073,7 +3073,7 @@ static RTGCPHYS ehciR3ServiceQTD(PPDMDEVINS pDevIns, PEHCI pThis, PEHCICC pThisC || GCPhysQTD == (RTGCPHYS)pQhd->CurrQTD.Pointer << EHCI_TD_PTR_SHIFT) ehciR3QHSetupOverlay(pDevIns, pQhd, GCPhysQHD, &qtd, GCPhysQTD); else - Log2Func(("transfer %RGp in progress -> don't update the overlay\n", (RTGCPHYS)(pQhd->CurrQTD.Pointer << EHCI_TD_PTR_SHIFT))); + Log2Func(("transfer %RGp in progress -> don't update the overlay\n", (RTGCPHYS)pQhd->CurrQTD.Pointer << EHCI_TD_PTR_SHIFT)); ehciR3SubmitQTD(pDevIns, pThis, pThisCC, GCPhysQHD, pQhd, GCPhysQTD, &qtd, iFrame); @@ -3119,14 +3119,14 @@ static RTGCPHYS ehciR3ServiceQTD(PPDMDEVINS pDevIns, PEHCI pThis, PEHCICC pThisC { Assert(qtd.AltNext.Pointer); Log2(("Taking alternate pointer %RGp\n", (RTGCPHYS)(qtd.AltNext.Pointer << EHCI_TD_PTR_SHIFT))); - return qtd.AltNext.Pointer << EHCI_TD_PTR_SHIFT; + return (RTGCPHYS)qtd.AltNext.Pointer << EHCI_TD_PTR_SHIFT; } else { Assert(qtd.Next.Pointer || qtd.Next.Terminate); if (qtd.Next.Terminate || !qtd.Next.Pointer) return 0; - return qtd.Next.Pointer << EHCI_TD_PTR_SHIFT; + return (RTGCPHYS)qtd.Next.Pointer << EHCI_TD_PTR_SHIFT; } } @@ -3206,8 +3206,8 @@ static bool ehciR3ServiceQHD(PPDMDEVINS pDevIns, PEHCI pThis, PEHCICC pThisCC, RTGCPHYS GCPhysQTD; if (qhd.Overlay.OrgQTD.Token.Bits.Active) { - Assert(ehciR3IsTdInFlight(pThisCC, qhd.CurrQTD.Pointer << EHCI_TD_PTR_SHIFT)); - GCPhysQTD = qhd.CurrQTD.Pointer << EHCI_TD_PTR_SHIFT; + Assert(ehciR3IsTdInFlight(pThisCC, (RTGCPHYS)qhd.CurrQTD.Pointer << EHCI_TD_PTR_SHIFT)); + GCPhysQTD = (RTGCPHYS)qhd.CurrQTD.Pointer << EHCI_TD_PTR_SHIFT; } else { @@ -3216,8 +3216,8 @@ static bool ehciR3ServiceQHD(PPDMDEVINS pDevIns, PEHCI pThis, PEHCICC pThisCC, && qhd.Overlay.OrgQTD.Token.Bits.Length) { Assert(qhd.Overlay.OrgQTD.AltNext.Pointer); - Log2(("Taking alternate pointer %RGp\n", (RTGCPHYS)(qhd.Overlay.OrgQTD.AltNext.Pointer << EHCI_TD_PTR_SHIFT))); - GCPhysQTD = qhd.Overlay.OrgQTD.AltNext.Pointer << EHCI_TD_PTR_SHIFT; + Log2(("Taking alternate pointer %RGp\n", (RTGCPHYS)qhd.Overlay.OrgQTD.AltNext.Pointer << EHCI_TD_PTR_SHIFT)); + GCPhysQTD = (RTGCPHYS)qhd.Overlay.OrgQTD.AltNext.Pointer << EHCI_TD_PTR_SHIFT; } else { @@ -3225,7 +3225,7 @@ static bool ehciR3ServiceQHD(PPDMDEVINS pDevIns, PEHCI pThis, PEHCICC pThisCC, if (qhd.Overlay.OrgQTD.Next.Terminate || !qhd.Overlay.OrgQTD.Next.Pointer || qhd.Overlay.OrgQTD.Token.Bits.Halted) GCPhysQTD = 0; else - GCPhysQTD = qhd.Overlay.OrgQTD.Next.Pointer << EHCI_TD_PTR_SHIFT; + GCPhysQTD = (RTGCPHYS)qhd.Overlay.OrgQTD.Next.Pointer << EHCI_TD_PTR_SHIFT; } } @@ -3308,7 +3308,7 @@ static void ehciR3ServiceAsyncList(PPDMDEVINS pDevIns, PEHCI pThis, PEHCICC pThi AssertMsgBreak(++cIterations < 128, ("Too many iterations, exiting\n")); /* next */ - GCPhys = ptr.Pointer << EHCI_TD_PTR_SHIFT; + GCPhys = (RTGCPHYS)ptr.Pointer << EHCI_TD_PTR_SHIFT; Assert(!(GCPhys & 0x1f)); if ( GCPhys == GCPhysHead || GCPhys == GCPhysLast) @@ -3357,7 +3357,7 @@ static void ehciR3ServicePeriodicList(PPDMDEVINS pDevIns, PEHCI pThis, PEHCICC p ehciR3ReadFrameListPtr(pDevIns, GCPhys, &FramePtr); while (!FramePtr.Terminate && (pThis->cmd & EHCI_CMD_RUN)) { - GCPhys = FramePtr.FrameAddr << EHCI_FRAME_LIST_NEXTPTR_SHIFT; + GCPhys = (RTGCPHYS)FramePtr.FrameAddr << EHCI_FRAME_LIST_NEXTPTR_SHIFT; /* Process the descriptor based on its type. Note that on the periodic * list, HCDs may (and do) mix iTDs and qHDs more or less freely. */ diff --git a/src/VBox/Devices/USB/DevOHCI.cpp b/src/VBox/Devices/USB/DevOHCI.cpp index 75c28aaf..cd139e98 100644 --- a/src/VBox/Devices/USB/DevOHCI.cpp +++ b/src/VBox/Devices/USB/DevOHCI.cpp @@ -668,7 +668,7 @@ typedef struct OHCIOPREG #define OHCI_INTR_START_OF_FRAME RT_BIT(2) /** RD - Resume detect. */ #define OHCI_INTR_RESUME_DETECT RT_BIT(3) -/** UE - Unrecoverable error. */ +/** UE - ",erable error. */ #define OHCI_INTR_UNRECOVERABLE_ERROR RT_BIT(4) /** FNO - Frame number overflow. */ #define OHCI_INTR_FRAMENUMBER_OVERFLOW RT_BIT(5) @@ -886,6 +886,7 @@ static void ohciR3PhysReadCacheInvalidate(POHCIPAGECACHE pPageCa static DECLCALLBACK(void) ohciR3RhXferCompletion(PVUSBIROOTHUBPORT pInterface, PVUSBURB pUrb); static DECLCALLBACK(bool) ohciR3RhXferError(PVUSBIROOTHUBPORT pInterface, PVUSBURB pUrb); +static bool ohciR3IsTdInFlight(POHCICC pThisCC, uint32_t GCPhysTD); static int ohciR3InFlightFind(POHCICC pThisCC, uint32_t GCPhysTD); # if defined(VBOX_STRICT) || defined(LOG_ENABLED) static int ohciR3InDoneQueueFind(POHCICC pThisCC, uint32_t GCPhysTD); @@ -1917,6 +1918,13 @@ DECLINLINE(int) ohciR3InFlightFindFree(POHCICC pThisCC, const int iStart) */ static void ohciR3InFlightAdd(POHCI pThis, POHCICC pThisCC, uint32_t GCPhysTD, PVUSBURB pUrb) { + if (ohciR3IsTdInFlight(pThisCC, GCPhysTD)) + { + PPDMDEVINS pDevIns = pThisCC->pDevInsR3; + ohciR3RaiseUnrecoverableError(pDevIns, pThis, 10); + return; + } + int i = ohciR3InFlightFindFree(pThisCC, (GCPhysTD >> 4) % RT_ELEMENTS(pThisCC->aInFlight)); if (i >= 0) { @@ -1995,6 +2003,7 @@ static bool ohciR3IsTdInFlight(POHCICC pThisCC, uint32_t GCPhysTD) return ohciR3InFlightFind(pThisCC, GCPhysTD) >= 0; } +#if 0 /** * Returns a URB associated with an in-flight TD, if any. * @@ -2012,6 +2021,7 @@ static PVUSBURB ohciR3TdInFlightUrb(POHCICC pThisCC, uint32_t GCPhysTD) return pThisCC->aInFlight[i].pUrb; return NULL; } +#endif /** * Removes a in-flight TD. @@ -3049,6 +3059,53 @@ static DECLCALLBACK(bool) ohciR3RhXferError(PVUSBIROOTHUBPORT pInterface, PVUSBU /** + * Determine transfer direction from an endpoint descriptor. + * NB: This may fail if the direction is not valid. If it does fail, + * we do not raise an unrecoverable error but the caller may wish to. + */ +static VUSBDIRECTION ohciR3GetDirection(PPDMDEVINS pDevIns, POHCI pThis, POHCICC pThisCC, PCOHCIED pEd) +{ + RT_NOREF(pThisCC); + RT_NOREF(pThis); + VUSBDIRECTION enmDir = VUSBDIRECTION_INVALID; + + if (pEd->hwinfo & ED_HWINFO_ISO) + { + switch (pEd->hwinfo & ED_HWINFO_DIR) + { + case ED_HWINFO_OUT: enmDir = VUSBDIRECTION_OUT; break; + case ED_HWINFO_IN: enmDir = VUSBDIRECTION_IN; break; + default: + Log(("ohciR3GetDirection: Invalid direction!!!! Ed.hwinfo=%#x\n", pEd->hwinfo)); + } + } + else + { + switch (pEd->hwinfo & ED_HWINFO_DIR) + { + case ED_HWINFO_OUT: enmDir = VUSBDIRECTION_OUT; break; + case ED_HWINFO_IN: enmDir = VUSBDIRECTION_IN; break; + default: + /* We must read the TD to determine direction. */ + uint32_t TdAddr = pEd->HeadP & ED_PTR_MASK; + OHCITD Td; + ohciR3ReadTd(pDevIns, TdAddr, &Td); + switch (Td.hwinfo & TD_HWINFO_DIR) + { + case TD_HWINFO_OUT: enmDir = VUSBDIRECTION_OUT; break; + case TD_HWINFO_IN: enmDir = VUSBDIRECTION_IN; break; + case 0: enmDir = VUSBDIRECTION_SETUP; break; + default: + Log(("ohciR3GetDirection: Invalid direction!!!! Td.hwinfo=%#x Ed.hwinfo=%#x\n", Td.hwinfo, pEd->hwinfo)); + } + } + } + + return enmDir; +} + + +/** * Service a general transport descriptor. */ static bool ohciR3ServiceTd(PPDMDEVINS pDevIns, POHCI pThis, POHCICC pThisCC, VUSBXFERTYPE enmType, @@ -3802,10 +3859,13 @@ static void ohciR3ServiceBulkList(PPDMDEVINS pDevIns, POHCI pThis, POHCICC pThis /* If the ED is in 'skip' state, no transactions on it are allowed and we must * cancel outstanding URBs, if any. */ - uint32_t TdAddr = Ed.HeadP & ED_PTR_MASK; - PVUSBURB pUrb = ohciR3TdInFlightUrb(pThisCC, TdAddr); - if (pUrb) - pThisCC->RootHub.pIRhConn->pfnCancelUrbsEp(pThisCC->RootHub.pIRhConn, pUrb); + uint8_t uAddr = Ed.hwinfo & ED_HWINFO_FUNCTION; + uint8_t uEndPt = (Ed.hwinfo & ED_HWINFO_ENDPOINT) >> ED_HWINFO_ENDPOINT_SHIFT; + VUSBDIRECTION enmDir = ohciR3GetDirection(pDevIns, pThis, pThisCC, &Ed); + if (enmDir != VUSBDIRECTION_INVALID) + { + pThisCC->RootHub.pIRhConn->pfnAbortEpByAddr(pThisCC->RootHub.pIRhConn, uAddr, uEndPt, enmDir); + } } } @@ -3858,9 +3918,14 @@ static void ohciR3UndoBulkList(PPDMDEVINS pDevIns, POHCI pThis, POHCICC pThisCC) if (ohciR3IsTdInFlight(pThisCC, TdAddr)) { LogFlow(("ohciR3UndoBulkList: Ed=%#010RX32 Ed.TailP=%#010RX32 UNDO\n", EdAddr, Ed.TailP)); - PVUSBURB pUrb = ohciR3TdInFlightUrb(pThisCC, TdAddr); - if (pUrb) - pThisCC->RootHub.pIRhConn->pfnCancelUrbsEp(pThisCC->RootHub.pIRhConn, pUrb); + /* First we need to determine the transfer direction, which may fail(!). */ + uint8_t uAddr = Ed.hwinfo & ED_HWINFO_FUNCTION; + uint8_t uEndPt = (Ed.hwinfo & ED_HWINFO_ENDPOINT) >> ED_HWINFO_ENDPOINT_SHIFT; + VUSBDIRECTION enmDir = ohciR3GetDirection(pDevIns, pThis, pThisCC, &Ed); + if (enmDir != VUSBDIRECTION_INVALID) + { + pThisCC->RootHub.pIRhConn->pfnAbortEpByAddr(pThisCC->RootHub.pIRhConn, uAddr, uEndPt, enmDir); + } } } @@ -4022,11 +4087,15 @@ static void ohciR3ServicePeriodicList(PPDMDEVINS pDevIns, POHCI pThis, POHCICC p Log3(("ohciR3ServicePeriodicList: Ed=%#010RX32 Ed.TailP=%#010RX32 SKIP\n", EdAddr, Ed.TailP)); /* If the ED is in 'skip' state, no transactions on it are allowed and we must * cancel outstanding URBs, if any. + * First we need to determine the transfer direction, which may fail(!). */ - uint32_t TdAddr = Ed.HeadP & ED_PTR_MASK; - PVUSBURB pUrb = ohciR3TdInFlightUrb(pThisCC, TdAddr); - if (pUrb) - pThisCC->RootHub.pIRhConn->pfnCancelUrbsEp(pThisCC->RootHub.pIRhConn, pUrb); + uint8_t uAddr = Ed.hwinfo & ED_HWINFO_FUNCTION; + uint8_t uEndPt = (Ed.hwinfo & ED_HWINFO_ENDPOINT) >> ED_HWINFO_ENDPOINT_SHIFT; + VUSBDIRECTION enmDir = ohciR3GetDirection(pDevIns, pThis, pThisCC, &Ed); + if (enmDir != VUSBDIRECTION_INVALID) + { + pThisCC->RootHub.pIRhConn->pfnAbortEpByAddr(pThisCC->RootHub.pIRhConn, uAddr, uEndPt, enmDir); + } } } /* Trivial loop detection. */ diff --git a/src/VBox/Devices/USB/DevXHCI.cpp b/src/VBox/Devices/USB/DevXHCI.cpp index 5df1cc5a..c8212158 100644 --- a/src/VBox/Devices/USB/DevXHCI.cpp +++ b/src/VBox/Devices/USB/DevXHCI.cpp @@ -1603,8 +1603,8 @@ typedef struct XHCI uint32_t Alignment00; /**< Force alignment. */ #endif - /** Flag indicating a sleeping worker thread. */ - volatile bool fWrkThreadSleeping; + /** Flag indicating a pending worker thread notification. */ + volatile bool fNotificationSent; volatile bool afPadding[3]; /** The event semaphore the worker thread waits on. */ @@ -2165,7 +2165,7 @@ static void xhciKickWorker(PPDMDEVINS pDevIns, PXHCI pThis, XHCI_JOB enmJob, uin RT_NOREF(enmJob, uWorkDesc); /* Tell the worker thread there's something to do. */ - if (ASMAtomicReadBool(&pThis->fWrkThreadSleeping)) + if (!ASMAtomicXchgBool(&pThis->fNotificationSent, true)) { LogFlowFunc(("Signal event semaphore\n")); int rc = PDMDevHlpSUPSemEventSignal(pDevIns, pThis->hEvtProcess); @@ -4352,18 +4352,21 @@ static unsigned xhciR3StopEndpoint(PPDMDEVINS pDevIns, PXHCI pThis, PXHCICC pThi uint32_t uPort; /* Abort the endpoint, i.e. cancel any outstanding URBs. This needs to be done after - * writing back the EP state so that the completion callback can operate. + * writing back the EP state so that the completion callback can operate. Note that + * the completion callback will not modify the TR when it sees that the EP is not in + * the 'running' state. + * NB: If a URB is canceled before it completed, we have no way to tell if any data + * was already (partially) transferred. */ if (RT_SUCCESS(xhciR3FindRhDevBySlot(pDevIns, pThis, pThisCC, uSlotID, &pRh, &uPort))) { /* Temporarily give up the lock so that the completion callbacks can run. */ RTCritSectLeave(&pThisCC->CritSectThrd); Log(("Aborting DCI %u -> ep=%u d=%u\n", uDCI, uDCI / 2, uDCI & 1 ? VUSBDIRECTION_IN : VUSBDIRECTION_OUT)); - pRh->pIRhConn->pfnAbortEp(pRh->pIRhConn, uPort, uDCI / 2, uDCI & 1 ? VUSBDIRECTION_IN : VUSBDIRECTION_OUT); + pRh->pIRhConn->pfnAbortEpByPort(pRh->pIRhConn, uPort, uDCI / 2, uDCI & 1 ? VUSBDIRECTION_IN : VUSBDIRECTION_OUT); RTCritSectEnter(&pThisCC->CritSectThrd); } - /// @todo The completion callbacks should do more work for canceled URBs. /* Once the completion callbacks had a chance to run, we have to adjust * the endpoint state. * NB: The guest may just ring the doorbell to continue and not execute @@ -4371,6 +4374,9 @@ static unsigned xhciR3StopEndpoint(PPDMDEVINS pDevIns, PXHCI pThis, PXHCICC pThi */ PDMDevHlpPCIPhysReadMeta(pDevIns, GCPhysEndp, &endp_ctx, sizeof(endp_ctx)); + /* If the enqueue and dequeue pointers are different, a transfer was + * in progress. + */ bool fXferWasInProgress = endp_ctx.trep != endp_ctx.trdp; /* Reset the TREP, but the EDTLA should be left alone. */ @@ -4557,6 +4563,8 @@ static unsigned xhciR3ConfigureDevice(PPDMDEVINS pDevIns, PXHCI pThis, uint64_t XHCI_DEV_CTX dc_out; unsigned uDCI; + RT_ZERO(dc_inp); + Assert(uSlotID); LogFlowFunc(("Slot ID %u, input control context @ %RGp\n", uSlotID, GCPhysInpCtx)); @@ -4638,15 +4646,6 @@ static unsigned xhciR3ConfigureDevice(PPDMDEVINS pDevIns, PXHCI pThis, uint64_t /// @todo Check input slot context according to 6.2.2.2 /// @todo Check input EP contexts according to 6.2.3.2 } -/** @todo r=bird: Looks like MSC is right that dc_inp can be used uninitalized. - * - * However, this function is so hard to read I'm leaving the exorcism of it to - * the author and just zeroing it in the mean time. - * - */ - else - RT_ZERO(dc_inp); - /* Read the output Slot Context plus all Endpoint Contexts up to and * including the one with the highest 'add' or 'drop' bit set. */ @@ -5252,20 +5251,17 @@ static DECLCALLBACK(int) xhciR3WorkerLoop(PPDMDEVINS pDevIns, PPDMTHREAD pThread while (pThread->enmState == PDMTHREADSTATE_RUNNING) { - uint32_t u32Tasks = 0; uint8_t uSlotID; - ASMAtomicWriteBool(&pThis->fWrkThreadSleeping, true); - u32Tasks = ASMAtomicXchgU32(&pThis->u32TasksNew, 0); - if (!u32Tasks) + bool fNotificationSent = ASMAtomicXchgBool(&pThis->fNotificationSent, false); + if (!fNotificationSent) { - Assert(ASMAtomicReadBool(&pThis->fWrkThreadSleeping)); rc = PDMDevHlpSUPSemEventWaitNoResume(pDevIns, pThis->hEvtProcess, RT_INDEFINITE_WAIT); AssertLogRelMsgReturn(RT_SUCCESS(rc) || rc == VERR_INTERRUPTED, ("%Rrc\n", rc), rc); if (RT_UNLIKELY(pThread->enmState != PDMTHREADSTATE_RUNNING)) break; LogFlowFunc(("Woken up with rc=%Rrc\n", rc)); - u32Tasks = ASMAtomicXchgU32(&pThis->u32TasksNew, 0); + ASMAtomicWriteBool(&pThis->fNotificationSent, false); } RTCritSectEnter(&pThisCC->CritSectThrd); @@ -5305,8 +5301,6 @@ static DECLCALLBACK(int) xhciR3WorkerLoop(PPDMDEVINS pDevIns, PPDMTHREAD pThread } RTCritSectLeave(&pThisCC->CritSectThrd); - - ASMAtomicWriteBool(&pThis->fWrkThreadSleeping, false); } /* While running */ LogFlow(("xHCI worker thread exiting.\n")); @@ -7565,6 +7559,68 @@ static DECLCALLBACK(void) xhciR3Info(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, con pThis->fDropUrb = true; return; } + + if (pszArgs && strstr(pszArgs, "genintrhw")) + { + pHlp->pfnPrintf(pHlp, "Generating hardware interrupt (external)...\n"); + int iIntr = 0; + PXHCIINTRPTR pIntr = &pThis->aInterrupters[iIntr & XHCI_INTR_MASK]; + xhciSetIntr(pDevIns, pThis, pIntr); + return; + } + + if (pszArgs && strstr(pszArgs, "genintrint")) + { + pHlp->pfnPrintf(pHlp, "Generating hardware interrupt (internal)...\n"); + int iIntr = 0; + PXHCIINTRPTR pIntr = &pThis->aInterrupters[iIntr & XHCI_INTR_MASK]; + xhciR3SetIntrPending(pDevIns, pThis, pIntr); + return; + } + + if (pszArgs && strstr(pszArgs, "genintrhw")) + { + pHlp->pfnPrintf(pHlp, "Generating hardware interrupt (external)...\n"); + int iIntr = 0; + PXHCIINTRPTR pIntr = &pThis->aInterrupters[iIntr & XHCI_INTR_MASK]; + xhciSetIntr(pDevIns, pThis, pIntr); + return; + } + + if (pszArgs && strstr(pszArgs, "genintrint")) + { + pHlp->pfnPrintf(pHlp, "Generating hardware interrupt (internal)...\n"); + int iIntr = 0; + PXHCIINTRPTR pIntr = &pThis->aInterrupters[iIntr & XHCI_INTR_MASK]; + xhciR3SetIntrPending(pDevIns, pThis, pIntr); + return; + } + + if (pszArgs && strstr(pszArgs, "genportchgevt")) + { + pHlp->pfnPrintf(pHlp, "Generating port change event...\n"); + int iPort = 0; + xhciR3GenPortChgEvent(pDevIns, pThis, IDX_TO_ID(iPort)); + return; + } + + if (pszArgs && strstr(pszArgs, "genmfiwrapevt")) + { + pHlp->pfnPrintf(pHlp, "Generating MF Index wrap event...\n"); + XHCI_EVENT_TRB ed; + RT_ZERO(ed); + ed.mwe.cc = XHCI_TCC_SUCCESS; + ed.mwe.type = XHCI_TRB_MFIDX_WRAP; + xhciR3WriteEvent(pDevIns, pThis, &ed, XHCI_PRIMARY_INTERRUPTER, false); + return; + } + + if (pszArgs && strstr(pszArgs, "gendoorbell")) + { + pHlp->pfnPrintf(pHlp, "Generating doorbell ring..\n"); + xhciKickWorker(pDevIns, pThis, XHCI_JOB_DOORBELL, 0); + return; + } #endif /* Show basic information. */ @@ -7731,6 +7787,7 @@ static DECLCALLBACK(void) xhciR3Info(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, con pcszDesc = ctxSlot.slot_state < RT_ELEMENTS(g_apszSltStates) ? g_apszSltStates[ctxSlot.slot_state] : "BAD!!!"; pHlp->pfnPrintf(pHlp, " Speed:%u Entries:%u RhPort:%u", ctxSlot.speed, ctxSlot.ctx_ent, ctxSlot.rh_port); pHlp->pfnPrintf(pHlp, " Address:%u State:%s \n", ctxSlot.dev_addr, pcszDesc); + pHlp->pfnPrintf(pHlp, " Doorbells:%08X\n", pThis->aBellsRung[ID_TO_IDX(uSlotID)]); /* Endpoint contexts. */ for (j = 1; j <= ctxSlot.ctx_ent; ++j) diff --git a/src/VBox/Devices/USB/DrvVUSBRootHub.cpp b/src/VBox/Devices/USB/DrvVUSBRootHub.cpp index 7088390c..c1d5ab9d 100644 --- a/src/VBox/Devices/USB/DrvVUSBRootHub.cpp +++ b/src/VBox/Devices/USB/DrvVUSBRootHub.cpp @@ -1109,17 +1109,52 @@ static DECLCALLBACK(int) vusbRhAbortEpWorker(PVUSBDEV pDev, int EndPt, VUSBDIREC } -/** @interface_method_impl{VUSBIROOTHUBCONNECTOR,pfnAbortEp} */ -static DECLCALLBACK(int) vusbRhAbortEp(PVUSBIROOTHUBCONNECTOR pInterface, uint32_t uPort, int EndPt, VUSBDIRECTION enmDir) +/** @interface_method_impl{VUSBIROOTHUBCONNECTOR,pfnAbortEpByPort} */ +static DECLCALLBACK(int) vusbRhAbortEpByPort(PVUSBIROOTHUBCONNECTOR pInterface, uint32_t uPort, int EndPt, VUSBDIRECTION enmDir) { PVUSBROOTHUB pRh = VUSBIROOTHUBCONNECTOR_2_VUSBROOTHUB(pInterface); - PVUSBDEV pDev = vusbR3RhGetVUsbDevByPortRetain(pRh, uPort, "vusbRhAbortEp"); + PVUSBDEV pDev = vusbR3RhGetVUsbDevByPortRetain(pRh, uPort, "vusbRhAbortEpByPort"); + + /* We expect to be called from a device like xHCI which keeps good track + * of device <--> port correspondence. Being called for a nonexistent + * device is an error. + */ + AssertPtrReturn(pDev, VERR_INVALID_PARAMETER); if (pDev->pHub != pRh) AssertFailedReturn(VERR_INVALID_PARAMETER); vusbDevIoThreadExecSync(pDev, (PFNRT)vusbRhAbortEpWorker, 3, pDev, EndPt, enmDir); - vusbDevRelease(pDev, "vusbRhAbortEp"); + vusbDevRelease(pDev, "vusbRhAbortEpByPort"); + + /* The reaper thread will take care of completing the URB. */ + + return VINF_SUCCESS; +} + + +/** @interface_method_impl{VUSBIROOTHUBCONNECTOR,pfnAbortEpByAddr} */ +static DECLCALLBACK(int) vusbRhAbortEpByAddr(PVUSBIROOTHUBCONNECTOR pInterface, uint8_t DstAddress, int EndPt, VUSBDIRECTION enmDir) +{ + PVUSBROOTHUB pRh = VUSBIROOTHUBCONNECTOR_2_VUSBROOTHUB(pInterface); + PVUSBDEV pDev = vusbR3RhGetVUsbDevByAddrRetain(pRh, DstAddress, "vusbRhAbortEpByAddr"); + + /* We expect to be called from a device like OHCI which does not + * keep track of device <--> address correspondence and may try to + * cancel an address that does not correspond to a device. If there's + * no device, just do nothing. + */ + if (!pDev) + return VINF_SUCCESS; + + if (pDev->pHub != pRh) + AssertFailedReturn(VERR_INVALID_PARAMETER); + + /* This method is the same as vusbRhAbortEp[ByPort], intended for old controllers + * which don't have a defined port <-> device relationship. + */ + vusbDevIoThreadExecSync(pDev, (PFNRT)vusbRhAbortEpWorker, 3, pDev, EndPt, enmDir); + vusbDevRelease(pDev, "vusbRhAbortEpByAddr"); /* The reaper thread will take care of completing the URB. */ @@ -1206,7 +1241,8 @@ static DECLCALLBACK(uint32_t) vusbRhUpdateIsocFrameDelta(PVUSBIROOTHUBCONNECTOR { PVUSBROOTHUB pRh = VUSBIROOTHUBCONNECTOR_2_VUSBROOTHUB(pInterface); AssertReturn(pRh, 0); - PVUSBDEV pDev = vusbR3RhGetVUsbDevByPortRetain(pRh, uPort, "vusbRhUpdateIsocFrameDelta"); AssertPtr(pDev); + PVUSBDEV pDev = vusbR3RhGetVUsbDevByPortRetain(pRh, uPort, "vusbRhUpdateIsocFrameDelta"); + AssertPtrReturn(pDev, 0); PVUSBPIPE pPipe = &pDev->aPipes[EndPt]; uint32_t *puLastFrame; int32_t uFrameDelta; @@ -1243,7 +1279,7 @@ static DECLCALLBACK(int) vusbR3RhDevPowerOn(PVUSBIROOTHUBCONNECTOR pInterface, u { PVUSBROOTHUB pThis = VUSBIROOTHUBCONNECTOR_2_VUSBROOTHUB(pInterface); PVUSBDEV pDev = vusbR3RhGetVUsbDevByPortRetain(pThis, uPort, "vusbR3RhDevPowerOn"); - AssertPtr(pDev); + AssertPtrReturn(pDev, VERR_VUSB_DEVICE_NOT_ATTACHED); int rc = VUSBIDevPowerOn(&pDev->IDevice); vusbDevRelease(pDev, "vusbR3RhDevPowerOn"); @@ -1256,7 +1292,7 @@ static DECLCALLBACK(int) vusbR3RhDevPowerOff(PVUSBIROOTHUBCONNECTOR pInterface, { PVUSBROOTHUB pThis = VUSBIROOTHUBCONNECTOR_2_VUSBROOTHUB(pInterface); PVUSBDEV pDev = vusbR3RhGetVUsbDevByPortRetain(pThis, uPort, "vusbR3RhDevPowerOff"); - AssertPtr(pDev); + AssertPtrReturn(pDev, VERR_VUSB_DEVICE_NOT_ATTACHED); int rc = VUSBIDevPowerOff(&pDev->IDevice); vusbDevRelease(pDev, "vusbR3RhDevPowerOff"); @@ -1269,7 +1305,7 @@ static DECLCALLBACK(VUSBDEVICESTATE) vusbR3RhDevGetState(PVUSBIROOTHUBCONNECTOR { PVUSBROOTHUB pThis = VUSBIROOTHUBCONNECTOR_2_VUSBROOTHUB(pInterface); PVUSBDEV pDev = vusbR3RhGetVUsbDevByPortRetain(pThis, uPort, "vusbR3RhDevGetState"); - AssertPtr(pDev); + AssertPtrReturn(pDev, VUSB_DEVICE_STATE_DETACHED); VUSBDEVICESTATE enmState = VUSBIDevGetState(&pDev->IDevice); vusbDevRelease(pDev, "vusbR3RhDevGetState"); @@ -1282,7 +1318,7 @@ static DECLCALLBACK(bool) vusbR3RhDevIsSavedStateSupported(PVUSBIROOTHUBCONNECTO { PVUSBROOTHUB pThis = VUSBIROOTHUBCONNECTOR_2_VUSBROOTHUB(pInterface); PVUSBDEV pDev = vusbR3RhGetVUsbDevByPortRetain(pThis, uPort, "vusbR3RhDevIsSavedStateSupported"); - AssertPtr(pDev); + AssertPtrReturn(pDev, false); bool fSavedStateSupported = VUSBIDevIsSavedStateSupported(&pDev->IDevice); vusbDevRelease(pDev, "vusbR3RhDevIsSavedStateSupported"); @@ -1295,7 +1331,7 @@ static DECLCALLBACK(VUSBSPEED) vusbR3RhDevGetSpeed(PVUSBIROOTHUBCONNECTOR pInter { PVUSBROOTHUB pThis = VUSBIROOTHUBCONNECTOR_2_VUSBROOTHUB(pInterface); PVUSBDEV pDev = vusbR3RhGetVUsbDevByPortRetain(pThis, uPort, "vusbR3RhDevGetSpeed"); - AssertPtr(pDev); + AssertPtrReturn(pDev, VUSB_SPEED_UNKNOWN); VUSBSPEED enmSpeed = pDev->IDevice.pfnGetSpeed(&pDev->IDevice); vusbDevRelease(pDev, "vusbR3RhDevGetSpeed"); @@ -1609,7 +1645,8 @@ static DECLCALLBACK(int) vusbRhConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uin pThis->IRhConnector.pfnReapAsyncUrbs = vusbRhReapAsyncUrbs; pThis->IRhConnector.pfnCancelUrbsEp = vusbRhCancelUrbsEp; pThis->IRhConnector.pfnCancelAllUrbs = vusbRhCancelAllUrbs; - pThis->IRhConnector.pfnAbortEp = vusbRhAbortEp; + pThis->IRhConnector.pfnAbortEpByPort = vusbRhAbortEpByPort; + pThis->IRhConnector.pfnAbortEpByAddr = vusbRhAbortEpByAddr; pThis->IRhConnector.pfnSetPeriodicFrameProcessing = vusbRhSetFrameProcessing; pThis->IRhConnector.pfnGetPeriodicFrameRate = vusbRhGetPeriodicFrameRate; pThis->IRhConnector.pfnUpdateIsocFrameDelta = vusbRhUpdateIsocFrameDelta; diff --git a/src/VBox/Devices/VirtIO/VirtioCore.cpp b/src/VBox/Devices/VirtIO/VirtioCore.cpp index 3849aa7c..23ecf30c 100644 --- a/src/VBox/Devices/VirtIO/VirtioCore.cpp +++ b/src/VBox/Devices/VirtIO/VirtioCore.cpp @@ -897,6 +897,18 @@ int virtioCoreR3VirtqAvailBufGet(PPDMDEVINS pDevIns, PVIRTIOCORE pVirtio, uint16 } break; } + /* Check if the limit has been reached for input chain (see section 2.4.4.1 of virtio 1.0 spec). */ + if (cSegsIn >= RT_ELEMENTS(pVirtqBuf->aSegsIn)) + { + LogRelMax(64, ("Too many input descriptors (cSegsIn=%u).\n", cSegsIn)); + break; + } + /* Check if the limit has been reached for output chain (see section 2.4.4.1 of virtio 1.0 spec). */ + if (cSegsOut >= RT_ELEMENTS(pVirtqBuf->aSegsOut)) + { + LogRelMax(64, ("Too many output descriptors (cSegsOut=%u).\n", cSegsOut)); + break; + } RT_UNTRUSTED_VALIDATED_FENCE(); virtioReadDesc(pDevIns, pVirtio, pVirtq, uDescIdx, &desc); @@ -1936,7 +1948,7 @@ static DECLCALLBACK(VBOXSTRICTRC) virtioMmioRead(PPDMDEVINS pDevIns, void *pvUse { PVIRTIOCORE pVirtio = PDMINS_2_DATA(pDevIns, PVIRTIOCORE); PVIRTIOCORECC pVirtioCC = PDMINS_2_DATA_CC(pDevIns, PVIRTIOCORECC); - AssertReturn(cb == 1 || cb == 2 || cb == 4, VERR_INVALID_PARAMETER); + AssertReturn(cb == 1 || cb == 2 || cb == 4, VINF_IOM_MMIO_UNUSED_FF); Assert(pVirtio == (PVIRTIOCORE)pvUser); RT_NOREF(pvUser); STAM_PROFILE_ADV_START(&pVirtio->CTX_SUFF(StatRead), a); @@ -1994,6 +2006,7 @@ static DECLCALLBACK(VBOXSTRICTRC) virtioMmioRead(PPDMDEVINS pDevIns, void *pvUse ASSERT_GUEST_MSG_FAILED(("Bad read access to mapped capabilities region: off=%RGp cb=%u\n", off, cb)); STAM_PROFILE_ADV_STOP(&pVirtio->CTX_SUFF(StatRead), a); + memset(pv, 0xFF, cb); int rc = PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, "virtioMmioRead: Bad MMIO access to capabilities, offset=%RTiop cb=%08x\n", off, cb); return rc; diff --git a/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/demo/ip/tcprst.d b/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/demo/ip/tcprst.d index a2d88e1c..a2d88e1c 100755..100644 --- a/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/demo/ip/tcprst.d +++ b/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/demo/ip/tcprst.d diff --git a/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/demo/mkdemo.pl b/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/demo/mkdemo.pl index f2bc3ec7..f2bc3ec7 100644..100755 --- a/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/demo/mkdemo.pl +++ b/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/demo/mkdemo.pl diff --git a/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/demo/tcp/tcpbytesstat.d b/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/demo/tcp/tcpbytesstat.d index ecd9b044..ecd9b044 100755..100644 --- a/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/demo/tcp/tcpbytesstat.d +++ b/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/demo/tcp/tcpbytesstat.d diff --git a/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/demo/tcp/tcpioflags.d b/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/demo/tcp/tcpioflags.d index cdfbd2aa..cdfbd2aa 100755..100644 --- a/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/demo/tcp/tcpioflags.d +++ b/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/demo/tcp/tcpioflags.d diff --git a/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/demo/tcp/tcpsnoop.d b/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/demo/tcp/tcpsnoop.d index 9d44519e..9d44519e 100755..100644 --- a/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/demo/tcp/tcpsnoop.d +++ b/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/demo/tcp/tcpsnoop.d diff --git a/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/demo/tcp/tcpstate.d b/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/demo/tcp/tcpstate.d index 38f0470a..38f0470a 100755..100644 --- a/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/demo/tcp/tcpstate.d +++ b/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/demo/tcp/tcpstate.d diff --git a/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/demo/tcp/tcptop.d b/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/demo/tcp/tcptop.d index 450f496e..450f496e 100755..100644 --- a/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/demo/tcp/tcptop.d +++ b/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/demo/tcp/tcptop.d diff --git a/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/demo/udp/udpbytesstat.d b/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/demo/udp/udpbytesstat.d index 58fa826a..58fa826a 100755..100644 --- a/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/demo/udp/udpbytesstat.d +++ b/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/demo/udp/udpbytesstat.d diff --git a/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/demo/udp/udpsnoop.d b/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/demo/udp/udpsnoop.d index fffc2904..fffc2904 100755..100644 --- a/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/demo/udp/udpsnoop.d +++ b/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/demo/udp/udpsnoop.d diff --git a/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/demo/udp/udptop.d b/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/demo/udp/udptop.d index a626e571..a626e571 100755..100644 --- a/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/demo/udp/udptop.d +++ b/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/demo/udp/udptop.d diff --git a/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/docsExamples/specopen.d b/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/docsExamples/specopen.d index dff3e622..dff3e622 100755..100644 --- a/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/docsExamples/specopen.d +++ b/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/docsExamples/specopen.d diff --git a/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/docsExamples/userfunc.d b/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/docsExamples/userfunc.d index 0d83465d..0d83465d 100755..100644 --- a/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/docsExamples/userfunc.d +++ b/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/docsExamples/userfunc.d diff --git a/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/ip/tst.ipv4localicmp.ksh b/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/ip/tst.ipv4localicmp.ksh index 0965040e..0965040e 100755..100644 --- a/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/ip/tst.ipv4localicmp.ksh +++ b/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/ip/tst.ipv4localicmp.ksh diff --git a/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/ip/tst.ipv4remoteicmp.ksh b/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/ip/tst.ipv4remoteicmp.ksh index efe0d30f..efe0d30f 100755..100644 --- a/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/ip/tst.ipv4remoteicmp.ksh +++ b/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/ip/tst.ipv4remoteicmp.ksh diff --git a/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/ip/tst.ipv6localicmp.ksh b/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/ip/tst.ipv6localicmp.ksh index 5912ee7c..5912ee7c 100755..100644 --- a/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/ip/tst.ipv6localicmp.ksh +++ b/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/ip/tst.ipv6localicmp.ksh diff --git a/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/ip/tst.ipv6remoteicmp.ksh b/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/ip/tst.ipv6remoteicmp.ksh index b94b7843..b94b7843 100755..100644 --- a/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/ip/tst.ipv6remoteicmp.ksh +++ b/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/ip/tst.ipv6remoteicmp.ksh diff --git a/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/safety/tst.vahole.d b/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/safety/tst.vahole.d index 2ef40a5a..2ef40a5a 100755..100644 --- a/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/safety/tst.vahole.d +++ b/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/safety/tst.vahole.d diff --git a/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/scripting/err.D_SYNTAX.concat.d b/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/scripting/err.D_SYNTAX.concat.d index 00a29969..00a29969 100755..100644 --- a/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/scripting/err.D_SYNTAX.concat.d +++ b/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/scripting/err.D_SYNTAX.concat.d diff --git a/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/scripting/err.D_SYNTAX.desc.d b/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/scripting/err.D_SYNTAX.desc.d index 3dfa2b26..3dfa2b26 100755..100644 --- a/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/scripting/err.D_SYNTAX.desc.d +++ b/src/VBox/ExtPacks/VBoxDTrace/onnv/cmd/dtrace/test/tst/common/scripting/err.D_SYNTAX.desc.d diff --git a/src/VBox/Frontends/VBoxManage/VBoxManageInfo.cpp b/src/VBox/Frontends/VBoxManage/VBoxManageInfo.cpp index 524c1be2..05bed8bf 100644 --- a/src/VBox/Frontends/VBoxManage/VBoxManageInfo.cpp +++ b/src/VBox/Frontends/VBoxManage/VBoxManageInfo.cpp @@ -1169,14 +1169,14 @@ HRESULT showVMInfo(ComPtr<IVirtualBox> pVirtualBox, Bstr strCipher; Bstr strPasswordId; HRESULT hrc2 = machine->GetEncryptionSettings(strCipher.asOutParam(), strPasswordId.asOutParam()); + + SHOW_UTF8_STRING( "encryption", Info::tr("Encryption:"), + SUCCEEDED(hrc2) ? "enabled" : "disabled"); if (SUCCEEDED(hrc2)) { - RTPrintf("Encryption: enabled\n"); - RTPrintf("Cipher: %ls\n", strCipher.raw()); - RTPrintf("Password ID: %ls\n", strPasswordId.raw()); + SHOW_BSTR_STRING( "enc_cipher", Info::tr("Cipher:"), strCipher); + SHOW_BSTR_STRING( "enc_password_id", Info::tr("Password ID:"), strPasswordId); } - else - RTPrintf("Encryption: disabled\n"); } SHOW_STRINGARRAY_PROP( machine, Groups, "groups", Info::tr("Groups:")); Bstr osTypeId; @@ -1372,7 +1372,7 @@ HRESULT showVMInfo(ComPtr<IVirtualBox> pVirtualBox, Bstr bstrNVRAMFile; CHECK_ERROR2I_RET(nvramStore, COMGETTER(NonVolatileStorageFile)(bstrNVRAMFile.asOutParam()), hrcCheck); if (bstrNVRAMFile.isNotEmpty()) - SHOW_BSTR_STRING("BIOS NVRAM File", Info::tr("BIOS NVRAM File:"), bstrNVRAMFile); + SHOW_BSTR_STRING("NvramFile", Info::tr("BIOS NVRAM File:"), bstrNVRAMFile); SHOW_BOOLEAN_PROP_EX(machine, RTCUseUTC, "rtcuseutc", Info::tr("RTC:"), "UTC", Info::tr("local time")); SHOW_BOOLEAN_METHOD(machine, GetHWVirtExProperty(HWVirtExPropertyType_Enabled, &f), "hwvirtex", Info::tr("Hardware Virtualization:")); SHOW_BOOLEAN_METHOD(machine, GetHWVirtExProperty(HWVirtExPropertyType_NestedPaging, &f),"nestedpaging", Info::tr("Nested Paging:")); diff --git a/src/VBox/Frontends/VirtualBox/src/main.cpp b/src/VBox/Frontends/VirtualBox/src/main.cpp index 02b1de55..dd6c6b64 100644 --- a/src/VBox/Frontends/VirtualBox/src/main.cpp +++ b/src/VBox/Frontends/VirtualBox/src/main.cpp @@ -423,8 +423,13 @@ extern "C" DECLEXPORT(int) TrustedMain(int argc, char **argv, char ** /*envp*/) #endif /* VBOX_WITH_HARDENING */ #ifdef VBOX_WS_MAC + /* Prevent AppNap for Runtime UI only: */ + bool fPreventAppNap = false; +# ifdef VBOX_RUNTIME_UI + fPreventAppNap = true; +# endif /* Instantiate own NSApplication before QApplication do it for us: */ - UICocoaApplication::instance(); + UICocoaApplication::create(fPreventAppNap); # ifdef VBOX_RUNTIME_UI /* If we're a helper app inside Resources in the main application bundle, diff --git a/src/VBox/Frontends/VirtualBox/src/platform/darwin/UICocoaApplication.h b/src/VBox/Frontends/VirtualBox/src/platform/darwin/UICocoaApplication.h index 5d17cb0d..5df6a407 100644 --- a/src/VBox/Frontends/VirtualBox/src/platform/darwin/UICocoaApplication.h +++ b/src/VBox/Frontends/VirtualBox/src/platform/darwin/UICocoaApplication.h @@ -67,12 +67,18 @@ class SHARED_LIBRARY_STUFF UICocoaApplication { public: + /** Creates singleton instance. + * @param fPreventAppNap Brings whether we should prevent AppNap. */ + static void create(bool fPreventAppNap); /** Returns singleton instance. */ static UICocoaApplication *instance(); /** Destructs cocoa application. */ virtual ~UICocoaApplication(); + /** Returns whether we should prevent AppNap. */ + bool isPreventAppNap() const { return m_fPreventAppNap; } + /** Returns whether application is currently active. */ bool isActive() const; @@ -111,12 +117,16 @@ public: private: - /** Constructs cocoa application. */ - UICocoaApplication(); + /** Constructs cocoa application. + * @param fPreventAppNap Brings whether we should prevent AppNap. */ + UICocoaApplication(bool fPreventAppNap); /** Holds the singleton access instance. */ static UICocoaApplication *s_pInstance; + /** Holds whether we should prevent AppNap. */ + const bool m_fPreventAppNap; + /** Holds the private NSApplication instance. */ NativeUICocoaApplicationPrivateRef m_pNative; /** Holds the private NSAutoreleasePool instance. */ diff --git a/src/VBox/Frontends/VirtualBox/src/platform/darwin/UICocoaApplication.mm b/src/VBox/Frontends/VirtualBox/src/platform/darwin/UICocoaApplication.mm index 42196b26..c73f5c1e 100644 --- a/src/VBox/Frontends/VirtualBox/src/platform/darwin/UICocoaApplication.mm +++ b/src/VBox/Frontends/VirtualBox/src/platform/darwin/UICocoaApplication.mm @@ -76,12 +76,17 @@ uint32_t m_fMask; /** Array of callbacks. */ NSMutableArray *m_pCallbacks; + /** AppNap preventing activity. */ + id <NSObject> m_activity; } - (id)init; - (void)sendEvent :(NSEvent *)theEvent; - (void)setCallback :(uint32_t)fMask :(PFNVBOXCACALLBACK)pfnCallback :(void *)pvUser; - (void)unsetCallback :(uint32_t)fMask :(PFNVBOXCACALLBACK)pfnCallback :(void *)pvUser; +- (void)finishLaunching; +- (void)terminate :(nullable id)sender; + - (void)registerToNotificationOfWorkspace :(NSString *)pstrNotificationName; - (void)unregisterFromNotificationOfWorkspace :(NSString *)pstrNotificationName; @@ -180,6 +185,38 @@ m_fMask = fNewMask; } +/** Standard handler called right after NSApp finished launching. */ +- (void)finishLaunching +{ + /* Call to base-class: */ + [super finishLaunching]; + + if (UICocoaApplication::instance()->isPreventAppNap()) + { + //printf("Start activity preventing AppNap!\n"); + NSActivityOptions options = NSActivityUserInitiatedAllowingIdleSystemSleep; + NSString *pstrReason = @"VirtualBox napping is prohibited!"; + m_activity = [[NSProcessInfo processInfo] beginActivityWithOptions:options + reason:pstrReason]; + [m_activity retain]; + } +} + +/** Standard handler called right before NSApp starting termination. */ +- (void)terminate :(nullable id)sender +{ + if (UICocoaApplication::instance()->isPreventAppNap()) + { + //printf("Finish activity preventing AppNap!\n"); + [[NSProcessInfo processInfo] endActivity:m_activity]; + [m_activity release]; + m_activity = Nil; + } + + /* Call to base-class: */ + [super terminate: sender]; +} + /** Registers to cocoa notification @a pstrNotificationName. */ - (void) registerToNotificationOfWorkspace :(NSString *)pstrNotificationName { @@ -294,18 +331,23 @@ *********************************************************************************************************************************/ /* static */ -UICocoaApplication* UICocoaApplication::s_pInstance = 0; +UICocoaApplication *UICocoaApplication::s_pInstance = 0; /* static */ -UICocoaApplication* UICocoaApplication::instance() +void UICocoaApplication::create(bool fPreventAppNap) { if (!s_pInstance) - s_pInstance = new UICocoaApplication; + s_pInstance = new UICocoaApplication(fPreventAppNap); +} +/* static */ +UICocoaApplication *UICocoaApplication::instance() +{ return s_pInstance; } -UICocoaApplication::UICocoaApplication() +UICocoaApplication::UICocoaApplication(bool fPreventAppNap) + : m_fPreventAppNap(fPreventAppNap) { /* Make sure our private NSApplication object is created: */ m_pNative = (UICocoaApplicationPrivate*)[UICocoaApplicationPrivate sharedApplication]; diff --git a/src/VBox/HostDrivers/Support/SUPDrv.cpp b/src/VBox/HostDrivers/Support/SUPDrv.cpp index 59573a31..8c9ffccb 100644 --- a/src/VBox/HostDrivers/Support/SUPDrv.cpp +++ b/src/VBox/HostDrivers/Support/SUPDrv.cpp @@ -1847,6 +1847,7 @@ static int supdrvIOCtlInnerUnrestricted(uintptr_t uIOCtl, PSUPDRVDEVEXT pDevExt, { /* validate */ PSUPLDRLOAD pReq = (PSUPLDRLOAD)pReqHdr; + uint8_t const * const pbSrcImage = pReq->u.In.abImage; REQ_CHECK_EXPR(Name, pReq->Hdr.cbIn >= SUP_IOCTL_LDR_LOAD_SIZE_IN(32)); REQ_CHECK_SIZES_EX(SUP_IOCTL_LDR_LOAD, SUP_IOCTL_LDR_LOAD_SIZE_IN(pReq->u.In.cbImageWithEverything), SUP_IOCTL_LDR_LOAD_SIZE_OUT); REQ_CHECK_EXPR_FMT( !pReq->u.In.cSymbols @@ -1875,14 +1876,14 @@ static int supdrvIOCtlInnerUnrestricted(uintptr_t uIOCtl, PSUPDRVDEVEXT pDevExt, if (pReq->u.In.cSymbols) { uint32_t i; - PSUPLDRSYM paSyms = (PSUPLDRSYM)&pReq->u.In.abImage[pReq->u.In.offSymbols]; + PSUPLDRSYM paSyms = (PSUPLDRSYM)(&pbSrcImage[pReq->u.In.offSymbols]); for (i = 0; i < pReq->u.In.cSymbols; i++) { REQ_CHECK_EXPR_FMT(paSyms[i].offSymbol < pReq->u.In.cbImageWithEverything, ("SUP_IOCTL_LDR_LOAD: sym #%ld: symb off %#lx (max=%#lx)\n", (long)i, (long)paSyms[i].offSymbol, (long)pReq->u.In.cbImageWithEverything)); REQ_CHECK_EXPR_FMT(paSyms[i].offName < pReq->u.In.cbStrTab, ("SUP_IOCTL_LDR_LOAD: sym #%ld: name off %#lx (max=%#lx)\n", (long)i, (long)paSyms[i].offName, (long)pReq->u.In.cbImageWithEverything)); - REQ_CHECK_EXPR_FMT(RTStrEnd((char const *)&pReq->u.In.abImage[pReq->u.In.offStrTab + paSyms[i].offName], + REQ_CHECK_EXPR_FMT(RTStrEnd((char const *)(&pbSrcImage[pReq->u.In.offStrTab + paSyms[i].offName]), pReq->u.In.cbStrTab - paSyms[i].offName), ("SUP_IOCTL_LDR_LOAD: sym #%ld: unterminated name! (%#lx / %#lx)\n", (long)i, (long)paSyms[i].offName, (long)pReq->u.In.cbImageWithEverything)); } @@ -1890,7 +1891,7 @@ static int supdrvIOCtlInnerUnrestricted(uintptr_t uIOCtl, PSUPDRVDEVEXT pDevExt, { uint32_t i; uint32_t offPrevEnd = 0; - PSUPLDRSEG paSegs = (PSUPLDRSEG)&pReq->u.In.abImage[pReq->u.In.offSegments]; + PSUPLDRSEG paSegs = (PSUPLDRSEG)(&pbSrcImage[pReq->u.In.offSegments]); for (i = 0; i < pReq->u.In.cSegments; i++) { REQ_CHECK_EXPR_FMT(paSegs[i].off < pReq->u.In.cbImageBits && !(paSegs[i].off & PAGE_OFFSET_MASK), @@ -5548,7 +5549,8 @@ static int supdrvIOCtl_LdrLoad(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, P pImage->cSegments = pReq->u.In.cSegments; { size_t cbSegments = pImage->cSegments * sizeof(SUPLDRSEG); - pImage->paSegments = (PSUPLDRSEG)RTMemDup(&pReq->u.In.abImage[pReq->u.In.offSegments], cbSegments); + uint8_t const * const pbSrcImage = pReq->u.In.abImage; + pImage->paSegments = (PSUPLDRSEG)RTMemDup(&pbSrcImage[pReq->u.In.offSegments], cbSegments); if (pImage->paSegments) /* Align the last segment size to avoid upsetting RTR0MemObjProtect. */ /** @todo relax RTR0MemObjProtect */ pImage->paSegments[pImage->cSegments - 1].cb = RT_ALIGN_32(pImage->paSegments[pImage->cSegments - 1].cb, PAGE_SIZE); else @@ -5617,10 +5619,11 @@ static int supdrvIOCtl_LdrLoad(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, P */ if (!pImage->fNative) { + uint8_t const * const pbSrcImage = pReq->u.In.abImage; pImage->cbStrTab = pReq->u.In.cbStrTab; if (pImage->cbStrTab) { - pImage->pachStrTab = (char *)RTMemDup(&pReq->u.In.abImage[pReq->u.In.offStrTab], pImage->cbStrTab); + pImage->pachStrTab = (char *)RTMemDup(&pbSrcImage[pReq->u.In.offStrTab], pImage->cbStrTab); if (!pImage->pachStrTab) rc = supdrvLdrLoadError(VERR_NO_MEMORY, pReq, "Out of memory for string table: %#x", pImage->cbStrTab); SUPDRV_CHECK_SMAP_CHECK(pDevExt, RT_NOTHING); @@ -5630,7 +5633,7 @@ static int supdrvIOCtl_LdrLoad(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, P if (RT_SUCCESS(rc) && pImage->cSymbols) { size_t cbSymbols = pImage->cSymbols * sizeof(SUPLDRSYM); - pImage->paSymbols = (PSUPLDRSYM)RTMemDup(&pReq->u.In.abImage[pReq->u.In.offSymbols], cbSymbols); + pImage->paSymbols = (PSUPLDRSYM)RTMemDup(&pbSrcImage[pReq->u.In.offSymbols], cbSymbols); if (!pImage->paSymbols) rc = supdrvLdrLoadError(VERR_NO_MEMORY, pReq, "Out of memory for symbol table: %#x", cbSymbols); SUPDRV_CHECK_SMAP_CHECK(pDevExt, RT_NOTHING); diff --git a/src/VBox/HostDrivers/Support/SUPDrvTracer.cpp b/src/VBox/HostDrivers/Support/SUPDrvTracer.cpp index 7b25b5ce..9ea87201 100644 --- a/src/VBox/HostDrivers/Support/SUPDrvTracer.cpp +++ b/src/VBox/HostDrivers/Support/SUPDrvTracer.cpp @@ -55,6 +55,15 @@ #include <iprt/param.h> #include <iprt/uuid.h> +#if defined(RT_OS_LINUX) +# if RTLNX_VER_MIN(4,15,10) +# include <asm/nospec-branch.h> +# endif /* < 4.15.10 */ +# if RTLNX_VER_MIN(5,17,0) +# include <asm/linkage.h> +# endif /* < 5.17.0 */ +#endif /* !RT_OS_LINUX */ + /********************************************************************************************************************************* * Structures and Typedefs * @@ -96,7 +105,8 @@ typedef struct SUPDRVTPPROVIDER * tracer. */ bool fRegistered; /** The provider name (for logging purposes). */ - char szName[1]; + RT_FLEXIBLE_ARRAY_EXTENSION + char szName[RT_FLEXIBLE_ARRAY]; } SUPDRVTPPROVIDER; /** Pointer to the data for a tracepoint provider. */ typedef SUPDRVTPPROVIDER *PSUPDRVTPPROVIDER; @@ -161,7 +171,8 @@ typedef struct SUPDRVTRACERUMOD /** The number of probe locations. */ uint32_t cProbeLocs; /** Ring-0 probe location info. */ - SUPDRVPROBELOC aProbeLocs[1]; + RT_FLEXIBLE_ARRAY_EXTENSION + SUPDRVPROBELOC aProbeLocs[RT_FLEXIBLE_ARRAY]; } SUPDRVTRACERUMOD; /** Magic value for SUPDRVVTGCOPY. */ #define SUPDRVTRACERUMOD_MAGIC UINT32_C(0x00080486) @@ -1495,11 +1506,25 @@ SUPR0TracerFireProbe: \n\ # if defined(RT_ARCH_AMD64) __asm__("\ movq g_pfnSupdrvProbeFireKernel(%rip), %rax \n\ + " +# if defined(RT_OS_LINUX) +# if RTLNX_VER_MIN(4,15,10) + ANNOTATE_RETPOLINE_SAFE +# endif +# endif + " \n\ jmp *%rax \n\ "); # elif defined(RT_ARCH_X86) __asm__("\ movl g_pfnSupdrvProbeFireKernel, %eax \n\ + " +# if defined(RT_OS_LINUX) +# if RTLNX_VER_MIN(4,15,10) + ANNOTATE_RETPOLINE_SAFE +# endif +# endif + " \n\ jmp *%eax \n\ "); # else @@ -1511,8 +1536,20 @@ __asm__("\ .type supdrvTracerProbeFireStub,@function \n\ .global supdrvTracerProbeFireStub \n\ supdrvTracerProbeFireStub: \n\ - ret \n\ - .size supdrvTracerProbeFireStub, . - supdrvTracerProbeFireStub \n\ + " +# if defined(RT_OS_LINUX) +# if RTLNX_VER_MIN(5,17,0) + ASM_RET "\n\ + " +# else /* < 5.17.0 */ + "ret \n\ + " +# endif /* < 5.17.0 */ +# else /* !RT_OS_LINUX */ + "ret \n\ + " +# endif /* !RT_OS_LINUX */ + ".size supdrvTracerProbeFireStub, . - supdrvTracerProbeFireStub \n\ \n\ .previous \n\ "); diff --git a/src/VBox/HostDrivers/Support/SUPR3HardenedMain.cpp b/src/VBox/HostDrivers/Support/SUPR3HardenedMain.cpp index 99b4278a..25c6b4c5 100644 --- a/src/VBox/HostDrivers/Support/SUPR3HardenedMain.cpp +++ b/src/VBox/HostDrivers/Support/SUPR3HardenedMain.cpp @@ -1398,6 +1398,21 @@ static void supR3HardenedGetFullExePath(void) default: supR3HardenedFatal("supR3HardenedExecDir: Unknown program binary location: %#x\n", g_fSupHardenedMain); } + +#ifdef RTPATH_APP_PRIVATE_ARCH + /* + * If the location is fixed, do not continue if it is not correct. Binaries + * must not be allowed to be started from anywhere else. (@bugref{10626}) + */ + if (suplibHardenedStrCmp(g_szSupLibHardenedAppBinPath, RTPATH_APP_PRIVATE_ARCH) != 0) + supR3HardenedFatal("supR3HardenedExecDir: Invalid program binary location: %s (expected %s)\n", + g_szSupLibHardenedAppBinPath, RTPATH_APP_PRIVATE_ARCH); +# ifdef RT_OS_WINDOWS +# error "Didn't expect RTPATH_APP_PRIVATE_ARCH to be defined on Windows." +# endif +#elif defined(RT_OS_LINUX) || defined(RT_OS_FREEBSD) || defined(RT_OS_SOLARIS) || defined(RT_OS_DARWIN) +# error "Expected RTPATH_APP_PRIVATE_ARCH to be define on this host." +#endif } diff --git a/src/VBox/HostDrivers/Support/linux/SUPDrv-linux.c b/src/VBox/HostDrivers/Support/linux/SUPDrv-linux.c index 2a77412c..6ce2a8d0 100644 --- a/src/VBox/HostDrivers/Support/linux/SUPDrv-linux.c +++ b/src/VBox/HostDrivers/Support/linux/SUPDrv-linux.c @@ -54,6 +54,7 @@ #include <VBox/err.h> #include <iprt/mem.h> #include <VBox/log.h> +#include <VBox/VBoxLnxModInline.h> #include <iprt/mp.h> /** @todo figure out the exact version number */ @@ -307,12 +308,12 @@ DECLINLINE(RTGID) vboxdrvLinuxKernGid(void) #ifdef VBOX_WITH_HARDENING -/** Get the effective UID within the current user namespace. */ -DECLINLINE(RTUID) vboxdrvLinuxEuidInNs(void) +/** Get the effective UID of the current process. */ +DECLINLINE(RTUID) vboxdrvLinuxEuid(void) { # if RTLNX_VER_MIN(2,6,29) # if RTLNX_VER_MIN(3,5,0) - return from_kuid(current_user_ns(), current->cred->euid); + return __kuid_val(current->cred->euid); # else return current->cred->euid; # endif @@ -332,6 +333,10 @@ static int __init VBoxDrvLinuxInit(void) { int rc; + /* Check if modue loading was disabled. */ + if (!vbox_mod_should_load()) + return -EINVAL; + #if RTLNX_VER_MIN(5,0,0) spin_lock_init(&g_supdrvLinuxWrapperModuleSpinlock); RTListInit(&g_supdrvLinuxWrapperModuleList); @@ -487,9 +492,9 @@ static int vboxdrvLinuxCreateCommon(struct inode *pInode, struct file *pFilp, bo * Only root is allowed to access the unrestricted device, enforce it! */ if ( fUnrestricted - && vboxdrvLinuxEuidInNs() != 0 /* root */ ) + && vboxdrvLinuxEuid() != 0 /* root */ ) { - Log(("VBoxDrvLinuxCreate: euid=%d, expected 0 (root)\n", vboxdrvLinuxEuidInNs())); + Log(("VBoxDrvLinuxCreate: euid=%d, expected 0 (root)\n", vboxdrvLinuxEuid())); return -EPERM; } #endif /* VBOX_WITH_HARDENING */ diff --git a/src/VBox/HostDrivers/Support/linux/files_vboxdrv b/src/VBox/HostDrivers/Support/linux/files_vboxdrv index cd8b214a..5fbf92a5 100755 --- a/src/VBox/HostDrivers/Support/linux/files_vboxdrv +++ b/src/VBox/HostDrivers/Support/linux/files_vboxdrv @@ -93,6 +93,7 @@ FILES_VBOXDRV_NOBIN=" \ ${PATH_ROOT}/include/VBox/types.h=>include/VBox/types.h \ ${PATH_ROOT}/include/VBox/SUPDrvMangling.h=>include/VBox/SUPDrvMangling.h \ ${PATH_ROOT}/include/VBox/VBoxTpG.h=>include/VBox/VBoxTpG.h \ + ${PATH_ROOT}/include/VBox/VBoxLnxModInline.h=>include/VBox/VBoxLnxModInline.h \ ${PATH_ROOT}/include/VBox/vmm/hm_vmx.h=>include/VBox/vmm/hm_vmx.h \ ${PATH_ROOT}/include/VBox/vmm/hm_svm.h=>include/VBox/vmm/hm_svm.h \ ${PATH_ROOT}/include/VBox/vmm/cpuidcall.h=>include/VBox/vmm/cpuidcall.h \ diff --git a/src/VBox/HostDrivers/VBoxNetAdp/linux/VBoxNetAdp-linux.c b/src/VBox/HostDrivers/VBoxNetAdp/linux/VBoxNetAdp-linux.c index 0654e1d7..bc827fe6 100644 --- a/src/VBox/HostDrivers/VBoxNetAdp/linux/VBoxNetAdp-linux.c +++ b/src/VBox/HostDrivers/VBoxNetAdp/linux/VBoxNetAdp-linux.c @@ -54,6 +54,7 @@ #include <iprt/initterm.h> #include <iprt/mem.h> #include <iprt/string.h> +#include <VBox/VBoxLnxModInline.h> /* #include <iprt/assert.h> @@ -529,6 +530,11 @@ int vboxNetAdpOsInit(PVBOXNETADP pThis) static int __init VBoxNetAdpLinuxInit(void) { int rc; + + /* Check if modue loading was disabled. */ + if (!vbox_mod_should_load()) + return -EINVAL; + /* * Initialize IPRT. */ diff --git a/src/VBox/HostDrivers/VBoxNetAdp/linux/files_vboxnetadp b/src/VBox/HostDrivers/VBoxNetAdp/linux/files_vboxnetadp index 3f028677..288f9b1e 100755 --- a/src/VBox/HostDrivers/VBoxNetAdp/linux/files_vboxnetadp +++ b/src/VBox/HostDrivers/VBoxNetAdp/linux/files_vboxnetadp @@ -86,6 +86,7 @@ VBOX_VBOXNETADP_SOURCES=" \ ${PATH_ROOT}/include/VBox/sup.h=>include/VBox/sup.h \ ${PATH_ROOT}/include/VBox/types.h=>include/VBox/types.h \ ${PATH_ROOT}/include/VBox/SUPDrvMangling.h=>include/VBox/SUPDrvMangling.h \ + ${PATH_ROOT}/include/VBox/VBoxLnxModInline.h=>include/VBox/VBoxLnxModInline.h \ ${PATH_ROOT}/src/VBox/HostDrivers/VBoxNetAdp/linux/VBoxNetAdp-linux.c=>linux/VBoxNetAdp-linux.c \ ${PATH_ROOT}/src/VBox/HostDrivers/VBoxNetAdp/VBoxNetAdp.c=>VBoxNetAdp.c \ ${PATH_ROOT}/src/VBox/HostDrivers/VBoxNetAdp/VBoxNetAdpInternal.h=>VBoxNetAdpInternal.h \ diff --git a/src/VBox/HostDrivers/VBoxNetFlt/linux/VBoxNetFlt-linux.c b/src/VBox/HostDrivers/VBoxNetFlt/linux/VBoxNetFlt-linux.c index eaf07e8c..85777fa1 100644 --- a/src/VBox/HostDrivers/VBoxNetFlt/linux/VBoxNetFlt-linux.c +++ b/src/VBox/HostDrivers/VBoxNetFlt/linux/VBoxNetFlt-linux.c @@ -73,6 +73,7 @@ #include <VBox/intnetinline.h> #include <VBox/vmm/pdmnetinline.h> #include <VBox/param.h> +#include <VBox/VBoxLnxModInline.h> #include <iprt/alloca.h> #include <iprt/assert.h> #include <iprt/spinlock.h> @@ -166,6 +167,17 @@ typedef struct VBOXNETFLTNOTIFIER *PVBOXNETFLTNOTIFIER; # endif #endif +#if RTLNX_VER_MIN(6,9,0) +# define VBOX_SKB_FRAG_LEN(_pFrag) ((_pFrag)->len) +# define VBOX_SKB_FRAG_OFFSET(_pFrag) ((_pFrag)->offset) +#elif RTLNX_VER_MIN(5,4,0) || RTLNX_SUSE_MAJ_PREREQ(15, 2) +# define VBOX_SKB_FRAG_LEN(_pFrag) ((_pFrag)->bv_len) +# define VBOX_SKB_FRAG_OFFSET(_pFrag) ((_pFrag)->bv_offset) +#else /* < KERNEL_VERSION(5, 4, 0) */ +# define VBOX_SKB_FRAG_LEN(_pFrag) ((_pFrag)->size) +# define VBOX_SKB_FRAG_OFFSET(_pFrag) ((_pFrag)->page_offset) +#endif /* > KERNEL_VERSION(6, 9, 0) */ + #if RTLNX_VER_MIN(3,20,0) || RTLNX_RHEL_RANGE(7,2, 8,0) || RTLNX_RHEL_RANGE(6,8, 7,0) # define VBOX_HAVE_SKB_VLAN #endif @@ -273,6 +285,11 @@ unsigned dev_get_flags(const struct net_device *dev) static int __init VBoxNetFltLinuxInit(void) { int rc; + + /* Check if modue loading was disabled. */ + if (!vbox_mod_should_load()) + return -EINVAL; + /* * Initialize IPRT. */ @@ -926,13 +943,8 @@ static void vboxNetFltLinuxSkBufToSG(PVBOXNETFLTINS pThis, struct sk_buff *pBuf, for (i = 0; i < skb_shinfo(pBuf)->nr_frags; i++) { skb_frag_t *pFrag = &skb_shinfo(pBuf)->frags[i]; -# if RTLNX_VER_MIN(5,4,0) || RTLNX_SUSE_MAJ_PREREQ(15, 2) - pSG->aSegs[iSeg].cb = pFrag->bv_len; - pSG->aSegs[iSeg].pv = VBOX_SKB_KMAP_FRAG(pFrag) + pFrag->bv_offset; -# else /* < KERNEL_VERSION(5, 4, 0) */ - pSG->aSegs[iSeg].cb = pFrag->size; - pSG->aSegs[iSeg].pv = VBOX_SKB_KMAP_FRAG(pFrag) + pFrag->page_offset; -# endif /* >= KERNEL_VERSION(5, 4, 0) */ + pSG->aSegs[iSeg].cb = VBOX_SKB_FRAG_LEN(pFrag); + pSG->aSegs[iSeg].pv = VBOX_SKB_KMAP_FRAG(pFrag) + VBOX_SKB_FRAG_OFFSET(pFrag); Log6((" %p", pSG->aSegs[iSeg].pv)); pSG->aSegs[iSeg++].Phys = NIL_RTHCPHYS; Assert(iSeg <= pSG->cSegsAlloc); @@ -947,13 +959,8 @@ static void vboxNetFltLinuxSkBufToSG(PVBOXNETFLTINS pThis, struct sk_buff *pBuf, for (i = 0; i < skb_shinfo(pFragBuf)->nr_frags; i++) { skb_frag_t *pFrag = &skb_shinfo(pFragBuf)->frags[i]; -# if RTLNX_VER_MIN(5,4,0) || RTLNX_SUSE_MAJ_PREREQ(15, 2) - pSG->aSegs[iSeg].cb = pFrag->bv_len; - pSG->aSegs[iSeg].pv = VBOX_SKB_KMAP_FRAG(pFrag) + pFrag->bv_offset; -# else /* < KERNEL_VERSION(5, 4, 0) */ - pSG->aSegs[iSeg].cb = pFrag->size; - pSG->aSegs[iSeg].pv = VBOX_SKB_KMAP_FRAG(pFrag) + pFrag->page_offset; -# endif /* >= KERNEL_VERSION(5, 4, 0) */ + pSG->aSegs[iSeg].cb = VBOX_SKB_FRAG_LEN(pFrag); + pSG->aSegs[iSeg].pv = VBOX_SKB_KMAP_FRAG(pFrag) + VBOX_SKB_FRAG_OFFSET(pFrag); Log6((" %p", pSG->aSegs[iSeg].pv)); pSG->aSegs[iSeg++].Phys = NIL_RTHCPHYS; Assert(iSeg <= pSG->cSegsAlloc); diff --git a/src/VBox/HostDrivers/VBoxNetFlt/linux/files_vboxnetflt b/src/VBox/HostDrivers/VBoxNetFlt/linux/files_vboxnetflt index f2f8f1f4..bdff6ed2 100755 --- a/src/VBox/HostDrivers/VBoxNetFlt/linux/files_vboxnetflt +++ b/src/VBox/HostDrivers/VBoxNetFlt/linux/files_vboxnetflt @@ -88,6 +88,7 @@ VBOX_VBOXNETFLT_SOURCES=" \ ${PATH_ROOT}/include/VBox/sup.h=>include/VBox/sup.h \ ${PATH_ROOT}/include/VBox/types.h=>include/VBox/types.h \ ${PATH_ROOT}/include/VBox/SUPDrvMangling.h=>include/VBox/SUPDrvMangling.h \ + ${PATH_ROOT}/include/VBox/VBoxLnxModInline.h=>include/VBox/VBoxLnxModInline.h \ ${PATH_ROOT}/src/VBox/HostDrivers/VBoxNetFlt/linux/VBoxNetFlt-linux.c=>linux/VBoxNetFlt-linux.c \ ${PATH_ROOT}/src/VBox/HostDrivers/VBoxNetFlt/VBoxNetFlt.c=>VBoxNetFlt.c \ ${PATH_ROOT}/src/VBox/HostDrivers/VBoxNetFlt/VBoxNetFltInternal.h=>VBoxNetFltInternal.h \ diff --git a/src/VBox/HostDrivers/VBoxNetFlt/win/drv/VBoxNetFltRt-win.cpp b/src/VBox/HostDrivers/VBoxNetFlt/win/drv/VBoxNetFltRt-win.cpp index 44c7338c..5913697b 100644 --- a/src/VBox/HostDrivers/VBoxNetFlt/win/drv/VBoxNetFltRt-win.cpp +++ b/src/VBox/HostDrivers/VBoxNetFlt/win/drv/VBoxNetFltRt-win.cpp @@ -1141,7 +1141,7 @@ DECLHIDDEN(NDIS_STATUS) vboxNetFltWinAllocSG(UINT cbPacket, PINTNETSG *ppSG) * 1. SG_PACKET - with one aSegs pointing to * 2. buffer of cbPacket containing the entire packet */ AssertCompileSizeAlignment(INTNETSG, sizeof(PVOID)); - Status = vboxNetFltWinMemAlloc((PVOID*)&pSG, cbPacket + sizeof(INTNETSG)); + Status = vboxNetFltWinMemAlloc((PVOID*)&pSG, cbPacket + RT_UOFFSETOF_DYN(INTNETSG, aSegs[1])); if (Status == NDIS_STATUS_SUCCESS) { IntNetSgInitTemp(pSG, pSG + 1, cbPacket); diff --git a/src/VBox/ImageMounter/vboximg-mount/vboximg-mount.cpp b/src/VBox/ImageMounter/vboximg-mount/vboximg-mount.cpp index 8e36358d..0fd8b335 100644 --- a/src/VBox/ImageMounter/vboximg-mount/vboximg-mount.cpp +++ b/src/VBox/ImageMounter/vboximg-mount/vboximg-mount.cpp @@ -254,7 +254,7 @@ briefUsage() ); RTPrintf("\n" "vboximg-mount is a utility to make VirtualBox disk images available to the host\n" - "operating system for privileged or non-priviliged access. Any version of the\n" + "operating system for privileged or non-privileged access. Any version of the\n" "disk can be mounted from its available history of snapshots.\n" "\n" "If the user specifies a base image identifier using the --image option, only\n" @@ -264,10 +264,10 @@ briefUsage() "\n" "The virtual disk is exposed as a device node within a FUSE-based filesystem\n" "that overlays the user-provided mount point. The FUSE filesystem consists of a\n" - "directory containing a number of files and possibly other directories:" + "directory containing a number of files and possibly other directories:\n" " * vhdd: Provides access to the raw disk image data as a flat image\n" " * vol<id>: Provides access to individual volumes on the accessed disk image\n" - " * fs<id>: Provides access to a supported filesystem without the need for a" + " * fs<id>: Provides access to a supported filesystem without the need for a\n" " host filesystem driver\n" "\n" "The directory will also contain a symbolic link which has the same basename(1)\n" @@ -1002,7 +1002,7 @@ static int vboxImgMntImageSetup(struct fuse_args *args) AccessMode_ReadOnly, false /* forceNewUuid */, pVDiskMedium.asOutParam())); if (FAILED(hrc)) - return RTMsgErrorExitFailure("\nCould't find specified VirtualBox base or snapshot disk image:\n%s", + return RTMsgErrorExitFailure("\nCouldn't find specified VirtualBox base or snapshot disk image:\n%s", g_vboximgOpts.pszImageUuidOrPath); diff --git a/src/VBox/Installer/darwin/Makefile.kmk b/src/VBox/Installer/darwin/Makefile.kmk index 494fd990..1b7a16f8 100644 --- a/src/VBox/Installer/darwin/Makefile.kmk +++ b/src/VBox/Installer/darwin/Makefile.kmk @@ -483,6 +483,12 @@ if defined(VBOX_WITH_PYTHON) && !defined(VBOX_WITHOUT_VBOXPYTHON_FOR_OSX_10_7) VBOX_DI_VBAPP_DYLIBS += \ MacOS/VBoxPython2_7.so endif +if defined(VBOX_WITH_PYTHON) \ + && !defined(VBOX_WITHOUT_PYTHON_LIMITED_API) \ + && exists "$(VBOX_PATH_DIST)/VirtualBox.app/Contents/MacOS/VBoxPython3.so" + VBOX_DI_VBAPP_DYLIBS += \ + MacOS/VBoxPython3.so +endif ifdef VBOX_WITH_VMSVGA3D VBOX_DI_VBAPP_DYLIBS += \ MacOS/VBoxSVGA3D.dylib \ diff --git a/src/VBox/Installer/linux/VBox.sh b/src/VBox/Installer/linux/VBox.sh index fb584d48..31e32f91 100755 --- a/src/VBox/Installer/linux/VBox.sh +++ b/src/VBox/Installer/linux/VBox.sh @@ -96,15 +96,33 @@ WARNING: The compilation of the vboxdrv.ko kernel module failed during the EOF fi -SERVER_PID=`ps -U \`whoami\` | grep VBoxSVC | awk '{ print $1 }'` +# Get effective user name to use it in order to compose XPCOM IPC socket path. +VBOX_EFFECTIVE_USER="$(whoami)" +if [ -z "$VBOX_EFFECTIVE_USER" ]; then + cat << EOF +WARNING: Unable to detect effective user name. VirtualBox might run incorrectly. +EOF +fi + +# Variables LOGNAME and USER are used by XPCOM code in order to +# compose IPC socket path. If they set to something which is different +# from the effective user name, it might result in misbehavior. +# Setting VBOX_IPC_SOCKETID will tell XPCOM code which path it should use explicitly. +[ -n "$LOGNAME" ] && [ "$LOGNAME" = "$VBOX_EFFECTIVE_USER" ] || vbox_override_env="1" +[ -n "$USER" ] && [ "$USER" = "$VBOX_EFFECTIVE_USER" ] || vbox_override_env="1" + +if [ -n "$vbox_override_env" ]; then +cat << EOF +WARNING: Environment variable LOGNAME or USER does not correspond to effective user id. +EOF + export VBOX_IPC_SOCKETID="$VBOX_EFFECTIVE_USER" +fi + +SERVER_PID=`ps -U "$VBOX_EFFECTIVE_USER" | grep VBoxSVC | awk '{ print $1 }'` if [ -z "$SERVER_PID" ]; then # Server not running yet/anymore, cleanup socket path. # See IPC_GetDefaultSocketPath()! - if [ -n "$LOGNAME" ]; then - rm -rf /tmp/.vbox-$LOGNAME-ipc > /dev/null 2>&1 - else - rm -rf /tmp/.vbox-$USER-ipc > /dev/null 2>&1 - fi + rm -rf "/tmp/.vbox-$VBOX_EFFECTIVE_USER-ipc" > /dev/null 2>&1 fi if [ "$SHUTDOWN" = "true" ]; then diff --git a/src/VBox/Installer/linux/install.sh b/src/VBox/Installer/linux/install.sh index 9c11eb9b..d32d9270 100755 --- a/src/VBox/Installer/linux/install.sh +++ b/src/VBox/Installer/linux/install.sh @@ -289,11 +289,8 @@ if [ "$ACTION" = "install" ]; then # create symlinks for working around unsupported $ORIGIN/.. in VBoxC.so (setuid), # and finally make sure the directory is only writable by the user (paranoid). if [ -n "$HARDENED" ]; then - if [ -f $INSTALLATION_DIR/VirtualBoxVM ]; then - test -e $INSTALLATION_DIR/VirtualBoxVM && chmod 4511 $INSTALLATION_DIR/VirtualBoxVM - else - test -e $INSTALLATION_DIR/VirtualBox && chmod 4511 $INSTALLATION_DIR/VirtualBox - fi + # Note! Update vboxdrv.sh if the VirtualBoxVM entry changes (bugref:10642). + test -e $INSTALLATION_DIR/VirtualBoxVM && chmod 4511 $INSTALLATION_DIR/VirtualBoxVM test -e $INSTALLATION_DIR/VBoxSDL && chmod 4511 $INSTALLATION_DIR/VBoxSDL test -e $INSTALLATION_DIR/VBoxHeadless && chmod 4511 $INSTALLATION_DIR/VBoxHeadless test -e $INSTALLATION_DIR/VBoxNetDHCP && chmod 4511 $INSTALLATION_DIR/VBoxNetDHCP @@ -325,9 +322,7 @@ if [ "$ACTION" = "install" ]; then # Create symlinks to start binaries ln -sf $INSTALLATION_DIR/VBox.sh /usr/bin/VirtualBox - if [ -f $INSTALLATION_DIR/VirtualBoxVM ]; then - ln -sf $INSTALLATION_DIR/VBox.sh /usr/bin/VirtualBoxVM - fi + ln -sf $INSTALLATION_DIR/VBox.sh /usr/bin/VirtualBoxVM ln -sf $INSTALLATION_DIR/VBox.sh /usr/bin/VBoxManage ln -sf $INSTALLATION_DIR/VBox.sh /usr/bin/VBoxSDL ln -sf $INSTALLATION_DIR/VBox.sh /usr/bin/VBoxVRDP @@ -362,9 +357,7 @@ if [ "$ACTION" = "install" ]; then # Convenience symlinks. The creation fails if the FS is not case sensitive ln -sf VirtualBox /usr/bin/virtualbox > /dev/null 2>&1 - if [ -f $INSTALLATION_DIR/VirtualBoxVM ]; then - ln -sf VirtualBoxVM /usr/bin/virtualboxvm > /dev/null 2>&1 - fi + ln -sf VirtualBoxVM /usr/bin/virtualboxvm > /dev/null 2>&1 ln -sf VBoxManage /usr/bin/vboxmanage > /dev/null 2>&1 ln -sf VBoxSDL /usr/bin/vboxsdl > /dev/null 2>&1 ln -sf VBoxHeadless /usr/bin/vboxheadless > /dev/null 2>&1 diff --git a/src/VBox/Installer/linux/rpm/VirtualBox.tmpl.spec b/src/VBox/Installer/linux/rpm/VirtualBox.tmpl.spec index 829322aa..bab95a70 100644 --- a/src/VBox/Installer/linux/rpm/VirtualBox.tmpl.spec +++ b/src/VBox/Installer/linux/rpm/VirtualBox.tmpl.spec @@ -223,13 +223,8 @@ if [ -f $RPM_BUILD_ROOT/usr/lib/virtualbox/libQt5CoreVBox.so.5 ]; then fi rm -f $RPM_BUILD_ROOT/usr/lib/virtualbox/chrpath ln -s ../VBoxVMM.so $RPM_BUILD_ROOT/usr/lib/virtualbox/components/VBoxVMM.so -for i in VBoxHeadless VBoxNetDHCP VBoxNetNAT VBoxNetAdpCtl; do +for i in VirtualBoxVM VBoxHeadless VBoxNetDHCP VBoxNetNAT VBoxNetAdpCtl; do chmod 4511 $RPM_BUILD_ROOT/usr/lib/virtualbox/$i; done -if test -e $RPM_BUILD_ROOT/usr/lib/virtualbox/VirtualBoxVM; then - chmod 4511 $RPM_BUILD_ROOT/usr/lib/virtualbox/VirtualBoxVM -else - chmod 4511 $RPM_BUILD_ROOT/usr/lib/virtualbox/VirtualBox -fi if [ -f $RPM_BUILD_ROOT/usr/lib/virtualbox/VBoxVolInfo ]; then chmod 4511 $RPM_BUILD_ROOT/usr/lib/virtualbox/VBoxVolInfo fi diff --git a/src/VBox/Installer/linux/vboxdrv.sh b/src/VBox/Installer/linux/vboxdrv.sh index 4077c169..5e6842cf 100755 --- a/src/VBox/Installer/linux/vboxdrv.sh +++ b/src/VBox/Installer/linux/vboxdrv.sh @@ -85,10 +85,12 @@ else # Applies to Debian packages only (but shouldn't hurt elsewhere) exit 0 fi -VIRTUALBOX="${INSTALL_DIR}/VirtualBox" VBOXMANAGE="${INSTALL_DIR}/VBoxManage" BUILDINTMP="${MODULE_SRC}/build_in_tmp" -if test -u "${VIRTUALBOX}"; then + +# If the VirtualBoxVM file has the set-uid bit set or if it doesn't exist, setup vboxdrv +# in hardened mode. Otherwise, do the developer mode using vboxusers for access control. +if test -u "${INSTALL_DIR}/VirtualBoxVM" || test '!' -e "${INSTALL_DIR}/VirtualBoxVM"; then GROUP=root DEVICE_MODE=0600 else diff --git a/src/VBox/Installer/win/InstallHelper/Makefile.kmk b/src/VBox/Installer/win/InstallHelper/Makefile.kmk index cad3c4c3..38525a7d 100644 --- a/src/VBox/Installer/win/InstallHelper/Makefile.kmk +++ b/src/VBox/Installer/win/InstallHelper/Makefile.kmk @@ -33,9 +33,16 @@ DLLS += VBoxInstallHelper VBoxInstallHelper_TEMPLATE = VBoxR3StaticDllNoAsan VBoxInstallHelper_SDKS = ReorderCompilerIncs $(VBOX_WINPSDK) $(VBOX_WINDDK) VBoxInstallHelper_DEFS = _WIN32_WINNT=0x0501 _UNICODE UNICODE VBOX_SVN_REV=$(VBOX_SVN_REV) -ifdef VBOX_WITH_NETFLT +if defined(VBOX_WITH_NETFLT) || defined(VBOX_WITH_NETADP) VBoxInstallHelper_SDKS += VBoxWinNewDevLib - VBoxInstallHelper_DEFS += VBOX_WITH_NETFLT=1 + VBoxInstallHelper_DEFS += \ + $(if $(VBOX_WITH_NETFLT),VBOX_WITH_NETFLT,) \ + $(if $(VBOX_WITH_NETADP),VBOX_WITH_NETADP,) + VBoxInstallHelper_LIBS += \ + $(PATH_STAGE_LIB)/WinNetConfigSharedStatic.lib \ + $(PATH_STAGE_LIB)/VBoxDrvCfgSharedStatic.lib \ + $(PATH_TOOL_$(VBOX_VCC_TOOL)_LIB)/comsupp.lib \ + $(PATH_SDK_$(VBOX_WINPSDK)_LIB)/WbemUuid.Lib endif VBoxInstallHelper_DEPS = $(VBOX_SVN_REV_KMK) VBoxInstallHelper_SOURCES = \ @@ -47,15 +54,8 @@ ifndef VBOX_OSE VBoxInstallHelper_SOURCES += \ internal/VBoxSerial.cpp endif -VBoxInstallHelper_LIBS = \ +VBoxInstallHelper_LIBS += \ $(PATH_SDK_$(VBOX_WINPSDK)_LIB)/Msi.lib -ifdef VBOX_WITH_NETFLT - VBoxInstallHelper_LIBS += \ - $(PATH_STAGE_LIB)/WinNetConfigSharedStatic.lib \ - $(PATH_STAGE_LIB)/VBoxDrvCfgSharedStatic.lib \ - $(PATH_TOOL_$(VBOX_VCC_TOOL)_LIB)/comsupp.lib \ - $(PATH_SDK_$(VBOX_WINPSDK)_LIB)/WbemUuid.Lib -endif if "$(KBUILD_TARGET)" == "win" && defined(VBOX_WITH_TESTCASES) && !defined(VBOX_OSE) include $(PATH_SUB_CURRENT)/testcase/Makefile.kmk diff --git a/src/VBox/Installer/win/InstallHelper/VBoxCommon.cpp b/src/VBox/Installer/win/InstallHelper/VBoxCommon.cpp index f02447bc..d76cb438 100644 --- a/src/VBox/Installer/win/InstallHelper/VBoxCommon.cpp +++ b/src/VBox/Installer/win/InstallHelper/VBoxCommon.cpp @@ -38,27 +38,28 @@ #include <iprt/string.h> #include <iprt/utf16.h> +#include "VBoxCommon.h" + +#ifndef TESTCASE +/** + * Retrieves a MSI property (in UTF-16). + * + * Convenience function for VBoxGetMsiProp(). + * + * @returns VBox status code. + * @param hMsi MSI handle to use. + * @param pwszName Name of property to retrieve. + * @param pwszValueBuf Where to store the allocated value on success. + * @param cwcValueBuf Size (in WCHARs) of \a pwszValueBuf. + */ UINT VBoxGetMsiProp(MSIHANDLE hMsi, const WCHAR *pwszName, WCHAR *pwszValueBuf, DWORD cwcValueBuf) { - RT_BZERO(pwszValueBuf, cwcValueBuf * sizeof(pwszValueBuf[0])); - - /** @todo r=bird: why do we need to query the size first and then the data. - * The API should be perfectly capable of doing that without our help. */ - DWORD cwcNeeded = 0; - UINT uiRet = MsiGetPropertyW(hMsi, pwszName, L"", &cwcNeeded); - if (uiRet == ERROR_MORE_DATA) - { - ++cwcNeeded; /* On output does not include terminating null, so add 1. */ - - if (cwcNeeded > cwcValueBuf) - return ERROR_MORE_DATA; - uiRet = MsiGetPropertyW(hMsi, pwszName, pwszValueBuf, &cwcNeeded); - } - return uiRet; + RT_BZERO(pwszValueBuf, cwcValueBuf * sizeof(WCHAR)); + return MsiGetPropertyW(hMsi, pwszName, pwszValueBuf, &cwcValueBuf); } +#endif -#if 0 /* unused */ /** * Retrieves a MSI property (in UTF-8). * @@ -77,7 +78,7 @@ int VBoxGetMsiPropUtf8(MSIHANDLE hMsi, const char *pcszName, char **ppszValue) if (RT_SUCCESS(rc)) { WCHAR wszValue[1024]; /* 1024 should be enough for everybody (tm). */ - if (VBoxGetMsiProp(hMsi, pwszName, wszValue, sizeof(wszValue)) == ERROR_SUCCESS) + if (VBoxGetMsiProp(hMsi, pwszName, wszValue, RT_ELEMENTS(wszValue)) == ERROR_SUCCESS) rc = RTUtf16ToUtf8(wszValue, ppszValue); else rc = VERR_NOT_FOUND; @@ -87,12 +88,13 @@ int VBoxGetMsiPropUtf8(MSIHANDLE hMsi, const char *pcszName, char **ppszValue) return rc; } -#endif +#ifndef TESTCASE UINT VBoxSetMsiProp(MSIHANDLE hMsi, const WCHAR *pwszName, const WCHAR *pwszValue) { return MsiSetPropertyW(hMsi, pwszName, pwszValue); } +#endif UINT VBoxSetMsiPropDWORD(MSIHANDLE hMsi, const WCHAR *pwszName, DWORD dwVal) { diff --git a/src/VBox/Installer/win/InstallHelper/VBoxInstallHelper.cpp b/src/VBox/Installer/win/InstallHelper/VBoxInstallHelper.cpp index f82f0848..d4ac6104 100644 --- a/src/VBox/Installer/win/InstallHelper/VBoxInstallHelper.cpp +++ b/src/VBox/Installer/win/InstallHelper/VBoxInstallHelper.cpp @@ -29,22 +29,24 @@ /********************************************************************************************************************************* * Header Files * *********************************************************************************************************************************/ -#ifdef VBOX_WITH_NETFLT +#if defined(VBOX_WITH_NETFLT) || defined(VBOX_WITH_NETADP) # include "VBox/VBoxNetCfg-win.h" # include "VBox/VBoxDrvCfg-win.h" #endif -#include <msi.h> -#include <msiquery.h> - #define _WIN32_DCOM #include <iprt/win/windows.h> +#include <aclapi.h> +#include <msi.h> +#include <msiquery.h> + #include <shellapi.h> #define INITGUID #include <guiddef.h> #include <cfgmgr32.h> #include <devguid.h> +#include <sddl.h> /* For ConvertSidToStringSidW. */ #include <iprt/win/objbase.h> #include <iprt/win/setupapi.h> @@ -54,9 +56,14 @@ #include <iprt/assert.h> #include <iprt/alloca.h> +#include <iprt/dir.h> +#include <iprt/err.h> +#include <iprt/file.h> #include <iprt/mem.h> #include <iprt/path.h> /* RTPATH_MAX, RTPATH_IS_SLASH */ #include <iprt/string.h> /* RT_ZERO */ +#include <iprt/stream.h> +#include <iprt/thread.h> #include <iprt/utf16.h> #include "VBoxCommon.h" @@ -78,6 +85,48 @@ #define MY_WTEXT(a_str) MY_WTEXT_HLP(a_str) +/********************************************************************************************************************************* +* Internal structures * +*********************************************************************************************************************************/ +/** + * Structure for keeping a target's directory security context. + */ +typedef struct TGTDIRSECCTX +{ + /** Initialized status. */ + bool fInitialized; + /** Handle of the target's parent directory. + * + * Kept open while the context is around and initialized. */ + RTDIR hParentDir; + /** Absolute (resolved) path of the target directory. */ + char szTargetDirAbs[RTPATH_MAX]; + /** Access mask which is forbidden for an ACE of type ACCESS_ALLOWED_ACE_TYPE. */ + uint32_t fAccessMaskForbidden; + /** Array of well-known SIDs which are forbidden. */ + PSID *paWellKnownSidsForbidden; + /** Number of entries in \a paWellKnownSidsForbidden. */ + size_t cWellKnownSidsForbidden; +} TGTDIRSECCTX; +/** Pointer to a target's directory security context. */ +typedef TGTDIRSECCTX *PTGTDIRSECCTX; + + +/********************************************************************************************************************************* +* Prototypes * +*********************************************************************************************************************************/ +static void destroyTargetDirSecurityCtx(PTGTDIRSECCTX pCtx); + + +/********************************************************************************************************************************* +* Globals * +*********************************************************************************************************************************/ +static uint32_t g_cRef = 0; +/** Our target directory security context. + * + * Has to be global in order to keep it around as long as the DLL is being loaded. */ +static TGTDIRSECCTX g_TargetDirSecCtx = { 0 }; + /** * DLL entry point. @@ -86,59 +135,94 @@ BOOL WINAPI DllMain(HANDLE hInst, ULONG uReason, LPVOID pReserved) { RT_NOREF(hInst, uReason, pReserved); -#if 0 - /* - * This is a trick for allowing the debugger to be attached, don't know if - * there is an official way to do that, but this is a pretty efficient. - * - * Monitor the debug output in DbgView and be ready to start windbg when - * the message below appear. This will happen 3-4 times during install, - * and 2-3 times during uninstall. - * - * Note! The DIFxApp.DLL will automatically trigger breakpoints when a - * debugger is attached. Just continue on these. - */ - if (uReason == DLL_PROCESS_ATTACH) +#ifdef DEBUG + WCHAR wszMsg[128]; + RTUtf16Printf(wszMsg, RT_ELEMENTS(wszMsg), "DllMain: hInst=%#x, uReason=%u (PID %u), g_cRef=%RU32\n", + hInst, uReason, GetCurrentProcessId(), g_cRef); + OutputDebugStringW(wszMsg); +#endif + + switch (uReason) { - WCHAR wszMsg[128]; - RTUtf16Printf(wszMsg, RT_ELEMENTS(wszMsg), "Waiting for debugger to attach: windbg -g -G -p %u\n", GetCurrentProcessId()); - for (unsigned i = 0; i < 128 && !IsDebuggerPresent(); i++) + case DLL_PROCESS_ATTACH: + { + g_cRef++; +#if 0 + /* + * This is a trick for allowing the debugger to be attached, don't know if + * there is an official way to do that, but this is a pretty efficient. + * + * Monitor the debug output in DbgView and be ready to start windbg when + * the message below appear. This will happen 3-4 times during install, + * and 2-3 times during uninstall. + * + * Note! The DIFxApp.DLL will automatically trigger breakpoints when a + * debugger is attached. Just continue on these. + */ + RTUtf16Printf(wszMsg, RT_ELEMENTS(wszMsg), "Waiting for debugger to attach: windbg -g -G -p %u\n", GetCurrentProcessId()); + for (unsigned i = 0; i < 128 && !IsDebuggerPresent(); i++) + { + OutputDebugStringW(wszMsg); + Sleep(1001); + } + Sleep(1002); + __debugbreak(); +#endif + break; + } + + case DLL_PROCESS_DETACH: { - OutputDebugStringW(wszMsg); - Sleep(1001); + g_cRef--; + break; } - Sleep(1002); - __debugbreak(); + + default: + break; } -#endif return TRUE; } /** - * Format and add message to the MSI log. + * Format a log message and print it to whatever is there (i.e. to the MSI log). * * UTF-16 strings are formatted using '%ls' (lowercase). * ANSI strings are formatted using '%s' (uppercase). + * + * @returns VBox status code. + * @param hInstall MSI installer handle. Optional and can be NULL. + * @param pszFmt Format string. + * @param ... Variable arguments for format string. */ -static UINT logStringF(MSIHANDLE hInstall, const char *pszFmt, ...) +static int logStringF(MSIHANDLE hInstall, const char *pszFmt, ...) { + RTUTF16 wszVa[RTPATH_MAX + 256]; + va_list va; + va_start(va, pszFmt); + ssize_t cwc = RTUtf16PrintfV(wszVa, RT_ELEMENTS(wszVa), pszFmt, va); + va_end(va); + + RTUTF16 wszMsg[RTPATH_MAX + 256]; + cwc = RTUtf16Printf(wszMsg, sizeof(wszMsg), "VBoxInstallHelper: %ls", wszVa); + if (cwc <= 0) + return VERR_BUFFER_OVERFLOW; + +#ifdef DEBUG + OutputDebugStringW(wszMsg); +#endif +#ifdef TESTCASE + RTPrintf("%ls\n", wszMsg); +#endif PMSIHANDLE hMSI = MsiCreateRecord(2 /* cParms */); if (hMSI) { - wchar_t wszBuf[RTPATH_MAX + 256]; - va_list va; - va_start(va, pszFmt); - ssize_t cwc = RTUtf16PrintfV(wszBuf, RT_ELEMENTS(wszBuf), pszFmt, va); - va_end(va); - - MsiRecordSetStringW(hMSI, 0, wszBuf); + MsiRecordSetStringW(hMSI, 0, wszMsg); MsiProcessMessage(hInstall, INSTALLMESSAGE(INSTALLMESSAGE_INFO), hMSI); - MsiCloseHandle(hMSI); - return cwc < RT_ELEMENTS(wszBuf) ? ERROR_SUCCESS : ERROR_BUFFER_OVERFLOW; } - return ERROR_ACCESS_DENIED; + + return cwc < RT_ELEMENTS(wszVa) ? VINF_SUCCESS : VERR_BUFFER_OVERFLOW; } UINT __stdcall IsSerialCheckNeeded(MSIHANDLE hModule) @@ -162,6 +246,483 @@ UINT __stdcall CheckSerial(MSIHANDLE hModule) } /** + * Initializes a target security context. + * + * @returns VBox status code. + * @param pCtx Target directory security context to initialize. + * @param hModule Windows installer module handle. + * @param pszPath Target directory path to use. + */ +static int initTargetDirSecurityCtx(PTGTDIRSECCTX pCtx, MSIHANDLE hModule, const char *pszPath) +{ + if (pCtx->fInitialized) + return VINF_SUCCESS; + +#ifdef DEBUG + logStringF(hModule, "initTargetDirSecurityCtx: pszPath=%s\n", pszPath); +#endif + + char szPathTemp[RTPATH_MAX]; + int vrc = RTStrCopy(szPathTemp, sizeof(szPathTemp), pszPath); + if (RT_FAILURE(vrc)) + return vrc; + + /* Try to find a parent path which exists. */ + char szPathParentAbs[RTPATH_MAX] = { 0 }; + for (int i = 0; i < 256; i++) /* Failsafe counter. */ + { + RTPathStripTrailingSlash(szPathTemp); + RTPathStripFilename(szPathTemp); + vrc = RTPathReal(szPathTemp, szPathParentAbs, sizeof(szPathParentAbs)); + if (RT_SUCCESS(vrc)) + break; + } + + if (RT_FAILURE(vrc)) + { + logStringF(hModule, "initTargetDirSecurityCtx: No existing / valid parent directory found (%Rrc), giving up\n", vrc); + return vrc; + } + + RTDIR hParentDir; + vrc = RTDirOpen(&hParentDir, szPathParentAbs); + if (RT_FAILURE(vrc)) + { + logStringF(hModule, "initTargetDirSecurityCtx: Locking parent directory '%s' failed with %Rrc\n", szPathParentAbs, vrc); + return vrc; + } + +#ifdef DEBUG + logStringF(hModule, "initTargetDirSecurityCtx: Locked parent directory '%s'\n", szPathParentAbs); +#endif + + char szPathTargetAbs[RTPATH_MAX]; + vrc = RTPathReal(pszPath, szPathTargetAbs, sizeof(szPathTargetAbs)); + if (RT_FAILURE(vrc)) + vrc = RTStrCopy(szPathTargetAbs, sizeof(szPathTargetAbs), pszPath); + if (RT_FAILURE(vrc)) + { + logStringF(hModule, "initTargetDirSecurityCtx: Failed to resolve absolute target path (%Rrc)\n", vrc); + return vrc; + } + +#ifdef DEBUG + logStringF(hModule, "initTargetDirSecurityCtx: szPathTargetAbs=%s, szPathParentAbs=%s\n", szPathTargetAbs, szPathParentAbs); +#endif + + /* Target directory validation. */ + if ( !RTStrCmp(szPathTargetAbs, szPathParentAbs) /* Don't allow installation into root directories. */ + || RTStrStr(szPathTargetAbs, "..")) + { + logStringF(hModule, "initTargetDirSecurityCtx: Directory '%s' invalid", szPathTargetAbs); + vrc = VERR_INVALID_NAME; + } + + if (RT_SUCCESS(vrc)) + { + RTFSOBJINFO fsObjInfo; + vrc = RTPathQueryInfo(szPathParentAbs, &fsObjInfo, RTFSOBJATTRADD_NOTHING); + if (RT_SUCCESS(vrc)) + { + if (RTFS_IS_DIRECTORY(fsObjInfo.Attr.fMode)) /* No symlinks or other fun stuff. */ + { + static WELL_KNOWN_SID_TYPE aForbiddenWellKnownSids[] = + { + WinNullSid, + WinWorldSid, + WinAuthenticatedUserSid, + WinBuiltinUsersSid, + WinBuiltinGuestsSid, + WinBuiltinPowerUsersSid + }; + + pCtx->paWellKnownSidsForbidden = (PSID *)RTMemAlloc(sizeof(PSID) * RT_ELEMENTS(aForbiddenWellKnownSids)); + AssertPtrReturn(pCtx->paWellKnownSidsForbidden, VERR_NO_MEMORY); + + size_t i = 0; + for(; i < RT_ELEMENTS(aForbiddenWellKnownSids); i++) + { + pCtx->paWellKnownSidsForbidden[i] = RTMemAlloc(SECURITY_MAX_SID_SIZE); + AssertPtrBreakStmt(pCtx->paWellKnownSidsForbidden, vrc = VERR_NO_MEMORY); + DWORD cbSid = SECURITY_MAX_SID_SIZE; + if (!CreateWellKnownSid(aForbiddenWellKnownSids[i], NULL, pCtx->paWellKnownSidsForbidden[i], &cbSid)) + { + vrc = RTErrConvertFromWin32(GetLastError()); + logStringF(hModule, "initTargetDirSecurityCtx: Creating SID (index %zu) failed with %Rrc\n", i, vrc); + break; + } + } + + if (RT_SUCCESS(vrc)) + { + vrc = RTStrCopy(pCtx->szTargetDirAbs, sizeof(pCtx->szTargetDirAbs), szPathTargetAbs); + if (RT_SUCCESS(vrc)) + { + pCtx->fInitialized = true; + pCtx->hParentDir = hParentDir; + pCtx->cWellKnownSidsForbidden = i; + pCtx->fAccessMaskForbidden = FILE_WRITE_DATA + | FILE_APPEND_DATA + | FILE_WRITE_ATTRIBUTES + | FILE_WRITE_EA; + + RTFILE fh; + RTFileOpen(&fh, "c:\\temp\\targetdir.ctx", RTFILE_O_CREATE_REPLACE | RTFILE_O_DENY_WRITE | RTFILE_O_WRITE); + RTFileClose(fh); + + return VINF_SUCCESS; + } + } + } + else + vrc = VERR_INVALID_NAME; + } + } + + RTDirClose(hParentDir); + + while (pCtx->cWellKnownSidsForbidden--) + { + RTMemFree(pCtx->paWellKnownSidsForbidden[pCtx->cWellKnownSidsForbidden]); + pCtx->paWellKnownSidsForbidden[pCtx->cWellKnownSidsForbidden] = NULL; + } + + logStringF(hModule, "initTargetDirSecurityCtx: Initialization failed failed with %Rrc\n", vrc); + return vrc; +} + +/** + * Destroys a target security context. + * + * @returns VBox status code. + * @param pCtx Target directory security context to destroy. + */ +static void destroyTargetDirSecurityCtx(PTGTDIRSECCTX pCtx) +{ + if ( !pCtx + || !pCtx->fInitialized) + return; + + if (pCtx->hParentDir != NIL_RTDIR) + { + RTDirClose(pCtx->hParentDir); + pCtx->hParentDir = NIL_RTDIR; + } + RT_ZERO(pCtx->szTargetDirAbs); + + for (size_t i = 0; i < pCtx->cWellKnownSidsForbidden; i++) + RTMemFree(pCtx->paWellKnownSidsForbidden[i]); + pCtx->cWellKnownSidsForbidden = 0; + + RTMemFree(pCtx->paWellKnownSidsForbidden); + pCtx->paWellKnownSidsForbidden = NULL; + + RTFileDelete("c:\\temp\\targetdir.ctx"); + + logStringF(NULL, "destroyTargetDirSecurityCtx\n"); +} + +#ifdef DEBUG +/** + * Returns a stingified version of an ACE type. + * + * @returns Stingified version of an ACE type. + * @param uType ACE type. + */ +inline const char *dbgAceTypeToString(uint8_t uType) +{ + switch (uType) + { + RT_CASE_RET_STR(ACCESS_ALLOWED_ACE_TYPE); + RT_CASE_RET_STR(ACCESS_DENIED_ACE_TYPE); + RT_CASE_RET_STR(SYSTEM_AUDIT_ACE_TYPE); + RT_CASE_RET_STR(SYSTEM_ALARM_ACE_TYPE); + default: break; + } + + return "<Invalid>"; +} + +/** + * Returns an allocated string for a SID containing the user/domain name. + * + * @returns Allocated string (UTF-8). Must be free'd using RTStrFree(). + * @param pSid SID to return allocated string for. + */ +inline char *dbgSidToNameA(const PSID pSid) +{ + char *pszName = NULL; + int vrc = VINF_SUCCESS; + + LPWSTR pwszSid = NULL; + if (ConvertSidToStringSid(pSid, &pwszSid)) + { + SID_NAME_USE SidNameUse; + + WCHAR wszUser[MAX_PATH]; + DWORD cbUser = sizeof(wszUser); + WCHAR wszDomain[MAX_PATH]; + DWORD cbDomain = sizeof(wszDomain); + if (LookupAccountSid(NULL, pSid, wszUser, &cbUser, wszDomain, &cbDomain, &SidNameUse)) + { + RTUTF16 wszName[RTPATH_MAX]; + if (RTUtf16Printf(wszName, RT_ELEMENTS(wszName), "%ls%s%ls (%ls)", + wszUser, wszDomain[0] == L'\0' ? "" : "\\", wszDomain, pwszSid)) + { + vrc = RTUtf16ToUtf8(wszName, &pszName); + } + else + vrc = VERR_NO_MEMORY; + } + else + vrc = RTStrAPrintf(&pszName, "<Lookup Error>"); + + LocalFree(pwszSid); + } + else + vrc = VERR_NOT_FOUND; + + return RT_SUCCESS(vrc) ? pszName : "<Invalid>"; +} +#endif /* DEBUG */ + +/** + * Checks a single target path whether it's safe to use or not. + * + * We check if the given path is owned by "NT Service\TrustedInstaller" and therefore assume that it's safe to use. + * + * @returns VBox status code. On error the path should be considered unsafe. + * @retval VERR_INVALID_NAME if the given path is considered unsafe. + * @retval VINF_SUCCESS if the given path is found to be safe to use. + * @param hModule Windows installer module handle. + * @param pszPath Path to check. + */ +static int checkTargetDirOne(MSIHANDLE hModule, PTGTDIRSECCTX pCtx, const char *pszPath) +{ + logStringF(hModule, "checkTargetDirOne: Checking '%s' ...", pszPath); + + PRTUTF16 pwszPath; + int vrc = RTStrToUtf16(pszPath, &pwszPath); + if (RT_FAILURE(vrc)) + return vrc; + + PACL pDacl = NULL; + PSECURITY_DESCRIPTOR pSecurityDescriptor = { 0 }; + DWORD dwErr = GetNamedSecurityInfo(pwszPath, SE_FILE_OBJECT, GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION, + NULL, NULL, NULL, NULL, &pSecurityDescriptor); + if (dwErr == ERROR_SUCCESS) + { + BOOL fDaclPresent = FALSE; + BOOL fDaclDefaultedIgnored = FALSE; + if (GetSecurityDescriptorDacl(pSecurityDescriptor, &fDaclPresent, + &pDacl, &fDaclDefaultedIgnored)) + { + if ( !fDaclPresent + || !pDacl) + { + /* Bail out early if the DACL isn't provided or is missing. */ + vrc = VERR_INVALID_NAME; + } + else + { + ACL_SIZE_INFORMATION aclSizeInfo; + RT_ZERO(aclSizeInfo); + if (GetAclInformation(pDacl, &aclSizeInfo, sizeof(aclSizeInfo), AclSizeInformation)) + { + for(DWORD idxACE = 0; idxACE < aclSizeInfo.AceCount; idxACE++) + { + ACE_HEADER *pAceHdr = NULL; + if (GetAce(pDacl, idxACE, (LPVOID *)&pAceHdr)) + { +#ifdef DEBUG + logStringF(hModule, "checkTargetDirOne: ACE type=%s, flags=%#x, size=%#x", + dbgAceTypeToString(pAceHdr->AceType), pAceHdr->AceFlags, pAceHdr->AceSize); +#endif + /* Note: We print the ACEs in canonoical order. */ + switch (pAceHdr->AceType) + { + case ACCESS_ALLOWED_ACE_TYPE: /* We're only interested in the ALLOW ACE. */ + { + ACCESS_ALLOWED_ACE const *pAce = (ACCESS_ALLOWED_ACE *)pAceHdr; + PSID const pSid = (PSID)&pAce->SidStart; +#ifdef DEBUG + char *pszSid = dbgSidToNameA(pSid); + logStringF(hModule, "checkTargetDirOne:\t%s fMask=%#x", pszSid, pAce->Mask); + RTStrFree(pszSid); +#endif + /* We check the flags here first for performance reasons. */ + if ((pAce->Mask & pCtx->fAccessMaskForbidden) == pCtx->fAccessMaskForbidden) + { + for (size_t idxSID = 0; idxSID < pCtx->cWellKnownSidsForbidden; idxSID++) + { + PSID const pSidForbidden = pCtx->paWellKnownSidsForbidden[idxSID]; + bool const fForbidden = EqualSid(pSid, pSidForbidden); +#ifdef DEBUG + char *pszName = dbgSidToNameA(pSidForbidden); + logStringF(hModule, "checkTargetDirOne:\t%s : %s", + fForbidden ? "** FORBIDDEN **" : "ALLOWED ", pszName); + RTStrFree(pszName); +#endif /* DEBUG */ + if (fForbidden) + { + vrc = VERR_INVALID_NAME; + break; + } + } + } + + break; + } +#ifdef DEBUG + case ACCESS_DENIED_ACE_TYPE: /* We're only interested in the ALLOW ACE. */ + { + ACCESS_DENIED_ACE const *pAce = (ACCESS_DENIED_ACE *)pAceHdr; + + LPWSTR pwszSid = NULL; + ConvertSidToStringSid((PSID)&pAce->SidStart, &pwszSid); + + logStringF(hModule, "checkTargetDirOne:\t%ls fMask=%#x (generic %#x specific %#x)", + pwszSid ? pwszSid : L"<Allocation Error>", pAce->Mask); + + LocalFree(pwszSid); + break; + } +#endif /* DEBUG */ + default: + /* Ignore everything else. */ + break; + } + } + else + dwErr = GetLastError(); + + /* No point in checking further if we failed somewhere above. */ + if (RT_FAILURE(vrc)) + break; + + } /* for ACE */ + } + else + dwErr = GetLastError(); + } + } + else + dwErr = GetLastError(); + + LocalFree(pSecurityDescriptor); + } + else + dwErr = GetLastError(); + + if (RT_SUCCESS(vrc)) + vrc = RTErrConvertFromWin32(dwErr); + +#ifdef DEBUG + logStringF(hModule, "checkTargetDirOne: Returning %Rrc", vrc); +#endif + + if ( RT_FAILURE(vrc) + && vrc != VERR_INVALID_NAME) + logStringF(hModule, "checkTargetDirOne: Failed with %Rrc (%#x)", vrc, dwErr); + + return vrc; +} + +/** + * Checks whether the path in the public property INSTALLDIR has the correct ACL permissions and returns whether + * it's valid or not. + * + * Called from the MSI installer as a custom action. + * + * @returns Success status (acccording to MSI custom actions). + * @retval ERROR_SUCCESS if checking the target directory turned out to be valid. + * @retval ERROR_NO_NET_OR_BAD_PATH is the target directory is invalid. + * @param hModule Windows installer module handle. + * + * @note Sets private property VBox_Target_Dir_Is_Valid to "1" (true) if the given target path is valid, + * or "0" (false) if it is not. An empty target directory is considered to be valid (i.e. INSTALLDIR not set yet). + * + * @sa @bugref{10616} + */ +UINT __stdcall CheckTargetDir(MSIHANDLE hModule) +{ + char *pszTargetDir; + + int vrc = VBoxGetMsiPropUtf8(hModule, "INSTALLDIR", &pszTargetDir); + if (RT_SUCCESS(vrc)) + { + logStringF(hModule, "CheckTargetDir: Checking target directory '%s' ...", pszTargetDir); + + if (!RTStrNLen(pszTargetDir, RTPATH_MAX)) + { + logStringF(hModule, "CheckTargetDir: No INSTALLDIR set (yet), skipping ..."); + VBoxSetMsiProp(hModule, L"VBox_Target_Dir_Is_Valid", L"1"); + } + else + { + union + { + RTPATHPARSED Parsed; + uint8_t ab[RTPATH_MAX]; + } u; + + vrc = RTPathParse(pszTargetDir, &u.Parsed, sizeof(u), RTPATH_STR_F_STYLE_DOS); + if (RT_SUCCESS(vrc)) + { + if (u.Parsed.fProps & RTPATH_PROP_DOTDOT_REFS) + vrc = VERR_INVALID_PARAMETER; + if (RT_SUCCESS(vrc)) + { + vrc = initTargetDirSecurityCtx(&g_TargetDirSecCtx, hModule, pszTargetDir); + if (RT_SUCCESS(vrc)) + { + uint16_t idxComp = u.Parsed.cComps; + char szPathToCheck[RTPATH_MAX]; + while (idxComp > 1) /* We traverse backwards from INSTALLDIR and leave out the root (e.g. C:\"). */ + { + u.Parsed.cComps = idxComp; + vrc = RTPathParsedReassemble(pszTargetDir, &u.Parsed, RTPATH_STR_F_STYLE_DOS, + szPathToCheck, sizeof(szPathToCheck)); + if (RT_FAILURE(vrc)) + break; + if (RTDirExists(szPathToCheck)) + { + vrc = checkTargetDirOne(hModule, &g_TargetDirSecCtx, szPathToCheck); + if (RT_FAILURE(vrc)) + break; + } + else + logStringF(hModule, "CheckTargetDir: Path '%s' does not exist (yet)", szPathToCheck); + idxComp--; + } + + destroyTargetDirSecurityCtx(&g_TargetDirSecCtx); + } + else + logStringF(hModule, "CheckTargetDir: initTargetDirSecurityCtx failed with %Rrc\n", vrc); + + if (RT_SUCCESS(vrc)) + VBoxSetMsiProp(hModule, L"VBox_Target_Dir_Is_Valid", L"1"); + } + } + else + logStringF(hModule, "CheckTargetDir: Parsing path failed with %Rrc", vrc); + } + + RTStrFree(pszTargetDir); + } + + if (RT_FAILURE(vrc)) /* On failure (or when in doubt), mark the installation directory as invalid. */ + { + logStringF(hModule, "CheckTargetDir: Checking failed with %Rrc", vrc); + VBoxSetMsiProp(hModule, L"VBox_Target_Dir_Is_Valid", L"0"); + } + + /* Return back outcome to the MSI engine. */ + return RT_SUCCESS(vrc) ? ERROR_SUCCESS : ERROR_NO_NET_OR_BAD_PATH; +} + +/** * Runs an executable on the OS. * * @returns Windows error code. @@ -869,7 +1430,7 @@ UINT __stdcall InstallBranding(MSIHANDLE hModule) return ERROR_SUCCESS; /* Do not fail here. */ } -#ifdef VBOX_WITH_NETFLT +#if defined(VBOX_WITH_NETFLT) || defined(VBOX_WITH_NETADP) /** @todo should use some real VBox app name */ #define VBOX_NETCFG_APP_NAME L"VirtualBox Installer" @@ -1051,7 +1612,9 @@ static UINT doNetCfgInit(MSIHANDLE hModule, INetCfg **ppnc, BOOL bWrite) return uErr; } +#endif /* defined(VBOX_WITH_NETFLT) || defined(VBOX_WITH_NETADP) */ +#ifdef VBOX_WITH_NETFLT static UINT vboxNetFltQueryInfArray(MSIHANDLE hModule, OUT LPWSTR pwszPtInf, DWORD cwcPtInf, OUT LPWSTR pwszMpInf, DWORD cwcMpInf) { @@ -1082,11 +1645,8 @@ static UINT vboxNetFltQueryInfArray(MSIHANDLE hModule, OUT LPWSTR pwszPtInf, DWO return uErr; } -#endif /*VBOX_WITH_NETFLT*/ - -/*static*/ UINT _uninstallNetFlt(MSIHANDLE hModule) +static UINT _uninstallNetFlt(MSIHANDLE hModule) { -#ifdef VBOX_WITH_NETFLT INetCfg *pNetCfg; UINT uErr; @@ -1123,21 +1683,26 @@ static UINT vboxNetFltQueryInfArray(MSIHANDLE hModule, OUT LPWSTR pwszPtInf, DWO } netCfgLoggerDisable(); } -#endif /* VBOX_WITH_NETFLT */ /* Never fail the uninstall even if we did not succeed. */ return ERROR_SUCCESS; } +#endif /* VBOX_WITH_NETFLT */ UINT __stdcall UninstallNetFlt(MSIHANDLE hModule) { - (void)_uninstallNetLwf(hModule); +#ifdef VBOX_WITH_NETFLT + _uninstallNetLwf(hModule); return _uninstallNetFlt(hModule); +#else + RT_NOREF(hModule); + return ERROR_SUCCESS; +#endif } +#ifdef VBOX_WITH_NETFLT static UINT _installNetFlt(MSIHANDLE hModule) { -#ifdef VBOX_WITH_NETFLT UINT uErr; INetCfg *pNetCfg; @@ -1184,22 +1749,26 @@ static UINT _installNetFlt(MSIHANDLE hModule) } netCfgLoggerDisable(); } -#endif /* VBOX_WITH_NETFLT */ /* Never fail the install even if we did not succeed. */ return ERROR_SUCCESS; } +#endif /* VBOX_WITH_NETFLT */ UINT __stdcall InstallNetFlt(MSIHANDLE hModule) { - (void)_uninstallNetLwf(hModule); +#ifdef VBOX_WITH_NETFLT + _uninstallNetLwf(hModule); return _installNetFlt(hModule); +#else + RT_NOREF(hModule); + return ERROR_SUCCESS; +#endif } - -/*static*/ UINT _uninstallNetLwf(MSIHANDLE hModule) -{ #ifdef VBOX_WITH_NETFLT +static UINT _uninstallNetLwf(MSIHANDLE hModule) +{ INetCfg *pNetCfg; UINT uErr; @@ -1236,21 +1805,26 @@ UINT __stdcall InstallNetFlt(MSIHANDLE hModule) } netCfgLoggerDisable(); } -#endif /* VBOX_WITH_NETFLT */ /* Never fail the uninstall even if we did not succeed. */ return ERROR_SUCCESS; } +#endif /* VBOX_WITH_NETFLT */ UINT __stdcall UninstallNetLwf(MSIHANDLE hModule) { - (void)_uninstallNetFlt(hModule); +#ifdef VBOX_WITH_NETFLT + _uninstallNetFlt(hModule); return _uninstallNetLwf(hModule); +#else + RT_NOREF(hModule); + return ERROR_SUCCESS; +#endif } +#ifdef VBOX_WITH_NETFLT static UINT _installNetLwf(MSIHANDLE hModule) { -#ifdef VBOX_WITH_NETFLT UINT uErr; INetCfg *pNetCfg; @@ -1313,20 +1887,25 @@ static UINT _installNetLwf(MSIHANDLE hModule) } netCfgLoggerDisable(); } -#endif /* VBOX_WITH_NETFLT */ /* Never fail the install even if we did not succeed. */ return ERROR_SUCCESS; } +#endif /* VBOX_WITH_NETFLT */ UINT __stdcall InstallNetLwf(MSIHANDLE hModule) { - (void)_uninstallNetFlt(hModule); +#ifdef VBOX_WITH_NETFLT + _uninstallNetFlt(hModule); return _installNetLwf(hModule); +#else + RT_NOREF(hModule); + return ERROR_SUCCESS; +#endif } -#if 0 +#if 0 /** @todo r=andy Remove this? */ static BOOL RenameHostOnlyConnectionsCallback(HDEVINFO hDevInfo, PSP_DEVINFO_DATA pDev, PVOID pContext) { WCHAR DevName[256]; @@ -1382,11 +1961,11 @@ static BOOL RenameHostOnlyConnectionsCallback(HDEVINFO hDevInfo, PSP_DEVINFO_DAT return TRUE; } -#endif +#endif /* 0 */ +#ifdef VBOX_WITH_NETADP static UINT _createHostOnlyInterface(MSIHANDLE hModule, LPCWSTR pwszId, LPCWSTR pwszInfName) { -#ifdef VBOX_WITH_NETFLT netCfgLoggerEnable(hModule); BOOL fSetupModeInteractive = SetupSetNonInteractiveMode(FALSE); @@ -1455,12 +2034,12 @@ static UINT _createHostOnlyInterface(MSIHANDLE hModule, LPCWSTR pwszId, LPCWSTR //in fail case call CreateHostOnlyInterface logStringF(hModule, "CreateHostOnlyInterface: VBoxNetCfgWinUpdateHostOnlyNetworkInterface failed, hr = %#x", hr); logStringF(hModule, "CreateHostOnlyInterface: calling VBoxNetCfgWinCreateHostOnlyNetworkInterface"); -#ifdef VBOXNETCFG_DELAYEDRENAME +# ifdef VBOXNETCFG_DELAYEDRENAME BSTR devId; hr = VBoxNetCfgWinCreateHostOnlyNetworkInterface(pwszInfPath, fIsFile, NULL, &guid, &devId, NULL); -#else /* !VBOXNETCFG_DELAYEDRENAME */ +# else /* !VBOXNETCFG_DELAYEDRENAME */ hr = VBoxNetCfgWinCreateHostOnlyNetworkInterface(pwszInfPath, fIsFile, NULL, &guid, NULL, NULL); -#endif /* !VBOXNETCFG_DELAYEDRENAME */ +# endif /* !VBOXNETCFG_DELAYEDRENAME */ logStringF(hModule, "CreateHostOnlyInterface: VBoxNetCfgWinCreateHostOnlyNetworkInterface returns %#x", hr); if (SUCCEEDED(hr)) { @@ -1471,12 +2050,12 @@ static UINT _createHostOnlyInterface(MSIHANDLE hModule, LPCWSTR pwszId, LPCWSTR logStringF(hModule, "CreateHostOnlyInterface: VBoxNetCfgWinEnableStaticIpConfig returns %#x", hr); if (FAILED(hr)) logStringF(hModule, "CreateHostOnlyInterface: VBoxNetCfgWinEnableStaticIpConfig failed, error = %#x", hr); -#ifdef VBOXNETCFG_DELAYEDRENAME +# ifdef VBOXNETCFG_DELAYEDRENAME hr = VBoxNetCfgWinRenameHostOnlyConnection(&guid, devId, NULL); if (FAILED(hr)) logStringF(hModule, "CreateHostOnlyInterface: VBoxNetCfgWinRenameHostOnlyConnection failed, error = %#x", hr); SysFreeString(devId); -#endif /* VBOXNETCFG_DELAYEDRENAME */ +# endif /* VBOXNETCFG_DELAYEDRENAME */ } else logStringF(hModule, "CreateHostOnlyInterface: VBoxNetCfgWinCreateHostOnlyNetworkInterface failed, error = %#x", hr); @@ -1493,21 +2072,26 @@ static UINT _createHostOnlyInterface(MSIHANDLE hModule, LPCWSTR pwszId, LPCWSTR netCfgLoggerDisable(); -#endif /* VBOX_WITH_NETFLT */ - logStringF(hModule, "CreateHostOnlyInterface: Returns success (ignoring all failures)"); /* Never fail the install even if we did not succeed. */ return ERROR_SUCCESS; } +#endif /* VBOX_WITH_NETADP */ UINT __stdcall CreateHostOnlyInterface(MSIHANDLE hModule) { +#ifdef VBOX_WITH_NETADP return _createHostOnlyInterface(hModule, NETADP_ID, L"VBoxNetAdp.inf"); +#else + RT_NOREF(hModule); + return ERROR_SUCCESS; +#endif } UINT __stdcall Ndis6CreateHostOnlyInterface(MSIHANDLE hModule) { -#if 0 /* Trick for allowing the debugger to be attached. */ +#ifdef VBOX_WITH_NETADP +# if 0 /* Trick for allowing the debugger to be attached. */ for (unsigned i = 0; i < 128 && !IsDebuggerPresent(); i++) { logStringF(hModule, "Waiting for debugger to attach: windbg -p %u", GetCurrentProcessId()); @@ -1515,13 +2099,17 @@ UINT __stdcall Ndis6CreateHostOnlyInterface(MSIHANDLE hModule) } Sleep(1002); __debugbreak(); -#endif +# endif return _createHostOnlyInterface(hModule, NETADP_ID, L"VBoxNetAdp6.inf"); +#else /* !VBOX_WITH_NETADP */ + RT_NOREF(hModule); + return ERROR_SUCCESS; +#endif } +#ifdef VBOX_WITH_NETADP static UINT _removeHostOnlyInterfaces(MSIHANDLE hModule, LPCWSTR pwszId) { -#ifdef VBOX_WITH_NETFLT netCfgLoggerEnable(hModule); logStringF(hModule, "RemoveHostOnlyInterfaces: Removing all host-only interfaces"); @@ -1545,20 +2133,25 @@ static UINT _removeHostOnlyInterfaces(MSIHANDLE hModule, LPCWSTR pwszId) SetupSetNonInteractiveMode(fSetupModeInteractive); netCfgLoggerDisable(); -#endif /* VBOX_WITH_NETFLT */ /* Never fail the uninstall even if we did not succeed. */ return ERROR_SUCCESS; } +#endif /* VBOX_WITH_NETADP */ UINT __stdcall RemoveHostOnlyInterfaces(MSIHANDLE hModule) { +#ifdef VBOX_WITH_NETADP return _removeHostOnlyInterfaces(hModule, NETADP_ID); +#else + RT_NOREF(hModule); + return ERROR_SUCCESS; +#endif } +#ifdef VBOX_WITH_NETADP static UINT _stopHostOnlyInterfaces(MSIHANDLE hModule, LPCWSTR pwszId) { -#ifdef VBOX_WITH_NETFLT netCfgLoggerEnable(hModule); logStringF(hModule, "StopHostOnlyInterfaces: Stopping all host-only interfaces"); @@ -1576,20 +2169,25 @@ static UINT _stopHostOnlyInterfaces(MSIHANDLE hModule, LPCWSTR pwszId) SetupSetNonInteractiveMode(fSetupModeInteractive); netCfgLoggerDisable(); -#endif /* VBOX_WITH_NETFLT */ /* Never fail the uninstall even if we did not succeed. */ return ERROR_SUCCESS; } +#endif /* VBOX_WITH_NETADP */ UINT __stdcall StopHostOnlyInterfaces(MSIHANDLE hModule) { +#ifdef VBOX_WITH_NETADP return _stopHostOnlyInterfaces(hModule, NETADP_ID); +#else + RT_NOREF(hModule); + return ERROR_SUCCESS; +#endif } +#ifdef VBOX_WITH_NETADP static UINT _updateHostOnlyInterfaces(MSIHANDLE hModule, LPCWSTR pwszInfName, LPCWSTR pwszId) { -#ifdef VBOX_WITH_NETFLT netCfgLoggerEnable(hModule); logStringF(hModule, "UpdateHostOnlyInterfaces: Updating all host-only interfaces"); @@ -1656,25 +2254,35 @@ static UINT _updateHostOnlyInterfaces(MSIHANDLE hModule, LPCWSTR pwszInfName, LP SetupSetNonInteractiveMode(fSetupModeInteractive); netCfgLoggerDisable(); -#endif /* VBOX_WITH_NETFLT */ /* Never fail the update even if we did not succeed. */ return ERROR_SUCCESS; } +#endif /* VBOX_WITH_NETADP */ UINT __stdcall UpdateHostOnlyInterfaces(MSIHANDLE hModule) { +#ifdef VBOX_WITH_NETADP return _updateHostOnlyInterfaces(hModule, L"VBoxNetAdp.inf", NETADP_ID); +#else + RT_NOREF(hModule); + return ERROR_SUCCESS; +#endif } UINT __stdcall Ndis6UpdateHostOnlyInterfaces(MSIHANDLE hModule) { +#ifdef VBOX_WITH_NETADP return _updateHostOnlyInterfaces(hModule, L"VBoxNetAdp6.inf", NETADP_ID); +#else + RT_NOREF(hModule); + return ERROR_SUCCESS; +#endif } +#ifdef VBOX_WITH_NETADP static UINT _uninstallNetAdp(MSIHANDLE hModule, LPCWSTR pwszId) { -#ifdef VBOX_WITH_NETFLT INetCfg *pNetCfg; UINT uErr; @@ -1711,15 +2319,20 @@ static UINT _uninstallNetAdp(MSIHANDLE hModule, LPCWSTR pwszId) } netCfgLoggerDisable(); } -#endif /* VBOX_WITH_NETFLT */ /* Never fail the uninstall even if we did not succeed. */ return ERROR_SUCCESS; } +#endif /* VBOX_WITH_NETADP */ UINT __stdcall UninstallNetAdp(MSIHANDLE hModule) { +#ifdef VBOX_WITH_NETADP return _uninstallNetAdp(hModule, NETADP_ID); +#else + RT_NOREF(hModule); + return ERROR_SUCCESS; +#endif } static bool isTAPDevice(const WCHAR *pwszGUID) diff --git a/src/VBox/Installer/win/InstallHelper/VBoxInstallHelper.def b/src/VBox/Installer/win/InstallHelper/VBoxInstallHelper.def index 03cb5d60..3ab891c1 100644 --- a/src/VBox/Installer/win/InstallHelper/VBoxInstallHelper.def +++ b/src/VBox/Installer/win/InstallHelper/VBoxInstallHelper.def @@ -29,6 +29,7 @@ LIBRARY "VBoxInstallHelper" EXPORTS IsSerialCheckNeeded CheckSerial + CheckTargetDir IsMSCRTInstalled IsPythonInstalled IsWindows10 @@ -38,8 +39,8 @@ EXPORTS UninstallBranding InstallNetFlt UninstallNetFlt - UninstallNetAdp - InstallNetLwf + UninstallNetAdp + InstallNetLwf UninstallNetLwf UninstallTAPInstances UninstallVBoxDrv diff --git a/src/VBox/Installer/win/NLS/de_DE.wxl b/src/VBox/Installer/win/NLS/de_DE.wxl index dcd4d3e1..d4b004f1 100644 --- a/src/VBox/Installer/win/NLS/de_DE.wxl +++ b/src/VBox/Installer/win/NLS/de_DE.wxl @@ -63,8 +63,7 @@ <String Id="VB_NetAdpDriver">[ProductName] Treiber für virtuellen Netzwerk-Adapter für Host-only Netzwerke.</String> <String Id="VB_NetLwfDriver">[ProductName] Treiber für NDIS6-Netzwerkbrücke.</String> <String Id="VB_NetAdp6Driver">[ProductName] Treiber für virtuellen Netzwerk-Adapter für NDIS6-Host-only-Netzwerke.</String> - - <String Id="VB_Python">Python-Support für VirtualBox.</String> + <String Id="VB_Python">Python-Support für VirtualBox.</String> <!----> @@ -75,6 +74,7 @@ <String Id="Only64Bit">Diese Applikation läuft nur auf 64-bit Windows-Systemen. Bitte installieren Sie die 32-bit Version von [ProductName]!</String> <String Id="SunFound">Eine alte Sun Version von VirtualBox wurde auf diesem Computer gefunden. Bitte deinstallieren Sie diese Version zuerst. Danach können Sie [ProductName] installieren!</String> <String Id="InnotekFound">Eine alte innotek Version von VirtualBox wurde auf diesem Computer gefunden. Bitte deinstallieren Sie diese Version zuerst. Danach können Sie [ProductName] installieren!</String> + <String Id="InvalidTargetDir">Ungültiges Installationsverzeichnis angegeben. Bitte ein anderes Installationsverzeichnis wählen, um [ProductName] zu installieren.</String> <!----> @@ -93,6 +93,11 @@ <String Id="LicenseAgreementDlg_Decline">Ich &akzeptiere die Bedingungen des Lizenzvertrags nicht.</String> <!----> + <String Id="InvalidTargetDirDlg_Header">Ungültiges Installationsverzeichnis</String> + <String Id="InvalidTargetDirDlg_Desc1">Das gewählte Installationsverzeichnis is ungültig, da dieses nicht den Sicherheitsrichtlinien entspricht.</String> + <String Id="InvalidTargetDirDlg_Desc2">Bitte ein anderes Installationsverzeichnis wählen um [ProductName] zu installieren.</String> + + <!----> <String Id="CheckSerialDlg_Header">Seriennummer</String> <String Id="CheckSerialDlg_Body">Bitte geben Sie die Seriennummer in die unten stehenden Felder ein. Sie finden die Nummer auf dem Aufkleber in der VirtualBox CD-Hülle.</String> diff --git a/src/VBox/Installer/win/NLS/el_GR.wxl b/src/VBox/Installer/win/NLS/el_GR.wxl index 8d98eab9..071a61e0 100644 --- a/src/VBox/Installer/win/NLS/el_GR.wxl +++ b/src/VBox/Installer/win/NLS/el_GR.wxl @@ -63,7 +63,6 @@ <String Id="VB_NetAdpDriver">Οδηγός [ProductName] εικονικής κάρτας δικτύου για μόνο-με-οικοδεσπότη δίκτυα.</String> <String Id="VB_NetLwfDriver">Οδηγός [ProductName] για NDIS6 γεφυρωμένα δίκτυα.</String> <String Id="VB_NetAdp6Driver">Οδηγός [ProductName] εικονικής κάρτας δικτύου για NDIS6 μόνο-με-οικοδεσπότη δίκτυα.</String> - <String Id="VB_Python">Υποστήριξη Python για το VirtualBox.</String> <!----> @@ -75,6 +74,7 @@ <String Id="Only64Bit">Αυτή η εφαρμογή τρέχει μόνο σε συστήματα Windows 64 bit. Εγκαταστήστε την έκδοση 32-bit του [ProductName]!</String> <String Id="SunFound">Βρέθηκε μία παλιότερη εγκατάσταση του Sun VirtualBox στον υπολογιστή. Καταργήστε πρώτα την εγκατάσταση αυτού του πακέτου και μετά εγκαταστήστε το [ProductName]!</String> <String Id="InnotekFound">Βρέθηκε μία παλιότερη εγκατάσταση του innotek VirtualBox στον υπολογιστή. Καταργήστε πρώτα την εγκατάσταση αυτού του πακέτου και μετά εγκαταστήστε το [ProductName]!</String> + <String Id="InvalidTargetDir">Invalid installation directory specified! Please use another installation directory to install [ProductName].</String> <!----> @@ -94,6 +94,12 @@ <!----> + <String Id="InvalidTargetDirDlg_Header">Invalid installation directory</String> + <String Id="InvalidTargetDirDlg_Desc1">The chosen installation directory is invalid, as it does not meet the security requirements.</String> + <String Id="InvalidTargetDirDlg_Desc2">Please choose another directory for installing [ProductName].</String> + + <!----> + <String Id="CheckSerialDlg_Header">Σειριακός Αριθμός</String> <String Id="CheckSerialDlg_Body">Εισάγετε τον σειριακό αριθμό σας στα παρακάτω πεδία. Θα το βρείτε στο αυτοκόλλητο μέσα στην θήκη του CD του VirtualBox.</String> <String Id="CheckSerialDlg_Footer">Όταν ολοκληρώσετε την εισαγωγή του σειριακού αριθμού, πατήστε το κουμπί "Check" παρακάτω.</String> diff --git a/src/VBox/Installer/win/NLS/en_US.wxl b/src/VBox/Installer/win/NLS/en_US.wxl index b3be4e45..3eac3530 100644 --- a/src/VBox/Installer/win/NLS/en_US.wxl +++ b/src/VBox/Installer/win/NLS/en_US.wxl @@ -63,7 +63,6 @@ <String Id="VB_NetAdpDriver">[ProductName] virtual network adapter driver for Host-Only Networking.</String> <String Id="VB_NetLwfDriver">[ProductName] driver for NDIS6 Bridged Networking.</String> <String Id="VB_NetAdp6Driver">[ProductName] virtual network adapter driver for NDIS6 Host-Only Networking.</String> - <String Id="VB_Python">Python support for VirtualBox.</String> <!----> @@ -75,6 +74,7 @@ <String Id="Only64Bit">This application only runs on 64-bit Windows systems. Please install the 32-bit version of [ProductName]!</String> <String Id="SunFound">An old Sun VirtualBox installation has been found on this machine. Please uninstall this package first and then install [ProductName]!</String> <String Id="InnotekFound">An old innotek VirtualBox installation has been found on this machine. Please uninstall this package first and then install [ProductName]!</String> + <String Id="InvalidTargetDir">Invalid installation directory specified! Please use another installation directory to install [ProductName].</String> <!----> @@ -94,6 +94,12 @@ <!----> + <String Id="InvalidTargetDirDlg_Header">Invalid installation directory</String> + <String Id="InvalidTargetDirDlg_Desc1">The chosen installation directory is invalid, as it does not meet the security requirements.</String> + <String Id="InvalidTargetDirDlg_Desc2">Please choose another directory for installing [ProductName].</String> + + <!----> + <String Id="CheckSerialDlg_Header">Serial Number</String> <String Id="CheckSerialDlg_Body">Please enter your serial number in the fields below. You'll find it on the sticker inside the VirtualBox CD case.</String> <String Id="CheckSerialDlg_Footer">When done entering the serial number, press the "Check" button below.</String> diff --git a/src/VBox/Installer/win/NLS/fa_IR.wxl b/src/VBox/Installer/win/NLS/fa_IR.wxl index f6b0173a..1eeedf8a 100644 --- a/src/VBox/Installer/win/NLS/fa_IR.wxl +++ b/src/VBox/Installer/win/NLS/fa_IR.wxl @@ -58,8 +58,7 @@ <String Id="VB_NetAdpDriver">درایور آداپتور شبکه مجازی [ProductName] برای شبکه فقط-میزبان.</String> <String Id="VB_NetLwfDriver">[ProductName] driver for NDIS6 Bridged Networking.</String> <String Id="VB_NetAdp6Driver">[ProductName] virtual network adapter driver for NDIS6 Host-Only Networking.</String> - - <String Id="VB_Python">پشتیبانی از پایتون برای ویرچوال باکس.</String> + <String Id="VB_Python">پشتیبانی از پایتون برای ویرچوال باکس.</String> <!----> <String Id="NeedAdmin">برای حذف [ProductName] شما نیاز به اجازه مدیر دارید! این راه انداز حالا لغو میشود.</String> <String Id="NeedMSCRT">[ProductName] needs the Microsoft Visual C++ 2019 Redistributable Package being installed first. Please install and restart the installation of [ProductName].</String> @@ -68,6 +67,7 @@ <String Id="Only64Bit">این برنامه فقط روی ویندوز 64 بیتی اِجرا میشود. لطفا نسخه 32 بیتی [ProductName] را نصب کنید!</String> <String Id="SunFound">یک نصب قدیمی ویرچوال باکس روی این رایانه یافت شد. لطفا اول این بسته را حذف سپس [ProductName] را نصب کنید!</String> <String Id="InnotekFound">یک نسخه قدیمی نصب ویرچوال باکس در این ماشین یافت شد. لطفا اول این بسته را حذف و سپس [ProductName] را نصب کنید!</String> + <String Id="InvalidTargetDir">Invalid installation directory specified! Please use another installation directory to install [ProductName].</String> <!----> <String Id="CancelDlg_Question">آیا میخواهید نصب [ProductName] را لغو کنید؟</String> <!----> @@ -79,6 +79,10 @@ <String Id="LicenseAgreementDlg_Accept">&من ضوابط را در توافقنامه مجوز می پذیرم</String> <String Id="LicenseAgreementDlg_Decline">&من ضوابط را در توافقنامه مجوز نمی پذیرم</String> <!----> + <String Id="InvalidTargetDirDlg_Header">Invalid installation directory</String> + <String Id="InvalidTargetDirDlg_Desc1">The chosen installation directory is invalid, as it does not meet the security requirements.</String> + <String Id="InvalidTargetDirDlg_Desc2">Please choose another directory for installing [ProductName].</String> + <!----> <String Id="CheckSerialDlg_Header">شماره سریال</String> <String Id="CheckSerialDlg_Body">لطفا شماره سریال را در فیلد زیر وارد کنید.آن را روی برچسب روی جلد سی دی ویرچوال باکس می یابید.</String> <String Id="CheckSerialDlg_Footer">وقتی که وارد کردن شماره سریال انجام شد،دکمه "بررسی" را در زیر فشار دهید.</String> diff --git a/src/VBox/Installer/win/NLS/fr_FR.wxl b/src/VBox/Installer/win/NLS/fr_FR.wxl index 773786c5..2624925b 100644 --- a/src/VBox/Installer/win/NLS/fr_FR.wxl +++ b/src/VBox/Installer/win/NLS/fr_FR.wxl @@ -63,8 +63,7 @@ <String Id="VB_NetAdpDriver">Pilote de carte réseau virtuelle [ProductName] pour l'accès réseau privé hôte.</String> <String Id="VB_NetLwfDriver">[ProductName] driver for NDIS6 Bridged Networking.</String> <String Id="VB_NetAdp6Driver">[ProductName] virtual network adapter driver for NDIS6 Host-Only Networking.</String> - - <String Id="VB_Python">Python support for VirtualBox.</String> + <String Id="VB_Python">Python support for VirtualBox.</String> <!----> @@ -74,6 +73,7 @@ <String Id="Only32Bit">Cette application ne marche que sur des systèmes Windows 32-bit. Veuillez installer la version 64-bit de [ProductName]!</String> <String Id="Only64Bit">Cette application ne marche que sur des systèmes Windows 64-bit. Veuillez installer la version 32-bit de [ProductName]!</String> <String Id="InnotekFound">Vous avez une ancienne installation de innotek VirtualBox sur cette machine. Il vous faudra la désinstaller avant de pouvoir installer [ProductName].</String> + <String Id="InvalidTargetDir">Invalid installation directory specified! Please use another installation directory to install [ProductName].</String> <!----> @@ -93,6 +93,12 @@ <!----> + <String Id="InvalidTargetDirDlg_Header">Invalid installation directory</String> + <String Id="InvalidTargetDirDlg_Desc1">The chosen installation directory is invalid, as it does not meet the security requirements.</String> + <String Id="InvalidTargetDirDlg_Desc2">Please choose another directory for installing [ProductName].</String> + + <!----> + <String Id="CheckSerialDlg_Header">Numéro de série</String> <String Id="CheckSerialDlg_Body">Veulliez entrer votre numéro de série dans les champs ci-dessous. Vous le trouverez sur l'autocollant à l'intérieur du boîtier du CD de VirtualBox.</String> <String Id="CheckSerialDlg_Footer">Quand vous avez fini d'entrer le numéro de série, appuyez sur le bouton Vérifier ci-dessous.</String> diff --git a/src/VBox/Installer/win/NLS/it_IT.wxl b/src/VBox/Installer/win/NLS/it_IT.wxl index adead2a5..ef0b25d5 100644 --- a/src/VBox/Installer/win/NLS/it_IT.wxl +++ b/src/VBox/Installer/win/NLS/it_IT.wxl @@ -58,8 +58,7 @@ <String Id="VB_NetAdpDriver">Driver di [ProductName] per la scheda di rete virtuale per la rete solo host.</String> <String Id="VB_NetLwfDriver">Driver di [ProductName] per la rete con bridge NDIS6.</String> <String Id="VB_NetAdp6Driver">Driver di [ProductName] per la scheda di rete virtuale per la rete solo host NDIS6.</String> - - <String Id="VB_Python">Supporto Python per VirtualBox.</String> + <String Id="VB_Python">Supporto Python per VirtualBox.</String> <!----> <String Id="NeedAdmin">Devi avere diritti di amministrazione per (dis)installare [ProductName]! L'installazione sarà interrotta immediatamente.</String> <String Id="NeedMSCRT">[ProductName] needs the Microsoft Visual C++ 2019 Redistributable Package being installed first. Please install and restart the installation of [ProductName].</String> @@ -68,6 +67,7 @@ <String Id="Only64Bit">Questa applicazione può essere eseguita solo su sistemi Windows a 64 bit. Installa la versione a 32 bit di [ProductName]!</String> <String Id="SunFound">Una vecchia installazione di Sun VirtualBox è stata trovata su questa macchina. Disinstalla prima questo pacchetto e poi installa [ProductName]!</String> <String Id="InnotekFound">Una vecchia installazione di innotek VirtualBox è stata trovata su questa macchina. Disinstalla prima questo pacchetto e poi installa [ProductName]!</String> + <String Id="InvalidTargetDir">Invalid installation directory specified! Please use another installation directory to install [ProductName].</String> <!----> <String Id="CancelDlg_Question">Sei sicuro di voler annullare l'installazione di [ProductName]?</String> <!----> @@ -79,6 +79,10 @@ <String Id="LicenseAgreementDlg_Accept">&Accetto i termini dell'accordo di licenza</String> <String Id="LicenseAgreementDlg_Decline">&Non accetto i termini dell'accordo di licenza</String> <!----> + <String Id="InvalidTargetDirDlg_Header">Invalid installation directory</String> + <String Id="InvalidTargetDirDlg_Desc1">The chosen installation directory is invalid, as it does not meet the security requirements.</String> + <String Id="InvalidTargetDirDlg_Desc2">Please choose another directory for installing [ProductName].</String> + <!----> <String Id="CheckSerialDlg_Header">Numero di serie</String> <String Id="CheckSerialDlg_Body">Digita il numero di serie nel campo seguente. Troverai il numero sull'adesivo all'interno della custodia del CD di VirtualBox.</String> <String Id="CheckSerialDlg_Footer">Una volta digitato il numero di serie, premi il pulsante "Controlla" in basso.</String> diff --git a/src/VBox/Installer/win/NLS/ru_RU.wxl b/src/VBox/Installer/win/NLS/ru_RU.wxl index b3be4e45..3eac3530 100644 --- a/src/VBox/Installer/win/NLS/ru_RU.wxl +++ b/src/VBox/Installer/win/NLS/ru_RU.wxl @@ -63,7 +63,6 @@ <String Id="VB_NetAdpDriver">[ProductName] virtual network adapter driver for Host-Only Networking.</String> <String Id="VB_NetLwfDriver">[ProductName] driver for NDIS6 Bridged Networking.</String> <String Id="VB_NetAdp6Driver">[ProductName] virtual network adapter driver for NDIS6 Host-Only Networking.</String> - <String Id="VB_Python">Python support for VirtualBox.</String> <!----> @@ -75,6 +74,7 @@ <String Id="Only64Bit">This application only runs on 64-bit Windows systems. Please install the 32-bit version of [ProductName]!</String> <String Id="SunFound">An old Sun VirtualBox installation has been found on this machine. Please uninstall this package first and then install [ProductName]!</String> <String Id="InnotekFound">An old innotek VirtualBox installation has been found on this machine. Please uninstall this package first and then install [ProductName]!</String> + <String Id="InvalidTargetDir">Invalid installation directory specified! Please use another installation directory to install [ProductName].</String> <!----> @@ -94,6 +94,12 @@ <!----> + <String Id="InvalidTargetDirDlg_Header">Invalid installation directory</String> + <String Id="InvalidTargetDirDlg_Desc1">The chosen installation directory is invalid, as it does not meet the security requirements.</String> + <String Id="InvalidTargetDirDlg_Desc2">Please choose another directory for installing [ProductName].</String> + + <!----> + <String Id="CheckSerialDlg_Header">Serial Number</String> <String Id="CheckSerialDlg_Body">Please enter your serial number in the fields below. You'll find it on the sticker inside the VirtualBox CD case.</String> <String Id="CheckSerialDlg_Footer">When done entering the serial number, press the "Check" button below.</String> diff --git a/src/VBox/Installer/win/NLS/tr_TR.wxl b/src/VBox/Installer/win/NLS/tr_TR.wxl index 2604eff9..ff7a3b89 100644 --- a/src/VBox/Installer/win/NLS/tr_TR.wxl +++ b/src/VBox/Installer/win/NLS/tr_TR.wxl @@ -63,8 +63,7 @@ <String Id="VB_NetAdpDriver">Yalnızca-Anamakine Ağı Oluşturma için [ProductName] sanal ağ bağdaştırıcısı sürücüsü.</String> <String Id="VB_NetLwfDriver">NDIS6 Köprü Ağı Oluşturma için [ProductName] sürücüsü.</String> <String Id="VB_NetAdp6Driver">NDIS6 Yalnızca-Anamakine Ağı Oluşturma için [ProductName] sanal ağ bağdaştırıcısı sürücüsü.</String> - - <String Id="VB_Python">VirtualBox için Python desteği.</String> + <String Id="VB_Python">VirtualBox için Python desteği.</String> <!----> @@ -75,6 +74,7 @@ <String Id="Only64Bit">Bu uygulama yalnızca 64-bit Windows sistemlerinde çalışır. Lütfen [ProductName] 32-bit sürümünü yükleyin!</String> <String Id="SunFound">Bu makinede eski bir Sun VirtualBox kurulumu bulundu. Lütfen önce bu paketi kaldırın ve sonra [ProductName] yükleyin!</String> <String Id="InnotekFound">Bu makinede eski bir innotek VirtualBox kurulumu bulundu. Lütfen önce bu paketi kaldırın ve sonra [ProductName] yükleyin!</String> + <String Id="InvalidTargetDir">Invalid installation directory specified! Please use another installation directory to install [ProductName].</String> <!----> @@ -94,6 +94,12 @@ <!----> + <String Id="InvalidTargetDirDlg_Header">Invalid installation directory</String> + <String Id="InvalidTargetDirDlg_Desc1">The chosen installation directory is invalid, as it does not meet the security requirements.</String> + <String Id="InvalidTargetDirDlg_Desc2">Please choose another directory for installing [ProductName].</String> + + <!----> + <String Id="CheckSerialDlg_Header">Seri Numarası</String> <String Id="CheckSerialDlg_Body">Lütfen aşağıdaki alana seri numaranızı girin. VirtualBox CD kutusu içerisindeki etikette bulacaksınız.</String> <String Id="CheckSerialDlg_Footer">Seri numarasını girmeniz bittiğinde, aşağıdaki "Denetle" düğmesine basın".</String> diff --git a/src/VBox/Installer/win/NLS/zh_CN.wxl b/src/VBox/Installer/win/NLS/zh_CN.wxl index 7ea1c68c..2d57834a 100644 --- a/src/VBox/Installer/win/NLS/zh_CN.wxl +++ b/src/VBox/Installer/win/NLS/zh_CN.wxl @@ -63,7 +63,6 @@ <String Id="VB_NetAdpDriver">[ProductName] 虚拟网络界面卡针对“仅主机”网络。</String> <String Id="VB_NetLwfDriver">[ProductName] driver for NDIS6 Bridged Networking.</String> <String Id="VB_NetAdp6Driver">[ProductName] virtual network adapter driver for NDIS6 Host-Only Networking.</String> - <String Id="VB_Python">VirtualBox 的 Python 支持。</String> <!----> @@ -75,6 +74,7 @@ <String Id="Only64Bit">此应用程序只能运行在 64 位 Windows 系统。 请安装 [ProductName] 的 32 位版本!</String> <String Id="SunFound">在此计算机发现旧的 Sun VirtualBox 安装。 请先卸载此组件然后安装 [ProductName]!</String> <String Id="InnotekFound">在此计算机发现旧的 innotek VirtualBox 安装。 请先卸载此组件然后安装 [ProductName]!</String> +<String Id="InvalidTargetDir">Invalid installation directory specified! Please use another installation directory to install [ProductName].</String> <!----> @@ -94,6 +94,12 @@ <!----> +<String Id="InvalidTargetDirDlg_Header">Invalid installation directory</String> +<String Id="InvalidTargetDirDlg_Desc1">The chosen installation directory is invalid, as it does not meet the security requirements.</String> +<String Id="InvalidTargetDirDlg_Desc2">Please choose another directory for installing [ProductName].</String> + +<!----> + <String Id="CheckSerialDlg_Header">序号</String> <String Id="CheckSerialDlg_Body">请在以下字段输入你的序号。 你可以在 VirtualBox CD 盒内的贴纸找到。</String> <String Id="CheckSerialDlg_Footer">序号输入完成时,单击以下"检查"按钮。</String> diff --git a/src/VBox/Installer/win/NLS/zh_TW.wxl b/src/VBox/Installer/win/NLS/zh_TW.wxl index cc7da673..c30e8113 100644 --- a/src/VBox/Installer/win/NLS/zh_TW.wxl +++ b/src/VBox/Installer/win/NLS/zh_TW.wxl @@ -63,7 +63,6 @@ <String Id="VB_NetAdpDriver">[ProductName] 虛擬網路介面卡針對「僅限主機」網路。</String> <String Id="VB_NetLwfDriver">[ProductName] 驅動程式針對 NDIS6 橋接網路。</String> <String Id="VB_NetAdp6Driver">[ProductName] 虛擬網路介面卡針對 NDIS6 「僅限主機」網路。</String> - <String Id="VB_Python">VirtualBox 的 Python 支援。</String> <!----> @@ -75,6 +74,7 @@ <String Id="Only64Bit">此應用程式只能執行在 64 位元的 Windows 系統。 請安裝 [ProductName] 的 32 位元版本!</String> <String Id="SunFound">在此電腦發現舊的 Sun VirtualBox 安裝。 請先解除安裝此套件然後安裝 [ProductName]!</String> <String Id="InnotekFound">在此電腦發現舊的 innotek VirtualBox 安裝。 請先解除安裝此套件然後安裝 [ProductName]!</String> + <String Id="InvalidTargetDir">Invalid installation directory specified! Please use another installation directory to install [ProductName].</String> <!----> @@ -94,6 +94,12 @@ <!----> + <String Id="InvalidTargetDirDlg_Header">Invalid installation directory</String> + <String Id="InvalidTargetDirDlg_Desc1">The chosen installation directory is invalid, as it does not meet the security requirements.</String> + <String Id="InvalidTargetDirDlg_Desc2">Please choose another directory for installing [ProductName].</String> + + <!----> + <String Id="CheckSerialDlg_Header">序號</String> <String Id="CheckSerialDlg_Body">請在以下欄位輸入您的序號。 您可以在 VirtualBox CD 盒內的貼紙找到。</String> <String Id="CheckSerialDlg_Footer">序號輸入完成時,按一下以下「檢查」按鈕。</String> diff --git a/src/VBox/Installer/win/UserInterface.wxi b/src/VBox/Installer/win/UserInterface.wxi index f371cd55..c3bbab13 100644 --- a/src/VBox/Installer/win/UserInterface.wxi +++ b/src/VBox/Installer/win/UserInterface.wxi @@ -206,6 +206,43 @@ </Dialog> + <!-- Shows a dialog which tells the user that the chosen installation directory is invalid and therefore cannot be used. --> + <Dialog Id="VBoxInvalidTargetDirDlg" Width="370" Height="270" Title="[ProductName] !(loc.Setup)" NoMinimize="yes"> + + <!-- The wizard has a bitmap as background. The source is defined as a property below. --> + <Control Id="Bitmap" Type="Bitmap" X="0" Y="0" Width="370" Height="234" TabSkip="no" Text="[DialogBitmap]" /> + + <!-- Title text drawn on the background --> + <Control Id="Title" Type="Text" X="135" Y="20" Width="220" Height="60" Transparent="yes" NoPrefix="yes"> + <Text>{\DlgInvalidSerial}!(loc.InvalidTargetDirDlg_Header)</Text> + </Control> + + <!-- Text saying what we gonna do --> + <Control Id="Description" Type="Text" X="135" Y="70" Width="220" Height="130" Transparent="yes" NoPrefix="yes"> + <Text>!(loc.InvalidTargetDirDlg_Desc1)</Text> + </Control> + + <Control Id="Description2" Type="Text" X="135" Y="95" Width="220" Height="130" Transparent="yes" NoPrefix="yes"> + <Text>!(loc.InvalidTargetDirDlg_Desc2)</Text> + </Control> + + <!-- And a line for looking nice... --> + <Control Id="BottomLine" Type="Line" X="0" Y="234" Width="370" Height="0" /> + + <!-- Build number text drawn left bottom --> + <Control Id="Build" Type="Text" X="20" Y="247" Width="220" Height="10" Transparent="yes" NoPrefix="yes"> + <Text>[Version_text] $(var.Property_Version)</Text> + </Control> + + <Control Id="Back" Type="PushButton" X="236" Y="243" Width="56" Height="17" Default="yes" Text="!(loc.ButtonText_Back)"/> + + <!-- Canceling will bring up a confirmation dialog ('SpawnDialog' attribute) --> + <Control Id="Cancel" Type="PushButton" X="304" Y="243" Width="56" Height="17" Cancel="yes" Text="!(loc.ButtonText_Cancel)"> + <Publish Event="SpawnDialog" Value="VBoxCancelDlg">1</Publish> + </Control> + + </Dialog> + <!-- Dialog used to set another installation path. This is taken from the tutorial template on the web and can also be used for package selection etc. if necessary after some tweaking. --> <Dialog Id="VBoxCustomizeDlg" Width="370" Height="270" Title="[ProductName] !(loc.Setup)" NoMinimize="yes" TrackDiskSpace="yes"> @@ -220,7 +257,7 @@ <Control Id="Text" Type="Text" X="25" Y="55" Width="320" Height="20"> <Text>!(loc.CustomizeDlg_IconTree)</Text> </Control> - <Control Id="Tree" Type="SelectionTree" X="25" Y="85" Width="175" Height="95" Property="_BrowseProperty" + <Control Id="Tree" Type="SelectionTree" X="25" Y="85" Width="175" Height="95" Property="VBOX_TARGET_DIR" Sunken="yes" TabSkip="no" Text="Tree of selections" /> <Control Id="Browse" Type="PushButton" X="304" Y="200" Width="56" Height="17" Text="!(loc.ButtonText_Browse)"> <Publish Event="SelectionBrowse" Value="VBoxBrowseDlg">1</Publish> @@ -465,18 +502,12 @@ <!-- Dialog used to change the installation directory --> <Dialog Id="VBoxBrowseDlg" Width="370" Height="270" Title="[ProductName] !(loc.Setup)" NoMinimize="yes"> - <Control Id="PathEdit" Type="PathEdit" X="84" Y="202" Width="261" Height="18" Property="_BrowseProperty" Indirect="yes" /> - <Control Id="OK" Type="PushButton" X="304" Y="243" Width="56" Height="17" Default="yes" Text="!(loc.ButtonText_OK)"> - <Publish Event="SetTargetPath" Value="[_BrowseProperty]">1</Publish> - <Publish Event="EndDialog" Value="Return">1</Publish> - </Control> - <Control Id="Cancel" Type="PushButton" X="240" Y="243" Width="56" Height="17" Cancel="yes" Text="!(loc.ButtonText_Cancel)"> - <Publish Event="Reset" Value="0">1</Publish> - <Publish Event="EndDialog" Value="Return">1</Publish> - </Control> + <Control Id="PathEdit" Type="PathEdit" X="84" Y="202" Width="261" Height="18" Property="VBOX_TARGET_DIR" Indirect="yes" /> + <Control Id="OK" Type="PushButton" X="304" Y="243" Width="56" Height="17" Default="yes" Text="!(loc.ButtonText_OK)" /> + <Control Id="Cancel" Type="PushButton" X="240" Y="243" Width="56" Height="17" Cancel="yes" Text="!(loc.ButtonText_Cancel)"/> <Control Id="ComboLabel" Type="Text" X="25" Y="58" Width="44" Height="10" TabSkip="no" Text="!(loc.BrowseDlg_LookIn)" /> <Control Id="DirectoryCombo" Type="DirectoryCombo" X="70" Y="55" Width="220" Height="80" - Property="_BrowseProperty" Indirect="yes" Fixed="yes" Remote="yes"> + Property="VBOX_TARGET_DIR" Indirect="yes" Fixed="yes" Remote="yes"> <Subscribe Event="IgnoreChange" Attribute="IgnoreChange" /> </Control> <Control Id="Up" Type="PushButton" X="298" Y="55" Width="19" Height="19" ToolTip="!(loc.BrowseDlg_UpOneLevelTooltip)" Icon="yes" FixedSize="yes" IconSize="16" Text="[FolderUp]"> @@ -487,7 +518,7 @@ <Publish Event="DirectoryListNew" Value="0">1</Publish> </Control> <Control Id="DirectoryList" Type="DirectoryList" X="25" Y="83" Width="320" Height="110" - Property="_BrowseProperty" Sunken="yes" Indirect="yes" TabSkip="no" /> + Property="VBOX_TARGET_DIR" Sunken="yes" Indirect="yes" TabSkip="no" /> <Control Id="PathLabel" Type="Text" X="25" Y="205" Width="59" Height="10" TabSkip="no" Text="!(loc.BrowseDlg_FolderName)" /> <Control Id="BannerBitmap" Type="Bitmap" X="0" Y="0" Width="370" Height="44" TabSkip="no" Text="[BannerBitmap]" /> <Control Id="Description" Type="Text" X="25" Y="23" Width="280" Height="15" Transparent="yes" NoPrefix="yes"> @@ -1177,15 +1208,33 @@ <Publish Dialog="VBoxWrongSerialDlg" Control="Back" Event="NewDialog" Value="VBoxCheckSerialDlg">1</Publish> - <!-- Note: We have to set (1) or unset ({}) the properties first (see order #), as those will be needed for further routing. --> - <Publish Dialog="VBoxCustomizeDlg" Control="Next" Property="VBOX_SHOW_WARN_PYTHONAPI_DLG" Value="1" Order="1"><![CDATA[(&VBoxPython=3) AND (VBOX_PYTHON_DEPS_INSTALLED="0")]]></Publish> - <Publish Dialog="VBoxCustomizeDlg" Control="Next" Property="VBOX_SHOW_WARN_PYTHONAPI_DLG" Value="{}" Order="2"><![CDATA[(&VBoxPython<3)]]></Publish> - <Publish Dialog="VBoxCustomizeDlg" Control="Next" Property="VBOX_SHOW_WARN_DISCONNECTIFACES_DLG" Value="1" Order="3"><![CDATA[&VBoxNetworkFlt=3]]></Publish> - <Publish Dialog="VBoxCustomizeDlg" Control="Next" Property="VBOX_SHOW_WARN_DISCONNECTIFACES_DLG" Value="{}" Order="4"><![CDATA[&VBoxNetworkFlt<3]]></Publish> - <Publish Dialog="VBoxCustomizeDlg" Control="Next" Event="NewDialog" Value="VBoxWarnDisconNetIfacesDlg" Order="10"><![CDATA[VBOX_SHOW_WARN_DISCONNECTIFACES_DLG]]></Publish> - <Publish Dialog="VBoxCustomizeDlg" Control="Next" Event="NewDialog" Value="VBoxWarnPythonDlg" Order="11"><![CDATA[VBOX_SHOW_WARN_PYTHONAPI_DLG AND (NOT VBOX_SHOW_WARN_DISCONNECTIFACES_DLG)]]></Publish> - <Publish Dialog="VBoxCustomizeDlg" Control="Next" Event="NewDialog" Value="VBoxCustomize2Dlg" Order="12"><![CDATA[VBOX_SHOW_CUSTOMIZE2_DLG AND (NOT VBOX_SHOW_WARN_DISCONNECTIFACES_DLG) AND (NOT VBOX_SHOW_WARN_PYTHONAPI_DLG)]]></Publish> - <Publish Dialog="VBoxCustomizeDlg" Control="Next" Event="NewDialog" Value="VBoxVerifyReadyDlg" Order="13"><![CDATA[(NOT VBOX_SHOW_CUSTOMIZE2_DLG) AND (NOT VBOX_SHOW_WARN_DISCONNECTIFACES_DLG) AND (NOT VBOX_SHOW_WARN_PYTHONAPI_DLG)]]></Publish> + <Publish Dialog="VBoxBrowseDlg" Control="OK" Event="SetTargetPath" Value="[VBOX_TARGET_DIR]" Order="1">1</Publish> + <Publish Dialog="VBoxBrowseDlg" Control="OK" Event="EndDialog" Value="Return" Order="2">1</Publish> + <Publish Dialog="VBoxBrowseDlg" Control="Cancel" Event="Reset" Value="0" Order="1">1</Publish> + <Publish Dialog="VBoxBrowseDlg" Control="Cancel" Event="EndDialog" Value="Return" Order="2">1</Publish> + + <Publish Dialog="VBoxInvalidTargetDirDlg" Control="Back" Event="NewDialog" Value="VBoxCustomizeDlg">1</Publish> + + <!-- Note: We have to set (1) or unset ({}) the properties first (see order #), as those will be needed for further routing. + Note2: I'd love to make this easier to read/follow, but this is how Windows Installer XML works for processing all these events, sigh. --> + + <!-- Check if the chosen installation directory turned out to be invalid by calling our installation helper DLL + and performing a custom action. See @bugref{10616} --> + <Publish Dialog="VBoxCustomizeDlg" Control="Next" Event="DoAction" Value="ca_CheckTargetDirPre" Order="1">1</Publish> + <Publish Dialog="VBoxCustomizeDlg" Control="Next" Property="VBOX_SHOW_INVALID_TARGET_DLG" Value="1" Order="2"><![CDATA[VBox_Target_Dir_Is_Valid="0"]]></Publish> + <Publish Dialog="VBoxCustomizeDlg" Control="Next" Property="VBOX_SHOW_INVALID_TARGET_DLG" Value="{}" Order="3"><![CDATA[VBox_Target_Dir_Is_Valid="1"]]></Publish> + <Publish Dialog="VBoxCustomizeDlg" Control="Next" Property="VBOX_SHOW_WARN_PYTHONAPI_DLG" Value="1" Order="4"><![CDATA[(&VBoxPython=3) AND (VBOX_PYTHON_DEPS_INSTALLED="0")]]></Publish> + <Publish Dialog="VBoxCustomizeDlg" Control="Next" Property="VBOX_SHOW_WARN_PYTHONAPI_DLG" Value="{}" Order="5"><![CDATA[(&VBoxPython<3)]]></Publish> + <Publish Dialog="VBoxCustomizeDlg" Control="Next" Property="VBOX_SHOW_WARN_DISCONNECTIFACES_DLG" Value="1" Order="6"><![CDATA[&VBoxNetworkFlt=3]]></Publish> + <Publish Dialog="VBoxCustomizeDlg" Control="Next" Property="VBOX_SHOW_WARN_DISCONNECTIFACES_DLG" Value="{}" Order="7"><![CDATA[&VBoxNetworkFlt<3]]></Publish> + + <!-- Show an error dialog if the chosen installation directory was found to be invalid. See @bugref{10616} --> + <Publish Dialog="VBoxCustomizeDlg" Control="Next" Event="NewDialog" Value="VBoxInvalidTargetDirDlg" Order="10"><![CDATA[VBOX_SHOW_INVALID_TARGET_DLG]]></Publish> + <Publish Dialog="VBoxCustomizeDlg" Control="Next" Event="NewDialog" Value="VBoxWarnDisconNetIfacesDlg" Order="20"><![CDATA[VBOX_SHOW_WARN_DISCONNECTIFACES_DLG and (NOT VBOX_SHOW_INVALID_TARGET_DLG)]]></Publish> + <Publish Dialog="VBoxCustomizeDlg" Control="Next" Event="NewDialog" Value="VBoxWarnPythonDlg" Order="30"><![CDATA[VBOX_SHOW_WARN_PYTHONAPI_DLG AND (NOT VBOX_SHOW_WARN_DISCONNECTIFACES_DLG) AND (NOT VBOX_SHOW_INVALID_TARGET_DLG)]]></Publish> + <!-- Only allow going to the next stage if the chosen installation directory is valid. See @bugref{10616} --> + <Publish Dialog="VBoxCustomizeDlg" Control="Next" Event="NewDialog" Value="VBoxCustomize2Dlg" Order="40"><![CDATA[VBOX_SHOW_CUSTOMIZE2_DLG AND (NOT VBOX_SHOW_WARN_DISCONNECTIFACES_DLG) AND (NOT VBOX_SHOW_WARN_PYTHONAPI_DLG) AND (NOT VBOX_SHOW_INVALID_TARGET_DLG)]]></Publish> + <Publish Dialog="VBoxCustomizeDlg" Control="Next" Event="NewDialog" Value="VBoxVerifyReadyDlg" Order="50"><![CDATA[(NOT VBOX_SHOW_CUSTOMIZE2_DLG) AND (NOT VBOX_SHOW_WARN_DISCONNECTIFACES_DLG) AND (NOT VBOX_SHOW_WARN_PYTHONAPI_DLG)]]></Publish> <Publish Dialog="VBoxCustomizeDlg" Control="Back" Event="NewDialog" Value="VBoxCheckSerialDlg"><![CDATA[VBOX_SHOW_SERIAL_CHECK_DLG]]></Publish> <Publish Dialog="VBoxCustomizeDlg" Control="Back" Event="NewDialog" Value="VBoxLicenseAgreementDlg"><![CDATA[NOT VBOX_SHOW_SERIAL_CHECK_DLG]]></Publish> @@ -1211,6 +1260,7 @@ <?if $(env.VBOX_WITH_CRT_PACKING) = "no" ?> <Custom Action="ca_IsMSCRTInstalled" After="AppSearch" /> <?endif?> + <Custom Action="ca_CheckTargetDirPre" After="AppSearch"/> <!-- Required for launch conditions. See @bugref{10616} --> <Custom Action="ca_OriginalTargetDir" After="FileCost"><![CDATA[(NOT INSTALLDIR) AND (NOT EXISTINGINSTALLDIR)]]></Custom> <Custom Action="ca_DefaultTargetDir" After="FileCost"><![CDATA[NOT Installed AND (NOT INSTALLDIR) AND EXISTINGINSTALLDIR]]></Custom> <Custom Action="ca_IsWindows10" After="CostFinalize" /> diff --git a/src/VBox/Installer/win/VBoxMergeAppCA.wxi b/src/VBox/Installer/win/VBoxMergeAppCA.wxi index ddc29f5e..2a3eef7f 100644 --- a/src/VBox/Installer/win/VBoxMergeAppCA.wxi +++ b/src/VBox/Installer/win/VBoxMergeAppCA.wxi @@ -35,5 +35,11 @@ <CustomAction Id="ca_IsWindows10" BinaryKey="VBoxInstallHelper" DllEntry="IsWindows10" Execute="immediate" Return="ignore" Impersonate="no" /> + <!-- Makes sure we check if the chosen target directory is valid before allowing to install. See @bugref{10616} --> + <CustomAction Id="ca_CheckTargetDirPre" BinaryKey="VBoxInstallHelper" + DllEntry="CheckTargetDir" Execute="immediate" Return="ignore" Impersonate="no" /> + <!-- Makes sure that the target directory we installed into still is valid. Rollback if it isn't. See @bugref{10616} --> + <CustomAction Id="ca_CheckTargetDirPost" BinaryKey="VBoxInstallHelper" + DllEntry="CheckTargetDir" Execute="immediate" Return="check" Impersonate="no" /> </Include> diff --git a/src/VBox/Installer/win/VBoxMergeAppSeq.wxi b/src/VBox/Installer/win/VBoxMergeAppSeq.wxi index b6340cef..6b7c3a1f 100644 --- a/src/VBox/Installer/win/VBoxMergeAppSeq.wxi +++ b/src/VBox/Installer/win/VBoxMergeAppSeq.wxi @@ -30,6 +30,11 @@ <?if $(env.VBOX_WITH_CRT_PACKING) = "no" ?> <Custom Action="ca_IsMSCRTInstalled" After="AppSearch">1</Custom> <?endif?> + <!-- Required for lauch conditions. See @bugref{10616} --> + <Custom Action="ca_CheckTargetDirPre" After="AppSearch"/> + <!-- Check if the installation directory still fits our security requirements after we finalized installation. + See @bugref{10616} --> + <Custom Action="ca_CheckTargetDirPost" After="InstallFinalize"><![CDATA[NOT REMOVE]]></Custom> <Custom Action="ca_IsWindows10" After="FileCost">1</Custom> diff --git a/src/VBox/Installer/win/VirtualBox.wxs b/src/VBox/Installer/win/VirtualBox.wxs index 1e4911cc..beccd815 100644 --- a/src/VBox/Installer/win/VirtualBox.wxs +++ b/src/VBox/Installer/win/VirtualBox.wxs @@ -127,6 +127,11 @@ Installed OR (VBOX_MSCRT_INSTALLED) </Condition> <?endif ?> + <!-- Check if the current INSTALLDIR is valid or not, or if VBox already is installed. + Thight might be handed-in via command line (MSI properties) or through a customized merge module. See @bugref{10616} --> + <Condition Message="!(loc.InvalidTargetDir)"> + Installed OR (VBox_Target_Dir_Is_Valid="1") + </Condition> <!-- Detect old innotek installation --> <!-- Force a manual uninstall of an already installed innotek VirtualBox version first --> diff --git a/src/VBox/Main/include/AudioSettingsImpl.h b/src/VBox/Main/include/AudioSettingsImpl.h index e5ec0b31..d9387165 100644 --- a/src/VBox/Main/include/AudioSettingsImpl.h +++ b/src/VBox/Main/include/AudioSettingsImpl.h @@ -64,6 +64,7 @@ public: // public methods only for internal purposes bool i_canChangeSettings(void); + Machine *i_getMachine(void); void i_onAdapterChanged(IAudioAdapter *pAdapter); void i_onHostDeviceChanged(IHostAudioDevice *pDevice, bool fIsNew, AudioDeviceState_T enmState, IVirtualBoxErrorInfo *pErrInfo); void i_onSettingsChanged(void); diff --git a/src/VBox/Main/src-all/win/VBoxProxyStub.c b/src/VBox/Main/src-all/win/VBoxProxyStub.c index 87125091..63d84b9c 100644 --- a/src/VBox/Main/src-all/win/VBoxProxyStub.c +++ b/src/VBox/Main/src-all/win/VBoxProxyStub.c @@ -2491,7 +2491,7 @@ static void vbpsUpdateWindowsService(VBPSREGSTATE *pState, const WCHAR *pwszVBox NULL /* pwszLoadOrderGroup */, NULL /* pdwTagId */, wszzDependencies, - NULL /* pwszServiceStartName */, + pwszServiceStartName /* pwszServiceStartName */, NULL /* pwszPassword */); if (hService != NULL) { diff --git a/src/VBox/Main/src-client/GuestSessionImplTasks.cpp b/src/VBox/Main/src-client/GuestSessionImplTasks.cpp index 59fbf06c..9a74e050 100644 --- a/src/VBox/Main/src-client/GuestSessionImplTasks.cpp +++ b/src/VBox/Main/src-client/GuestSessionImplTasks.cpp @@ -2969,77 +2969,41 @@ int GuestSessionTaskUpdateAdditions::Run(void) } else { + if (RT_SUCCESS(vrc)) + vrc = setProgress(5); + Utf8Str strUpdateDir; - vrc = setProgress(5); + /* + * Prepare the update directory. + */ if (RT_SUCCESS(vrc)) { - /* Try getting the installed Guest Additions version to know whether we - * can install our temporary Guest Addition data into the original installation - * directory. - * - * Because versions prior to 4.2 had bugs wrt spaces in paths we have to choose - * a different location then. - */ - bool fUseInstallDir = false; - - Utf8Str strAddsVer; - vrc = getGuestProperty(pGuest, "/VirtualBox/GuestAdd/Version", strAddsVer); - if ( RT_SUCCESS(vrc) - && RTStrVersionCompare(strAddsVer.c_str(), "4.2r80329") > 0) - { - fUseInstallDir = true; - } - - if (fUseInstallDir) - { - vrc = getGuestProperty(pGuest, "/VirtualBox/GuestAdd/InstallDir", strUpdateDir); - if (RT_SUCCESS(vrc)) - { - if (strUpdateDir.isNotEmpty()) - { - if (osType == eOSType_Windows) - { - strUpdateDir.findReplace('/', '\\'); - strUpdateDir.append("\\Update\\"); - } - else - strUpdateDir.append("/update/"); - } - /* else Older Guest Additions might not handle this property correctly. */ - } - /* Ditto. */ - } - - /** @todo Set fallback installation directory. Make this a *lot* smarter. Later. */ - if (strUpdateDir.isEmpty()) + /* Note: No fallback to unsafe guest locations! See @bugref{10625}. */ + int vrcGuest; + vrc = pSession->i_fsCreateTemp("VBoxAutoUpdate-XXXXXXXXXXXX", "" /* Use default temp dir */, + true /* fDirectory */, strUpdateDir, 755 /* Mode */, false /* fSecure */, &vrcGuest); + if (RT_SUCCESS(vrc)) { if (osType == eOSType_Windows) - strUpdateDir = "C:\\Temp\\"; + strUpdateDir.append("\\"); else - strUpdateDir = "/tmp/"; - } - } - - /* Create the installation directory. */ - int vrcGuest = VERR_IPE_UNINITIALIZED_STATUS; - if (RT_SUCCESS(vrc)) - { - LogRel(("Guest Additions update directory is: %s\n", strUpdateDir.c_str())); + strUpdateDir.append("/"); - vrc = pSession->i_directoryCreate(strUpdateDir, 755 /* Mode */, DirectoryCreateFlag_Parents, &vrcGuest); - if (RT_FAILURE(vrc)) + LogRel(("Guest Additions update directory is: %s\n", strUpdateDir.c_str())); + } + else { switch (vrc) { case VERR_GSTCTL_GUEST_ERROR: - hrc = setProgressErrorMsg(VBOX_E_IPRT_ERROR, tr("Creating installation directory on guest failed"), + hrc = setProgressErrorMsg(VBOX_E_IPRT_ERROR, tr("Creating update directory on guest failed"), GuestErrorInfo(GuestErrorInfo::Type_Directory, vrcGuest, strUpdateDir.c_str())); break; default: hrc = setProgressErrorMsg(VBOX_E_IPRT_ERROR, - Utf8StrFmt(tr("Creating installation directory \"%s\" on guest failed: %Rrc"), + Utf8StrFmt(tr("Creating update directory \"%s\" on guest failed: %Rrc"), strUpdateDir.c_str(), vrc)); break; } diff --git a/src/VBox/Main/src-global/win/VBoxSDS.cpp b/src/VBox/Main/src-global/win/VBoxSDS.cpp index 6bc7506f..e89bfd7a 100644 --- a/src/VBox/Main/src-global/win/VBoxSDS.cpp +++ b/src/VBox/Main/src-global/win/VBoxSDS.cpp @@ -104,6 +104,7 @@ #include <iprt/buildconfig.h> #include <iprt/dir.h> #include <iprt/env.h> +#include <iprt/err.h> #include <iprt/getopt.h> #include <iprt/initterm.h> #include <iprt/path.h> @@ -911,10 +912,14 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine } /* - * Default log location is %ProgramData%\VirtualBox\VBoxSDS.log, falling back - * on %_CWD%\VBoxSDS.log (where _CWD typicaly is 'C:\Windows\System32'). + * Default log location (LOGDIR) is %APPDATA%\VirtualBox\VBoxSDS.log. * - * We change the current directory to %ProgramData%\VirtualBox\ if possible. + * When running VBoxSDS as a regular user, LOGDIR typically will be 'C:\Users\<User>\AppData\Roaming\VirtualBox\'. + * When running VBoxSDS as a service (via SCM), LOGDIR typically will be 'C:\Windows\System32\config\systemprofile\AppData\Roaming\VirtualBox\'. + * + * We change the current directory to LOGDIR if possible. + * + * See @bugref{10632}. * * We only create the log file when running VBoxSDS normally, but not * when registering/unregistering, at least for now. @@ -924,14 +929,19 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine char szLogFile[RTPATH_MAX]; if (!pszLogFile || !*pszLogFile) { - WCHAR wszAppData[MAX_PATH + 16]; - if (SHGetSpecialFolderPathW(NULL, wszAppData, CSIDL_COMMON_APPDATA, TRUE /*fCreate*/)) + WCHAR wszSpecialFolder[MAX_PATH + 16]; + if (SHGetSpecialFolderPathW(NULL, wszSpecialFolder, CSIDL_APPDATA, TRUE /*fCreate*/)) { char *pszConv = szLogFile; - vrc = RTUtf16ToUtf8Ex(wszAppData, RTSTR_MAX, &pszConv, sizeof(szLogFile) - 12, NULL); + vrc = RTUtf16ToUtf8Ex(wszSpecialFolder, RTSTR_MAX, &pszConv, sizeof(szLogFile) - 12, NULL); } - else - vrc = RTEnvGetUtf8("ProgramData", szLogFile, sizeof(szLogFile) - sizeof("VBoxSDS.log"), NULL); + else if (SHGetSpecialFolderPathW(NULL, wszSpecialFolder, CSIDL_SYSTEM, TRUE /*fCreate*/)) + { + char *pszConv = szLogFile; + vrc = RTUtf16ToUtf8Ex(wszSpecialFolder, RTSTR_MAX, &pszConv, sizeof(szLogFile) - 12, NULL); + } + else /* Note! No fallback to environment variables or such. See @bugref{10632}. */ + vrc = VERR_PATH_NOT_FOUND; if (RT_SUCCESS(vrc)) { vrc = RTPathAppend(szLogFile, sizeof(szLogFile), "VirtualBox\\"); @@ -942,14 +952,14 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine vrc = RTDirCreate(szLogFile, 0755, RTDIRCREATE_FLAGS_NOT_CONTENT_INDEXED_DONT_SET); if (RT_SUCCESS(vrc)) { - /* Change into it. */ - RTPathSetCurrent(szLogFile); + /* Change into it. + * If this fails, better don't continue, as there might be something fishy. */ + vrc = RTPathSetCurrent(szLogFile); + if (RT_SUCCESS(vrc)) + vrc = RTStrCat(szLogFile, sizeof(szLogFile), "VBoxSDS.log"); } } } - if (RT_FAILURE(vrc)) /* ignore any failure above */ - szLogFile[0] = '\0'; - vrc = RTStrCat(szLogFile, sizeof(szLogFile), "VBoxSDS.log"); if (RT_FAILURE(vrc)) return RTMsgErrorExit(RTEXITCODE_FAILURE, "Failed to construct release log filename: %Rrc", vrc); pszLogFile = szLogFile; diff --git a/src/VBox/Main/src-global/win/VirtualBoxSDSImpl.cpp b/src/VBox/Main/src-global/win/VirtualBoxSDSImpl.cpp index 1b98c629..1db8fa61 100644 --- a/src/VBox/Main/src-global/win/VirtualBoxSDSImpl.cpp +++ b/src/VBox/Main/src-global/win/VirtualBoxSDSImpl.cpp @@ -609,7 +609,7 @@ STDMETHODIMP VirtualBoxSDS::LaunchVMProcess(IN_BSTR aMachine, IN_BSTR aComment, else { hrc = VBOX_E_IPRT_ERROR; - LogRel(("VirtualBoxSDS::LaunchVMProcess: launchVM failed: %Rhrc (%Rrc)\n", hrc)); + LogRel(("VirtualBoxSDS::LaunchVMProcess: launchVM failed: %Rhrc (%Rrc)\n", hrc, vrc)); } } catch (...) diff --git a/src/VBox/Main/src-server/AudioAdapterImpl.cpp b/src/VBox/Main/src-server/AudioAdapterImpl.cpp index 66e40c6e..5c388771 100644 --- a/src/VBox/Main/src-server/AudioAdapterImpl.cpp +++ b/src/VBox/Main/src-server/AudioAdapterImpl.cpp @@ -233,6 +233,10 @@ HRESULT AudioAdapter::setEnabled(BOOL aEnabled) AutoCaller autoCaller(this); if (FAILED(autoCaller.hrc())) return autoCaller.hrc(); + /* the machine needs to be mutable */ + AutoMutableStateDependency adep(m->pParent->i_getMachine()); + if (FAILED(adep.hrc())) return adep.hrc(); + AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); if (m->bd->fEnabled != RT_BOOL(aEnabled)) @@ -241,7 +245,7 @@ HRESULT AudioAdapter::setEnabled(BOOL aEnabled) m->bd->fEnabled = RT_BOOL(aEnabled); alock.release(); - m->pParent->i_onSettingsChanged(); // mParent is const, needs no locking + m->pParent->i_onSettingsChanged(); // m->pParent is const, needs no locking m->pParent->i_onAdapterChanged(this); } @@ -265,6 +269,10 @@ HRESULT AudioAdapter::setEnabledIn(BOOL aEnabled) AutoCaller autoCaller(this); if (FAILED(autoCaller.hrc())) return autoCaller.hrc(); + /* the machine needs to be mutable */ + AutoMutableOrSavedOrRunningStateDependency adep(m->pParent->i_getMachine()); + if (FAILED(adep.hrc())) return adep.hrc(); + AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); if (RT_BOOL(aEnabled) != m->bd->fEnabledIn) @@ -274,7 +282,7 @@ HRESULT AudioAdapter::setEnabledIn(BOOL aEnabled) alock.release(); - m->pParent->i_onSettingsChanged(); // mParent is const, needs no locking + m->pParent->i_onSettingsChanged(); // m->pParent is const, needs no locking m->pParent->i_onAdapterChanged(this); } @@ -298,6 +306,10 @@ HRESULT AudioAdapter::setEnabledOut(BOOL aEnabled) AutoCaller autoCaller(this); if (FAILED(autoCaller.hrc())) return autoCaller.hrc(); + /* the machine needs to be mutable */ + AutoMutableOrSavedOrRunningStateDependency adep(m->pParent->i_getMachine()); + if (FAILED(adep.hrc())) return adep.hrc(); + AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); if (RT_BOOL(aEnabled) != m->bd->fEnabledOut) @@ -307,7 +319,7 @@ HRESULT AudioAdapter::setEnabledOut(BOOL aEnabled) alock.release(); - m->pParent->i_onSettingsChanged(); // mParent is const, needs no locking + m->pParent->i_onSettingsChanged(); // m->pParent is const, needs no locking m->pParent->i_onAdapterChanged(this); } @@ -331,6 +343,10 @@ HRESULT AudioAdapter::setAudioDriver(AudioDriverType_T aAudioDriver) AutoCaller autoCaller(this); if (FAILED(autoCaller.hrc())) return autoCaller.hrc(); + /* the machine needs to be mutable */ + AutoMutableOrSavedStateDependency adep(m->pParent->i_getMachine()); + if (FAILED(adep.hrc())) return adep.hrc(); + AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); HRESULT hrc = S_OK; @@ -344,7 +360,7 @@ HRESULT AudioAdapter::setAudioDriver(AudioDriverType_T aAudioDriver) alock.release(); - m->pParent->i_onSettingsChanged(); // mParent is const, needs no locking + m->pParent->i_onSettingsChanged(); // m->pParent is const, needs no locking } else { @@ -373,6 +389,10 @@ HRESULT AudioAdapter::setAudioController(AudioControllerType_T aAudioController) AutoCaller autoCaller(this); if (FAILED(autoCaller.hrc())) return autoCaller.hrc(); + /* the machine needs to be mutable */ + AutoMutableStateDependency adep(m->pParent->i_getMachine()); + if (FAILED(adep.hrc())) return adep.hrc(); + AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); HRESULT hrc = S_OK; @@ -411,7 +431,7 @@ HRESULT AudioAdapter::setAudioController(AudioControllerType_T aAudioController) alock.release(); - m->pParent->i_onSettingsChanged(); // mParent is const, needs no locking + m->pParent->i_onSettingsChanged(); // m->pParent is const, needs no locking } } @@ -435,6 +455,10 @@ HRESULT AudioAdapter::setAudioCodec(AudioCodecType_T aAudioCodec) AutoCaller autoCaller(this); if (FAILED(autoCaller.hrc())) return autoCaller.hrc(); + /* the machine needs to be mutable */ + AutoMutableStateDependency adep(m->pParent->i_getMachine()); + if (FAILED(adep.hrc())) return adep.hrc(); + AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); HRESULT hrc = S_OK; @@ -484,7 +508,7 @@ HRESULT AudioAdapter::setAudioCodec(AudioCodecType_T aAudioCodec) alock.release(); - m->pParent->i_onSettingsChanged(); // mParent is const, needs no locking + m->pParent->i_onSettingsChanged(); // m->pParent is const, needs no locking } return hrc; @@ -530,6 +554,10 @@ HRESULT AudioAdapter::setProperty(const com::Utf8Str &aKey, const com::Utf8Str & AutoCaller autoCaller(this); if (FAILED(autoCaller.hrc())) return autoCaller.hrc(); + /* the machine needs to be mutable */ + AutoMutableStateDependency adep(m->pParent->i_getMachine()); + if (FAILED(adep.hrc())) return adep.hrc(); + AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS); /* Generic properties processing. diff --git a/src/VBox/Main/src-server/AudioSettingsImpl.cpp b/src/VBox/Main/src-server/AudioSettingsImpl.cpp index b7736f1f..851fea77 100644 --- a/src/VBox/Main/src-server/AudioSettingsImpl.cpp +++ b/src/VBox/Main/src-server/AudioSettingsImpl.cpp @@ -247,6 +247,16 @@ bool AudioSettings::i_canChangeSettings(void) } /** + * Returns a (weak) pointer of the audio setting's machine object. + * + * @returns Wweak pointer of the audio setting's machine object. + */ +Machine *AudioSettings::i_getMachine(void) +{ + return m->pMachine; // m->pMachine is const, needs no locking +} + +/** * Gets called when the machine object needs to know that audio adapter settings * have been changed. * @@ -255,7 +265,7 @@ bool AudioSettings::i_canChangeSettings(void) void AudioSettings::i_onAdapterChanged(IAudioAdapter *pAdapter) { AssertPtrReturnVoid(pAdapter); - m->pMachine->i_onAudioAdapterChange(pAdapter); // mParent is const, needs no locking + m->pMachine->i_onAudioAdapterChange(pAdapter); // m->pMachine is const, needs no locking } /** @@ -271,7 +281,7 @@ void AudioSettings::i_onHostDeviceChanged(IHostAudioDevice *pDevice, bool fIsNew, AudioDeviceState_T enmState, IVirtualBoxErrorInfo *pErrInfo) { AssertPtrReturnVoid(pDevice); - m->pMachine->i_onHostAudioDeviceChange(pDevice, fIsNew, enmState, pErrInfo); // mParent is const, needs no locking + m->pMachine->i_onHostAudioDeviceChange(pDevice, fIsNew, enmState, pErrInfo); // m->pMachine is const, needs no locking } /** diff --git a/src/VBox/Main/webservice/vboxweb.cpp b/src/VBox/Main/webservice/vboxweb.cpp index eb1c44a0..e3052600 100644 --- a/src/VBox/Main/webservice/vboxweb.cpp +++ b/src/VBox/Main/webservice/vboxweb.cpp @@ -139,7 +139,7 @@ static int g_iWatchdogCheckInterval = 5; static const char *g_pcszBindToHost = NULL; // host; NULL = localhost static unsigned int g_uBindToPort = 18083; // port -static unsigned int g_uBacklog = 100; // backlog = max queue size for requests +static unsigned int g_uBacklog = 100; // backlog = max queue size for connections #ifdef WITH_OPENSSL static bool g_fSSL = false; // if SSL is enabled @@ -306,7 +306,7 @@ static void DisplayHelp() break; case 'k': - pcszDescr = "Maximum number of requests before a socket will be closed (100)."; + pcszDescr = "Maximum number of requests before a connection will be closed (100)."; break; case 'A': @@ -361,30 +361,13 @@ public: * Constructor. Creates the new thread and makes it call process() for processing the queue. * @param u Thread number. (So we can count from 1 and be readable.) * @param q SoapQ instance which has the queue to process. - * @param soap struct soap instance from main() which we copy here. */ SoapThread(size_t u, - SoapQ &q, - const struct soap *soap) + SoapQ &q) : m_u(u), - m_strThread(com::Utf8StrFmt("SQW%02d", m_u)), m_pQ(&q) { - // make a copy of the soap struct for the new thread - m_soap = soap_copy(soap); - m_soap->fget = fnHttpGet; - - /* The soap.max_keep_alive value can be set to the maximum keep-alive calls allowed, - * which is important to avoid a client from holding a thread indefinitely. - * http://www.cs.fsu.edu/~engelen/soapdoc2.html#sec:keepalive - * - * Strings with 8-bit content can hold ASCII (default) or UTF8. The latter is - * possible by enabling the SOAP_C_UTFSTRING flag. - */ - soap_set_omode(m_soap, SOAP_IO_KEEPALIVE | SOAP_C_UTFSTRING); - soap_set_imode(m_soap, SOAP_IO_KEEPALIVE | SOAP_C_UTFSTRING); - m_soap->max_keep_alive = g_cMaxKeepAlive; - + m_strThread = com::Utf8StrFmt("SQW%02d", m_u); int vrc = RTThreadCreate(&m_pThread, fntWrapper, this, // pvUser @@ -431,7 +414,6 @@ public: size_t m_u; // thread number com::Utf8Str m_strThread; // thread name ("SoapQWrkXX") SoapQ *m_pQ; // the single SOAP queue that all the threads service - struct soap *m_soap; // copy of the soap structure for this thread (from soap_copy()) RTTHREAD m_pThread; // IPRT thread struct for this thread }; @@ -446,11 +428,9 @@ public: /** * Constructor. Creates the soap queue. - * @param pSoap */ - SoapQ(const struct soap *pSoap) - : m_soap(pSoap), - m_mutex(util::LOCKCLASS_OBJECTSTATE), // lowest lock order, no other may be held while this is held + SoapQ() + : m_mutex(util::LOCKCLASS_OBJECTSTATE), // lowest lock order, no other may be held while this is held m_cIdleThreads(0) { RTSemEventMultiCreate(&m_event); @@ -474,16 +454,29 @@ public: } RTSemEventMultiDestroy(m_event); + + while (!m_llSocketsQ.empty()) + { + struct soap *pSoap = m_llSocketsQ.front(); + m_llSocketsQ.pop_front(); + + if (pSoap == NULL || !soap_valid_socket(pSoap->socket)) + continue; + + soap_destroy(pSoap); // clean up class instances + soap_end(pSoap); // clean up everything and close socket + soap_free(pSoap); // free soap connection + } } /** - * Adds the given socket to the SOAP queue and posts the + * Adds the given soap connection to the SOAP queue and posts the * member event sem to wake up the workers. Called on the main thread - * whenever a socket has work to do. Creates a new SOAP thread on the + * whenever a connection comes in. Creates a new SOAP thread on the * first call or when all existing threads are busy. - * @param s Socket from soap_accept() which has work to do. + * @param pSoap connection */ - size_t add(SOAP_SOCKET s) + size_t add(const struct soap *pSoap) { size_t cItems; util::AutoWriteLock qlock(m_mutex COMMA_LOCKVAL_SRC_POS); @@ -496,17 +489,16 @@ public: ) { SoapThread *pst = new SoapThread(m_llAllThreads.size() + 1, - *this, - m_soap); + *this); m_llAllThreads.push_back(pst); util::AutoWriteLock thrLock(g_pThreadsLockHandle COMMA_LOCKVAL_SRC_POS); g_mapThreads[pst->m_pThread] = com::Utf8StrFmt("[%3u]", pst->m_u); ++m_cIdleThreads; } - // enqueue the socket of this connection and post eventsem so that - // one of the threads (possibly the one just created) can pick it up - m_llSocketsQ.push_back(s); + // enqueue this connection and post eventsem so that one of the threads + // (possibly the one just created) can pick it up + m_llSocketsQ.push_back(soap_copy(pSoap)); cItems = m_llSocketsQ.size(); qlock.release(); @@ -518,14 +510,14 @@ public: /** * Blocks the current thread until work comes in; then returns - * the SOAP socket which has work to do. This reduces m_cIdleThreads + * the SOAP connection which has work to do. This reduces m_cIdleThreads * by one, and the caller MUST call done() when it's done processing. * Called from the worker threads. * @param cIdleThreads out: no. of threads which are currently idle (not counting the caller) * @param cThreads out: total no. of SOAP threads running * @return */ - SOAP_SOCKET get(size_t &cIdleThreads, size_t &cThreads) + struct soap *get(size_t &cIdleThreads, size_t &cThreads) { while (g_fKeepRunning) { @@ -538,7 +530,7 @@ public: util::AutoWriteLock qlock(m_mutex COMMA_LOCKVAL_SRC_POS); if (!m_llSocketsQ.empty()) { - SOAP_SOCKET socket = m_llSocketsQ.front(); + struct soap *pSoap = m_llSocketsQ.front(); m_llSocketsQ.pop_front(); cIdleThreads = --m_cIdleThreads; cThreads = m_llAllThreads.size(); @@ -551,12 +543,12 @@ public: qlock.release(); - return socket; + return pSoap; } // nothing to do: keep looping } - return SOAP_INVALID_SOCKET; + return NULL; } /** @@ -571,7 +563,7 @@ public: /** * To be called by a worker thread when signing off, i.e. no longer - * willing to process requests. + * willing to process SOAP connections. */ void signoff(SoapThread *th) { @@ -587,8 +579,6 @@ public: } } - const struct soap *m_soap; // soap structure created by main(), passed to constructor - util::WriteLockHandle m_mutex; RTSEMEVENTMULTI m_event; // posted by add(), blocked on by get() @@ -596,15 +586,15 @@ public: size_t m_cIdleThreads; // threads which are currently idle (statistics) // A std::list abused as a queue; this contains the actual jobs to do, - // each int being a socket from soap_accept() - std::list<SOAP_SOCKET> m_llSocketsQ; + // each entry being a connection from soap_accept() passed through SoapQ::add. + std::list<struct soap *> m_llSocketsQ; }; /** * Thread function for each of the SOAP queue worker threads. This keeps * running, blocks on the event semaphore in SoapThread.SoapQ and picks - * up a socket from the queue therein, which has been put there by - * beginProcessing(). + * up a connection from the queue therein, which has been put there by + * SoapQ::add(). */ void SoapThread::process() { @@ -612,39 +602,54 @@ void SoapThread::process() while (g_fKeepRunning) { - // wait for a socket to arrive on the queue + // wait for a job to arrive on the queue size_t cIdleThreads = 0, cThreads = 0; - m_soap->socket = m_pQ->get(cIdleThreads, cThreads); + struct soap *pSoap = m_pQ->get(cIdleThreads, cThreads); - if (!soap_valid_socket(m_soap->socket)) + if (pSoap == NULL || !soap_valid_socket(pSoap->socket)) continue; + pSoap->fget = fnHttpGet; + + /* The soap.max_keep_alive value can be set to the maximum keep-alive calls allowed, + * which is important to avoid a client from holding a thread indefinitely. + * http://www.cs.fsu.edu/~engelen/soapdoc2.html#sec:keepalive + * + * Strings with 8-bit content can hold ASCII (default) or UTF8. The latter is + * possible by enabling the SOAP_C_UTFSTRING flag. + */ + soap_set_omode(pSoap, SOAP_IO_KEEPALIVE | SOAP_C_UTFSTRING); + soap_set_imode(pSoap, SOAP_IO_KEEPALIVE | SOAP_C_UTFSTRING); + pSoap->max_keep_alive = g_cMaxKeepAlive; + LogRel(("Processing connection from IP=%RTnaipv4 socket=%d (%d out of %d threads idle)\n", - RT_H2N_U32(m_soap->ip), m_soap->socket, cIdleThreads, cThreads)); + RT_H2N_U32(pSoap->ip), pSoap->socket, cIdleThreads, cThreads)); // Ensure that we don't get stuck indefinitely for connections using // keepalive, otherwise stale connections tie up worker threads. - m_soap->send_timeout = 60; - m_soap->recv_timeout = 60; + pSoap->send_timeout = 60; + pSoap->recv_timeout = 60; // Limit the maximum SOAP request size to a generous amount, just to // be on the safe side (SOAP is quite wordy when representing arrays, // and some API uses need to deal with large arrays). Good that binary // data is no longer represented by byte arrays... - m_soap->recv_maxlength = _16M; + pSoap->recv_maxlength = _16M; // process the request; this goes into the COM code in methodmaps.cpp + do { #ifdef WITH_OPENSSL - if (g_fSSL && soap_ssl_accept(m_soap)) + if (g_fSSL && soap_ssl_accept(pSoap)) { - WebLogSoapError(m_soap); + WebLogSoapError(pSoap); break; } #endif /* WITH_OPENSSL */ - soap_serve(m_soap); + soap_serve(pSoap); } while (0); - soap_destroy(m_soap); // clean up class instances - soap_end(m_soap); // clean up everything and close socket + soap_destroy(pSoap); // clean up class instances + soap_end(pSoap); // clean up everything and close connection + soap_free(pSoap); // free soap connection // tell the queue we're idle again m_pQ->done(); @@ -908,6 +913,7 @@ static void doQueuesLoop() } #endif /* WITH_OPENSSL */ + soap.accept_timeout = 60; soap.bind_flags |= SO_REUSEADDR; // avoid EADDRINUSE on bind() @@ -915,7 +921,7 @@ static void doQueuesLoop() m = soap_bind(&soap, g_pcszBindToHost ? g_pcszBindToHost : "localhost", // safe default host g_uBindToPort, // port - g_uBacklog); // backlog = max queue size for requests + g_uBacklog); // backlog = max queue size for connections if (m == SOAP_INVALID_SOCKET) WebLogSoapError(&soap); else @@ -930,65 +936,30 @@ static void doQueuesLoop() g_uBindToPort, pszSsl, m)); // initialize thread queue, mutex and eventsem - g_pSoapQ = new SoapQ(&soap); + g_pSoapQ = new SoapQ(); uint64_t cAccepted = 1; while (g_fKeepRunning) { - struct timeval timeout; - fd_set ReadFds, WriteFds, XcptFds; - int rv; - for (;;) - { - timeout.tv_sec = 60; - timeout.tv_usec = 0; - FD_ZERO(&ReadFds); - FD_SET(soap.master, &ReadFds); - FD_ZERO(&WriteFds); - FD_SET(soap.master, &WriteFds); - FD_ZERO(&XcptFds); - FD_SET(soap.master, &XcptFds); - rv = select((int)soap.master + 1, &ReadFds, &WriteFds, &XcptFds, &timeout); - if (rv > 0) - break; // work is waiting - if (rv == 0) - continue; // timeout, not necessary to bother gsoap - // r < 0, errno -#if GSOAP_VERSION >= 208103 - if (soap_socket_errno == SOAP_EINTR) -#else - if (soap_socket_errno(soap.master) == SOAP_EINTR) -#endif - rv = 0; // re-check if we should terminate - break; - } - if (rv == 0) - continue; - - // call gSOAP to handle incoming SOAP connection - soap.accept_timeout = -1; // 1usec timeout, actual waiting is above s = soap_accept(&soap); if (!soap_valid_socket(s)) { - if (soap.errnum) + if (soap.errnum != SOAP_EINTR) WebLogSoapError(&soap); continue; } - // add the socket to the queue and tell worker threads to + // add the connection to the queue and tell worker threads to // pick up the job - size_t cItemsOnQ = g_pSoapQ->add(s); - LogRel(("Request %llu on socket %d queued for processing (%d items on Q)\n", cAccepted, s, cItemsOnQ)); + size_t cItemsOnQ = g_pSoapQ->add(&soap); + LogRel(("Connection %llu on socket %d queued for processing (%d items on Q)\n", cAccepted, s, cItemsOnQ)); cAccepted++; } delete g_pSoapQ; g_pSoapQ = NULL; - LogRel(("ending SOAP request handling\n")); - - delete g_pSoapQ; - g_pSoapQ = NULL; + LogRel(("Ending SOAP connection handling\n")); } soap_done(&soap); // close master socket and detach environment @@ -1001,7 +972,7 @@ static void doQueuesLoop() /** * Thread function for the "queue pumper" thread started from main(). This implements - * the loop that takes SOAP calls from HTTP and serves them by handing sockets to the + * the loop that takes SOAP calls from HTTP and serves them by handing connections to the * SOAP queue worker threads. */ static DECLCALLBACK(int) fntQPumper(RTTHREAD hThreadSelf, void *pvUser) diff --git a/src/VBox/Main/webservice/websrv-python.xsl b/src/VBox/Main/webservice/websrv-python.xsl index c49677b5..c49677b5 100644..100755 --- a/src/VBox/Main/webservice/websrv-python.xsl +++ b/src/VBox/Main/webservice/websrv-python.xsl diff --git a/src/VBox/Runtime/common/misc/reqpool.cpp b/src/VBox/Runtime/common/misc/reqpool.cpp index 1489c5b7..594289c6 100644 --- a/src/VBox/Runtime/common/misc/reqpool.cpp +++ b/src/VBox/Runtime/common/misc/reqpool.cpp @@ -395,6 +395,7 @@ static DECLCALLBACK(int) rtReqPoolThreadProc(RTTHREAD hThreadSelf, void *pvArg) if (pReq) { Assert(RTListIsEmpty(&pThread->IdleNode)); /* Must not be in the idle list. */ + ASMAtomicDecU32(&pPool->cIdleThreads); /* Was already marked as idle above. */ RTCritSectLeave(&pPool->CritSect); rtReqPoolThreadProcessRequest(pPool, pThread, pReq); @@ -437,7 +438,10 @@ static DECLCALLBACK(int) rtReqPoolThreadProc(RTTHREAD hThreadSelf, void *pvArg) { uint64_t cNsIdle = RTTimeNanoTS() - pThread->uIdleNanoTs; if (cNsIdle >= pPool->cNsMinIdle) + { + ASMAtomicDecU32(&pPool->cIdleThreads); /* Was already marked as idle above. */ return rtReqPoolThreadExit(pPool, pThread, true /*fLocked*/); + } } if (RTListIsEmpty(&pThread->IdleNode)) @@ -578,7 +582,7 @@ DECLHIDDEN(void) rtReqPoolSubmit(PRTREQPOOLINT pPool, PRTREQINT pReq) * If there is an incoming worker thread already or we've reached the * maximum number of worker threads, we're done. */ - if ( pPool->cIdleThreads > 0 + if ( pPool->cIdleThreads >= pPool->cCurPendingRequests || pPool->cCurThreads >= pPool->cMaxThreads) { RTCritSectLeave(&pPool->CritSect); diff --git a/src/VBox/Runtime/common/path/RTPathGlob.cpp b/src/VBox/Runtime/common/path/RTPathGlob.cpp index 46a634b2..16527527 100644 --- a/src/VBox/Runtime/common/path/RTPathGlob.cpp +++ b/src/VBox/Runtime/common/path/RTPathGlob.cpp @@ -486,7 +486,7 @@ static DECLCALLBACK(int) rtPathVarQuery_Path(uint32_t iItem, char *pszBuf, size_ #endif if (rc == VERR_BUFFER_OVERFLOW) { - for (uint32_t iTry = 0; iTry < 10; iTry++) + for (uint32_t iTry = 0;; iTry++) { size_t cbPathBuf = RT_ALIGN_Z(cchActual + 1 + 64 * iTry, 64); pszPathFree = (char *)RTMemTmpAlloc(cbPathBuf); @@ -495,6 +495,8 @@ static DECLCALLBACK(int) rtPathVarQuery_Path(uint32_t iItem, char *pszBuf, size_ break; RTMemTmpFree(pszPathFree); AssertReturn(cchActual >= cbPathBuf, VERR_INTERNAL_ERROR_3); + if (iTry >= 9) + return rc; } pszPath = pszPathFree; } diff --git a/src/VBox/Runtime/r0drv/linux/memobj-r0drv-linux.c b/src/VBox/Runtime/r0drv/linux/memobj-r0drv-linux.c index 8342fbf8..70c5e3dc 100644 --- a/src/VBox/Runtime/r0drv/linux/memobj-r0drv-linux.c +++ b/src/VBox/Runtime/r0drv/linux/memobj-r0drv-linux.c @@ -144,7 +144,8 @@ typedef struct RTR0MEMOBJLNX /** The pages in the apPages array. */ size_t cPages; /** Array of struct page pointers. (variable size) */ - struct page *apPages[1]; + RT_FLEXIBLE_ARRAY_EXTENSION + struct page *apPages[RT_FLEXIBLE_ARRAY]; } RTR0MEMOBJLNX; /** Pointer to the linux memory object. */ typedef RTR0MEMOBJLNX *PRTR0MEMOBJLNX; @@ -215,9 +216,21 @@ static pgprot_t rtR0MemObjLinuxConvertProt(unsigned fProt, bool fKernel) #if defined(RT_ARCH_X86) || defined(RT_ARCH_AMD64) if (fKernel) { +# if RTLNX_VER_MIN(6,6,0) + /* In kernel 6.6 mk_pte() macro was fortified with additional + * check which does not allow to use our custom mask anymore + * (see kernel commit ae1f05a617dcbc0a732fbeba0893786cd009536c). + * For this particular mapping case, an existing mask PAGE_KERNEL_ROX + * can be used instead. PAGE_KERNEL_ROX was introduced in + * kernel 5.8, however, lets apply it for kernels 6.6 and newer + * to be on a safe side. + */ + return PAGE_KERNEL_ROX; +# else pgprot_t fPg = MY_PAGE_KERNEL_EXEC; pgprot_val(fPg) &= ~_PAGE_RW; return fPg; +# endif } return PAGE_READONLY_EXEC; #else @@ -1174,7 +1187,11 @@ RTDECL(struct page *) rtR0MemObjLinuxVirtToPage(void *pv) u.Four = *p4d_offset(&u.Global, ulAddr); if (RT_UNLIKELY(p4d_none(u.Four))) return NULL; +# if RTLNX_VER_MIN(5,6,0) + if (p4d_leaf(u.Four)) +# else if (p4d_large(u.Four)) +# endif { pPage = p4d_page(u.Four); AssertReturn(pPage, NULL); @@ -1190,7 +1207,11 @@ RTDECL(struct page *) rtR0MemObjLinuxVirtToPage(void *pv) if (RT_UNLIKELY(pud_none(u.Upper))) return NULL; # if RTLNX_VER_MIN(2,6,25) +# if RTLNX_VER_MIN(5,6,0) + if (pud_leaf(u.Upper)) +# else if (pud_large(u.Upper)) +# endif { pPage = pud_page(u.Upper); AssertReturn(pPage, NULL); @@ -1206,7 +1227,11 @@ RTDECL(struct page *) rtR0MemObjLinuxVirtToPage(void *pv) if (RT_UNLIKELY(pmd_none(u.Middle))) return NULL; #if RTLNX_VER_MIN(2,6,0) +# if RTLNX_VER_MIN(5,6,0) + if (pmd_leaf(u.Middle)) +# else if (pmd_large(u.Middle)) +# endif { pPage = pmd_page(u.Middle); AssertReturn(pPage, NULL); diff --git a/src/VBox/Runtime/r3/win/process-win.cpp b/src/VBox/Runtime/r3/win/process-win.cpp index 18ed9ab0..8f84d231 100644 --- a/src/VBox/Runtime/r3/win/process-win.cpp +++ b/src/VBox/Runtime/r3/win/process-win.cpp @@ -730,7 +730,7 @@ static bool rtProcWinFindTokenByProcess(const char * const *papszNames, PSID pSi for (size_t i = 0; papszNames[i] && !fFound; i++) { PROCESSENTRY32W ProcEntry; - ProcEntry.dwSize = sizeof(PROCESSENTRY32); + ProcEntry.dwSize = sizeof(ProcEntry); ProcEntry.szExeFile[0] = '\0'; if (g_pfnProcess32FirstW(hSnap, &ProcEntry)) { diff --git a/src/VBox/Runtime/r3/xml.cpp b/src/VBox/Runtime/r3/xml.cpp index a6661760..f96d45f5 100644 --- a/src/VBox/Runtime/r3/xml.cpp +++ b/src/VBox/Runtime/r3/xml.cpp @@ -1856,12 +1856,20 @@ static void xmlParserBaseGenericError(void *pCtx, const char *pszMsg, ...) RT_NO va_end(args); } +#if LIBXML_VERSION >= 21206 +static void xmlStructuredErrorFunc(void *userData, const xmlError *error) RT_NOTHROW_DEF +{ + NOREF(userData); + NOREF(error); +} +#else static void xmlParserBaseStructuredError(void *pCtx, xmlErrorPtr error) RT_NOTHROW_DEF { NOREF(pCtx); /* we expect that there is always a trailing NL */ LogRel(("XML error at '%s' line %d: %s", error->file, error->line, error->message)); } +#endif XmlParserBase::XmlParserBase() { @@ -1870,7 +1878,11 @@ XmlParserBase::XmlParserBase() throw std::bad_alloc(); /* per-thread so it must be here */ xmlSetGenericErrorFunc(NULL, xmlParserBaseGenericError); +#if LIBXML_VERSION >= 21206 + xmlSetStructuredErrorFunc(NULL, xmlStructuredErrorFunc); +#else xmlSetStructuredErrorFunc(NULL, xmlParserBaseStructuredError); +#endif } XmlParserBase::~XmlParserBase() @@ -1931,7 +1943,7 @@ void XmlMemParser::read(const void *pvBuf, size_t cbSize, pcszFilename, NULL, // encoding = auto options))) - throw XmlError(xmlCtxtGetLastError(m_ctxt)); + throw XmlError((xmlErrorPtr)xmlCtxtGetLastError(m_ctxt)); doc.refreshInternals(); } @@ -2191,7 +2203,7 @@ void XmlFileParser::read(const RTCString &strFilename, pcszFilename, NULL, // encoding = auto options))) - throw XmlError(xmlCtxtGetLastError(m_ctxt)); + throw XmlError((xmlErrorPtr)xmlCtxtGetLastError(m_ctxt)); doc.refreshInternals(); } diff --git a/src/VBox/VMM/VMMAll/CPUMAllMsrs.cpp b/src/VBox/VMM/VMMAll/CPUMAllMsrs.cpp index 29a4e52d..ab8ba45c 100644 --- a/src/VBox/VMM/VMMAll/CPUMAllMsrs.cpp +++ b/src/VBox/VMM/VMMAll/CPUMAllMsrs.cpp @@ -1731,7 +1731,8 @@ static DECLCALLBACK(VBOXSTRICTRC) cpumMsrRd_Amd64SyscallFlagMask(PVMCPUCC pVCpu, static DECLCALLBACK(VBOXSTRICTRC) cpumMsrWr_Amd64SyscallFlagMask(PVMCPUCC pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue) { RT_NOREF_PV(idMsr); RT_NOREF_PV(pRange); RT_NOREF_PV(uRawValue); - pVCpu->cpum.s.Guest.msrSFMASK = uValue; + /* The high bits are ignored and read-as-zero, writing to them does not raise #GP. See @bugref{10610}.*/ + pVCpu->cpum.s.Guest.msrSFMASK = uValue & UINT32_MAX; return VINF_SUCCESS; } @@ -1749,8 +1750,13 @@ static DECLCALLBACK(VBOXSTRICTRC) cpumMsrRd_Amd64FsBase(PVMCPUCC pVCpu, uint32_t static DECLCALLBACK(VBOXSTRICTRC) cpumMsrWr_Amd64FsBase(PVMCPUCC pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue) { RT_NOREF_PV(idMsr); RT_NOREF_PV(pRange); RT_NOREF_PV(uRawValue); - pVCpu->cpum.s.Guest.fs.u64Base = uValue; - return VINF_SUCCESS; + if (X86_IS_CANONICAL(uValue)) + { + pVCpu->cpum.s.Guest.fs.u64Base = uValue; + return VINF_SUCCESS; + } + Log(("CPUM: wrmsr %s(%#x), %#llx -> #GP - not canonical\n", pRange->szName, idMsr, uValue)); + return VERR_CPUM_RAISE_GP_0; } @@ -1766,8 +1772,13 @@ static DECLCALLBACK(VBOXSTRICTRC) cpumMsrRd_Amd64GsBase(PVMCPUCC pVCpu, uint32_t static DECLCALLBACK(VBOXSTRICTRC) cpumMsrWr_Amd64GsBase(PVMCPUCC pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue) { RT_NOREF_PV(idMsr); RT_NOREF_PV(pRange); RT_NOREF_PV(uRawValue); - pVCpu->cpum.s.Guest.gs.u64Base = uValue; - return VINF_SUCCESS; + if (X86_IS_CANONICAL(uValue)) + { + pVCpu->cpum.s.Guest.gs.u64Base = uValue; + return VINF_SUCCESS; + } + Log(("CPUM: wrmsr %s(%#x), %#llx -> #GP - not canonical\n", pRange->szName, idMsr, uValue)); + return VERR_CPUM_RAISE_GP_0; } @@ -1784,8 +1795,13 @@ static DECLCALLBACK(VBOXSTRICTRC) cpumMsrRd_Amd64KernelGsBase(PVMCPUCC pVCpu, ui static DECLCALLBACK(VBOXSTRICTRC) cpumMsrWr_Amd64KernelGsBase(PVMCPUCC pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t uValue, uint64_t uRawValue) { RT_NOREF_PV(idMsr); RT_NOREF_PV(pRange); RT_NOREF_PV(uRawValue); - pVCpu->cpum.s.Guest.msrKERNELGSBASE = uValue; - return VINF_SUCCESS; + if (X86_IS_CANONICAL(uValue)) + { + pVCpu->cpum.s.Guest.msrKERNELGSBASE = uValue; + return VINF_SUCCESS; + } + Log(("CPUM: wrmsr %s(%#x), %#llx -> #GP - not canonical\n", pRange->szName, idMsr, uValue)); + return VERR_CPUM_RAISE_GP_0; } diff --git a/src/VBox/VMM/VMMAll/IOMAllMmioNew.cpp b/src/VBox/VMM/VMMAll/IOMAllMmioNew.cpp index c737bf1f..4a924f78 100644 --- a/src/VBox/VMM/VMMAll/IOMAllMmioNew.cpp +++ b/src/VBox/VMM/VMMAll/IOMAllMmioNew.cpp @@ -448,7 +448,7 @@ static VBOXSTRICTRC iomMMIODoComplicatedRead(PVM pVM, CTX_SUFF(PIOMMMIOENTRY) pR /* * Do DWORD read from the device. */ - uint32_t u32Value; + uint32_t u32Value = 0; VBOXSTRICTRC rcStrict2 = pRegEntry->pfnReadCallback(pRegEntry->pDevIns, pRegEntry->pvUser, !(pRegEntry->fFlags & IOMMMIO_FLAGS_ABS) ? offRegion & ~(RTGCPHYS)3 : GCPhys & ~(RTGCPHYS)3, diff --git a/src/VBox/VMM/VMMAll/PGMAllGstSlatEpt.cpp.h b/src/VBox/VMM/VMMAll/PGMAllGstSlatEpt.cpp.h index 410abae1..56895dfb 100644 --- a/src/VBox/VMM/VMMAll/PGMAllGstSlatEpt.cpp.h +++ b/src/VBox/VMM/VMMAll/PGMAllGstSlatEpt.cpp.h @@ -35,16 +35,25 @@ * @returns @c true if valid, @c false otherwise. * @param pVCpu The cross context virtual CPU structure of the calling EMT. * @param uEntry The EPT page table entry to check. + * + * @remarks Current this ASSUMES @c uEntry is present (debug asserted)! */ DECLINLINE(bool) PGM_GST_SLAT_NAME_EPT(WalkIsPermValid)(PCVMCPUCC pVCpu, uint64_t uEntry) { if (!(uEntry & EPT_E_READ)) { - Assert(!pVCpu->CTX_SUFF(pVM)->cpum.ro.GuestFeatures.fVmxModeBasedExecuteEpt); - Assert(!RT_BF_GET(pVCpu->pgm.s.uEptVpidCapMsr, VMX_BF_EPT_VPID_CAP_EXEC_ONLY)); - NOREF(pVCpu); - if (uEntry & (EPT_E_WRITE | EPT_E_EXECUTE)) + if (uEntry & EPT_E_WRITE) return false; + + /* + * Currently all callers of this function check for the present mask prior + * to calling this function. Hence, the execute bit must be set now. + */ + Assert(uEntry & EPT_E_EXECUTE); + Assert(!pVCpu->CTX_SUFF(pVM)->cpum.ro.GuestFeatures.fVmxModeBasedExecuteEpt); + if (pVCpu->pgm.s.uEptVpidCapMsr & VMX_BF_EPT_VPID_CAP_EXEC_ONLY_MASK) + return true; + return false; } return true; } diff --git a/src/VBox/VMM/VMMAll/PGMAllPhys.cpp b/src/VBox/VMM/VMMAll/PGMAllPhys.cpp index 457f7de0..9aa351d9 100644 --- a/src/VBox/VMM/VMMAll/PGMAllPhys.cpp +++ b/src/VBox/VMM/VMMAll/PGMAllPhys.cpp @@ -2504,6 +2504,11 @@ static VBOXSTRICTRC pgmPhysReadHandler(PVMCC pVM, PPGMPAGE pPage, RTGCPHYS GCPhy /* Release the PGM lock as MMIO handlers take the IOM lock. (deadlock prevention) */ PGM_UNLOCK(pVM); + /* If the access origins with a device, make sure the buffer is initialized + as a guard against leaking heap, stack and other info via badly written + MMIO handling. @bugref{10651} */ + if (enmOrigin == PGMACCESSORIGIN_DEVICE) + memset(pvBuf, 0xff, cb); rcStrict = pfnHandler(pVM, pVCpu, GCPhys, (void *)pvSrc, pvBuf, cb, PGMACCESSTYPE_READ, enmOrigin, uUser); PGM_LOCK_VOID(pVM); diff --git a/src/VBox/VMM/VMMAll/PGMAllPool.cpp b/src/VBox/VMM/VMMAll/PGMAllPool.cpp index 59f946e5..aec01623 100644 --- a/src/VBox/VMM/VMMAll/PGMAllPool.cpp +++ b/src/VBox/VMM/VMMAll/PGMAllPool.cpp @@ -4774,6 +4774,31 @@ DECLINLINE(void) pgmPoolTrackDerefNestedPDEpt(PPGMPOOL pPool, PPGMPOOLPAGE pPage } } + +/** + * Clear references to shadowed pages in a SLAT EPT PML4 table. + * + * @param pPool The pool. + * @param pPage The page. + * @param pShwPml4 The shadow PML4 table. + */ +DECLINLINE(void) pgmPoolTrackDerefNestedPML4(PPGMPOOL pPool, PPGMPOOLPAGE pPage, PEPTPML4 pShwPml4) +{ + Assert(PGMPOOL_PAGE_IS_NESTED(pPage)); + for (unsigned i = 0; i < RT_ELEMENTS(pShwPml4->a); i++) + { + X86PGPAEUINT const uPml4e = pShwPml4->a[i].u; + AssertMsg((uPml4e & (EPT_PML4E_MBZ_MASK | 0xfff0000000000f00)) == 0, ("uPml4e=%RX64\n", uPml4e)); + if (uPml4e & EPT_PRESENT_MASK) + { + PPGMPOOLPAGE pSubPage = (PPGMPOOLPAGE)RTAvloHCPhysGet(&pPool->HCPhysTree, uPml4e & EPT_PML4E_PG_MASK); + if (pSubPage) + pgmPoolTrackFreeUser(pPool, pSubPage, pPage->idx, i); + else + AssertFatalMsgFailed(("%RX64\n", uPml4e & X86_PML4E_PG_MASK)); + } + } +} #endif /* VBOX_WITH_NESTED_HWVIRT_VMX_EPT */ @@ -5122,6 +5147,10 @@ static void pgmPoolTrackDeref(PPGMPOOL pPool, PPGMPOOLPAGE pPage) case PGMPOOLKIND_EPT_PDPT_FOR_EPT_PDPT: pgmPoolTrackDerefPDPTEPT(pPool, pPage, (PEPTPDPT)pvShw); break; + + case PGMPOOLKIND_EPT_PML4_FOR_EPT_PML4: + pgmPoolTrackDerefNestedPML4(pPool, pPage, (PEPTPML4)pvShw); + break; #endif default: diff --git a/src/VBox/VMM/VMMAll/VMXAllTemplate.cpp.h b/src/VBox/VMM/VMMAll/VMXAllTemplate.cpp.h index 85db8a47..efd44121 100644 --- a/src/VBox/VMM/VMMAll/VMXAllTemplate.cpp.h +++ b/src/VBox/VMM/VMMAll/VMXAllTemplate.cpp.h @@ -9428,6 +9428,8 @@ HMVMX_EXIT_DECL vmxHCExitEptMisconfig(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransien /* * Frequent exit or something needing probing. Call EMHistoryExec. */ + int rc2 = vmxHCImportGuestState<HMVMX_CPUMCTX_EXTRN_ALL, IEM_CPUMCTX_EXTRN_MUST_MASK>(pVCpu, pVmcsInfo, __FUNCTION__); + AssertRCReturn(rc2, rc2); Log4(("EptMisscfgExit/%u: %04x:%08RX64: %RGp -> EMHistoryExec\n", pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip, GCPhys)); diff --git a/src/VBox/VMM/VMMR0/HMVMXR0.cpp b/src/VBox/VMM/VMMR0/HMVMXR0.cpp index 26b6252e..0bb3b490 100644 --- a/src/VBox/VMM/VMMR0/HMVMXR0.cpp +++ b/src/VBox/VMM/VMMR0/HMVMXR0.cpp @@ -382,13 +382,20 @@ static void hmR0VmxLazyLoadGuestMsrs(PVMCPUCC pVCpu) } else { - ASMWrMsr(MSR_K8_KERNEL_GS_BASE, pCtx->msrKERNELGSBASE); - ASMWrMsr(MSR_K8_LSTAR, pCtx->msrLSTAR); - ASMWrMsr(MSR_K6_STAR, pCtx->msrSTAR); - /* The system call flag mask register isn't as benign and accepting of all - values as the above, so mask it to avoid #GP'ing on corrupted input. */ - Assert(!(pCtx->msrSFMASK & ~(uint64_t)UINT32_MAX)); - ASMWrMsr(MSR_K8_SF_MASK, pCtx->msrSFMASK & UINT32_MAX); + /* Avoid raising #GP caused by writing illegal values to these MSRs. */ + if ( X86_IS_CANONICAL(pCtx->msrKERNELGSBASE) + && X86_IS_CANONICAL(pCtx->msrLSTAR)) + { + ASMWrMsr(MSR_K8_KERNEL_GS_BASE, pCtx->msrKERNELGSBASE); + ASMWrMsr(MSR_K8_LSTAR, pCtx->msrLSTAR); + ASMWrMsr(MSR_K6_STAR, pCtx->msrSTAR); + /* The system call flag mask register isn't as benign and accepting of all + values as the above, so mask it to avoid #GP'ing on corrupted input. */ + Assert(!(pCtx->msrSFMASK & ~(uint64_t)UINT32_MAX)); + ASMWrMsr(MSR_K8_SF_MASK, pCtx->msrSFMASK & UINT32_MAX); + } + else + AssertMsgFailed(("Incompatible lazily-loaded guest MSR values\n")); } } pVCpu->hmr0.s.vmx.fLazyMsrs |= VMX_LAZY_MSRS_LOADED_GUEST; diff --git a/src/VBox/VMM/VMMR3/CPUMR3CpuId.cpp b/src/VBox/VMM/VMMR3/CPUMR3CpuId.cpp index a2288250..04d8ac3c 100644 --- a/src/VBox/VMM/VMMR3/CPUMR3CpuId.cpp +++ b/src/VBox/VMM/VMMR3/CPUMR3CpuId.cpp @@ -2233,6 +2233,53 @@ static int cpumR3CpuIdSanitize(PVM pVM, PCPUM pCpum, PCPUMCPUIDCONFIG pConfig) * 0x80000006 L2 cache information */ + uSubLeaf = 0; + while ((pCurLeaf = cpumR3CpuIdGetExactLeaf(pCpum, UINT32_C(0x80000006), uSubLeaf)) != NULL) + { + if ( pCpum->GuestFeatures.enmCpuVendor == CPUMCPUVENDOR_AMD + || pCpum->GuestFeatures.enmCpuVendor == CPUMCPUVENDOR_HYGON) + { + /* + * Some AMD CPUs (e.g. Ryzen 7940HS) report zero L3 cache line size here and refer + * to CPUID Fn8000_001D. This triggers division by zero in Linux if the + * TopologyExtensions aka TOPOEXT bit in Fn8000_0001_ECX is not set, or if the kernel + * is old enough (e.g. Linux 3.13) that it does not know about the topology extension + * CPUID leaves. + * We put a non-zero value in the cache line size here, if possible the actual value + * gleaned from Fn8000_001D, or worst case a made-up valid number. + */ + PCPUMCPUIDLEAF pTopoLeaf; + uint32_t uTopoSubLeaf; + uint32_t uCacheLineSize; + + if ((pCurLeaf->uEdx & 0xff) == 0) + { + uTopoSubLeaf = 0; + + uCacheLineSize = 64; /* Use 64-byte line size as a fallback. */ + + /* Find L3 cache information. Have to check the cache level in EAX. */ + while ((pTopoLeaf = cpumR3CpuIdGetExactLeaf(pCpum, UINT32_C(0x8000001d), uTopoSubLeaf)) != NULL) + { + if (((pTopoLeaf->uEax >> 5) & 0x07) == 3) { + uCacheLineSize = (pTopoLeaf->uEbx & 0xfff) + 1; + /* Fn8000_0006 can't report power of two line sizes greater than 128. */ + if (uCacheLineSize > 128) + uCacheLineSize = 128; + + break; + } + uTopoSubLeaf++; + } + + Assert(uCacheLineSize < 256); + pCurLeaf->uEdx |= uCacheLineSize; + LogRel(("CPUM: AMD L3 cache line size in CPUID leaf 0x80000006 was zero, adjusting to %u\n", uCacheLineSize)); + } + } + uSubLeaf++; + } + /* Cpuid 0x80000007: Advanced Power Management Information. * AMD: EAX: Processor feedback capabilities. * EBX: RAS capabilites. diff --git a/src/VBox/VMM/testcase/Instructions/itgTableDaa.py b/src/VBox/VMM/testcase/Instructions/itgTableDaa.py index 2606d99b..2606d99b 100644..100755 --- a/src/VBox/VMM/testcase/Instructions/itgTableDaa.py +++ b/src/VBox/VMM/testcase/Instructions/itgTableDaa.py diff --git a/src/VBox/VMM/testcase/Instructions/itgTableDas.py b/src/VBox/VMM/testcase/Instructions/itgTableDas.py index 96557cfd..96557cfd 100644..100755 --- a/src/VBox/VMM/testcase/Instructions/itgTableDas.py +++ b/src/VBox/VMM/testcase/Instructions/itgTableDas.py diff --git a/src/VBox/VMM/testcase/Makefile.kmk b/src/VBox/VMM/testcase/Makefile.kmk index 43cb7b40..3028aaf1 100644 --- a/src/VBox/VMM/testcase/Makefile.kmk +++ b/src/VBox/VMM/testcase/Makefile.kmk @@ -800,6 +800,7 @@ $(VBOX_VMM_TESTCASE_OUT_DIR)/tstAsmStructsHC.h: $(VBOX_VMM_TESTCASE_OUT_DIR)/tst -e '/VMMCPU_size$$/d' \ -e '/SUPDRVTRACERUSRCTX32_size$$/d' \ -e '/HMCPU_size$$/d' \ + -e '/SUPGLOBALINFOPAGE_size$$/d' \ \ -e '/^\(0x\)\{0,1\}00[0-9a-fA-F]* [aAnN] [^_.]*_size$$/!d' \ -e 's/^\(0x\)\{0,1\}\(00[0-9a-fA-F]*\) [aAnN] \([^_.]*\)_size/ CHECK_SIZE(\3, 0x0\2);/' \ diff --git a/src/VBox/ValidationKit/common/pathutils.py b/src/VBox/ValidationKit/common/pathutils.py index 6787f1aa..6787f1aa 100644..100755 --- a/src/VBox/ValidationKit/common/pathutils.py +++ b/src/VBox/ValidationKit/common/pathutils.py diff --git a/src/VBox/ValidationKit/common/utils.py b/src/VBox/ValidationKit/common/utils.py index e8a50604..d392c9ee 100755 --- a/src/VBox/ValidationKit/common/utils.py +++ b/src/VBox/ValidationKit/common/utils.py @@ -39,7 +39,7 @@ terms and conditions of either the GPL or the CDDL or both. SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 """ -__version__ = "$Revision: 155244 $" +__version__ = "$Revision: 162363 $" # Standard Python imports. @@ -301,7 +301,7 @@ def getHostOsVersion(): sVersion += ' / OS X ' + sOsxVersion + ' (' + getMacVersionName(sOsxVersion) + ')' elif sOs == 'win': - class OSVersionInfoEx(ctypes.Structure): + class OSVersionInfoEx(ctypes.Structure): # pylint: disable=used-before-assignment """ OSVERSIONEX """ kaFields = [ ('dwOSVersionInfoSize', ctypes.c_ulong), @@ -424,7 +424,7 @@ def openNoDenyDeleteNoInherit(sFile, sMode = 'r'): # Need to use CreateFile directly to open the file so we can feed it FILE_SHARE_DELETE. # pylint: disable=no-member,c-extension-no-member fAccess = 0; - fDisposition = win32file.OPEN_EXISTING; + fDisposition = win32file.OPEN_EXISTING; # pylint: disable=used-before-assignment if 'r' in sMode or '+' in sMode: fAccess |= win32file.GENERIC_READ; if 'a' in sMode: @@ -458,7 +458,7 @@ def openNoDenyDeleteNoInherit(sFile, sMode = 'r'): fOpen |= os.O_APPEND; if 'b' in sMode or 't' in sMode: fOpen |= os.O_TEXT; # pylint: disable=no-member - fdFile = msvcrt.open_osfhandle(hDetachedFile, fOpen); + fdFile = msvcrt.open_osfhandle(hDetachedFile, fOpen); # pylint: disable=used-before-assignment # Tell python to use this handle. oFile = os.fdopen(fdFile, sMode); @@ -1016,8 +1016,8 @@ def processExists(uPid): try: hProcess = win32api.OpenProcess(win32con.SYNCHRONIZE, # pylint: disable=no-member,c-extension-no-member False, uPid); - except pywintypes.error as oXcpt: # pylint: disable=no-member - if oXcpt.winerror == winerror.ERROR_ACCESS_DENIED: + except pywintypes.error as oXcpt: # pylint: disable=no-member,used-before-assignment + if oXcpt.winerror == winerror.ERROR_ACCESS_DENIED: # pylint: disable=used-before-assignment fRc = True; except: pass; diff --git a/src/VBox/ValidationKit/testboxscript/testboxscript_real.py b/src/VBox/ValidationKit/testboxscript/testboxscript_real.py index 7a2581ae..af7df36e 100755 --- a/src/VBox/ValidationKit/testboxscript/testboxscript_real.py +++ b/src/VBox/ValidationKit/testboxscript/testboxscript_real.py @@ -37,7 +37,7 @@ terms and conditions of either the GPL or the CDDL or both. SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 """ -__version__ = "$Revision: 155244 $" +__version__ = "$Revision: 162363 $" # Standard python imports. @@ -714,7 +714,7 @@ class TestBoxScript(object): sFullName = os.path.join(self._oOptions.sScratchRoot, sName); try: if os.path.isdir(sFullName): - shutil.rmtree(sFullName, False, oRc.onErrorCallback); + shutil.rmtree(sFullName, False, oRc.onErrorCallback); # pylint: disable=deprecated-argument else: os.remove(sFullName); if os.path.exists(sFullName): diff --git a/src/VBox/ValidationKit/testmanager/config.py b/src/VBox/ValidationKit/testmanager/config.py index b4ef94cc..b4ef94cc 100644..100755 --- a/src/VBox/ValidationKit/testmanager/config.py +++ b/src/VBox/ValidationKit/testmanager/config.py diff --git a/src/VBox/ValidationKit/testmanager/core/schedqueue.py b/src/VBox/ValidationKit/testmanager/core/schedqueue.py index f49c4ad3..f49c4ad3 100755..100644 --- a/src/VBox/ValidationKit/testmanager/core/schedqueue.py +++ b/src/VBox/ValidationKit/testmanager/core/schedqueue.py diff --git a/src/VBox/ValidationKit/testmanager/webui/wuivcshistory.py b/src/VBox/ValidationKit/testmanager/webui/wuivcshistory.py index 1df9bbb2..1df9bbb2 100755..100644 --- a/src/VBox/ValidationKit/testmanager/webui/wuivcshistory.py +++ b/src/VBox/ValidationKit/testmanager/webui/wuivcshistory.py diff --git a/src/VBox/ValidationKit/tests/serial/loopback.py b/src/VBox/ValidationKit/tests/serial/loopback.py index b5ad831a..b5ad831a 100755..100644 --- a/src/VBox/ValidationKit/tests/serial/loopback.py +++ b/src/VBox/ValidationKit/tests/serial/loopback.py |