VirtualBox

Changeset 66526 in vbox for trunk/src/VBox/HostDrivers


Ignore:
Timestamp:
Apr 12, 2017 12:09:01 PM (8 years ago)
Author:
vboxsync
Message:

HostDrivers/Support: bugref:8740: additional checks for non-Windows hosts

Location:
trunk/src/VBox/HostDrivers/Support
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/HostDrivers/Support/Makefile.kmk

    r66525 r66526  
    416416endif
    417417
     418# Things specific to the posix crowd.
     419if1of ($(KBUILD_TARGET), linux darwin solaris)
     420 SUPR3HardenedStatic_DEFS += \
     421        IN_DIS \
     422        DIS_CORE_ONLY \
     423        LOG_DISABLED
     424 SUPR3HardenedStatic_DEFS.linux += \
     425        SUP_HARDENED_WITH_DLMOPEN
     426 SUPR3HardenedStatic_DEFS.solaris += \
     427        SUP_HARDENED_WITH_DLMOPEN
     428
     429 SUPR3HardenedStatic_INCS += $(VBOX_PATH_RUNTIME_SRC)/include
     430
     431 SUPR3HardenedStatic_SOURCES += \
     432        posix/SUPR3HardenedMain-posix.cpp \
     433        posix/SUPR3HardenedMainA-posix.asm \
     434       \
     435        $(VBOX_PATH_RUNTIME_SRC)/common/misc/RTAssertMsg1Weak.cpp \
     436        $(VBOX_PATH_RUNTIME_SRC)/common/misc/RTAssertMsg2.cpp \
     437        $(VBOX_PATH_RUNTIME_SRC)/common/misc/RTAssertMsg2Weak.cpp \
     438        $(VBOX_PATH_RUNTIME_SRC)/common/misc/RTAssertMsg2WeakV.cpp \
     439        $(VBOX_PATH_RUNTIME_SRC)/generic/RTAssertShouldPanic-generic.cpp \
     440       \
     441        ../../Disassembler/DisasmCore.cpp \
     442        ../../Disassembler/DisasmTables.cpp \
     443        ../../Disassembler/DisasmTablesX64.cpp \
     444        ../../Disassembler/DisasmReg.cpp
     445endif
     446
    418447SUPR3HardenedMain.cpp_DEFS = VBOX_SVN_REV=$(VBOX_SVN_REV)
    419448
  • trunk/src/VBox/HostDrivers/Support/SUPLibInternal.h

    r62677 r66526  
    449449DECLHIDDEN(int)     supR3HardenedVerifyFile(const char *pszFilename, RTHCUINTPTR hNativeFile, bool fMaybe3rdParty,
    450450                                            PRTERRINFO pErrInfo);
     451#ifdef RT_OS_DARWIN
     452DECLHIDDEN(int)     supR3HardenedVerifyFileFollowSymlinks(const char *pszFilename, RTHCUINTPTR hNativeFile, bool fMaybe3rdParty,
     453                                                          PRTERRINFO pErrInfo);
     454#endif
    451455DECLHIDDEN(void)    supR3HardenedGetPreInitData(PSUPPREINITDATA pPreInitData);
    452456DECLHIDDEN(int)     supR3HardenedRecvPreInitData(PCSUPPREINITDATA pPreInitData);
     
    484488DECLHIDDEN(void)    supR3HardenedWinReportErrorToParent(const char *pszWhere, SUPINITOP enmWhat, int rc,
    485489                                                        const char *pszFormat, va_list va);
    486 #endif
     490#else   /* !RT_OS_WINDOWS */
     491DECLHIDDEN(void)    supR3HardenedPosixInit(void);
     492#endif  /* !RT_OS_WINDOWS */
    487493
    488494SUPR3DECL(int)      supR3PageLock(void *pvStart, size_t cPages, PSUPPAGE paPages);
  • trunk/src/VBox/HostDrivers/Support/SUPR3HardenedMain.cpp

    r63674 r66526  
    404404
    405405#else /* UNIXes */
     406# ifdef RT_OS_DARWIN
     407#  define _POSIX_C_SOURCE 1 /* pick the correct prototype for unsetenv. */
     408# endif
    406409# include <iprt/types.h> /* stdint fun on darwin. */
    407410
     
    487490
    488491
     492/**
     493 * Descriptor of an environment variable to purge.
     494 */
     495typedef struct SUPENVPURGEDESC
     496{
     497    /** Name of the environment variable to purge. */
     498    const char         *pszEnv;
     499    /** The length of the variable name. */
     500    uint8_t             cchEnv;
     501    /** Flag whether a failure in purging the variable leads to
     502     * a fatal error resulting in an process exit. */
     503    bool                fPurgeErrFatal;
     504} SUPENVPURGEDESC;
     505/** Pointer to a environment variable purge descriptor. */
     506typedef SUPENVPURGEDESC *PSUPENVPURGEDESC;
     507/** Pointer to a const environment variable purge descriptor. */
     508typedef const SUPENVPURGEDESC *PCSUPENVPURGEDESC;
     509
     510/**
     511 * Descriptor of an command line argument to purge.
     512 */
     513typedef struct SUPARGPURGEDESC
     514{
     515    /** Name of the argument to purge. */
     516    const char         *pszArg;
     517    /** The length of the argument name. */
     518    uint8_t             cchArg;
     519    /** Flag whether the argument is followed by an extra argument
     520     * which must be purged too */
     521    bool                fTakesValue;
     522} SUPARGPURGEDESC;
     523/** Pointer to a environment variable purge descriptor. */
     524typedef SUPARGPURGEDESC *PSUPARGPURGEDESC;
     525/** Pointer to a const environment variable purge descriptor. */
     526typedef const SUPARGPURGEDESC *PCSUPARGPURGEDESC;
     527
     528
    489529/*********************************************************************************************************************************
    490530*   Global Variables                                                                                                             *
     
    537577#endif
    538578
     579/** Environment variables to purge from the process because
     580 * they are known to be harmful. */
     581static const SUPENVPURGEDESC g_aSupEnvPurgeDescs[] =
     582{
     583    /* pszEnv                                       fPurgeErrFatal */
     584    /* Qt related environment variables: */
     585    { RT_STR_TUPLE("QT_QPA_PLATFORM_PLUGIN_PATH"),  true },
     586    { RT_STR_TUPLE("QT_PLUGIN_PATH"),               true },
     587    /* ALSA related environment variables: */
     588    { RT_STR_TUPLE("ALSA_MIXER_SIMPLE_MODULES"),    true },
     589    { RT_STR_TUPLE("LADSPA_PATH"),                  true },
     590};
     591
     592/** Arguments to purge from the argument vector because
     593 * they are known to be harmful. */
     594static const SUPARGPURGEDESC g_aSupArgPurgeDescs[] =
     595{
     596    /* pszArg                        fTakesValue */
     597    /* Qt related environment variables: */
     598    { RT_STR_TUPLE("-platformpluginpath"),          true },
     599};
    539600
    540601/*********************************************************************************************************************************
     
    20042065
    20052066/**
     2067 * Purge the process environment from any environment vairable which can lead
     2068 * to loading untrusted binaries compromising the process address space.
     2069 *
     2070 * @param   envp        The initial environment vector. (Can be NULL.)
     2071 */
     2072static void supR3HardenedMainPurgeEnvironment(char **envp)
     2073{
     2074    for (unsigned i = 0; i < RT_ELEMENTS(g_aSupEnvPurgeDescs); i++)
     2075    {
     2076        /*
     2077         * Update the initial environment vector, just in case someone actually cares about it.
     2078         */
     2079        if (envp)
     2080        {
     2081            const char * const  pszEnv = g_aSupEnvPurgeDescs[i].pszEnv;
     2082            size_t const        cchEnv = g_aSupEnvPurgeDescs[i].cchEnv;
     2083            unsigned            iSrc   = 0;
     2084            unsigned            iDst   = 0;
     2085            char               *pszTmp;
     2086
     2087            while ((pszTmp = envp[iSrc]) != NULL)
     2088            {
     2089                if (   memcmp(pszTmp, pszEnv, cchEnv) != 0
     2090                    || (pszTmp[cchEnv] != '=' && pszTmp[cchEnv] != '\0'))
     2091                {
     2092                    if (iDst != iSrc)
     2093                        envp[iDst] = pszTmp;
     2094                    iDst++;
     2095                }
     2096                else
     2097                    SUP_DPRINTF(("supR3HardenedMainPurgeEnvironment: dropping envp[%d]=%s\n", iSrc, pszTmp));
     2098                iSrc++;
     2099            }
     2100
     2101            if (iDst != iSrc)
     2102                while (iDst <= iSrc)
     2103                    envp[iDst++] = NULL;
     2104        }
     2105
     2106        /*
     2107         * Remove from the process environment if present.
     2108         */
     2109#ifndef RT_OS_WINDOWS
     2110        const char *pszTmp = getenv(g_aSupEnvPurgeDescs[i].pszEnv);
     2111        if (pszTmp != NULL)
     2112        {
     2113            if (unsetenv((char *)g_aSupEnvPurgeDescs[i].pszEnv) == 0)
     2114                SUP_DPRINTF(("supR3HardenedMainPurgeEnvironment: dropped %s\n", pszTmp));
     2115            else
     2116                if (g_aSupEnvPurgeDescs[i].fPurgeErrFatal)
     2117                    supR3HardenedFatal("SUPR3HardenedMain: failed to purge %s environment variable! (errno=%d %s)\n",
     2118                                       g_aSupEnvPurgeDescs[i].pszEnv, errno, strerror(errno));
     2119                else
     2120                    SUP_DPRINTF(("supR3HardenedMainPurgeEnvironment: dropping %s failed! errno=%d\n", pszTmp, errno));
     2121        }
     2122#else
     2123        /** @todo Call NT API to do the same. */
     2124#endif
     2125    }
     2126}
     2127
     2128
     2129/**
     2130 * Returns the argument purge descriptor of the given argument if available.
     2131 *
     2132 * @retval 0 if it should not be purged.
     2133 * @retval 1 if it only the current argument should be purged.
     2134 * @retval 2 if the argument and the following (if present) should be purged.
     2135 * @param   pszArg           The argument to look for.
     2136 */
     2137static unsigned supR3HardenedMainShouldPurgeArg(const char *pszArg)
     2138{
     2139    for (unsigned i = 0; i < RT_ELEMENTS(g_aSupArgPurgeDescs); i++)
     2140    {
     2141        size_t const cchPurge = g_aSupArgPurgeDescs[i].cchArg;
     2142        if (!memcmp(pszArg, g_aSupArgPurgeDescs[i].pszArg, cchPurge))
     2143        {
     2144            if (pszArg[cchPurge] == '\0')
     2145                return 1 + g_aSupArgPurgeDescs[i].fTakesValue;
     2146            if (   g_aSupArgPurgeDescs[i].fTakesValue
     2147                && (pszArg[cchPurge] == ':' || pszArg[cchPurge] == '='))
     2148                return 1;
     2149        }
     2150    }
     2151
     2152    return 0;
     2153}
     2154
     2155
     2156/**
     2157 * Purges any command line arguments considered harmful.
     2158 *
     2159 * @returns nothing.
     2160 * @param   cArgsOrig        The original number of arguments.
     2161 * @param   papszArgsOrig    The original argument vector.
     2162 * @param   pcArgsNew        Where to store the new number of arguments on success.
     2163 * @param   ppapszArgsNew    Where to store the pointer to the purged argument vector.
     2164 */
     2165static void supR3HardenedMainPurgeArgs(int cArgsOrig, char **papszArgsOrig, int *pcArgsNew, char ***ppapszArgsNew)
     2166{
     2167    int    iDst = 0;
     2168#ifdef RT_OS_WINDOWS
     2169    char **papszArgsNew = papszArgsOrig; /* We allocated this, no need to allocate again. */
     2170#else
     2171    char **papszArgsNew = (char **)malloc((cArgsOrig + 1) * sizeof(char *));
     2172#endif
     2173    if (papszArgsNew)
     2174    {
     2175        for (int iSrc = 0; iSrc < cArgsOrig; iSrc++)
     2176        {
     2177            unsigned cPurgedArgs = supR3HardenedMainShouldPurgeArg(papszArgsOrig[iSrc]);
     2178            if (!cPurgedArgs)
     2179                papszArgsNew[iDst++] = papszArgsOrig[iSrc];
     2180            else
     2181                iSrc += cPurgedArgs - 1;
     2182        }
     2183
     2184        papszArgsNew[iDst] = NULL; /* The array is NULL terminated, just like envp. */
     2185    }
     2186    else
     2187        supR3HardenedFatal("SUPR3HardenedMain: failed to allocate memory for purged command line!\n");
     2188    *pcArgsNew     = iDst;
     2189    *ppapszArgsNew = papszArgsNew;
     2190
     2191#ifdef RT_OS_WINDOWS
     2192    /** @todo Update command line pointers in PEB, wont really work without it. */
     2193#endif
     2194}
     2195
     2196
     2197/**
    20062198 * Loads the VBoxRT DLL/SO/DYLIB, hands it the open driver,
    20072199 * and calls RTR3InitEx.
     
    23682560    supR3HardenedWinResolveVerifyTrustApiAndHookThreadCreation(g_pszSupLibHardenedProgName);
    23692561    g_enmSupR3HardenedMainState = SUPR3HARDENEDMAINSTATE_WIN_VERIFY_TRUST_READY;
    2370 #endif
     2562#else /* !RT_OS_WINDOWS */
     2563# ifndef RT_OS_FREEBSD /** @todo portme */
     2564    /*
     2565     * Posix: Hook the load library interface interface.
     2566     */
     2567    supR3HardenedPosixInit();
     2568# endif
     2569#endif /* !RT_OS_WINDOWS */
    23712570
    23722571#ifdef SUP_HARDENED_SUID
     
    23812580    supR3HardenedMainDropPrivileges();
    23822581#endif
     2582
     2583    /*
     2584     * Purge any environment variables and command line arguments considered harmful.
     2585     */
     2586    /** @todo May need to move this to a much earlier stage on windows.  */
     2587    supR3HardenedMainPurgeEnvironment(envp);
     2588    supR3HardenedMainPurgeArgs(argc, argv, &argc, &argv);
    23832589
    23842590    /*
  • trunk/src/VBox/HostDrivers/Support/SUPR3HardenedVerify.cpp

    r63677 r66526  
    10361036}
    10371037
    1038 
    1039 /**
    1040  * Copies the three messages into the error buffer and returns @a rc.
     1038#ifdef RT_OS_DARWIN
     1039/**
     1040 * Copies the four messages into the error buffer and returns @a rc.
    10411041 *
    10421042 * @returns Returns @a rc
     
    10461046 * @param   pszMsg2             The second message part.
    10471047 * @param   pszMsg3             The third message part.
    1048  */
    1049 static int supR3HardenedSetError3(int rc, PRTERRINFO pErrInfo, const char *pszMsg1,
    1050                                   const char *pszMsg2, const char *pszMsg3)
    1051 {
    1052     return supR3HardenedSetErrorN(rc, pErrInfo, 3, pszMsg1, pszMsg2, pszMsg3);
    1053 }
    1054 
    1055 #ifdef SOME_UNUSED_FUNCTION
    1056 
    1057 /**
    1058  * Copies the two messages into the error buffer and returns @a rc.
     1048 * @param   pszMsg4             The fourth message part.
     1049 */
     1050static int supR3HardenedSetError4(int rc, PRTERRINFO pErrInfo, const char *pszMsg1,
     1051                                  const char *pszMsg2, const char *pszMsg3, const char *pszMsg4)
     1052{
     1053    return supR3HardenedSetErrorN(rc, pErrInfo, 4, pszMsg1, pszMsg2, pszMsg3, pszMsg4);
     1054}
     1055#endif /* RT_OS_DARWIN */
     1056
     1057
     1058/**
     1059 * Copies the three messages into the error buffer and returns @a rc.
    10591060 *
    10601061 * @returns Returns @a rc
     
    10631064 * @param   pszMsg1             The first message part.
    10641065 * @param   pszMsg2             The second message part.
     1066 * @param   pszMsg3             The third message part.
     1067 */
     1068static int supR3HardenedSetError3(int rc, PRTERRINFO pErrInfo, const char *pszMsg1,
     1069                                  const char *pszMsg2, const char *pszMsg3)
     1070{
     1071    return supR3HardenedSetErrorN(rc, pErrInfo, 3, pszMsg1, pszMsg2, pszMsg3);
     1072}
     1073
     1074#ifdef SOME_UNUSED_FUNCTION
     1075
     1076/**
     1077 * Copies the two messages into the error buffer and returns @a rc.
     1078 *
     1079 * @returns Returns @a rc
     1080 * @param   rc                  The return code.
     1081 * @param   pErrInfo            The error info structure.
     1082 * @param   pszMsg1             The first message part.
     1083 * @param   pszMsg2             The second message part.
    10651084 */
    10661085static int supR3HardenedSetError2(int rc, PRTERRINFO pErrInfo, const char *pszMsg1,
     
    10701089}
    10711090
     1091#endif /* SOME_UNUSED_FUNCTION */
     1092
     1093#ifdef RT_OS_DARWIN
    10721094
    10731095/**
     
    10841106}
    10851107
    1086 #endif /* SOME_UNUSED_FUNCTION */
     1108#endif
     1109
    10871110
    10881111/**
     
    13711394 *                              directory (only used for grand parent
    13721395 *                              directories).
     1396 * @param   fSymlinksAllowed    Flag whether symlinks are allowed or not.
     1397 *                              If allowed the symlink object is verified not the target.
    13731398 * @param   pszPath             The path to the object. For error messages and
    13741399 *                              securing a couple of hacks.
     
    13761401 */
    13771402static int supR3HardenedVerifyFsObject(PCSUPR3HARDENEDFSOBJSTATE pFsObjState, bool fDir, bool fRelaxed,
    1378                                        const char *pszPath, PRTERRINFO pErrInfo)
     1403                                       bool fSymlinksAllowed, const char *pszPath, PRTERRINFO pErrInfo)
    13791404{
    13801405#if defined(RT_OS_WINDOWS)
     
    13981423
    13991424    /*
    1400      * The object type must be directory or file, no symbolic links or other
    1401      * risky stuff (sorry dude, but we're paranoid on purpose here).
    1402      */
    1403     if (   !S_ISDIR(pFsObjState->Stat.st_mode)
    1404         && !S_ISREG(pFsObjState->Stat.st_mode))
    1405     {
    1406         if (S_ISLNK(pFsObjState->Stat.st_mode))
    1407             return supR3HardenedSetError3(VERR_SUPLIB_SYMLINKS_ARE_NOT_PERMITTED, pErrInfo,
    1408                                           "Symlinks are not permitted: '", pszPath, "'");
    1409         return supR3HardenedSetError3(VERR_SUPLIB_NOT_DIR_NOT_FILE, pErrInfo,
    1410                                       "Not regular file or directory: '", pszPath, "'");
    1411     }
    1412     if (fDir != !!S_ISDIR(pFsObjState->Stat.st_mode))
    1413     {
    1414         if (S_ISDIR(pFsObjState->Stat.st_mode))
    1415             return supR3HardenedSetError3(VERR_SUPLIB_IS_DIRECTORY, pErrInfo,
    1416                                           "Expected file but found directory: '", pszPath, "'");
    1417         return supR3HardenedSetError3(VERR_SUPLIB_IS_FILE, pErrInfo,
    1418                                       "Expected directory but found file: '", pszPath, "'");
     1425     * The object type must be directory or file. It can be a symbolic link
     1426     * if explicitely allowed. Otherwise this and other risky stuff is not allowed
     1427     * (sorry dude, but we're paranoid on purpose here).
     1428     */
     1429    if (   !S_ISLNK(pFsObjState->Stat.st_mode)
     1430        || !fSymlinksAllowed)
     1431    {
     1432
     1433        if (   !S_ISDIR(pFsObjState->Stat.st_mode)
     1434            && !S_ISREG(pFsObjState->Stat.st_mode))
     1435        {
     1436            if (S_ISLNK(pFsObjState->Stat.st_mode))
     1437                return supR3HardenedSetError3(VERR_SUPLIB_SYMLINKS_ARE_NOT_PERMITTED, pErrInfo,
     1438                                              "Symlinks are not permitted: '", pszPath, "'");
     1439            return supR3HardenedSetError3(VERR_SUPLIB_NOT_DIR_NOT_FILE, pErrInfo,
     1440                                          "Not regular file or directory: '", pszPath, "'");
     1441        }
     1442        if (fDir != !!S_ISDIR(pFsObjState->Stat.st_mode))
     1443        {
     1444            if (S_ISDIR(pFsObjState->Stat.st_mode))
     1445                return supR3HardenedSetError3(VERR_SUPLIB_IS_DIRECTORY, pErrInfo,
     1446                                              "Expected file but found directory: '", pszPath, "'");
     1447            return supR3HardenedSetError3(VERR_SUPLIB_IS_FILE, pErrInfo,
     1448                                          "Expected directory but found file: '", pszPath, "'");
     1449        }
    14191450    }
    14201451
     
    16011632            break;
    16021633        rc = supR3HardenedVerifyFsObject(pFsObjState, S_ISDIR(pFsObjState->Stat.st_mode), false /*fRelaxed*/,
    1603                                          pszDirPath, pErrInfo);
     1634                                         false /*fSymlinksAllowed*/, pszDirPath, pErrInfo);
    16041635        if (RT_FAILURE(rc))
    16051636            break;
     
    16591690        rc = supR3HardenedQueryFsObjectByPath(Info.szPath, &FsObjState, pErrInfo);
    16601691        if (RT_SUCCESS(rc))
    1661             rc = supR3HardenedVerifyFsObject(&FsObjState, true /*fDir*/, fRelaxed, Info.szPath, pErrInfo);
     1692            rc = supR3HardenedVerifyFsObject(&FsObjState, true /*fDir*/, fRelaxed,
     1693                                             false /*fSymlinksAllowed*/, Info.szPath, pErrInfo);
    16621694        if (RT_FAILURE(rc))
    16631695            return rc;
     
    17201752        rc = supR3HardenedQueryFsObjectByPath(Info.szPath, &FsObjState, pErrInfo);
    17211753        if (RT_SUCCESS(rc))
    1722             rc = supR3HardenedVerifyFsObject(&FsObjState, !fFinal /*fDir*/, fRelaxed, Info.szPath, pErrInfo);
     1754            rc = supR3HardenedVerifyFsObject(&FsObjState, !fFinal /*fDir*/, fRelaxed,
     1755                                             false /*fSymlinksAllowed*/, Info.szPath, pErrInfo);
    17231756        if (RT_FAILURE(rc))
    17241757            return rc;
     
    17991832
    18001833
     1834#ifdef RT_OS_DARWIN
     1835/**
     1836 * Verfies a file following symlinks.
     1837 *
     1838 * @returns VBox status code, error buffer filled on failure.
     1839 * @param   pszFilename         The file to verify.
     1840 * @param   hNativeFile         Handle to the file, verify that it's the same
     1841 *                              as we ended up with when verifying the path.
     1842 *                              RTHCUINTPTR_MAX means NIL here.
     1843 * @param   fMaybe3rdParty      Set if the file is could be a supplied by a
     1844 *                              third party.  Different validation rules may
     1845 *                              apply to 3rd party code on some platforms.
     1846 * @param   pErrInfo            Where to return extended error information.
     1847 *                              Optional.
     1848 *
     1849 * @note    This is only used on OS X for libraries loaded with dlopen() because
     1850 *          the frameworks use symbolic links to point to the relevant library.
     1851 *
     1852 * @sa      supR3HardenedVerifyFile
     1853 */
     1854DECLHIDDEN(int) supR3HardenedVerifyFileFollowSymlinks(const char *pszFilename, RTHCUINTPTR hNativeFile, bool fMaybe3rdParty,
     1855                                                      PRTERRINFO pErrInfo)
     1856{
     1857    RT_NOREF1(fMaybe3rdParty);
     1858
     1859    /*
     1860     * Validate the input path and parse it.
     1861     */
     1862    SUPR3HARDENEDPATHINFO Info;
     1863    int rc = supR3HardenedVerifyPathSanity(pszFilename, pErrInfo, &Info);
     1864    if (RT_FAILURE(rc))
     1865        return rc;
     1866    if (Info.fDirSlash)
     1867        return supR3HardenedSetError3(VERR_SUPLIB_IS_DIRECTORY, pErrInfo,
     1868                                      "The file path specifies a directory: '", pszFilename, "'");
     1869
     1870    /*
     1871     * Verify each component from the root up.
     1872     */
     1873    uint32_t                iLoops = 0;
     1874    SUPR3HARDENEDFSOBJSTATE FsObjState;
     1875    uint32_t                iComponent = 0;
     1876    while (iComponent < Info.cComponents)
     1877    {
     1878        bool fFinal   = iComponent + 1 == Info.cComponents;
     1879        bool fRelaxed = iComponent + 2 < Info.cComponents;
     1880        Info.szPath[Info.aoffComponents[iComponent + 1] - 1] = '\0';
     1881        rc = supR3HardenedQueryFsObjectByPath(Info.szPath, &FsObjState, pErrInfo);
     1882        if (RT_SUCCESS(rc))
     1883        {
     1884            /*
     1885             * In case the component is a symlink expand it and start from the beginning after
     1886             * verifying it has the proper access rights.
     1887             * Furthermore only allow symlinks which don't contain any .. or . in the target
     1888             * (enforced by supR3HardenedVerifyPathSanity).
     1889             */
     1890            rc = supR3HardenedVerifyFsObject(&FsObjState, !fFinal /*fDir*/, fRelaxed,
     1891                                             true /*fSymlinksAllowed*/, Info.szPath, pErrInfo);
     1892            if (   RT_SUCCESS(rc)
     1893                && S_ISLNK(FsObjState.Stat.st_mode))
     1894            {
     1895                /* Don't loop forever. */
     1896                iLoops++;
     1897                if (iLoops < 8)
     1898                {
     1899                    /*
     1900                     * Construct new path by replacing the current component by the symlink value.
     1901                     * Note! readlink() is a weird API that doesn't necessarily indicates if the
     1902                     *       buffer is too small.
     1903                     */
     1904                    char   szPath[RTPATH_MAX];
     1905                    size_t const cchBefore = Info.aoffComponents[iComponent]; /* includes slash */
     1906                    size_t const cchAfter  = fFinal ? 0 : 1 /*slash*/ + Info.cch - Info.aoffComponents[iComponent + 1];
     1907                    if (sizeof(szPath) > cchBefore + cchAfter + 2)
     1908                    {
     1909                        ssize_t cchTarget = readlink(Info.szPath, szPath, sizeof(szPath) - 1);
     1910                        if (cchTarget > 0)
     1911                        {
     1912                            /* Some serious paranoia against embedded zero terminator and weird return values. */
     1913                            szPath[cchTarget] = '\0';
     1914                            size_t cchLink = strlen(szPath);
     1915
     1916                            /* Strip trailing dirslashes of non-final link. */
     1917                            if (!fFinal)
     1918                                while (cchLink > 1 and szPath[cchLink - 1] == '/')
     1919                                    cchLink--;
     1920
     1921                            /* Check link value sanity and buffer size. */
     1922                            if (cchLink == 0)
     1923                                return supR3HardenedSetError3(VERR_ACCESS_DENIED, pErrInfo,
     1924                                                              "Bad readlink return for '", Info.szPath, "'");
     1925                            if (szPath[0] == '/')
     1926                                return supR3HardenedSetError3(VERR_ACCESS_DENIED, pErrInfo,
     1927                                                              "Absolute symbolic link not allowed: '", szPath, "'");
     1928                            if (cchBefore + cchLink + cchAfter + 1 /*terminator*/ > sizeof(szPath))
     1929                                return supR3HardenedSetError(VERR_SUPLIB_PATH_TOO_LONG, pErrInfo,
     1930                                                             "Symlinks causing too long path!");
     1931
     1932                            /* Construct the new path. */
     1933                            if (cchBefore)
     1934                                memmove(&szPath[cchBefore], &szPath[0], cchLink);
     1935                            memcpy(&szPath[0], Info.szPath, cchBefore);
     1936                            if (!cchAfter)
     1937                                szPath[cchBefore + cchLink] = '\0';
     1938                            else
     1939                            {
     1940                                szPath[cchBefore + cchLink] = RTPATH_SLASH;
     1941                                memcpy(&szPath[cchBefore + cchLink + 1],
     1942                                       &Info.szPath[Info.aoffComponents[iComponent + 1]],
     1943                                       cchAfter); /* cchAfter includes a zero terminator */
     1944                            }
     1945
     1946                            /* Parse, copy and check the sanity (no '..' or '.') of the altered path. */
     1947                            rc = supR3HardenedVerifyPathSanity(szPath, pErrInfo, &Info);
     1948                            if (RT_FAILURE(rc))
     1949                                return rc;
     1950                            if (Info.fDirSlash)
     1951                                return supR3HardenedSetError3(VERR_SUPLIB_IS_DIRECTORY, pErrInfo,
     1952                                                              "The file path specifies a directory: '", szPath, "'");
     1953
     1954                            /* Restart from the current component. */
     1955                            continue;
     1956                        }
     1957                        int iErr = errno;
     1958                        supR3HardenedError(VERR_ACCESS_DENIED, false /*fFatal*/,
     1959                                           "supR3HardenedVerifyFileFollowSymlinks: Failed to readlink '%s': %s (%d)\n",
     1960                                           Info.szPath, strerror(iErr), iErr);
     1961                        return supR3HardenedSetError4(VERR_ACCESS_DENIED, pErrInfo,
     1962                                                      "readlink failed for '", Info.szPath, "': ", strerror(iErr));
     1963                    }
     1964                    return supR3HardenedSetError(VERR_SUPLIB_PATH_TOO_LONG, pErrInfo, "Path too long for symlink replacing!");
     1965                }
     1966                else
     1967                    return supR3HardenedSetError3(VERR_TOO_MANY_SYMLINKS, pErrInfo,
     1968                                                  "Too many symbolic links: '", pszFilename, "'");
     1969            }
     1970        }
     1971        if (RT_FAILURE(rc))
     1972            return rc;
     1973        Info.szPath[Info.aoffComponents[iComponent + 1] - 1] = !fFinal ? RTPATH_SLASH : '\0';
     1974        iComponent++;
     1975    }
     1976
     1977    /*
     1978     * Verify the file handle against the last component, if specified.
     1979     */
     1980    if (hNativeFile != RTHCUINTPTR_MAX)
     1981    {
     1982        rc = supR3HardenedVerifySameFsObject(hNativeFile, &FsObjState, Info.szPath, pErrInfo);
     1983        if (RT_FAILURE(rc))
     1984            return rc;
     1985    }
     1986
     1987    return VINF_SUCCESS;
     1988}
     1989#endif /* RT_OS_DARWIN */
     1990
     1991
    18011992/**
    18021993 * Gets the pre-init data for the hand-over to the other version
  • trunk/src/VBox/HostDrivers/Support/darwin/SUPLib-darwin.cpp

    r63463 r66526  
    3232#ifdef IN_SUP_HARDENED_R3
    3333# undef DEBUG /* Warning: disables RT_STRICT */
    34 # define LOG_DISABLED
     34# ifndef LOG_DISABLED
     35#  define LOG_DISABLED
     36# endif
    3537# define RTLOG_REL_DISABLED
    3638# include <iprt/log.h>
  • trunk/src/VBox/HostDrivers/Support/linux/SUPLib-linux.cpp

    r62877 r66526  
    3333# undef DEBUG /* Warning: disables RT_STRICT */
    3434# undef RT_STRICT
    35 # define LOG_DISABLED
     35# ifndef LOG_DISABLED
     36#  define LOG_DISABLED
     37# endif
    3638# define RTLOG_REL_DISABLED
    3739# include <iprt/log.h>
  • trunk/src/VBox/HostDrivers/Support/solaris/SUPLib-solaris.cpp

    r62490 r66526  
    3232#ifdef IN_SUP_HARDENED_R3
    3333# undef DEBUG /* Warning: disables RT_STRICT */
    34 # define LOG_DISABLED
     34# ifndef LOG_DISABLED
     35#  define LOG_DISABLED
     36# endif
    3537# define RTLOG_REL_DISABLED
    3638# include <iprt/log.h>
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette