SUPLib.cpp revision 00c0f6aad1f43632e70b7e66a28aa5c41445277f
683N/A * available from http://www.virtualbox.org. This file is free software;
1919N/A#include "SUPLibInternal.h"
1919N/A#include "SUPDrvIOC.h"
755N/Astatic bool g_fPreInited = false;
669N/A#if defined(RT_OS_DARWIN)
785N/Astatic bool g_fSupportsPageAllocNoKernel = true;
1919N/Astatic int supLoadModule(const char *pszFilename, const char *pszModule, const char *pszSrvReqHandler, void **ppvImageBase);
1919N/Astatic DECLCALLBACK(int) supLoadModuleResolveImport(RTLDRMOD hLdrMod, const char *pszModule, const char *pszSymbol, unsigned uSymbol, RTUINTPTR *pValue, void *pvUser);
669N/A return suplibOsInstall();
1751N/A return suplibOsUninstall();
669N/A return VERR_INVALID_POINTER;
return VERR_WRONG_ORDER;
return VERR_INVALID_MAGIC;
return VERR_INVALID_HANDLE;
return VERR_INVALID_PARAMETER;
return rc;
/** @todo This may need some small restructuring later, it doesn't quite work with a root service flag... */
g_fPreInited = true;
return VINF_SUCCESS;
if (ppSession)
if (g_cInits++ > 0)
g_cInits--;
if (ppSession)
return VINF_SUCCESS;
if (g_u32FakeMode == ~0U)
if (pFuncsReq)
ASMAtomicCmpXchgPtr((void * volatile *)&g_pSUPGlobalInfoPageR0, (void *)GipMapReq.u.Out.pGipR0, NULL);
if (ppSession)
return VINF_SUCCESS;
LogRel(("Support driver version mismatch: SessionVersion=%#x DriverVersion=%#x ClientVersion=%#x MinVersion=%#x\n",
CookieReq.u.Out.u32SessionVersion, CookieReq.u.Out.u32DriverVersion, SUPDRV_IOC_VERSION, uMinVersion));
LogRel(("Support driver version mismatch: DriverVersion=too-old ClientVersion=%#x\n", SUPDRV_IOC_VERSION));
g_cInits--;
return rc;
g_pFunctions = (PSUPQUERYFUNCS)RTMemAllocZ(SUP_IOCTL_QUERY_FUNCS_SIZE(RT_ELEMENTS(s_aFakeFunctions)));
if (g_pFunctions)
if (ppSession)
if (g_pSUPGlobalInfoPage)
return VINF_SUCCESS;
return VERR_NO_MEMORY;
if (g_cInits == 0)
return VERR_WRONG_ORDER;
if (g_pSUPGlobalInfoPage)
if (rc)
return rc;
g_u32Cookie = 0;
g_u32SessionCookie = 0;
g_cInits = 0;
g_cInits--;
#ifdef RT_ARCH_AMD64
return SUPPAGINGMODE_AMD64_GLOBAL_NX;
return SUPPAGINGMODE_32_BIT_GLOBAL;
int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_GET_PAGING_MODE, &Req, SUP_IOCTL_GET_PAGING_MODE_SIZE);
static int supCallVMMR0ExFake(PVMR0 pVMR0, unsigned uOperation, uint64_t u64Arg, PSUPVMMR0REQHDR pReqHdr)
AssertMsgFailed(("%d\n", uOperation)); NOREF(pVMR0); NOREF(uOperation); NOREF(u64Arg); NOREF(pReqHdr);
return VERR_NOT_SUPPORTED;
return VERR_INTERNAL_ERROR;
SUPR3DECL(int) SUPR3CallVMMR0Ex(PVMR0 pVMR0, VMCPUID idCpu, unsigned uOperation, uint64_t u64Arg, PSUPVMMR0REQHDR pReqHdr)
int rc;
if (!pReqHdr)
rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_CALL_VMMR0(cbReq), pReq, SUP_IOCTL_CALL_VMMR0_SIZE(cbReq));
rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_CALL_VMMR0_BIG, pReq, SUP_IOCTL_CALL_VMMR0_BIG_SIZE(cbReq));
return rc;
return VINF_SUCCESS;
int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_SET_VM_FOR_FAST, &Req, SUP_IOCTL_SET_VM_FOR_FAST_SIZE);
return rc;
SUPR3DECL(int) SUPR3CallR0Service(const char *pszService, size_t cchService, uint32_t uOperation, uint64_t u64Arg, PSUPR0SERVICEREQHDR pReqHdr)
return VERR_NOT_SUPPORTED;
int rc;
if (!pReqHdr)
rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_CALL_SERVICE(cbReq), pReq, SUP_IOCTL_CALL_SERVICE_SIZE(cbReq));
return rc;
static int supR3LoggerSettings(SUPLOGGER enmWhich, uint32_t fWhat, const char *pszFlags, const char *pszGroups, const char *pszDest)
switch (enmWhich)
return VERR_INVALID_PARAMETER;
if (cchFlags)
if (cchGroups)
if (cchDest)
if (!off)
off++;
int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_LOGGER_SETTINGS(cbStrTab), pReq, SUP_IOCTL_LOGGER_SETTINGS_SIZE(cbStrTab));
return rc;
SUPR3DECL(int) SUPR3LoggerSettings(SUPLOGGER enmWhich, const char *pszFlags, const char *pszGroups, const char *pszDest)
return supR3LoggerSettings(enmWhich, SUPLOGGERSETTINGS_WHAT_SETTINGS, pszFlags, pszGroups, pszDest);
SUPR3DECL(int) SUPR3LoggerCreate(SUPLOGGER enmWhich, const char *pszFlags, const char *pszGroups, const char *pszDest)
AssertMsg(RT_ALIGN_P(pvStart, PAGE_SIZE) == pvStart, ("pvStart (%p) must be page aligned\n", pvStart));
while (iPage-- > 0)
return VINF_SUCCESS;
int rc;
return rc;
AssertMsg(RT_ALIGN_P(pvStart, PAGE_SIZE) == pvStart, ("pvStart (%p) must be page aligned\n", pvStart));
return VINF_SUCCESS;
return rc;
if (!paPages)
return rc;
SUPR3DECL(int) SUPR3PageAllocEx(size_t cPages, uint32_t fFlags, void **ppvPages, PRTR0PTR pR0Ptr, PSUPPAGE paPages)
if (pR0Ptr)
AssertMsgReturn(cPages > 0 && cPages <= VBOX_MAX_ALLOC_PAGE_COUNT, ("cPages=%zu\n", cPages), VERR_PAGE_COUNT_OUT_OF_RANGE);
if (!pv)
return VERR_NO_MEMORY;
if (pR0Ptr)
if (paPages)
return VINF_SUCCESS;
if ( !pR0Ptr
int rc;
if (pReq)
rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_PAGE_ALLOC_EX, pReq, SUP_IOCTL_PAGE_ALLOC_EX_SIZE(cPages));
if (pR0Ptr)
if (paPages)
&& !pR0Ptr)
g_fSupportsPageAllocNoKernel = false;
return rc;
SUPR3DECL(int) SUPR3PageMapKernel(void *pvR3, uint32_t off, uint32_t cb, uint32_t fFlags, PRTR0PTR pR0Ptr)
return VERR_NOT_SUPPORTED;
int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_PAGE_MAP_KERNEL, &Req, SUP_IOCTL_PAGE_MAP_KERNEL_SIZE);
return rc;
SUPR3DECL(int) SUPR3PageProtect(void *pvR3, RTR0PTR R0Ptr, uint32_t off, uint32_t cb, uint32_t fProt)
AssertReturn(!(fProt & ~(RTMEM_PROT_NONE | RTMEM_PROT_READ | RTMEM_PROT_WRITE | RTMEM_PROT_EXEC)), VERR_INVALID_PARAMETER);
#if !defined(RT_OS_SOLARIS)
return rc;
return VINF_SUCCESS;
return rc;
if (pR0Ptr)
if (pR0Ptr)
if (pHCPhys)
return pv;
if (pR0Ptr)
return NULL;
if (!pv)
return VINF_SUCCESS;
return VINF_SUCCESS;
return rc;
AssertMsgReturn(cPages > 0 && cPages < 256, ("cPages=%d must be > 0 and < 256\n", cPages), VERR_PAGE_COUNT_OUT_OF_RANGE);
if (!*ppvPages)
return VERR_NO_LOW_MEMORY;
while (iPage-- > 0)
return VINF_SUCCESS;
int rc;
if (pReq)
if (ppvPagesR0)
if (paPages)
return rc;
if (!pv)
return VINF_SUCCESS;
return VINF_SUCCESS;
return rc;
AssertReturn(!phFile, VERR_NOT_IMPLEMENTED); /** @todo Implement this. The deal is that we make sure the
#ifdef VBOX_WITH_HARDENING
LogRel(("SUPR3HardenedVerifyFile: %s: Verification of \"%s\" failed, rc=%Rrc\n", pszMsg, pszFilename, rc));
return rc;
return VINF_SUCCESS;
int rc;
if (fInternal)
#ifdef VBOX_WITH_HARDENING
return rc;
return VINF_SUCCESS;
SUPR3DECL(int) SUPR3HardenedVerifyDir(const char *pszDirPath, bool fRecursive, bool fCheckFiles, PRTERRINFO pErrInfo)
#ifdef VBOX_WITH_HARDENING
return rc;
return VINF_SUCCESS;
#ifdef VBOX_WITH_HARDENING
return rc;
return VINF_SUCCESS;
SUPR3DECL(int) SUPR3LoadModule(const char *pszFilename, const char *pszModule, void **ppvImageBase, PRTERRINFO pErrInfo)
return rc;
return rc;
if ( pszModule
&& *pszModule
AssertMsgFailed(("%s is importing from %s! (expected 'SUPR0.dll' or 'VMMR0.r0', case-sensitive)\n", pvUser, pszModule));
return VERR_SYMBOL_NOT_FOUND;
return VERR_SYMBOL_NOT_FOUND;
void *pvValue;
return VINF_SUCCESS;
return VINF_SUCCESS;
pFunc++;
if ( pszSymbol
return VINF_SUCCESS;
#ifdef RT_OS_SOLARIS
static const char * const s_apszConvSyms[] =
return VINF_SUCCESS;
pFunc++;
if (g_u32FakeMode)
return VINF_SUCCESS;
return VERR_SYMBOL_NOT_FOUND;
typedef struct SUPLDRCALCSIZEARGS
static DECLCALLBACK(int) supLoadModuleCalcSizeCB(RTLDRMOD hLdrMod, const char *pszSymbol, unsigned uSymbol, RTUINTPTR Value, void *pvUser)
&& *pszSymbol
return VINF_SUCCESS;
typedef struct SUPLDRCREATETABSARGS
char *pszBase;
char *psz;
static DECLCALLBACK(int) supLoadModuleCreateTabsCB(RTLDRMOD hLdrMod, const char *pszSymbol, unsigned uSymbol, RTUINTPTR Value, void *pvUser)
&& *pszSymbol
return VINF_SUCCESS;
static int supLoadModule(const char *pszFilename, const char *pszModule, const char *pszSrvReqHandler, void **ppvImageBase)
int rc;
return rc;
return rc;
if (!g_u32FakeMode)
if (pLoadReq)
if (fIsVMMR0)
rc = RTLdrGetSymbolEx(hLdrMod, &pLoadReq->u.In.abImage[0], (uintptr_t)OpenReq.u.Out.pvImageBase, "VMMR0EntryInt", &VMMR0EntryInt);
rc = RTLdrGetSymbolEx(hLdrMod, &pLoadReq->u.In.abImage[0], (uintptr_t)OpenReq.u.Out.pvImageBase, "VMMR0EntryFast", &VMMR0EntryFast);
rc = RTLdrGetSymbolEx(hLdrMod, &pLoadReq->u.In.abImage[0], (uintptr_t)OpenReq.u.Out.pvImageBase, "VMMR0EntryEx", &VMMR0EntryEx);
else if (pszSrvReqHandler)
rc = RTLdrGetSymbolEx(hLdrMod, &pLoadReq->u.In.abImage[0], (uintptr_t)OpenReq.u.Out.pvImageBase, pszSrvReqHandler, &SrvReqHandler);
int rc2 = RTLdrGetSymbolEx(hLdrMod, &pLoadReq->u.In.abImage[0], (uintptr_t)OpenReq.u.Out.pvImageBase, "ModuleInit", &ModuleInit);
ModuleInit = 0;
rc2 = RTLdrGetSymbolEx(hLdrMod, &pLoadReq->u.In.abImage[0], (uintptr_t)OpenReq.u.Out.pvImageBase, "ModuleTerm", &ModuleTerm);
ModuleTerm = 0;
AssertRelease((size_t)(CreateArgs.pSym - (PSUPLDRSYM)&pLoadReq->u.In.abImage[offSymTab]) <= CalcArgs.cSymbols);
if (fIsVMMR0)
else if (pszSrvReqHandler)
if (!g_u32FakeMode)
rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_LDR_LOAD, pLoadReq, SUP_IOCTL_LDR_LOAD_SIZE(cbImageWithTabs));
if (fIsVMMR0)
LogRel(("SUP: VMMR0EntryEx located at %RTptr, VMMR0EntryFast at %RTptr and VMMR0EntryInt at %RTptr\n",
#ifdef RT_OS_WINDOWS
return VINF_SUCCESS;
AssertMsgFailed(("failed to allocated %u bytes for SUPLDRLOAD_IN structure!\n", SUP_IOCTL_LDR_LOAD_SIZE(cbImageWithTabs)));
if (fIsVMMR0)
#ifdef RT_OS_WINDOWS
return rc;
return VINF_SUCCESS;
return rc;
return VINF_SUCCESS;
return VERR_SYMBOL_NOT_FOUND;
int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_LDR_GET_SYMBOL, &Req, SUP_IOCTL_LDR_GET_SYMBOL_SIZE);
return rc;
void *pvImageBase;
if (g_pSUPGlobalInfoPage)
return VINF_SUCCESS;
return VERR_WRONG_ORDER;
static int supR3HardenedLdrLoadIt(const char *pszFilename, PRTLDRMOD phLdrMod, uint32_t fFlags, PRTERRINFO pErrInfo)
#ifdef VBOX_WITH_HARDENING
SUPR3DECL(int) SUPR3HardenedLdrLoad(const char *pszFilename, PRTLDRMOD phLdrMod, uint32_t fFlags, PRTERRINFO pErrInfo)
SUPR3DECL(int) SUPR3HardenedLdrLoadAppPriv(const char *pszFilename, PRTLDRMOD phLdrMod, uint32_t fFlags, PRTERRINFO pErrInfo)
LogFlow(("SUPR3HardenedLdrLoadAppPriv: pszFilename=%p:{%s} phLdrMod=%p fFlags=%08x pErrInfo=%p\n", pszFilename, pszFilename, phLdrMod, fFlags, pErrInfo));
AssertMsgReturn(cchFilename < (RTPATH_MAX / 4) * 3, ("%zu\n", cchFilename), VERR_INVALID_PARAMETER);
return VERR_FILE_NOT_FOUND;
return rc;
SUPR3DECL(int) SUPR3HardenedLdrLoadPlugIn(const char *pszFilename, PRTLDRMOD phLdrMod, PRTERRINFO pErrInfo)
#ifdef VBOX_WITH_HARDENING
return rc;
#ifdef RT_OS_LINUX
return suplibOsQueryVTxSupported();
return VINF_SUCCESS;
*pfCaps = 0;
return VINF_SUCCESS;
return rc;
return VINF_SUCCESS;
return rc;
return VINF_SUCCESS;
return rc;
return VERR_NOT_SUPPORTED;
return rc;
typedef struct SUPDRVTRACERSTRTAB
char *pchStrTab;
static void supr3TracerDestroyStrTab(PSUPDRVTRACERSTRTAB pThis, PVTGPROBELOC32 paProbeLocs32, PVTGPROBELOC64 paProbeLocs64,
if (f32Bit)
bool f32Bit)
return NULL;
if (!pThis)
return NULL;
if (!pbmHash)
return NULL;
cbMax = 0;
if (cbMax > 0)
return NULL;
offPrev = 0;
if (f32Bit)
return pThis;
SUPR3DECL(int) SUPR3TracerRegisterModule(uintptr_t hModNative, const char *pszModule, struct VTGOBJHDR *pVtgHdr,
AssertReturn(!memcmp(pVtgHdr->szMagic, VTGOBJHDR_MAGIC, sizeof(pVtgHdr->szMagic)), VERR_SUPDRV_VTG_MAGIC);
AssertReturn(fFlags == SUP_TRACER_UMOD_FLAGS_EXE || fFlags == SUP_TRACER_UMOD_FLAGS_SHARED, VERR_INVALID_PARAMETER);
return VERR_SUPDRV_VTG_BAD_HDR_TOO_MUCH;
LogRel(("SUPR3TracerRegisterModule: VERR_SUPDRV_VTG_BAD_HDR_PTR - u64Tmp=%#llx uProbeLocs=%#llx uVtgHdrAddr=%RTptr\n",
return VERR_SUPDRV_VTG_BAD_HDR_PTR;
return VINF_SUCCESS;
return VINF_SUCCESS;
if (!pStrTab)
return VERR_NO_MEMORY;
int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_TRACER_UMOD_REG, &Req, SUP_IOCTL_TRACER_UMOD_REG_SIZE);
return rc;
AssertReturn(!memcmp(pVtgHdr->szMagic, VTGOBJHDR_MAGIC, sizeof(pVtgHdr->szMagic)), VERR_SUPDRV_VTG_MAGIC);
return VINF_SUCCESS;
return VINF_SUCCESS;
int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_TRACER_UMOD_DEREG, &Req, SUP_IOCTL_TRACER_UMOD_DEREG_SIZE);
return rc;