void VBOXCALL supdrvOSLdrNotifyOpened(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage) { #if 1 NOREF(pDevExt); NOREF(pImage); #else /* * Try store the image load address in NVRAM so we can retrived it on panic. * Note! This only works if you're root! - Acutally, it doesn't work at all at the moment. FIXME! */ IORegistryEntry *pEntry = IORegistryEntry::fromPath("/options", gIODTPlane); if (pEntry) { char szVar[80]; RTStrPrintf(szVar, sizeof(szVar), "vboximage"/*-%s*/, pImage->szName); char szValue[48]; RTStrPrintf(szValue, sizeof(szValue), "%#llx,%#llx", (uint64_t)(uintptr_t)pImage->pvImage, (uint64_t)(uintptr_t)pImage->pvImage + pImage->cbImageBits - 1); bool fRc = pEntry->setProperty(szVar, szValue); NOREF(fRc); pEntry->release(); SUPR0Printf("fRc=%d '%s'='%s'\n", fRc, szVar, szValue); } /*else SUPR0Printf("failed to find /options in gIODTPlane\n");*/ #endif }
/** * Module initialization code. * * @param hMod Opque module handle. */ const SUPDRVTRACERREG * VBOXCALL supdrvDTraceInit(void) { #ifdef RT_OS_DARWIN /* * Resolve the kernel symbols we need. */ RTDBGKRNLINFO hKrnlInfo; int rc = RTR0DbgKrnlInfoOpen(&hKrnlInfo, 0); if (RT_FAILURE(rc)) { SUPR0Printf("supdrvDTraceInit: RTR0DbgKrnlInfoOpen failed with rc=%d.\n", rc); return NULL; } static const struct { const char *pszName; PFNRT *ppfn; } s_aDTraceFunctions[] = { { "dtrace_probe", (PFNRT*)&dtrace_probe }, { "dtrace_probe_create", (PFNRT*)&dtrace_probe_create }, { "dtrace_probe_lookup", (PFNRT*)&dtrace_probe_lookup }, { "dtrace_register", (PFNRT*)&dtrace_register }, { "dtrace_invalidate", (PFNRT*)&dtrace_invalidate }, { "dtrace_unregister", (PFNRT*)&dtrace_unregister }, }; for (unsigned i = 0; i < RT_ELEMENTS(s_aDTraceFunctions); i++) { rc = RTR0DbgKrnlInfoQuerySymbol(hKrnlInfo, NULL, s_aDTraceFunctions[i].pszName, (void **)s_aDTraceFunctions[i].ppfn); if (RT_FAILURE(rc)) { SUPR0Printf("supdrvDTraceInit: Failed to resolved '%s' (rc=%Rrc, i=%u).\n", s_aDTraceFunctions[i].pszName, rc, i); break; } } RTR0DbgKrnlInfoRelease(hKrnlInfo); if (RT_FAILURE(rc)) return NULL; #endif return &g_VBoxDTraceReg; }
void VBOXCALL supdrvOSLdrUnload(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage) { if (pImage->pvNtSectionObj) { if (pImage->hMemLock != NIL_RTR0MEMOBJ) { RTR0MemObjFree(pImage->hMemLock, false /*fFreeMappings*/); pImage->hMemLock = NIL_RTR0MEMOBJ; } NTSTATUS rcNt = ZwSetSystemInformation(MY_SystemUnloadGdiDriverInformation, &pImage->pvNtSectionObj, sizeof(pImage->pvNtSectionObj)); if (rcNt != STATUS_SUCCESS) SUPR0Printf("VBoxDrv: failed to unload '%s', rcNt=%#x\n", pImage->szName, rcNt); pImage->pvNtSectionObj = NULL; } NOREF(pDevExt); }
/** * memcmp + log. * * @returns Same as memcmp. * @param pImage The image. * @param pbImageBits The image bits ring-3 uploads. * @param uRva The RVA to start comparing at. * @param cb The number of bytes to compare. */ static int supdrvNtCompare(PSUPDRVLDRIMAGE pImage, const uint8_t *pbImageBits, uint32_t uRva, uint32_t cb) { int iDiff = memcmp((uint8_t const *)pImage->pvImage + uRva, pbImageBits + uRva, cb); if (iDiff) { uint32_t cbLeft = cb; const uint8_t *pbNativeBits = (const uint8_t *)pImage->pvImage; for (size_t off = uRva; cbLeft > 0; off++, cbLeft--) if (pbNativeBits[off] != pbImageBits[off]) { char szBytes[128]; RTStrPrintf(szBytes, sizeof(szBytes), "native: %.*Rhxs our: %.*Rhxs", RT_MIN(12, cbLeft), &pbNativeBits[off], RT_MIN(12, cbLeft), &pbImageBits[off]); SUPR0Printf("VBoxDrv: Mismatch at %#x of %s: %s\n", off, pImage->szName, szBytes); break; } } return iDiff; }
int VBOXCALL supdrvOSLdrOpen(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage, const char *pszFilename) { pImage->pvNtSectionObj = NULL; pImage->hMemLock = NIL_RTR0MEMOBJ; #ifdef VBOX_WITHOUT_NATIVE_R0_LOADER # ifndef RT_ARCH_X86 # error "VBOX_WITHOUT_NATIVE_R0_LOADER is only safe on x86." # endif NOREF(pDevExt); NOREF(pszFilename); NOREF(pImage); return VERR_NOT_SUPPORTED; #else /* * Convert the filename from DOS UTF-8 to NT UTF-16. */ size_t cwcFilename; int rc = RTStrCalcUtf16LenEx(pszFilename, RTSTR_MAX, &cwcFilename); if (RT_FAILURE(rc)) return rc; PRTUTF16 pwcsFilename = (PRTUTF16)RTMemTmpAlloc((4 + cwcFilename + 1) * sizeof(RTUTF16)); if (!pwcsFilename) return VERR_NO_TMP_MEMORY; pwcsFilename[0] = '\\'; pwcsFilename[1] = '?'; pwcsFilename[2] = '?'; pwcsFilename[3] = '\\'; PRTUTF16 pwcsTmp = &pwcsFilename[4]; rc = RTStrToUtf16Ex(pszFilename, RTSTR_MAX, &pwcsTmp, cwcFilename + 1, NULL); if (RT_SUCCESS(rc)) { /* * Try load it. */ MYSYSTEMGDIDRIVERINFO Info; RtlInitUnicodeString(&Info.Name, pwcsFilename); Info.ImageAddress = NULL; Info.SectionPointer = NULL; Info.EntryPointer = NULL; Info.ExportSectionPointer = NULL; Info.ImageLength = 0; NTSTATUS rcNt = ZwSetSystemInformation(MY_SystemLoadGdiDriverInSystemSpaceInformation, &Info, sizeof(Info)); if (NT_SUCCESS(rcNt)) { pImage->pvImage = Info.ImageAddress; pImage->pvNtSectionObj = Info.SectionPointer; Log(("ImageAddress=%p SectionPointer=%p ImageLength=%#x cbImageBits=%#x rcNt=%#x '%ls'\n", Info.ImageAddress, Info.SectionPointer, Info.ImageLength, pImage->cbImageBits, rcNt, Info.Name.Buffer)); # ifdef DEBUG_bird SUPR0Printf("ImageAddress=%p SectionPointer=%p ImageLength=%#x cbImageBits=%#x rcNt=%#x '%ws'\n", Info.ImageAddress, Info.SectionPointer, Info.ImageLength, pImage->cbImageBits, rcNt, Info.Name.Buffer); # endif if (pImage->cbImageBits == Info.ImageLength) { /* * Lock down the entire image, just to be on the safe side. */ rc = RTR0MemObjLockKernel(&pImage->hMemLock, pImage->pvImage, pImage->cbImageBits, RTMEM_PROT_READ); if (RT_FAILURE(rc)) { pImage->hMemLock = NIL_RTR0MEMOBJ; supdrvOSLdrUnload(pDevExt, pImage); } } else { supdrvOSLdrUnload(pDevExt, pImage); rc = VERR_LDR_MISMATCH_NATIVE; } } else { Log(("rcNt=%#x '%ls'\n", rcNt, pwcsFilename)); SUPR0Printf("VBoxDrv: rcNt=%x '%ws'\n", rcNt, pwcsFilename); switch (rcNt) { case /* 0xc0000003 */ STATUS_INVALID_INFO_CLASS: # ifdef RT_ARCH_AMD64 /* Unwind will crash and BSOD, so no fallback here! */ rc = VERR_NOT_IMPLEMENTED; # else /* * Use the old way of loading the modules. * * Note! We do *NOT* try class 26 because it will probably * not work correctly on terminal servers and such. */ rc = VERR_NOT_SUPPORTED; # endif break; case /* 0xc0000034 */ STATUS_OBJECT_NAME_NOT_FOUND: rc = VERR_MODULE_NOT_FOUND; break; case /* 0xC0000263 */ STATUS_DRIVER_ENTRYPOINT_NOT_FOUND: rc = VERR_LDR_IMPORTED_SYMBOL_NOT_FOUND; break; case 0xC0000428 /* STATUS_INVALID_IMAGE_HASH */ : rc = VERR_LDR_IMAGE_HASH; break; case 0xC000010E /* STATUS_IMAGE_ALREADY_LOADED */ : Log(("WARNING: see @bugref{4853} for cause of this failure on Windows 7 x64\n")); rc = VERR_ALREADY_LOADED; break; default: rc = VERR_LDR_GENERAL_FAILURE; break; } pImage->pvNtSectionObj = NULL; } } RTMemTmpFree(pwcsFilename); NOREF(pDevExt); return rc; #endif }
static int VBoxDrvLinuxIOCtl(struct inode *pInode, struct file *pFilp, unsigned int uCmd, unsigned long ulArg) #endif { PSUPDRVSESSION pSession = (PSUPDRVSESSION)pFilp->private_data; int rc; #if defined(VBOX_STRICT) || defined(VBOX_WITH_EFLAGS_AC_SET_IN_VBOXDRV) RTCCUINTREG fSavedEfl; /* * Refuse all I/O control calls if we've ever detected EFLAGS.AC being cleared. * * This isn't a problem, as there is absolutely nothing in the kernel context that * depend on user context triggering cleanups. That would be pretty wild, right? */ if (RT_UNLIKELY(g_DevExt.cBadContextCalls > 0)) { SUPR0Printf("VBoxDrvLinuxIOCtl: EFLAGS.AC=0 detected %u times, refusing all I/O controls!\n", g_DevExt.cBadContextCalls); return ESPIPE; } fSavedEfl = ASMAddFlags(X86_EFL_AC); # else stac(); # endif /* * Deal with the two high-speed IOCtl that takes it's arguments from * the session and iCmd, and only returns a VBox status code. */ #ifdef HAVE_UNLOCKED_IOCTL if (RT_LIKELY( ( uCmd == SUP_IOCTL_FAST_DO_RAW_RUN || uCmd == SUP_IOCTL_FAST_DO_HM_RUN || uCmd == SUP_IOCTL_FAST_DO_NOP) && pSession->fUnrestricted == true)) rc = supdrvIOCtlFast(uCmd, ulArg, &g_DevExt, pSession); else rc = VBoxDrvLinuxIOCtlSlow(pFilp, uCmd, ulArg, pSession); #else /* !HAVE_UNLOCKED_IOCTL */ unlock_kernel(); if (RT_LIKELY( ( uCmd == SUP_IOCTL_FAST_DO_RAW_RUN || uCmd == SUP_IOCTL_FAST_DO_HM_RUN || uCmd == SUP_IOCTL_FAST_DO_NOP) && pSession->fUnrestricted == true)) rc = supdrvIOCtlFast(uCmd, ulArg, &g_DevExt, pSession); else rc = VBoxDrvLinuxIOCtlSlow(pFilp, uCmd, ulArg, pSession); lock_kernel(); #endif /* !HAVE_UNLOCKED_IOCTL */ #if defined(VBOX_STRICT) || defined(VBOX_WITH_EFLAGS_AC_SET_IN_VBOXDRV) /* * Before we restore AC and the rest of EFLAGS, check if the IOCtl handler code * accidentially modified it or some other important flag. */ if (RT_UNLIKELY( (ASMGetFlags() & (X86_EFL_AC | X86_EFL_IF | X86_EFL_DF | X86_EFL_IOPL)) != ((fSavedEfl & (X86_EFL_AC | X86_EFL_IF | X86_EFL_DF | X86_EFL_IOPL)) | X86_EFL_AC) )) { char szTmp[48]; RTStrPrintf(szTmp, sizeof(szTmp), "uCmd=%#x: %#x->%#x!", _IOC_NR(uCmd), (uint32_t)fSavedEfl, (uint32_t)ASMGetFlags()); supdrvBadContext(&g_DevExt, "SUPDrv-linux.c", __LINE__, szTmp); } ASMSetFlags(fSavedEfl); #else clac(); #endif return rc; }