SUPR3HardenedVerify.cpp revision 3c36c06229c460f138561516170abc867297f256
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync * VirtualBox Support Library - Verification of Hardened Installation.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * Copyright (C) 2006-2013 Oracle Corporation
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync * available from http://www.virtualbox.org. This file is free software;
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync * you can redistribute it and/or modify it under the terms of the GNU
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync * General Public License (GPL) as published by the Free Software
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync * The contents of this file may alternatively be used under the terms
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync * of the Common Development and Distribution License Version 1.0
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync * VirtualBox OSE distribution, in which case the provisions of the
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync * CDDL are applicable instead of those of the GPL.
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync * You may elect to license modified versions of this file under the
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * terms and conditions of either the GPL or the CDDL or both.
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync/*******************************************************************************
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync* Header Files *
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync*******************************************************************************/
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync#else /* UNIXes */
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync#if defined(RT_OS_WINDOWS) && defined(VBOX_WITH_HARDENING)
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync/*******************************************************************************
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync* Defined Constants And Macros *
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync*******************************************************************************/
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync/** The max path length acceptable for a trusted path. */
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync/** Compare table file names with externally supplied names. */
0c94a8282c9042b02f022302a3d987746140eab9vboxsync/*******************************************************************************
0c94a8282c9042b02f022302a3d987746140eab9vboxsync* Global Variables *
0c94a8282c9042b02f022302a3d987746140eab9vboxsync*******************************************************************************/
0c94a8282c9042b02f022302a3d987746140eab9vboxsync * The files that gets verified.
0c94a8282c9042b02f022302a3d987746140eab9vboxsync * @todo This needs reviewing against the linux packages.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * @todo The excessive use of kSupID_SharedLib needs to be reviewed at some point. For
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * the time being we're building the linux packages with SharedLib pointing to
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * AppPrivArch (lazy bird).
0c94a8282c9042b02f022302a3d987746140eab9vboxsync /* type, dir, fOpt, "pszFile" */
0c94a8282c9042b02f022302a3d987746140eab9vboxsync /* ---------------------------------------------------------------------- */
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync { kSupIFT_Dll, kSupID_AppPrivArch, false, "VMMR0.r0" },
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync { kSupIFT_Dll, kSupID_AppPrivArch, false, "VBoxDDR0.r0" },
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync { kSupIFT_Dll, kSupID_AppPrivArch, false, "VBoxDD2R0.r0" },
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync { kSupIFT_Rc, kSupID_AppPrivArch, false, "VMMGC.gc" },
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync { kSupIFT_Rc, kSupID_AppPrivArch, false, "VBoxDDGC.gc" },
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync { kSupIFT_Rc, kSupID_AppPrivArch, false, "VBoxDD2GC.gc" },
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync { kSupIFT_Dll, kSupID_SharedLib, false, "VBoxRT" SUPLIB_DLL_SUFF },
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync { kSupIFT_Dll, kSupID_SharedLib, false, "VBoxVMM" SUPLIB_DLL_SUFF },
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync { kSupIFT_Dll, kSupID_SharedLib, false, "VBoxREM" SUPLIB_DLL_SUFF },
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync { kSupIFT_Dll, kSupID_SharedLib, true, "VBoxREM32" SUPLIB_DLL_SUFF },
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync { kSupIFT_Dll, kSupID_SharedLib, true, "VBoxREM64" SUPLIB_DLL_SUFF },
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync { kSupIFT_Dll, kSupID_SharedLib, false, "VBoxDD" SUPLIB_DLL_SUFF },
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync { kSupIFT_Dll, kSupID_SharedLib, false, "VBoxDD2" SUPLIB_DLL_SUFF },
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync { kSupIFT_Dll, kSupID_SharedLib, false, "VBoxDDU" SUPLIB_DLL_SUFF },
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync//#ifdef VBOX_WITH_DEBUGGER_GUI
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync { kSupIFT_Dll, kSupID_SharedLib, true, "VBoxDbg" SUPLIB_DLL_SUFF },
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync { kSupIFT_Dll, kSupID_SharedLib, true, "VBoxDbg3" SUPLIB_DLL_SUFF },
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync//#ifdef VBOX_WITH_SHARED_CLIPBOARD
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync { kSupIFT_Dll, kSupID_AppPrivArch, true, "VBoxSharedClipboard" SUPLIB_DLL_SUFF },
f9cdd92d151d9c28eb0f1aed25863fc04f85691dvboxsync//#ifdef VBOX_WITH_SHARED_FOLDERS
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync { kSupIFT_Dll, kSupID_AppPrivArch, true, "VBoxSharedFolders" SUPLIB_DLL_SUFF },
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync//#ifdef VBOX_WITH_DRAG_AND_DROP
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync { kSupIFT_Dll, kSupID_AppPrivArch, true, "VBoxDragAndDropSvc" SUPLIB_DLL_SUFF },
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync//#ifdef VBOX_WITH_GUEST_PROPS
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync { kSupIFT_Dll, kSupID_AppPrivArch, true, "VBoxGuestPropSvc" SUPLIB_DLL_SUFF },
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync//#ifdef VBOX_WITH_GUEST_CONTROL
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync { kSupIFT_Dll, kSupID_AppPrivArch, true, "VBoxGuestControlSvc" SUPLIB_DLL_SUFF },
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync { kSupIFT_Dll, kSupID_AppPrivArch, true, "VBoxHostChannel" SUPLIB_DLL_SUFF },
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync { kSupIFT_Dll, kSupID_AppPrivArch, true, "VBoxSharedCrOpenGL" SUPLIB_DLL_SUFF },
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync { kSupIFT_Dll, kSupID_AppPrivArch, true, "VBoxOGLhostcrutil" SUPLIB_DLL_SUFF },
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync { kSupIFT_Dll, kSupID_AppPrivArch, true, "VBoxOGLhosterrorspu" SUPLIB_DLL_SUFF },
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync { kSupIFT_Dll, kSupID_AppPrivArch, true, "VBoxOGLrenderspu" SUPLIB_DLL_SUFF },
44372afb953dc9f1f1ec71943f5f561a607c0307vboxsync { kSupIFT_Exe, kSupID_AppBin, true, "VBoxManage" SUPLIB_EXE_SUFF },
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync { kSupIFT_Exe, kSupID_AppBin, false, "VBoxSVC" SUPLIB_EXE_SUFF },
0c94a8282c9042b02f022302a3d987746140eab9vboxsync { kSupIFT_Dll, kSupID_SharedLib, false, "VBoxC" SUPLIB_DLL_SUFF },
0c94a8282c9042b02f022302a3d987746140eab9vboxsync { kSupIFT_Exe, kSupID_AppPrivArch, false, "VBoxXPCOMIPCD" SUPLIB_EXE_SUFF },
0c94a8282c9042b02f022302a3d987746140eab9vboxsync { kSupIFT_Dll, kSupID_SharedLib, false, "VBoxXPCOM" SUPLIB_DLL_SUFF },
0c94a8282c9042b02f022302a3d987746140eab9vboxsync { kSupIFT_Dll, kSupID_AppPrivArchComp, false, "VBoxXPCOMIPCC" SUPLIB_DLL_SUFF },
0c94a8282c9042b02f022302a3d987746140eab9vboxsync { kSupIFT_Dll, kSupID_AppPrivArchComp, false, "VBoxC" SUPLIB_DLL_SUFF },
0c94a8282c9042b02f022302a3d987746140eab9vboxsync { kSupIFT_Dll, kSupID_AppPrivArchComp, false, "VBoxSVCM" SUPLIB_DLL_SUFF },
0c94a8282c9042b02f022302a3d987746140eab9vboxsync { kSupIFT_Data, kSupID_AppPrivArchComp, false, "VBoxXPCOMBase.xpt" },
0c94a8282c9042b02f022302a3d987746140eab9vboxsync { kSupIFT_Dll, kSupID_SharedLib, true, "VRDPAuth" SUPLIB_DLL_SUFF },
0c94a8282c9042b02f022302a3d987746140eab9vboxsync { kSupIFT_Dll, kSupID_SharedLib, true, "VBoxAuth" SUPLIB_DLL_SUFF },
0c94a8282c9042b02f022302a3d987746140eab9vboxsync { kSupIFT_Dll, kSupID_SharedLib, true, "VBoxVRDP" SUPLIB_DLL_SUFF },
0c94a8282c9042b02f022302a3d987746140eab9vboxsync//#ifdef VBOX_WITH_HEADLESS
0c94a8282c9042b02f022302a3d987746140eab9vboxsync { kSupIFT_Exe, kSupID_AppBin, true, "VBoxHeadless" SUPLIB_EXE_SUFF },
0c94a8282c9042b02f022302a3d987746140eab9vboxsync { kSupIFT_Dll, kSupID_AppPrivArch, true, "VBoxHeadless" SUPLIB_DLL_SUFF },
0c94a8282c9042b02f022302a3d987746140eab9vboxsync { kSupIFT_Dll, kSupID_AppPrivArch, true, "VBoxVideoRecFB" SUPLIB_DLL_SUFF },
0c94a8282c9042b02f022302a3d987746140eab9vboxsync//#ifdef VBOX_WITH_QTGUI
0c94a8282c9042b02f022302a3d987746140eab9vboxsync { kSupIFT_Exe, kSupID_AppBin, true, "VirtualBox" SUPLIB_EXE_SUFF },
0c94a8282c9042b02f022302a3d987746140eab9vboxsync { kSupIFT_Dll, kSupID_AppPrivArch, true, "VirtualBox" SUPLIB_DLL_SUFF },
0c94a8282c9042b02f022302a3d987746140eab9vboxsync# if !defined(RT_OS_DARWIN) && !defined(RT_OS_WINDOWS) && !defined(RT_OS_OS2)
0c94a8282c9042b02f022302a3d987746140eab9vboxsync { kSupIFT_Dll, kSupID_SharedLib, true, "VBoxKeyboard" SUPLIB_DLL_SUFF },
0c94a8282c9042b02f022302a3d987746140eab9vboxsync//#ifdef VBOX_WITH_VBOXSDL
0c94a8282c9042b02f022302a3d987746140eab9vboxsync { kSupIFT_Exe, kSupID_AppBin, true, "VBoxSDL" SUPLIB_EXE_SUFF },
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync { kSupIFT_Dll, kSupID_AppPrivArch, true, "VBoxSDL" SUPLIB_DLL_SUFF },
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync//#ifdef VBOX_WITH_WEBSERVICES
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync { kSupIFT_Exe, kSupID_AppBin, true, "vboxwebsrv" SUPLIB_EXE_SUFF },
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync { kSupIFT_Exe, kSupID_AppBin, true, "VBoxTunctl" SUPLIB_EXE_SUFF },
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync//#ifdef VBOX_WITH_NETFLT
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync { kSupIFT_Exe, kSupID_AppBin, true, "VBoxNetDHCP" SUPLIB_EXE_SUFF },
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync { kSupIFT_Dll, kSupID_AppPrivArch, true, "VBoxNetDHCP" SUPLIB_DLL_SUFF },
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync//#ifdef VBOX_WITH_LWIP_NAT
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync { kSupIFT_Exe, kSupID_AppBin, true, "VBoxNetNAT" SUPLIB_EXE_SUFF },
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync { kSupIFT_Dll, kSupID_AppPrivArch, true, "VBoxNetNAT" SUPLIB_DLL_SUFF },
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync#if defined(VBOX_WITH_HARDENING) && defined(RT_OS_WINDOWS)
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync { kSupIFT_TestExe, kSupID_AppBin, true, a_szName SUPLIB_EXE_SUFF }, \
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync { kSupIFT_TestDll, kSupID_AppBin, true, a_szName SUPLIB_DLL_SUFF }
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync HARDENED_TESTCASE_BIN_ENTRY("tstPDMAsyncCompletion"),
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync HARDENED_TESTCASE_BIN_ENTRY("tstPDMAsyncCompletionStress"),
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync { kSupIFT_TestExe, kSupID_Testcase, true, a_szName SUPLIB_EXE_SUFF }, \
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync { kSupIFT_TestDll, kSupID_Testcase, true, a_szName SUPLIB_DLL_SUFF }
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync HARDENED_TESTCASE_ENTRY("tstR0ThreadPreemptionDriver"),
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync HARDENED_TESTCASE_ENTRY("tstRTR0MemUserKernelDriver"),
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync/** Array parallel to g_aSupInstallFiles containing per-file status info. */
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsyncstatic SUPVERIFIEDFILE g_aSupVerifiedFiles[RT_ELEMENTS(g_aSupInstallFiles)];
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync/** Array index by install directory specifier containing info about verified directories. */
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsyncstatic SUPVERIFIEDDIR g_aSupVerifiedDirs[kSupID_End];
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync * Assembles the path to a directory.
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync * @returns VINF_SUCCESS on success, some error code on failure (fFatal
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync * decides whether it returns or not).
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync * @param enmDir The directory.
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync * @param pszDst Where to assemble the path.
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync * @param cchDst The size of the buffer.
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync * @param fFatal Whether failures should be treated as fatal (true) or not (false).
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsyncstatic int supR3HardenedMakePath(SUPINSTDIR enmDir, char *pszDst, size_t cchDst, bool fFatal)
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync case kSupID_AppBin: /** @todo fix this AppBin crap (uncertain wtf some binaries actually are installed). */
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync rc = supR3HardenedPathAppPrivateArch(pszDst, cchDst);
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync rc = supR3HardenedPathAppPrivateArch(pszDst, cchDst);
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync suplibHardenedMemCopy(&pszDst[off], "/components", sizeof("/components"));
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync rc = supR3HardenedPathAppPrivateNoArch(pszDst, cchDst);
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync suplibHardenedMemCopy(&pszDst[off], "/testcase", sizeof("/testcase"));
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync return supR3HardenedError(VERR_INTERNAL_ERROR, fFatal,
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync "supR3HardenedMakePath: enmDir=%d rc=%d\n", enmDir, rc);
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * Assembles the path to a file table entry, with or without the actual filename.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * @returns VINF_SUCCESS on success, some error code on failure (fFatal
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * decides whether it returns or not).
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * @param pFile The file table entry.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * @param pszDst Where to assemble the path.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * @param cchDst The size of the buffer.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * @param fWithFilename If set, the filename is included, otherwise it is omitted (no trailing slash).
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * @param fFatal Whether failures should be treated as fatal (true) or not (false).
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsyncstatic int supR3HardenedMakeFilePath(PCSUPINSTFILE pFile, char *pszDst, size_t cchDst, bool fWithFilename, bool fFatal)
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * Combine supR3HardenedMakePath and the filename.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync int rc = supR3HardenedMakePath(pFile->enmDir, pszDst, cchDst, fFatal);
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync size_t cchFile = suplibHardenedStrLen(pFile->pszFile);
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync suplibHardenedMemCopy(&pszDst[off], pFile->pszFile, cchFile + 1);
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync rc = supR3HardenedError(VERR_BUFFER_OVERFLOW, fFatal,
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync "supR3HardenedMakeFilePath: pszFile=%s off=%lu\n",
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync * Verifies a directory.
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync * @returns VINF_SUCCESS on success. On failure, an error code is returned if
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync * fFatal is clear and if it's set the function wont return.
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync * @param enmDir The directory specifier.
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync * @param fFatal Whether validation failures should be treated as
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync * fatal (true) or not (false).
66b58af085e22ee26be57f98127fb49ee2e91790vboxsyncDECLHIDDEN(int) supR3HardenedVerifyFixedDir(SUPINSTDIR enmDir, bool fFatal)
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync * Validate the index just to be on the safe side...
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync if (enmDir <= kSupID_Invalid || enmDir >= kSupID_End)
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync return supR3HardenedError(VERR_INTERNAL_ERROR, fFatal,
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync * Already validated?
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync /* initialize the entry. */
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync "supR3HardenedVerifyDir: hDir=%p enmDir=%d\n",
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync * Make the path and open the directory.
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync int rc = supR3HardenedMakePath(enmDir, szPath, sizeof(szPath), fFatal);
0c94a8282c9042b02f022302a3d987746140eab9vboxsync FILE_SHARE_READ | FILE_SHARE_DELETE | FILE_SHARE_WRITE,
0c94a8282c9042b02f022302a3d987746140eab9vboxsync FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS,
0c94a8282c9042b02f022302a3d987746140eab9vboxsync /** @todo check the type */
0c94a8282c9042b02f022302a3d987746140eab9vboxsync /* That's all on windows, for now at least... */
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync rc = VINF_SUCCESS; /* Optional directory, ignore if missing. */
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync rc = supR3HardenedError(VERR_PATH_NOT_FOUND, fFatal,
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync "supR3HardenedVerifyDir: Failed to open \"%s\": err=%d\n",
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync "supR3HardenedVerifyDir: Failed to convert \"%s\" to UTF-16: err=%d\n", szPath, rc);
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync#else /* UNIXY */
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync * On unixy systems we'll make sure the directory is owned by root
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync * and not writable by the group and user.
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync rc = supR3HardenedError(VERR_NOT_A_DIRECTORY, fFatal,
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync "supR3HardenedVerifyDir: \"%s\" is not a directory\n",
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync rc = supR3HardenedError(VERR_ACCESS_DENIED, fFatal,
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync "supR3HardenedVerifyDir: Cannot trust the directory \"%s\": not owned by root (st_uid=%ld)\n",
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync rc = supR3HardenedError(VERR_ACCESS_DENIED, fFatal,
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync "supR3HardenedVerifyDir: Cannot trust the directory \"%s\": group and/or other writable (st_mode=0%lo)\n",
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync rc = supR3HardenedError(VERR_ACCESS_DENIED, fFatal,
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync "supR3HardenedVerifyDir: Failed to fstat \"%s\": %s (%d)\n",
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync rc = VINF_SUCCESS; /* Optional directory, ignore if missing. */
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync rc = supR3HardenedError(VERR_PATH_NOT_FOUND, fFatal,
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync "supR3HardenedVerifyDir: Failed to open \"%s\": %s (%d)\n",
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync#endif /* UNIXY */
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync * Opens the file for verification.
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync * @returns VINF_SUCCESS on success. On failure, an error code is returned if
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync * fFatal is clear and if it's set the function wont return.
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync * @param pFile The file entry.
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync * @param fFatal Whether validation failures should be treated as
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync * kl fatal (true) or not (false).
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync * @param phFile The file handle, set to -1 if we failed to open
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync * the file. The function may return VINF_SUCCESS
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync * and a -1 handle if the file is optional.
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsyncstatic int supR3HardenedVerifyFileOpen(PCSUPINSTFILE pFile, bool fFatal, intptr_t *phFile)
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync int rc = supR3HardenedMakeFilePath(pFile, szPath, sizeof(szPath), true /*fWithFilename*/, fFatal);
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync && (err != ERROR_PATH_NOT_FOUND || pFile->enmDir != kSupID_Testcase) ) )
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync rc = supR3HardenedError(VERR_PATH_NOT_FOUND, fFatal,
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync "supR3HardenedVerifyFileInternal: Failed to open '%s': err=%d\n", szPath, err);
0c94a8282c9042b02f022302a3d987746140eab9vboxsync rc = supR3HardenedError(rc, fFatal, "supR3HardenedVerifyFileInternal: Failed to convert '%s' to UTF-16: %Rrc\n",
0c94a8282c9042b02f022302a3d987746140eab9vboxsync * Worker for supR3HardenedVerifyFileInternal.
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync * @returns VINF_SUCCESS on success. On failure, an error code is returned if
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync * fFatal is clear and if it's set the function wont return.
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync * @param pFile The file entry.
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync * @param pVerified The verification record.
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync * @param fFatal Whether validation failures should be treated as
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync * fatal (true) or not (false).
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync * @param fLeaveFileOpen Whether the file should be left open.
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsyncstatic int supR3HardenedVerifyFileSignature(PCSUPINSTFILE pFile, PSUPVERIFIEDFILE pVerified, bool fFatal, bool fLeaveFileOpen)
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync# if defined(VBOX_WITH_HARDENING) && !defined(IN_SUP_R3_STATIC) /* Latter: Not in VBoxCpuReport and friends. */
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync * Open the file if we have to.
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync rc = supR3HardenedVerifyFileOpen(pFile, fFatal, &hFileOpened);
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync * Verify the signature.
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync rc = supHardenedWinVerifyImageByHandleNoName((HANDLE)hFile, fFlags, &ErrInfo);
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync rc = supR3HardenedError(rc, fFatal, "supR3HardenedVerifyFileInternal: '%s': Image verify error rc=%Rrc: %s\n",
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync * Close the handle if we opened the file and we should close it.
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync# else /* Not checking signatures. */
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync# endif /* Not checking signatures. */
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync * Verifies a file entry.
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync * @returns VINF_SUCCESS on success. On failure, an error code is returned if
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync * fFatal is clear and if it's set the function wont return.
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync * @param iFile The file table index of the file to be verified.
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync * @param fFatal Whether validation failures should be treated as
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync * fatal (true) or not (false).
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync * @param fLeaveFileOpen Whether the file should be left open.
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync * @param fVerifyAll Set if this is an verify all call and we will
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync * postpone signature checking.
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsyncstatic int supR3HardenedVerifyFileInternal(int iFile, bool fFatal, bool fLeaveFileOpen, bool fVerifyAll)
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync PSUPVERIFIEDFILE pVerified = &g_aSupVerifiedFiles[iFile];
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync * Already done validation? Do signature validation if we haven't yet.
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync /** @todo revalidate? Check that the file hasn't been replace or similar. */
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync return supR3HardenedVerifyFileSignature(pFile, pVerified, fFatal, fLeaveFileOpen);
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync /* initialize the entry. */
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync "supR3HardenedVerifyFileInternal: hFile=%p (%s)\n",
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync * Verify the directory then proceed to open it.
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync * (This'll make sure the directory is opened and that we can (later)
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync * use openat if we wish.)
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync int rc = supR3HardenedVerifyFixedDir(pFile->enmDir, fFatal);
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync rc = supR3HardenedVerifyFileOpen(pFile, fFatal, &pVerified->hFile);
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync rc = supR3HardenedVerifyFileSignature(pFile, pVerified, fFatal, fLeaveFileOpen);
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync#else /* !RT_OS_WINDOWS */
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync rc = supR3HardenedMakeFilePath(pFile, szPath, sizeof(szPath), true /*fWithFilename*/, fFatal);
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync * On unixy systems we'll make sure the file is owned by root
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync * and not writable by the group and user.
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync /* it's valid. */
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync rc = supR3HardenedError(VERR_IS_A_DIRECTORY, fFatal,
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync "supR3HardenedVerifyFileInternal: \"%s\" is not a regular file\n",
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync rc = supR3HardenedError(VERR_ACCESS_DENIED, fFatal,
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync "supR3HardenedVerifyFileInternal: Cannot trust the file \"%s\": not owned by root (st_uid=%ld)\n",
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync rc = supR3HardenedError(VERR_ACCESS_DENIED, fFatal,
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync "supR3HardenedVerifyFileInternal: Cannot trust the file \"%s\": group and/or other writable (st_mode=0%lo)\n",
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync rc = supR3HardenedError(VERR_ACCESS_DENIED, fFatal,
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync "supR3HardenedVerifyFileInternal: Failed to fstat \"%s\": %s (%d)\n",
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync rc = supR3HardenedError(VERR_PATH_NOT_FOUND, fFatal,
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync "supR3HardenedVerifyFileInternal: Failed to open \"%s\": %s (%d)\n",
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync#endif /* !RT_OS_WINDOWS */
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync * Verifies that the specified table entry matches the given filename.
44372afb953dc9f1f1ec71943f5f561a607c0307vboxsync * @returns VINF_SUCCESS if matching. On mismatch fFatal indicates whether an
44372afb953dc9f1f1ec71943f5f561a607c0307vboxsync * error is returned or we terminate the application.
44372afb953dc9f1f1ec71943f5f561a607c0307vboxsync * @param iFile The file table index.
44372afb953dc9f1f1ec71943f5f561a607c0307vboxsync * @param pszFilename The filename.
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync * @param fFatal Whether validation failures should be treated as
9c9db71d639cf066ed41d49629d46d48bff4be2fvboxsync * fatal (true) or not (false).
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsyncstatic int supR3HardenedVerifySameFile(int iFile, const char *pszFilename, bool fFatal)
44372afb953dc9f1f1ec71943f5f561a607c0307vboxsync * Construct the full path for the file table entry
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync * and compare it with the specified file.
44372afb953dc9f1f1ec71943f5f561a607c0307vboxsync int rc = supR3HardenedMakeFilePath(pFile, szName, sizeof(szName), true /*fWithFilename*/, fFatal);
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync * Normalize the two paths and compare again.
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync if ( GetFullPathName(szName, RT_ELEMENTS(szName2), &szName2[0], &pszIgnored)
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync && GetFullPathName(pszFilename, RT_ELEMENTS(szName), &szName[0], &pszIgnored))
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync supR3HardenedMakeFilePath(pFile, szName, sizeof(szName), true /*fWithFilename*/, fFatal);
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync "supR3HardenedVerifySameFile: \"%s\" isn't the same as \"%s\"\n",
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * Check more stuff like the stat info if it's an already open file?
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync * Verifies a file.
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync * @returns VINF_SUCCESS on success.
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync * VERR_NOT_FOUND if the file isn't in the table, this isn't ever a fatal error.
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync * On verification failure, an error code will be returned when fFatal is clear,
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync * otherwise the program will be terminated.
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync * @param pszFilename The filename.
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync * @param fFatal Whether validation failures should be treated as
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync * fatal (true) or not (false).
66b58af085e22ee26be57f98127fb49ee2e91790vboxsyncDECLHIDDEN(int) supR3HardenedVerifyFixedFile(const char *pszFilename, bool fFatal)
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * Lookup the file and check if it's the same file.
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync const char *pszName = supR3HardenedPathFilename(pszFilename);
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync for (unsigned iFile = 0; iFile < RT_ELEMENTS(g_aSupInstallFiles); iFile++)
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync if (!SUP_COMP_FILENAME(pszName, g_aSupInstallFiles[iFile].pszFile))
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync int rc = supR3HardenedVerifySameFile(iFile, pszFilename, fFatal);
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync rc = supR3HardenedVerifyFileInternal(iFile, fFatal, false /* fLeaveFileOpen */, false /* fVerifyAll */);
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync * Verifies a program, worker for supR3HardenedVerifyAll.
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync * @returns See supR3HardenedVerifyAll.
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync * @param pszProgName See supR3HardenedVerifyAll.
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync * @param fFatal See supR3HardenedVerifyAll.
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync * @param fLeaveOpen The leave open setting used by
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync * supR3HardenedVerifyAll.
66b58af085e22ee26be57f98127fb49ee2e91790vboxsyncstatic int supR3HardenedVerifyProgram(const char *pszProgName, bool fFatal, bool fLeaveOpen)
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync * Search the table looking for the executable and the DLL/DYLIB/SO.
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync bool fExe = false;
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync bool fDll = false;
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync size_t const cchProgName = suplibHardenedStrLen(pszProgName);
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync for (unsigned iFile = 0; iFile < RT_ELEMENTS(g_aSupInstallFiles); iFile++)
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync if (!suplibHardenedStrNCmp(pszProgName, g_aSupInstallFiles[iFile].pszFile, cchProgName))
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync if ( ( g_aSupInstallFiles[iFile].enmType == kSupIFT_Dll
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync || g_aSupInstallFiles[iFile].enmType == kSupIFT_TestDll)
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync && !suplibHardenedStrCmp(&g_aSupInstallFiles[iFile].pszFile[cchProgName], SUPLIB_DLL_SUFF))
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync /* This only has to be found (once). */
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync rc = supR3HardenedError(VERR_INTERNAL_ERROR, fFatal,
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync "supR3HardenedVerifyProgram: duplicate DLL entry for \"%s\"\n", pszProgName);
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync rc = supR3HardenedVerifyFileInternal(iFile, fFatal, fLeaveOpen, false /* fVerifyAll */);
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync else if ( ( g_aSupInstallFiles[iFile].enmType == kSupIFT_Exe
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync || g_aSupInstallFiles[iFile].enmType == kSupIFT_TestExe)
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync && !suplibHardenedStrCmp(&g_aSupInstallFiles[iFile].pszFile[cchProgName], SUPLIB_EXE_SUFF))
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync /* Here we'll have to check that the specific program is the same as the entry. */
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync rc = supR3HardenedError(VERR_INTERNAL_ERROR, fFatal,
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync "supR3HardenedVerifyProgram: duplicate EXE entry for \"%s\"\n", pszProgName);
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync rc = supR3HardenedVerifyFileInternal(iFile, fFatal, fLeaveOpen, false /* fVerifyAll */);
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync int rc2 = supR3HardenedPathExecDir(szFilename, sizeof(szFilename) - cchProgName - sizeof(SUPLIB_EXE_SUFF));
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync suplibHardenedStrCat(szFilename, g_aSupInstallFiles[iFile].pszFile);
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync supR3HardenedVerifySameFile(iFile, szFilename, fFatal);
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync "supR3HardenedVerifyProgram: failed to query program path: rc=%d\n", rc2);
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync * Check the findings.
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync "supR3HardenedVerifyProgram: Couldn't find the program \"%s\"\n", pszProgName);
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync "supR3HardenedVerifyProgram: Couldn't find the EXE entry for \"%s\"\n", pszProgName);
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync "supR3HardenedVerifyProgram: Couldn't find the DLL entry for \"%s\"\n", pszProgName);
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync * Verifies all the known files (called from SUPR3HardenedMain).
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync * @returns VINF_SUCCESS on success.
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync * On verification failure, an error code will be returned when fFatal is clear,
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync * otherwise the program will be terminated.
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync * @param fFatal Whether validation failures should be treated as
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync * fatal (true) or not (false).
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsync * @param pszProgName The program name. This is used to verify that
f9cdd92d151d9c28eb0f1aed25863fc04f85691dvboxsync * both the executable and corresponding
f9cdd92d151d9c28eb0f1aed25863fc04f85691dvboxsync * DLL/DYLIB/SO are valid.
c66c4413faa5a72ce047742f9acfa85e94dec8afvboxsyncDECLHIDDEN(int) supR3HardenedVerifyAll(bool fFatal, const char *pszProgName)
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync * On windows
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync bool fLeaveOpen = false;
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync * The verify all the files.
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync for (unsigned iFile = 0; iFile < RT_ELEMENTS(g_aSupInstallFiles); iFile++)
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync int rc2 = supR3HardenedVerifyFileInternal(iFile, fFatal, fLeaveOpen, true /* fVerifyAll */);
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync * Verify the program name, that is to say, check that it's in the table
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync * (thus verified above) and verify the signature on platforms where we
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync * sign things.
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync int rc2 = supR3HardenedVerifyProgram(pszProgName, fFatal, fLeaveOpen);
66b58af085e22ee26be57f98127fb49ee2e91790vboxsync * Copies the N messages into the error buffer and returns @a rc.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * @returns Returns @a rc
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * @param rc The return code.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * @param pErrInfo The error info structure.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * @param cMsgs The number of messages in the ellipsis.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * @param ... Message parts.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsyncstatic int supR3HardenedSetErrorN(int rc, PRTERRINFO pErrInfo, unsigned cMsgs, ...)
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync size_t cchMsg = VALID_PTR(pszMsg) ? suplibHardenedStrLen(pszMsg) : 0;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * Copies the three messages into the error buffer and returns @a rc.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * @returns Returns @a rc
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * @param rc The return code.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * @param pErrInfo The error info structure.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * @param pszMsg1 The first message part.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * @param pszMsg2 The second message part.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * @param pszMsg3 The third message part.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsyncstatic int supR3HardenedSetError3(int rc, PRTERRINFO pErrInfo, const char *pszMsg1,
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync return supR3HardenedSetErrorN(rc, pErrInfo, 3, pszMsg1, pszMsg2, pszMsg3);
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * Copies the two messages into the error buffer and returns @a rc.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * @returns Returns @a rc
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * @param rc The return code.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * @param pErrInfo The error info structure.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * @param pszMsg1 The first message part.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * @param pszMsg2 The second message part.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsyncstatic int supR3HardenedSetError2(int rc, PRTERRINFO pErrInfo, const char *pszMsg1,
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync const char *pszMsg2)
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync return supR3HardenedSetErrorN(rc, pErrInfo, 2, pszMsg1, pszMsg2);
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * Copies the error message to the error buffer and returns @a rc.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * @returns Returns @a rc
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * @param rc The return code.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * @param pErrInfo The error info structure.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * @param pszMsg The message.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsyncstatic int supR3HardenedSetError(int rc, PRTERRINFO pErrInfo, const char *pszMsg)
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync return supR3HardenedSetErrorN(rc, pErrInfo, 1, pszMsg);
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync#endif /* SOME_UNUSED_FUNCTION */
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * Output from a successfull supR3HardenedVerifyPathSanity call.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync /** The length of the path in szCopy. */
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync /** The number of path components. */
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync /** Set if the path ends with slash, indicating that it's a directory
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync * reference and not a file reference. The slash has been removed from
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync * the copy. */
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync /** The offset where each path component starts, i.e. the char after the
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync * slash. The array has cComponents + 1 entries, where the final one is
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync * cch + 1 so that one can always terminate the current component by
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync * szPath[aoffComponent[i] - 1] = '\0'. */
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync /** A normalized copy of the path.
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync * Reserve some extra space so we can be more relaxed about overflow
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync * checks and terminator paddings, especially when recursing. */
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync/** Pointer to a parsed path. */
88e56f700a3b8dfdf1646f96320f335e22339caavboxsynctypedef SUPR3HARDENEDPATHINFO *PSUPR3HARDENEDPATHINFO;
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync * Verifies that the path is absolutely sane, it also parses the path.
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync * A sane path starts at the root (w/ drive letter on DOS derived systems) and
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync * does not have any relative bits (/../) or unnecessary slashes (/bin//ls).
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync * Sane paths are less or equal to SUPR3HARDENED_MAX_PATH bytes in length. UNC
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync * paths are not supported.
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync * @returns VBox status code.
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync * @param pszPath The path to check.
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync * @param pErrInfo The error info structure.
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync * @param pInfo Where to return a copy of the path along with
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync * parsing information.
88e56f700a3b8dfdf1646f96320f335e22339caavboxsyncstatic int supR3HardenedVerifyPathSanity(const char *pszPath, PRTERRINFO pErrInfo, PSUPR3HARDENEDPATHINFO pInfo)
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * Check that it's an absolute path and copy the volume/root specifier.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync return supR3HardenedSetError3(VERR_SUPLIB_PATH_NOT_ABSOLUTE, pErrInfo, "The path is not absolute: '", pszPath, "'");
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync return supR3HardenedSetError3(VERR_SUPLIB_PATH_NOT_ABSOLUTE, pErrInfo, "The path is not absolute: '", pszPath, "'");
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * No path specifying the root or something very shortly thereafter will
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * be approved of.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync return supR3HardenedSetError3(VERR_SUPLIB_PATH_IS_ROOT, pErrInfo, "The path is root: '", pszPath, "'");
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync return supR3HardenedSetError3(VERR_SUPLIB_PATH_TOO_SHORT, pErrInfo, "The path is too short: '", pszPath, "'");
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync * Check each component. No parent references or double slashes.
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync /* Sanity checks. */
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync if (RTPATH_IS_SLASH(pszSrc[0])) /* can be relaxed if we care. */
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync return supR3HardenedSetError3(VERR_SUPLIB_PATH_NOT_CLEAN, pErrInfo,
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync "The path is not clean of double slashes: '", pszPath, "'");
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync return supR3HardenedSetError3(VERR_SUPLIB_PATH_NOT_ABSOLUTE, pErrInfo,
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync /* Record the start of the component. */
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync if (pInfo->cComponents >= RT_ELEMENTS(pInfo->aoffComponents) - 1)
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync return supR3HardenedSetError3(VERR_SUPLIB_PATH_TOO_MANY_COMPONENTS, pErrInfo,
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync "The path has too many components: '", pszPath, "'");
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync pInfo->aoffComponents[pInfo->cComponents++] = pszDst - &pInfo->szPath[0];
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync /* Traverse to the end of the component, copying it as we go along. */
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync if ((uintptr_t)(pszDst - &pInfo->szPath[0]) >= SUPR3HARDENED_MAX_PATH)
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync return supR3HardenedSetError3(VERR_SUPLIB_PATH_TOO_LONG, pErrInfo,
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync /* Terminate the string and enter its length. */
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync pInfo->cch = (uint16_t)(pszDst - &pInfo->szPath[0]);
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync pInfo->aoffComponents[pInfo->cComponents] = pInfo->cch + 1;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * The state information collected by supR3HardenedVerifyFsObject.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * This can be used to verify that a directory we've opened for enumeration is
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * the same as the one that supR3HardenedVerifyFsObject just verified. It can
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * equally be used to verify a native specfied by the user.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync /** Not implemented for windows yet. */
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync /** The stat output. */
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync/** Pointer to a file system object state. */
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsynctypedef SUPR3HARDENEDFSOBJSTATE *PSUPR3HARDENEDFSOBJSTATE;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync/** Pointer to a const file system object state. */
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsynctypedef SUPR3HARDENEDFSOBJSTATE const *PCSUPR3HARDENEDFSOBJSTATE;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * Query information about a file system object by path.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * @returns VBox status code, error buffer filled on failure.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * @param pszPath The path to the object.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * @param pFsObjState Where to return the state information.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * @param pErrInfo The error info structure.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsyncstatic int supR3HardenedQueryFsObjectByPath(char const *pszPath, PSUPR3HARDENEDFSOBJSTATE pFsObjState, PRTERRINFO pErrInfo)
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync /** @todo Windows hardening. */
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync * Stat the object, do not follow links.
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync /* Ignore access errors */
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync return supR3HardenedSetErrorN(VERR_SUPLIB_STAT_FAILED, pErrInfo,
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync 5, "stat failed with ", strerror(errno), " on: '", pszPath, "'");
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync * Read ACLs.
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync /** @todo */
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync * Query information about a file system object by native handle.
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync * @returns VBox status code, error buffer filled on failure.
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync * @param hNative The native handle to the object @a pszPath
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync * specifies and this should be verified to be the
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync * same file system object.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * @param pFsObjState Where to return the state information.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * @param pszPath The path to the object. (For the error message
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * @param pErrInfo The error info structure.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsyncstatic int supR3HardenedQueryFsObjectByHandle(RTHCUINTPTR hNative, PSUPR3HARDENEDFSOBJSTATE pFsObjState,
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync /** @todo Windows hardening. */
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * Stat the object, do not follow links.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync return supR3HardenedSetErrorN(VERR_SUPLIB_STAT_FAILED, pErrInfo,
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync 5, "fstat failed with ", strerror(errno), " on '", pszPath, "'");
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * Read ACLs.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync /** @todo */
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * Verifies that the file system object indicated by the native handle is the
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * same as the one @a pFsObjState indicates.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * @returns VBox status code, error buffer filled on failure.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * @param pFsObjState1 File system object information/state by path.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * @param pFsObjState2 File system object information/state by handle.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * @param pszPath The path to the object @a pFsObjState
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * describes. (For the error message.)
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync * @param pErrInfo The error info structure.
88e56f700a3b8dfdf1646f96320f335e22339caavboxsyncstatic int supR3HardenedIsSameFsObject(PCSUPR3HARDENEDFSOBJSTATE pFsObjState1, PCSUPR3HARDENEDFSOBJSTATE pFsObjState2,
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync /** @todo Windows hardening. */
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync * Compare the ino+dev, then the uid+gid and finally the important mode
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * bits. Technically the first one should be enough, but we're paranoid.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync if ( pFsObjState1->Stat.st_ino != pFsObjState2->Stat.st_ino
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync || pFsObjState1->Stat.st_dev != pFsObjState2->Stat.st_dev)
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync return supR3HardenedSetError3(VERR_SUPLIB_NOT_SAME_OBJECT, pErrInfo,
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync "The native handle is not the same as '", pszPath, "' (ino/dev)");
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync if ( pFsObjState1->Stat.st_uid != pFsObjState2->Stat.st_uid
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync || pFsObjState1->Stat.st_gid != pFsObjState2->Stat.st_gid)
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync return supR3HardenedSetError3(VERR_SUPLIB_NOT_SAME_OBJECT, pErrInfo,
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync "The native handle is not the same as '", pszPath, "' (uid/gid)");
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync if ( (pFsObjState1->Stat.st_mode & (S_IFMT | S_IWUSR | S_IWGRP | S_IWOTH))
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync != (pFsObjState2->Stat.st_mode & (S_IFMT | S_IWUSR | S_IWGRP | S_IWOTH)))
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync return supR3HardenedSetError3(VERR_SUPLIB_NOT_SAME_OBJECT, pErrInfo,
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync "The native handle is not the same as '", pszPath, "' (mode)");
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * Verifies a file system object (file or directory).
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * @returns VBox status code, error buffer filled on failure.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * @param pFsObjState The file system object information/state to be
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * verified.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * @param fDir Whether this is a directory or a file.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * @param fRelaxed Whether we can be more relaxed about this
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * directory (only used for grand parent
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * directories).
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * @param pszPath The path to the object. For error messages and
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * securing a couple of hacks.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * @param pErrInfo The error info structure.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsyncstatic int supR3HardenedVerifyFsObject(PCSUPR3HARDENEDFSOBJSTATE pFsObjState, bool fDir, bool fRelaxed,
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync /** @todo Windows hardening. */
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync NOREF(pFsObjState); NOREF(fDir); NOREF(fRelaxed); NOREF(pszPath); NOREF(pErrInfo);
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync /* No hardening here - it's a single user system. */
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync NOREF(pFsObjState); NOREF(fDir); NOREF(fRelaxed); NOREF(pszPath); NOREF(pErrInfo);
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * The owner must be root.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * This can be extended to include predefined system users if necessary.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync return supR3HardenedSetError3(VERR_SUPLIB_OWNER_NOT_ROOT, pErrInfo, "The owner is not root: '", pszPath, "'");
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * The object type must be directory or file, no symbolic links or other
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * risky stuff (sorry dude, but we're paranoid on purpose here).
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync return supR3HardenedSetError3(VERR_SUPLIB_SYMLINKS_ARE_NOT_PERMITTED, pErrInfo,
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync return supR3HardenedSetError3(VERR_SUPLIB_NOT_DIR_NOT_FILE, pErrInfo,
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync return supR3HardenedSetError3(VERR_SUPLIB_IS_DIRECTORY, pErrInfo,
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync "Expected file but found directory: '", pszPath, "'");
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync return supR3HardenedSetError3(VERR_SUPLIB_IS_FILE, pErrInfo,
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync "Expected directory but found file: '", pszPath, "'");
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * The group does not matter if it does not have write access, if it has
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * write access it must be group 0 (root/wheel/whatever).
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * This can be extended to include predefined system groups or groups that
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * only root is member of.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync /* HACK ALERT: On Darwin /Applications is root:admin with admin having
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync full access. So, to work around we relax the hardening a bit and
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync permit grand parents and beyond to be group writable by admin. */
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync /** @todo dynamically resolve the admin group? */
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync bool fBad = !fRelaxed || pFsObjState->Stat.st_gid != 80 /*admin*/ || suplibHardenedStrCmp(pszPath, "/Applications");
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync /* HACK ALERT: PC-BSD 9 has group-writable /usr/pib directory which is
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync similar to /Applications on OS X (see above).
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync On FreeBSD root is normally the only member of this group, on
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync PC-BSD the default user is a member. */
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync /** @todo dynamically resolve the operator group? */
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync bool fBad = !fRelaxed || pFsObjState->Stat.st_gid != 5 /*operator*/ || suplibHardenedStrCmp(pszPath, "/usr/pbi");
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync bool fBad = true;
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync return supR3HardenedSetError3(VERR_SUPLIB_WRITE_NON_SYS_GROUP, pErrInfo,
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync "The group is not a system group and it has write access to '", pszPath, "'");
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * World must not have write access. There is no relaxing this rule.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync return supR3HardenedSetError3(VERR_SUPLIB_WORLD_WRITABLE, pErrInfo,
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * Check the ACLs.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync /** @todo */
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * Verifies that the file system object indicated by the native handle is the
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * same as the one @a pFsObjState indicates.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * @returns VBox status code, error buffer filled on failure.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * @param hNative The native handle to the object @a pszPath
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * specifies and this should be verified to be the
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * same file system object.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * @param pFsObjState The information/state returned by a previous
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * query call.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * @param pszPath The path to the object @a pFsObjState
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * describes. (For the error message.)
661bfa5aae55ac2f94fa1cb131ea2323e5f6e633vboxsync * @param pErrInfo The error info structure.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsyncstatic int supR3HardenedVerifySameFsObject(RTHCUINTPTR hNative, PCSUPR3HARDENEDFSOBJSTATE pFsObjState,
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync int rc = supR3HardenedQueryFsObjectByHandle(hNative, &FsObjState2, pszPath, pErrInfo);
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync rc = supR3HardenedIsSameFsObject(pFsObjState, &FsObjState2, pszPath, pErrInfo);
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * Does the recursive directory enumeration.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * @returns VBox status code, error buffer filled on failure.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * @param pszDirPath The path buffer containing the subdirectory to
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * enumerate followed by a slash (this is never
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * the root slash). The buffer is RTPATH_MAX in
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * size and anything starting at @a cchDirPath
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * - 1 and beyond is scratch space.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * @param cchDirPath The length of the directory path + slash.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * @param pFsObjState Pointer to the file system object state buffer.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * On input this will hold the stats for
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * the directory @a pszDirPath indicates and will
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * be used to verified that we're opening the same
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * @param fRecursive Whether to recurse into subdirectories.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * @param pErrInfo The error info structure.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsyncstatic int supR3HardenedVerifyDirRecursive(char *pszDirPath, size_t cchDirPath, PSUPR3HARDENEDFSOBJSTATE pFsObjState,
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync /** @todo Windows hardening. */
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync /* No hardening here - it's a single user system. */
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * Open the directory. Now, we could probably eliminate opendir here
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * and go down on kernel API level (open + getdents for instance), however
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * that's not very portable and hopefully not necessary.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync /* Ignore access errors. */
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync return supR3HardenedSetErrorN(VERR_SUPLIB_DIR_ENUM_FAILED, pErrInfo,
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync 5, "opendir failed with ", strerror(errno), " on '", pszDirPath, "'");
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync int rc = supR3HardenedVerifySameFsObject(dirfd(pDir), pFsObjState, pszDirPath, pErrInfo);
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync * Enumerate the directory, check all the requested bits.
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync pszDirPath[cchDirPath] = '\0'; /* for error messages. */
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync rc = supR3HardenedSetErrorN(VERR_SUPLIB_DIR_ENUM_FAILED, pErrInfo,
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync 5, "readdir_r failed with ", strerror(iErr), " in '", pszDirPath, "'");
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * Check the length and copy it into the path buffer so it can be
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync * stat()'ed.
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync size_t cchName = suplibHardenedStrLen(pEntry->d_name);
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync rc = supR3HardenedSetErrorN(VERR_SUPLIB_PATH_TOO_LONG, pErrInfo,
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync 4, "Path grew too long during recursion: '", pszDirPath, pEntry->d_name, "'");
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync suplibHardenedMemCopy(&pszDirPath[cchName], pEntry->d_name, cchName + 1);
0c94a8282c9042b02f022302a3d987746140eab9vboxsync * Query the information about the entry and verify it.
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync * (We don't bother skipping '.' and '..' at this point, a little bit
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync * of extra checks doesn't hurt and neither requires relaxed handling.)
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync rc = supR3HardenedQueryFsObjectByPath(pszDirPath, pFsObjState, pErrInfo);
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync rc = supR3HardenedVerifyFsObject(pFsObjState, S_ISDIR(pFsObjState->Stat.st_mode), false /*fRelaxed*/,
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * Recurse into subdirectories if requested.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync rc = supR3HardenedVerifyDirRecursive(pszDirPath, cchDirPath + cchName + 1, pFsObjState,
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync * Worker for SUPR3HardenedVerifyDir.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * @returns See SUPR3HardenedVerifyDir.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * @param pszDirPath See SUPR3HardenedVerifyDir.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * @param fRecursive See SUPR3HardenedVerifyDir.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * @param fCheckFiles See SUPR3HardenedVerifyDir.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * @param pErrInfo See SUPR3HardenedVerifyDir.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsyncDECLHIDDEN(int) supR3HardenedVerifyDir(const char *pszDirPath, bool fRecursive, bool fCheckFiles, PRTERRINFO pErrInfo)
0c94a8282c9042b02f022302a3d987746140eab9vboxsync * Validate the input path and parse it.
0c94a8282c9042b02f022302a3d987746140eab9vboxsync int rc = supR3HardenedVerifyPathSanity(pszDirPath, pErrInfo, &Info);
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * Verify each component from the root up.
0c94a8282c9042b02f022302a3d987746140eab9vboxsync for (uint32_t iComponent = 0; iComponent < cComponents; iComponent++)
0c94a8282c9042b02f022302a3d987746140eab9vboxsync Info.szPath[Info.aoffComponents[iComponent + 1] - 1] = '\0';
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync rc = supR3HardenedQueryFsObjectByPath(Info.szPath, &FsObjState, pErrInfo);
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync rc = supR3HardenedVerifyFsObject(&FsObjState, true /*fDir*/, fRelaxed, Info.szPath, pErrInfo);
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync Info.szPath[Info.aoffComponents[iComponent + 1] - 1] = iComponent + 1 != cComponents ? RTPATH_SLASH : '\0';
0c94a8282c9042b02f022302a3d987746140eab9vboxsync * Check files and subdirectories if requested.
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync return supR3HardenedVerifyDirRecursive(Info.szPath, Info.cch + 1, &FsObjState,
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync * Verfies a file.
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync * @returns VBox status code, error buffer filled on failure.
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync * @param pszFilename The file to verify.
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync * @param hNativeFile Handle to the file, verify that it's the same
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync * as we ended up with when verifying the path.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * RTHCUINTPTR_MAX means NIL here.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * @param fMaybe3rdParty Set if the file is could be a supplied by a
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * third party. Different validation rules may
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync * apply to 3rd party code on some platforms.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * @param pErrInfo Where to return extended error information.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * Optional.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsyncDECLHIDDEN(int) supR3HardenedVerifyFile(const char *pszFilename, RTHCUINTPTR hNativeFile,
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * Validate the input path and parse it.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync int rc = supR3HardenedVerifyPathSanity(pszFilename, pErrInfo, &Info);
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync return supR3HardenedSetError3(VERR_SUPLIB_IS_DIRECTORY, pErrInfo,
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync "The file path specifies a directory: '", pszFilename, "'");
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * Verify each component from the root up.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync for (uint32_t iComponent = 0; iComponent < cComponents; iComponent++)
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync Info.szPath[Info.aoffComponents[iComponent + 1] - 1] = '\0';
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync rc = supR3HardenedQueryFsObjectByPath(Info.szPath, &FsObjState, pErrInfo);
29099c2d04b11e614f1fa399fab9e9162f2788b9vboxsync rc = supR3HardenedVerifyFsObject(&FsObjState, !fFinal /*fDir*/, fRelaxed, Info.szPath, pErrInfo);
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync Info.szPath[Info.aoffComponents[iComponent + 1] - 1] = !fFinal ? RTPATH_SLASH : '\0';
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync * Verify the file handle against the last component, if specified.
49a6b09abb20015b0af3e618a1f92b7e26785e90vboxsync rc = supR3HardenedVerifySameFsObject(hNativeFile, &FsObjState, Info.szPath, pErrInfo);
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync * The files shall be signed on windows, verify that.
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync hVerify = CreateFileW(pwszPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
88e56f700a3b8dfdf1646f96320f335e22339caavboxsync rc = RTErrInfoSetF(pErrInfo, rc, "Error converting '%s' to UTF-16: %Rrc", pszFilename, rc);
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync else if (!DuplicateHandle(GetCurrentProcess(), (HANDLE)hNativeFile, GetCurrentProcess(), &hVerify,
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync GENERIC_READ, false /*bInheritHandle*/, 0 /*dwOptions*/))
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync uint32_t fFlags = SUPHNTVI_F_REQUIRE_KERNEL_CODE_SIGNING;
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync# ifndef IN_SUP_R3_STATIC /* Not in VBoxCpuReport and friends. */
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync rc = supHardenedWinVerifyImageByHandleNoName(hVerify, fFlags, pErrInfo);
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync rc = RTErrInfoSetF(pErrInfo, RTErrConvertFromWin32(GetLastError()),
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync "Error %u trying to open (or duplicate handle for) '%s'", GetLastError(), pszFilename);
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * Gets the pre-init data for the hand-over to the other version
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * of this code.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * The reason why we pass this information on is that it contains
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * open directories and files. Later it may include even more info
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * (int the verified arrays mostly).
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * The receiver is supR3HardenedRecvPreInitData.
5c4d7e2aae42bbf39793dfa686925f076a56b4d5vboxsync * @param pPreInitData Where to store it.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsyncDECLHIDDEN(void) supR3HardenedGetPreInitData(PSUPPREINITDATA pPreInitData)
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync pPreInitData->cInstallFiles = RT_ELEMENTS(g_aSupInstallFiles);
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync pPreInitData->paInstallFiles = &g_aSupInstallFiles[0];
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync pPreInitData->paVerifiedFiles = &g_aSupVerifiedFiles[0];
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync pPreInitData->cVerifiedDirs = RT_ELEMENTS(g_aSupVerifiedDirs);
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync pPreInitData->paVerifiedDirs = &g_aSupVerifiedDirs[0];
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * Receives the pre-init data from the static executable stub.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * @returns VBox status code. Will not bitch on failure since the
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * runtime isn't ready for it, so that is left to the exe stub.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * @param pPreInitData The hand-over data.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsyncDECLHIDDEN(int) supR3HardenedRecvPreInitData(PCSUPPREINITDATA pPreInitData)
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * Compare the array lengths and the contents of g_aSupInstallFiles.
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync if ( pPreInitData->cInstallFiles != RT_ELEMENTS(g_aSupInstallFiles)
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync || pPreInitData->cVerifiedDirs != RT_ELEMENTS(g_aSupVerifiedDirs))
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync SUPINSTFILE const *paInstallFiles = pPreInitData->paInstallFiles;
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync for (unsigned iFile = 0; iFile < RT_ELEMENTS(g_aSupInstallFiles); iFile++)
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync if ( g_aSupInstallFiles[iFile].enmDir != paInstallFiles[iFile].enmDir
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync || g_aSupInstallFiles[iFile].enmType != paInstallFiles[iFile].enmType
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync || g_aSupInstallFiles[iFile].fOptional != paInstallFiles[iFile].fOptional
19320d55d1417c39b3b5673a53aaa5ef177242c8vboxsync || suplibHardenedStrCmp(g_aSupInstallFiles[iFile].pszFile, paInstallFiles[iFile].pszFile))
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * Check that we're not called out of order.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync * If dynamic linking it screwed up, we may end up here.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync if ( ASMMemIsAll8(&g_aSupVerifiedFiles[0], sizeof(g_aSupVerifiedFiles), 0) != NULL
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync || ASMMemIsAll8(&g_aSupVerifiedDirs[0], sizeof(g_aSupVerifiedDirs), 0) != NULL)
44372afb953dc9f1f1ec71943f5f561a607c0307vboxsync * Copy the verification data over.
0c69348b58bb8eabb1bea8867ee932b667bd0d34vboxsync suplibHardenedMemCopy(&g_aSupVerifiedFiles[0], pPreInitData->paVerifiedFiles, sizeof(g_aSupVerifiedFiles));