Changeset 66526 in vbox for trunk/src/VBox/HostDrivers
- Timestamp:
- Apr 12, 2017 12:09:01 PM (8 years ago)
- Location:
- trunk/src/VBox/HostDrivers/Support
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/HostDrivers/Support/Makefile.kmk
r66525 r66526 416 416 endif 417 417 418 # Things specific to the posix crowd. 419 if1of ($(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 445 endif 446 418 447 SUPR3HardenedMain.cpp_DEFS = VBOX_SVN_REV=$(VBOX_SVN_REV) 419 448 -
trunk/src/VBox/HostDrivers/Support/SUPLibInternal.h
r62677 r66526 449 449 DECLHIDDEN(int) supR3HardenedVerifyFile(const char *pszFilename, RTHCUINTPTR hNativeFile, bool fMaybe3rdParty, 450 450 PRTERRINFO pErrInfo); 451 #ifdef RT_OS_DARWIN 452 DECLHIDDEN(int) supR3HardenedVerifyFileFollowSymlinks(const char *pszFilename, RTHCUINTPTR hNativeFile, bool fMaybe3rdParty, 453 PRTERRINFO pErrInfo); 454 #endif 451 455 DECLHIDDEN(void) supR3HardenedGetPreInitData(PSUPPREINITDATA pPreInitData); 452 456 DECLHIDDEN(int) supR3HardenedRecvPreInitData(PCSUPPREINITDATA pPreInitData); … … 484 488 DECLHIDDEN(void) supR3HardenedWinReportErrorToParent(const char *pszWhere, SUPINITOP enmWhat, int rc, 485 489 const char *pszFormat, va_list va); 486 #endif 490 #else /* !RT_OS_WINDOWS */ 491 DECLHIDDEN(void) supR3HardenedPosixInit(void); 492 #endif /* !RT_OS_WINDOWS */ 487 493 488 494 SUPR3DECL(int) supR3PageLock(void *pvStart, size_t cPages, PSUPPAGE paPages); -
trunk/src/VBox/HostDrivers/Support/SUPR3HardenedMain.cpp
r63674 r66526 404 404 405 405 #else /* UNIXes */ 406 # ifdef RT_OS_DARWIN 407 # define _POSIX_C_SOURCE 1 /* pick the correct prototype for unsetenv. */ 408 # endif 406 409 # include <iprt/types.h> /* stdint fun on darwin. */ 407 410 … … 487 490 488 491 492 /** 493 * Descriptor of an environment variable to purge. 494 */ 495 typedef 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. */ 506 typedef SUPENVPURGEDESC *PSUPENVPURGEDESC; 507 /** Pointer to a const environment variable purge descriptor. */ 508 typedef const SUPENVPURGEDESC *PCSUPENVPURGEDESC; 509 510 /** 511 * Descriptor of an command line argument to purge. 512 */ 513 typedef 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. */ 524 typedef SUPARGPURGEDESC *PSUPARGPURGEDESC; 525 /** Pointer to a const environment variable purge descriptor. */ 526 typedef const SUPARGPURGEDESC *PCSUPARGPURGEDESC; 527 528 489 529 /********************************************************************************************************************************* 490 530 * Global Variables * … … 537 577 #endif 538 578 579 /** Environment variables to purge from the process because 580 * they are known to be harmful. */ 581 static 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. */ 594 static const SUPARGPURGEDESC g_aSupArgPurgeDescs[] = 595 { 596 /* pszArg fTakesValue */ 597 /* Qt related environment variables: */ 598 { RT_STR_TUPLE("-platformpluginpath"), true }, 599 }; 539 600 540 601 /********************************************************************************************************************************* … … 2004 2065 2005 2066 /** 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 */ 2072 static 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 */ 2137 static 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 */ 2165 static 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 /** 2006 2198 * Loads the VBoxRT DLL/SO/DYLIB, hands it the open driver, 2007 2199 * and calls RTR3InitEx. … … 2368 2560 supR3HardenedWinResolveVerifyTrustApiAndHookThreadCreation(g_pszSupLibHardenedProgName); 2369 2561 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 */ 2371 2570 2372 2571 #ifdef SUP_HARDENED_SUID … … 2381 2580 supR3HardenedMainDropPrivileges(); 2382 2581 #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); 2383 2589 2384 2590 /* -
trunk/src/VBox/HostDrivers/Support/SUPR3HardenedVerify.cpp
r63677 r66526 1036 1036 } 1037 1037 1038 1039 /** 1040 * Copies the threemessages 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. 1041 1041 * 1042 1042 * @returns Returns @a rc … … 1046 1046 * @param pszMsg2 The second message part. 1047 1047 * @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 */ 1050 static 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. 1059 1060 * 1060 1061 * @returns Returns @a rc … … 1063 1064 * @param pszMsg1 The first message part. 1064 1065 * @param pszMsg2 The second message part. 1066 * @param pszMsg3 The third message part. 1067 */ 1068 static 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. 1065 1084 */ 1066 1085 static int supR3HardenedSetError2(int rc, PRTERRINFO pErrInfo, const char *pszMsg1, … … 1070 1089 } 1071 1090 1091 #endif /* SOME_UNUSED_FUNCTION */ 1092 1093 #ifdef RT_OS_DARWIN 1072 1094 1073 1095 /** … … 1084 1106 } 1085 1107 1086 #endif /* SOME_UNUSED_FUNCTION */ 1108 #endif 1109 1087 1110 1088 1111 /** … … 1371 1394 * directory (only used for grand parent 1372 1395 * directories). 1396 * @param fSymlinksAllowed Flag whether symlinks are allowed or not. 1397 * If allowed the symlink object is verified not the target. 1373 1398 * @param pszPath The path to the object. For error messages and 1374 1399 * securing a couple of hacks. … … 1376 1401 */ 1377 1402 static int supR3HardenedVerifyFsObject(PCSUPR3HARDENEDFSOBJSTATE pFsObjState, bool fDir, bool fRelaxed, 1378 const char *pszPath, PRTERRINFO pErrInfo)1403 bool fSymlinksAllowed, const char *pszPath, PRTERRINFO pErrInfo) 1379 1404 { 1380 1405 #if defined(RT_OS_WINDOWS) … … 1398 1423 1399 1424 /* 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 } 1419 1450 } 1420 1451 … … 1601 1632 break; 1602 1633 rc = supR3HardenedVerifyFsObject(pFsObjState, S_ISDIR(pFsObjState->Stat.st_mode), false /*fRelaxed*/, 1603 pszDirPath, pErrInfo);1634 false /*fSymlinksAllowed*/, pszDirPath, pErrInfo); 1604 1635 if (RT_FAILURE(rc)) 1605 1636 break; … … 1659 1690 rc = supR3HardenedQueryFsObjectByPath(Info.szPath, &FsObjState, pErrInfo); 1660 1691 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); 1662 1694 if (RT_FAILURE(rc)) 1663 1695 return rc; … … 1720 1752 rc = supR3HardenedQueryFsObjectByPath(Info.szPath, &FsObjState, pErrInfo); 1721 1753 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); 1723 1756 if (RT_FAILURE(rc)) 1724 1757 return rc; … … 1799 1832 1800 1833 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 */ 1854 DECLHIDDEN(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 1801 1992 /** 1802 1993 * Gets the pre-init data for the hand-over to the other version -
trunk/src/VBox/HostDrivers/Support/darwin/SUPLib-darwin.cpp
r63463 r66526 32 32 #ifdef IN_SUP_HARDENED_R3 33 33 # undef DEBUG /* Warning: disables RT_STRICT */ 34 # define LOG_DISABLED 34 # ifndef LOG_DISABLED 35 # define LOG_DISABLED 36 # endif 35 37 # define RTLOG_REL_DISABLED 36 38 # include <iprt/log.h> -
trunk/src/VBox/HostDrivers/Support/linux/SUPLib-linux.cpp
r62877 r66526 33 33 # undef DEBUG /* Warning: disables RT_STRICT */ 34 34 # undef RT_STRICT 35 # define LOG_DISABLED 35 # ifndef LOG_DISABLED 36 # define LOG_DISABLED 37 # endif 36 38 # define RTLOG_REL_DISABLED 37 39 # include <iprt/log.h> -
trunk/src/VBox/HostDrivers/Support/solaris/SUPLib-solaris.cpp
r62490 r66526 32 32 #ifdef IN_SUP_HARDENED_R3 33 33 # undef DEBUG /* Warning: disables RT_STRICT */ 34 # define LOG_DISABLED 34 # ifndef LOG_DISABLED 35 # define LOG_DISABLED 36 # endif 35 37 # define RTLOG_REL_DISABLED 36 38 # include <iprt/log.h>
Note:
See TracChangeset
for help on using the changeset viewer.