- Timestamp:
- Aug 29, 2008 6:05:18 PM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/HostDrivers/Support/SUPR3HardenedMain.cpp
r11725 r11843 98 98 typedef FNTRUSTEDMAIN *PFNTRUSTEDMAIN; 99 99 100 typedef DECLCALLBACK(int) FNRTR3INIT(bool fInitSUPLib, size_t cbReserve); 101 typedef FNRTR3INIT *PFNRTR3INIT; 100 /** @see RTR3InitEx */ 101 typedef DECLCALLBACK(int) FNRTR3INITEX(uint32_t iVersion, const char *pszProgramPath, bool fInitSUPLib); 102 typedef FNRTR3INITEX *PFNRTR3INITEX; 102 103 103 104 … … 107 108 /** The pre-init data we pass on to SUPR3 (residing in VBoxRT). */ 108 109 static SUPPREINITDATA g_SupPreInitData; 109 /** The program path. */ 110 static char g_szSupLibHardenedProgramPath[RTPATH_MAX]; 110 /** The progam executable path. */ 111 static char g_szSupLibHardenedExePath[RTPATH_MAX]; 112 /** The program directory path. */ 113 static char g_szSupLibHardenedDirPath[RTPATH_MAX]; 111 114 112 115 /** The program name. */ 113 static const char *g_ szSupLibHardenedProgName;116 static const char *g_pszSupLibHardenedProgName; 114 117 115 118 … … 268 271 269 272 /** 270 * @copydoc RTPathProgram 271 */ 272 DECLHIDDEN(int) supR3HardenedPathProgram(char *pszPath, size_t cchPath) 273 { 274 /* 275 * First time only. 276 */ 277 if (!g_szSupLibHardenedProgramPath[0]) 278 { 279 /* 280 * Get the program filename. 281 * 282 * Most UNIXes have no API for obtaining the executable path, but provides a symbolic 283 * link in the proc file system that tells who was exec'ed. The bad thing about this 284 * is that we have to use readlink, one of the weirder UNIX APIs. 285 * 286 * Darwin, OS/2 and Windows all have proper APIs for getting the program file name. 287 */ 273 * Returns the full path to the executable. 274 * 275 * @returns IPRT status code. 276 * @param pszPath Where to store it. 277 * @param cchPath How big that buffer is. 278 */ 279 static void supR3HardenedGetFullExePath(void) 280 { 281 /* 282 * Get the program filename. 283 * 284 * Most UNIXes have no API for obtaining the executable path, but provides a symbolic 285 * link in the proc file system that tells who was exec'ed. The bad thing about this 286 * is that we have to use readlink, one of the weirder UNIX APIs. 287 * 288 * Darwin, OS/2 and Windows all have proper APIs for getting the program file name. 289 */ 288 290 #if defined(RT_OS_LINUX) || defined(RT_OS_FREEBSD) || defined(RT_OS_SOLARIS) 289 291 # ifdef RT_OS_LINUX 290 int cchLink = readlink("/proc/self/exe", &g_szSupLibHardenedProgramPath[0], sizeof(g_szSupLibHardenedProgramPath) - 1);292 int cchLink = readlink("/proc/self/exe", &g_szSupLibHardenedExePath[0], sizeof(g_szSupLibHardenedExePath) - 1); 291 293 # elif defined(RT_OS_SOLARIS) 292 293 294 int cchLink = readlink(szFileBuf, &g_szSupLibHardenedProgramPath[0], sizeof(g_szSupLibHardenedProgramPath) - 1);294 char szFileBuf[PATH_MAX + 1]; 295 sprintf(szFileBuf, "/proc/%ld/path/a.out", (long)getpid()); 296 int cchLink = readlink(szFileBuf, &g_szSupLibHardenedExePath[0], sizeof(g_szSupLibHardenedExePath) - 1); 295 297 # else /* RT_OS_FREEBSD: */ 296 int cchLink = readlink("/proc/curproc/file", &g_szSupLibHardenedProgramPath[0], sizeof(g_szSupLibHardenedProgramPath) - 1);298 int cchLink = readlink("/proc/curproc/file", &g_szSupLibHardenedExePath[0], sizeof(g_szSupLibHardenedExePath) - 1); 297 299 # endif 298 if (cchLink < 0 || cchLink == sizeof(g_szSupLibHardenedProgramPath) - 1)299 300 g_szSupLibHardenedProgramPath, errno, cchLink);301 g_szSupLibHardenedProgramPath[cchLink] = '\0';300 if (cchLink < 0 || cchLink == sizeof(g_szSupLibHardenedExePath) - 1) 301 supR3HardenedFatal("supR3HardenedPathProgram: couldn't read \"%s\", errno=%d cchLink=%d\n", 302 g_szSupLibHardenedExePath, errno, cchLink); 303 g_szSupLibHardenedExePath[cchLink] = '\0'; 302 304 303 305 #elif defined(RT_OS_OS2) || defined(RT_OS_L4) 304 _execname(g_szSupLibHardenedProgramPath, sizeof(g_szSupLibHardenedProgramPath));306 _execname(g_szSupLibHardenedExePath, sizeof(g_szSupLibHardenedExePath)); 305 307 306 308 #elif defined(RT_OS_DARWIN) 307 308 309 310 311 if (!cchImageName || cchImageName >= sizeof(g_szSupLibHardenedProgramPath))312 313 memcpy(g_szSupLibHardenedProgramPath, pszImageName, cchImageName + 1);309 const char *pszImageName = _dyld_get_image_name(0); 310 if (!pszImageName) 311 supR3HardenedFatal("supR3HardenedPathProgram: _dyld_get_image_name(0) failed\n"); 312 size_t cchImageName = strlen(pszImageName); 313 if (!cchImageName || cchImageName >= sizeof(g_szSupLibHardenedExePath)) 314 supR3HardenedFatal("supR3HardenedPathProgram: _dyld_get_image_name(0) failed, cchImageName=%d\n", cchImageName); 315 memcpy(g_szSupLibHardenedExePath, pszImageName, cchImageName + 1); 314 316 315 317 #elif defined(RT_OS_WINDOWS) 316 317 if (!GetModuleFileName(hExe, &g_szSupLibHardenedProgramPath[0], sizeof(g_szSupLibHardenedProgramPath)))318 318 HMODULE hExe = GetModuleHandle(NULL); 319 if (!GetModuleFileName(hExe, &g_szSupLibHardenedExePath[0], sizeof(g_szSupLibHardenedExePath))) 320 supR3HardenedFatal("supR3HardenedPathProgram: GetModuleFileName failed, rc=%d\n", GetLastError()); 319 321 #else 320 322 # error needs porting. 321 323 #endif 322 323 /* 324 * Strip off the filename part (RTPathStripFilename()). 325 */ 326 suplibHardenedPathStripFilename(g_szSupLibHardenedProgramPath); 327 } 324 325 /* 326 * Strip off the filename part (RTPathStripFilename()). 327 */ 328 strcpy(g_szSupLibHardenedDirPath, g_szSupLibHardenedExePath); 329 suplibHardenedPathStripFilename(g_szSupLibHardenedDirPath); 330 } 331 332 333 #ifdef RT_OS_LINUX 334 /** 335 * Checks if we can read /proc/self/exe. 336 * 337 * This is used on linux to see if we have to call init 338 * with program path or not. 339 * 340 * @returns true / false. 341 */ 342 static bool supR3HardenedMainIsProcSelfExeAccssible(void) 343 { 344 char szPath[RTPATH_MAX]; 345 int cchLink = readlink("/proc/self/exe", szPath, sizeof(szPath)); 346 return cchLink != -1; 347 } 348 #endif /* RT_OS_LINUX */ 349 350 351 352 /** 353 * @copydoc RTPathProgram 354 */ 355 DECLHIDDEN(int) supR3HardenedPathProgram(char *pszPath, size_t cchPath) 356 { 357 /* 358 * Lazy init (probably not required). 359 */ 360 if (!g_szSupLibHardenedDirPath[0]) 361 supR3HardenedGetFullExePath(); 328 362 329 363 /* 330 364 * Calc the length and check if there is space before copying. 331 365 */ 332 unsigned cch = strlen(g_szSupLibHardened ProgramPath) + 1;366 unsigned cch = strlen(g_szSupLibHardenedDirPath) + 1; 333 367 if (cch <= cchPath) 334 368 { 335 memcpy(pszPath, g_szSupLibHardened ProgramPath, cch + 1);369 memcpy(pszPath, g_szSupLibHardenedDirPath, cch + 1); 336 370 return VINF_SUCCESS; 337 371 } … … 345 379 DECLHIDDEN(void) supR3HardenedFatalV(const char *pszFormat, va_list va) 346 380 { 347 fprintf(stderr, "%s: ", g_ szSupLibHardenedProgName);381 fprintf(stderr, "%s: ", g_pszSupLibHardenedProgName); 348 382 vfprintf(stderr, pszFormat, va); 349 383 for (;;) … … 370 404 supR3HardenedFatalV(pszFormat, va); 371 405 372 fprintf(stderr, "%s: ", g_ szSupLibHardenedProgName);406 fprintf(stderr, "%s: ", g_pszSupLibHardenedProgName); 373 407 vfprintf(stderr, pszFormat, va); 374 408 return rc; … … 469 503 supR3HardenedFatal("supR3HardenedMainGetTrustedMain: LoadLibraryEx(\"%s\",,) failed, rc=%d\n", 470 504 szPath, GetLastError()); 471 PFNRTR3INIT pfnRTInit = (PFNRTR3INIT)GetProcAddress(hMod, SUP_HARDENED_SYM("RTR3Init"));472 if (!pfnRTInit )473 supR3HardenedFatal("supR3HardenedMainGetTrustedMain: Entrypoint \"RTR3Init \" not found in \"%s\" (rc=%d)\n",505 PFNRTR3INITEX pfnRTInitEx = (PFNRTR3INITEX)GetProcAddress(hMod, SUP_HARDENED_SYM("RTR3InitEx")); 506 if (!pfnRTInitEx) 507 supR3HardenedFatal("supR3HardenedMainGetTrustedMain: Entrypoint \"RTR3InitEx\" not found in \"%s\" (rc=%d)\n", 474 508 szPath, GetLastError()); 475 509 … … 485 519 supR3HardenedFatal("supR3HardenedMainGetTrustedMain: dlopen(\"%s\",) failed: %s\n", 486 520 szPath, dlerror()); 487 PFNRTR3INIT pfnRTInit = (PFNRTR3INIT)(uintptr_t)dlsym(pvMod, SUP_HARDENED_SYM("RTR3Init"));488 if (!pfnRTInit )489 supR3HardenedFatal("supR3HardenedMainGetTrustedMain: Entrypoint \"RTR3Init \" not found in \"%s\"!\ndlerror: %s\n",521 PFNRTR3INITEX pfnRTInitEx = (PFNRTR3INITEX)(uintptr_t)dlsym(pvMod, SUP_HARDENED_SYM("RTR3InitEx")); 522 if (!pfnRTInitEx) 523 supR3HardenedFatal("supR3HardenedMainGetTrustedMain: Entrypoint \"RTR3InitEx\" not found in \"%s\"!\ndlerror: %s\n", 490 524 szPath, dlerror()); 491 525 PFNSUPR3PREINIT pfnSUPPreInit = (PFNSUPR3PREINIT)(uintptr_t)dlsym(pvMod, SUP_HARDENED_SYM("supR3PreInit")); … … 502 536 if (RT_FAILURE(rc)) 503 537 supR3HardenedFatal("supR3PreInit: Failed with rc=%d\n", rc); 504 rc = pfnRTInit(!(fFlags & SUPSECMAIN_FLAGS_DONT_OPEN_DEV), 0); 538 const char *pszExePath = NULL; 539 #ifdef RT_OS_LINUX 540 if (!supR3HardenedMainIsProcSelfExeAccssible()) 541 pszExePath = g_szSupLibHardenedExePath; 542 #endif 543 rc = pfnRTInitEx(0, pszExePath, !(fFlags & SUPSECMAIN_FLAGS_DONT_OPEN_DEV)); 505 544 if (RT_FAILURE(rc)) 506 545 supR3HardenedFatal("RTR3Init: Failed with rc=%d\n", rc); … … 582 621 * to basic CRT functions that everyone agree upon. 583 622 */ 584 g_ szSupLibHardenedProgName = pszProgName;623 g_pszSupLibHardenedProgName = pszProgName; 585 624 g_SupPreInitData.u32Magic = SUPPREINITDATA_MAGIC; 586 625 g_SupPreInitData.Data.hDevice = NIL_RTFILE; … … 596 635 supR3HardenedFatal("SUPR3HardenedMain: effective uid is not root (euid=%d egid=%d uid=%d gid=%d)\n", 597 636 geteuid(), getegid(), uid, gid); 637 638 # ifdef RT_OS_LINUX 639 /* 640 * On linux we have to make sure the path is initialized because we 641 * *might* not be able to access /proc/self/exe after the seteuid call. 642 */ 643 supR3HardenedGetFullExePath(); 644 # endif 598 645 #endif 599 646
Note:
See TracChangeset
for help on using the changeset viewer.