VirtualBox

Changeset 11843 in vbox for trunk/src


Ignore:
Timestamp:
Aug 29, 2008 6:05:18 PM (16 years ago)
Author:
vboxsync
Message:

#3076: Deal with /proc/self/exe becomming inaccessible on some systems.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/HostDrivers/Support/SUPR3HardenedMain.cpp

    r11725 r11843  
    9898typedef FNTRUSTEDMAIN *PFNTRUSTEDMAIN;
    9999
    100 typedef DECLCALLBACK(int) FNRTR3INIT(bool fInitSUPLib, size_t cbReserve);
    101 typedef FNRTR3INIT *PFNRTR3INIT;
     100/** @see RTR3InitEx */
     101typedef DECLCALLBACK(int) FNRTR3INITEX(uint32_t iVersion, const char *pszProgramPath, bool fInitSUPLib);
     102typedef FNRTR3INITEX *PFNRTR3INITEX;
    102103
    103104
     
    107108/** The pre-init data we pass on to SUPR3 (residing in VBoxRT). */
    108109static SUPPREINITDATA g_SupPreInitData;
    109 /** The program path. */
    110 static char g_szSupLibHardenedProgramPath[RTPATH_MAX];
     110/** The progam executable path. */
     111static char g_szSupLibHardenedExePath[RTPATH_MAX];
     112/** The program directory path. */
     113static char g_szSupLibHardenedDirPath[RTPATH_MAX];
    111114
    112115/** The program name. */
    113 static const char *g_szSupLibHardenedProgName;
     116static const char *g_pszSupLibHardenedProgName;
    114117
    115118
     
    268271
    269272/**
    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 */
     279static 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     */
    288290#if defined(RT_OS_LINUX) || defined(RT_OS_FREEBSD) || defined(RT_OS_SOLARIS)
    289291# 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);
    291293# elif defined(RT_OS_SOLARIS)
    292         char szFileBuf[PATH_MAX + 1];
    293         sprintf(szFileBuf, "/proc/%ld/path/a.out", (long)getpid());
    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);
    295297# 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);
    297299# endif
    298         if (cchLink < 0 || cchLink == sizeof(g_szSupLibHardenedProgramPath) - 1)
    299             supR3HardenedFatal("supR3HardenedPathProgram: couldn't read \"%s\", errno=%d cchLink=%d\n",
    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';
    302304
    303305#elif defined(RT_OS_OS2) || defined(RT_OS_L4)
    304         _execname(g_szSupLibHardenedProgramPath, sizeof(g_szSupLibHardenedProgramPath));
     306    _execname(g_szSupLibHardenedExePath, sizeof(g_szSupLibHardenedExePath));
    305307
    306308#elif defined(RT_OS_DARWIN)
    307         const char *pszImageName = _dyld_get_image_name(0);
    308         if (!pszImageName)
    309             supR3HardenedFatal("supR3HardenedPathProgram: _dyld_get_image_name(0) failed\n");
    310         size_t cchImageName = strlen(pszImageName);
    311         if (!cchImageName || cchImageName >= sizeof(g_szSupLibHardenedProgramPath))
    312             supR3HardenedFatal("supR3HardenedPathProgram: _dyld_get_image_name(0) failed, cchImageName=%d\n", cchImageName);
    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);
    314316
    315317#elif defined(RT_OS_WINDOWS)
    316         HMODULE hExe = GetModuleHandle(NULL);
    317         if (!GetModuleFileName(hExe, &g_szSupLibHardenedProgramPath[0], sizeof(g_szSupLibHardenedProgramPath)))
    318             supR3HardenedFatal("supR3HardenedPathProgram: GetModuleFileName failed, rc=%d\n", GetLastError());
     318    HMODULE hExe = GetModuleHandle(NULL);
     319    if (!GetModuleFileName(hExe, &g_szSupLibHardenedExePath[0], sizeof(g_szSupLibHardenedExePath)))
     320        supR3HardenedFatal("supR3HardenedPathProgram: GetModuleFileName failed, rc=%d\n", GetLastError());
    319321#else
    320322# error needs porting.
    321323#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 */
     342static 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 */
     355DECLHIDDEN(int) supR3HardenedPathProgram(char *pszPath, size_t cchPath)
     356{
     357    /*
     358     * Lazy init (probably not required).
     359     */
     360    if (!g_szSupLibHardenedDirPath[0])
     361        supR3HardenedGetFullExePath();
    328362
    329363    /*
    330364     * Calc the length and check if there is space before copying.
    331365     */
    332     unsigned cch = strlen(g_szSupLibHardenedProgramPath) + 1;
     366    unsigned cch = strlen(g_szSupLibHardenedDirPath) + 1;
    333367    if (cch <= cchPath)
    334368    {
    335         memcpy(pszPath, g_szSupLibHardenedProgramPath, cch + 1);
     369        memcpy(pszPath, g_szSupLibHardenedDirPath, cch + 1);
    336370        return VINF_SUCCESS;
    337371    }
     
    345379DECLHIDDEN(void) supR3HardenedFatalV(const char *pszFormat, va_list va)
    346380{
    347     fprintf(stderr, "%s: ", g_szSupLibHardenedProgName);
     381    fprintf(stderr, "%s: ", g_pszSupLibHardenedProgName);
    348382    vfprintf(stderr, pszFormat, va);
    349383    for (;;)
     
    370404        supR3HardenedFatalV(pszFormat, va);
    371405
    372     fprintf(stderr, "%s: ", g_szSupLibHardenedProgName);
     406    fprintf(stderr, "%s: ", g_pszSupLibHardenedProgName);
    373407    vfprintf(stderr, pszFormat, va);
    374408    return rc;
     
    469503        supR3HardenedFatal("supR3HardenedMainGetTrustedMain: LoadLibraryEx(\"%s\",,) failed, rc=%d\n",
    470504                            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",
    474508                            szPath, GetLastError());
    475509
     
    485519        supR3HardenedFatal("supR3HardenedMainGetTrustedMain: dlopen(\"%s\",) failed: %s\n",
    486520                            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",
    490524                            szPath, dlerror());
    491525    PFNSUPR3PREINIT pfnSUPPreInit = (PFNSUPR3PREINIT)(uintptr_t)dlsym(pvMod, SUP_HARDENED_SYM("supR3PreInit"));
     
    502536    if (RT_FAILURE(rc))
    503537        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));
    505544    if (RT_FAILURE(rc))
    506545        supR3HardenedFatal("RTR3Init: Failed with rc=%d\n", rc);
     
    582621     * to basic CRT functions that everyone agree upon.
    583622     */
    584     g_szSupLibHardenedProgName = pszProgName;
     623    g_pszSupLibHardenedProgName = pszProgName;
    585624    g_SupPreInitData.u32Magic = SUPPREINITDATA_MAGIC;
    586625    g_SupPreInitData.Data.hDevice = NIL_RTFILE;
     
    596635        supR3HardenedFatal("SUPR3HardenedMain: effective uid is not root (euid=%d egid=%d uid=%d gid=%d)\n",
    597636                           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
    598645#endif
    599646
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