VirtualBox

Changeset 82955 in vbox for trunk


Ignore:
Timestamp:
Feb 3, 2020 12:45:15 PM (5 years ago)
Author:
vboxsync
Message:

FE/Qt: Alternative HideSetUidRootFromAppKit code. bugref:9466

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Frontends/VirtualBox/src/main.cpp

    r79365 r82955  
    124124
    125125#ifdef VBOX_WS_MAC
     126
     127# include <unistd.h>
     128# include <stdio.h>
     129# include <dlfcn.h>
     130# include <iprt/formats/mach-o.h>
     131
     132/**
     133 * Override this one to try hide the fact that we're setuid to root
     134 * orginially.
     135 */
     136int issetugid_for_AppKit(void)
     137{
     138    Dl_info Info = {0};
     139    char szMsg[512];
     140    size_t cchMsg;
     141    const void * uCaller = __builtin_return_address(0);
     142    if (dladdr(uCaller, &Info))
     143        cchMsg = snprintf(szMsg, sizeof(szMsg), "DEBUG: issetugid_for_AppKit was called by %p %s::%s+%p (via %p)\n",
     144                          uCaller, Info.dli_fname, Info.dli_sname, (void *)((uintptr_t)uCaller - (uintptr_t)Info.dli_saddr), __builtin_return_address(1));
     145    else
     146        cchMsg = snprintf(szMsg, sizeof(szMsg), "DEBUG: issetugid_for_AppKit was called by %p (via %p)\n", uCaller, __builtin_return_address(1));
     147    write(2, szMsg, cchMsg);
     148    return 0;
     149}
     150
     151static bool patchExtSym(mach_header_64_t *pHdr, const char *pszSymbol, uintptr_t uNewValue)
     152{
     153    /*
     154     * First do some basic header checks and the scan the load
     155     * commands for the symbol table info.
     156     */
     157    AssertLogRelMsgReturn(pHdr->magic == (ARCH_BITS == 64 ? MH_MAGIC_64 : MH_MAGIC),
     158                          ("%p: magic=%#x\n", pHdr, pHdr->magic), false);
     159    uint32_t const cCmds = pHdr->ncmds;
     160    uint32_t const cbCmds = pHdr->sizeofcmds;
     161    AssertLogRelMsgReturn(cCmds < 16384 && cbCmds < _2M, ("%p: ncmds=%u sizeofcmds=%u\n", pHdr, cCmds, cbCmds), false);
     162
     163    /*
     164     * First command pass: Locate the symbol table and dynamic symbol table info
     165     *                     commands, also calc the slide (load addr - link addr).
     166     */
     167    dysymtab_command_t const   *pDySymTab = NULL;
     168    symtab_command_t const     *pSymTab   = NULL;
     169    segment_command_64_t const *pFirstSeg = NULL;
     170    uintptr_t                   offSlide  = 0;
     171    uint32_t                    offCmd    = 0;
     172    for (uint32_t iCmd = 0; iCmd < cCmds; iCmd++)
     173    {
     174        AssertLogRelMsgReturn(offCmd + sizeof(load_command_t) <= cbCmds,
     175                              ("%p: iCmd=%u offCmd=%#x cbCmds=%#x\n", pHdr, iCmd, offCmd, cbCmds), false);
     176        load_command_t const * const pCmd = (load_command_t const *)((uintptr_t)(pHdr + 1) + offCmd);
     177        uint32_t const cbCurCmd = pCmd->cmdsize;
     178        AssertLogRelMsgReturn(offCmd + cbCurCmd <= cbCmds && cbCurCmd <= cbCmds,
     179                              ("%p: iCmd=%u offCmd=%#x cbCurCmd=%#x cbCmds=%#x\n", pHdr, iCmd, offCmd, cbCurCmd, cbCmds), false);
     180        offCmd += cbCurCmd;
     181
     182        if (pCmd->cmd == LC_SYMTAB)
     183        {
     184            AssertLogRelMsgReturn(!pSymTab, ("%p: pSymTab=%p pCmd=%p\n", pHdr, pSymTab, pCmd), false);
     185            pSymTab = (symtab_command_t const *)pCmd;
     186            AssertLogRelMsgReturn(cbCurCmd == sizeof(*pSymTab), ("%p: pSymTab=%p cbCurCmd=%#x\n", pHdr, pCmd, cbCurCmd), false);
     187
     188        }
     189        else if (pCmd->cmd == LC_DYSYMTAB)
     190        {
     191            AssertLogRelMsgReturn(!pDySymTab, ("%p: pDySymTab=%p pCmd=%p\n", pHdr, pDySymTab, pCmd), false);
     192            pDySymTab = (dysymtab_command_t const *)pCmd;
     193            AssertLogRelMsgReturn(cbCurCmd == sizeof(*pDySymTab), ("%p: pDySymTab=%p cbCurCmd=%#x\n", pHdr, pCmd, cbCurCmd),
     194                                  false);
     195        }
     196        else if (pCmd->cmd == LC_SEGMENT_64 && !pFirstSeg) /* ASSUMES the first seg is the one with the header and stuff. */
     197        {
     198            /* Note! the fileoff and vmaddr seems to be modified. */
     199            pFirstSeg = (segment_command_64_t const *)pCmd;
     200            AssertLogRelMsgReturn(cbCurCmd >= sizeof(*pFirstSeg), ("%p: iCmd=%u cbCurCmd=%#x\n", pHdr, iCmd, cbCurCmd), false);
     201            AssertLogRelMsgReturn(/*pFirstSeg->fileoff == 0 && */ pFirstSeg->vmsize >= sizeof(*pHdr) + cbCmds,
     202                                  ("%p: iCmd=%u fileoff=%llx vmsize=%#llx cbCmds=%#x name=%.16s\n",
     203                                   pHdr, iCmd, pFirstSeg->fileoff, pFirstSeg->vmsize, cbCmds, pFirstSeg->segname), false);
     204            offSlide = (uintptr_t)pHdr - pFirstSeg->vmaddr;
     205        }
     206    }
     207    AssertLogRelMsgReturn(pSymTab, ("%p: no LC_SYMTAB\n", pHdr), false);
     208    AssertLogRelMsgReturn(pDySymTab, ("%p: no LC_DYSYMTAB\n", pHdr), false);
     209    AssertLogRelMsgReturn(pFirstSeg, ("%p: no LC_SEGMENT_64\n", pHdr), false);
     210
     211    /*
     212     * Second command pass: Locate the memory locations of the symbol table, string
     213     *                      table and the indirect symbol table by checking LC_SEGMENT_xx.
     214     */
     215    macho_nlist_64_t const *paSymbols  = NULL;
     216    uint32_t const          offSymbols = pSymTab->symoff;
     217    uint32_t const          cSymbols   = pSymTab->nsyms;
     218    AssertLogRelMsgReturn(cSymbols > 0 && offSymbols >= sizeof(pHdr) + cbCmds,
     219                          ("%p: cSymbols=%#x offSymbols=%#x\n", pHdr, cSymbols, offSymbols), false);
     220
     221    const char    *pchStrTab = NULL;
     222    uint32_t const offStrTab = pSymTab->stroff;
     223    uint32_t const cbStrTab  = pSymTab->strsize;
     224    AssertLogRelMsgReturn(cbStrTab > 0 && offStrTab >= sizeof(pHdr) + cbCmds,
     225                          ("%p: cbStrTab=%#x offStrTab=%#x\n", pHdr, cbStrTab, offStrTab), false);
     226
     227    uint32_t const *paidxIndirSymbols = NULL;
     228    uint32_t const  offIndirSymbols = pDySymTab->indirectsymboff;
     229    uint32_t const  cIndirSymbols   = pDySymTab->nindirectsymb;
     230    AssertLogRelMsgReturn(cIndirSymbols > 0 && offIndirSymbols >= sizeof(pHdr) + cbCmds,
     231                          ("%p: cIndirSymbols=%#x offIndirSymbols=%#x\n", pHdr, cIndirSymbols, offIndirSymbols), false);
     232
     233    offCmd = 0;
     234    for (uint32_t iCmd = 0; iCmd < cCmds; iCmd++)
     235    {
     236        load_command_t const * const pCmd = (load_command_t const *)((uintptr_t)(pHdr + 1) + offCmd);
     237        uint32_t const cbCurCmd = pCmd->cmdsize;
     238        AssertLogRelMsgReturn(offCmd + cbCurCmd <= cbCmds && cbCurCmd <= cbCmds,
     239                              ("%p: iCmd=%u offCmd=%#x cbCurCmd=%#x cbCmds=%#x\n", pHdr, iCmd, offCmd, cbCurCmd, cbCmds), false);
     240        offCmd += cbCurCmd;
     241
     242        if (pCmd->cmd == LC_SEGMENT_64)
     243        {
     244            segment_command_64_t const *pSeg = (segment_command_64_t const *)pCmd;
     245            AssertLogRelMsgReturn(cbCurCmd >= sizeof(*pSeg), ("%p: iCmd=%u cbCurCmd=%#x\n", pHdr, iCmd, cbCurCmd), false);
     246            uintptr_t const uPtrSeg = pSeg->vmaddr + offSlide;
     247            uint64_t const  cbSeg   = pSeg->vmsize;
     248            uint64_t const  offFile = pSeg->fileoff;
     249
     250            uint64_t offSeg = offSymbols - offFile;
     251            if (offSeg < cbSeg)
     252            {
     253                AssertLogRelMsgReturn(!paSymbols, ("%p: paSymbols=%p uPtrSeg=%p off=%#llx\n", pHdr, paSymbols, uPtrSeg, offSeg),
     254                                      false);
     255                AssertLogRelMsgReturn(offSeg + cSymbols * sizeof(paSymbols[0]) <= cbSeg,
     256                                      ("%p: offSeg=%#llx cSymbols=%#x cbSeg=%llx\n", pHdr, offSeg, cSymbols, cbSeg), false);
     257                paSymbols = (macho_nlist_64_t const *)(uPtrSeg + offSeg);
     258            }
     259
     260            offSeg = offStrTab - offFile;
     261            if (offSeg < cbSeg)
     262            {
     263                AssertLogRelMsgReturn(!pchStrTab, ("%p: paSymbols=%p uPtrSeg=%p\n", pHdr, pchStrTab, uPtrSeg), false);
     264                AssertLogRelMsgReturn(offSeg + cbStrTab <= cbSeg,
     265                                      ("%p: offSeg=%#llx cbStrTab=%#x cbSeg=%llx\n", pHdr, offSeg, cbStrTab, cbSeg), false);
     266                pchStrTab = (const char *)(uPtrSeg + offSeg);
     267            }
     268
     269            offSeg = offIndirSymbols - offFile;
     270            if (offSeg < cbSeg)
     271            {
     272                AssertLogRelMsgReturn(!paidxIndirSymbols,
     273                                      ("%p: paidxIndirSymbols=%p uPtrSeg=%p\n", pHdr, paidxIndirSymbols, uPtrSeg), false);
     274                AssertLogRelMsgReturn(offSeg + cIndirSymbols * sizeof(paidxIndirSymbols[0]) <= cbSeg,
     275                                      ("%p: offSeg=%#llx cIndirSymbols=%#x cbSeg=%llx\n", pHdr, offSeg, cIndirSymbols, cbSeg),
     276                                      false);
     277                paidxIndirSymbols = (uint32_t const *)(uPtrSeg + offSeg);
     278            }
     279        }
     280    }
     281
     282    AssertLogRelMsgReturn(paSymbols, ("%p: offSymbols=%#x\n", pHdr, offSymbols), false);
     283    AssertLogRelMsgReturn(pchStrTab, ("%p: offStrTab=%#x\n", pHdr, offStrTab), false);
     284    AssertLogRelMsgReturn(paidxIndirSymbols, ("%p: offIndirSymbols=%#x\n", pHdr, offIndirSymbols), false);
     285
     286    /*
     287     * Third command pass: Process sections of types S_NON_LAZY_SYMBOL_POINTERS
     288     *                     and S_LAZY_SYMBOL_POINTERS
     289     */
     290    bool fFound = false;
     291    offCmd = 0;
     292    for (uint32_t iCmd = 0; iCmd < cCmds; iCmd++)
     293    {
     294        load_command_t const * const pCmd = (load_command_t const *)((uintptr_t)(pHdr + 1) + offCmd);
     295        uint32_t const cbCurCmd = pCmd->cmdsize;
     296        AssertLogRelMsgReturn(offCmd + cbCurCmd <= cbCmds && cbCurCmd <= cbCmds,
     297                              ("%p: iCmd=%u offCmd=%#x cbCurCmd=%#x cbCmds=%#x\n", pHdr, iCmd, offCmd, cbCurCmd, cbCmds), false);
     298        offCmd += cbCurCmd;
     299        if (pCmd->cmd == LC_SEGMENT_64)
     300        {
     301            segment_command_64_t const *pSeg = (segment_command_64_t const *)pCmd;
     302            AssertLogRelMsgReturn(cbCurCmd >= sizeof(*pSeg), ("%p: iCmd=%u cbCurCmd=%#x\n", pHdr, iCmd, cbCurCmd), false);
     303            uint64_t const  uSegAddr = pSeg->vmaddr;
     304            uint64_t const  cbSeg    = pSeg->vmsize;
     305
     306            uint32_t const             cSections  = pSeg->nsects;
     307            section_64_t const * const paSections = (section_64_t const *)(pSeg + 1);
     308            AssertLogRelMsgReturn(cSections < _256K && sizeof(*pSeg) + cSections * sizeof(paSections[0]) <= cbCurCmd,
     309                                  ("%p: iCmd=%u cSections=%#x cbCurCmd=%#x\n", pHdr, iCmd, cSections, cbCurCmd), false);
     310            for (uint32_t iSection = 0; iSection < cSections; iSection++)
     311            {
     312                if (   paSections[iSection].flags == S_NON_LAZY_SYMBOL_POINTERS
     313                    || paSections[iSection].flags == S_LAZY_SYMBOL_POINTERS)
     314                {
     315                    uint32_t const idxIndirBase = paSections[iSection].reserved1;
     316                    uint32_t const cEntries     = paSections[iSection].size / sizeof(uintptr_t);
     317                    AssertLogRelMsgReturn(idxIndirBase <= cIndirSymbols && idxIndirBase + cEntries <= cIndirSymbols,
     318                                          ("%p: idxIndirBase=%#x cEntries=%#x cIndirSymbols=%#x\n",
     319                                           pHdr, idxIndirBase, cEntries, cIndirSymbols), false);
     320                    uint64_t const uSecAddr = paSections[iSection].addr;
     321                    uint64_t const offInSeg = uSecAddr - uSegAddr;
     322                    AssertLogRelMsgReturn(offInSeg < cbSeg && offInSeg + cEntries * sizeof(uintptr_t) <= cbSeg,
     323                                          ("%p: offInSeg=%#llx cEntries=%#x cbSeg=%#llx\n", pHdr, offInSeg, cEntries, cbSeg),
     324                                          false);
     325                    uintptr_t *pauPtrs = (uintptr_t *)(uSecAddr + offSlide);
     326                    for (uint32_t iEntry = 0; iEntry < cEntries; iEntry++)
     327                    {
     328                        uint32_t const idxSym = paidxIndirSymbols[idxIndirBase + iEntry];
     329                        if (idxSym < cSymbols)
     330                        {
     331                            macho_nlist_64_t const * const pSym    = &paSymbols[idxSym];
     332                            const char * const             pszName = pSym->n_un.n_strx < cbStrTab
     333                                                                   ? &pchStrTab[pSym->n_un.n_strx] : "!invalid symtab offset!";
     334                            if (strcmp(pszName, pszSymbol) == 0)
     335                            {
     336                                pauPtrs[iEntry] = uNewValue;
     337                                fFound = true;
     338                                break;
     339                            }
     340                        }
     341                        else
     342                            AssertMsg(idxSym == INDIRECT_SYMBOL_LOCAL || idxSym == INDIRECT_SYMBOL_ABS, ("%#x\n", idxSym));
     343                    }
     344                }
     345            }
     346        }
     347    }
     348    AssertLogRel(fFound);
     349    return fFound;
     350}
     351
    126352/**
    127353 * Mac OS X: Really ugly hack to bypass a set-uid check in AppKit.
     
    135361static void HideSetUidRootFromAppKit()
    136362{
     363    void *pvAddr;
    137364    /* Find issetguid() and make it always return 0 by modifying the code: */
    138     void *pvAddr = dlsym(RTLD_DEFAULT, "issetugid");
     365# if 0
     366    pvAddr = dlsym(RTLD_DEFAULT, "issetugid");
    139367    int rc = mprotect((void *)((uintptr_t)pvAddr & ~(uintptr_t)0xfff), 0x2000, PROT_WRITE | PROT_READ | PROT_EXEC);
    140368    if (!rc)
    141369        ASMAtomicWriteU32((volatile uint32_t *)pvAddr, 0xccc3c031); /* xor eax, eax; ret; int3 */
     370    else
     371# endif
     372    {
     373        /* Failing that, find AppKit and patch its import table: */
     374        void *pvAppKit = dlopen("/System/Library/Frameworks/AppKit.framework/AppKit", RTLD_NOLOAD);
     375        pvAddr = dlsym(pvAppKit, "NSApplicationMain");
     376        Dl_info Info = {0};
     377        if (   dladdr(pvAddr, &Info)
     378            && Info.dli_fbase != NULL)
     379        {
     380            if (!patchExtSym((mach_header_64_t *)Info.dli_fbase, "_issetugid", (uintptr_t)&issetugid_for_AppKit))
     381                write(2, RT_STR_TUPLE("WARNING: Failed to patch issetugid in AppKit! (patchExtSym)\n"));
     382# ifdef DEBUG
     383            else
     384                write(2, RT_STR_TUPLE("INFO: Successfully patched _issetugid import for AppKit!\n"));
     385# endif
     386        }
     387        else
     388            write(2, RT_STR_TUPLE("WARNING: Failed to patch issetugid in AppKit! (dladdr)\n"));
     389    }
     390
    142391}
     392
    143393#endif /* VBOX_WS_MAC */
    144394
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