VirtualBox

Changeset 85488 in vbox for trunk/src/VBox/Frontends


Ignore:
Timestamp:
Jul 28, 2020 1:38:39 PM (4 years ago)
Author:
vboxsync
Message:

FE/VBoxHeadless: ticketref:19706 Apply alternative hideSetUidRootFromAppKit() from VirtualBox/src/main.cpp (r135961)

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Frontends/VBoxHeadless/VBoxHeadless.cpp

    r82968 r85488  
    529529
    530530#ifdef RT_OS_DARWIN
     531
     532# include <unistd.h>
     533# include <stdio.h>
     534# include <dlfcn.h>
     535# include <iprt/formats/mach-o.h>
     536
     537/**
     538 * Override this one to try hide the fact that we're setuid to root
     539 * orginially.
     540 */
     541int issetugid_for_AppKit(void)
     542{
     543    Dl_info Info = {0};
     544    char szMsg[512];
     545    size_t cchMsg;
     546    const void * uCaller = __builtin_return_address(0);
     547    if (dladdr(uCaller, &Info))
     548        cchMsg = snprintf(szMsg, sizeof(szMsg), "DEBUG: issetugid_for_AppKit was called by %p %s::%s+%p (via %p)\n",
     549                          uCaller, Info.dli_fname, Info.dli_sname, (void *)((uintptr_t)uCaller - (uintptr_t)Info.dli_saddr), __builtin_return_address(1));
     550    else
     551        cchMsg = snprintf(szMsg, sizeof(szMsg), "DEBUG: issetugid_for_AppKit was called by %p (via %p)\n", uCaller, __builtin_return_address(1));
     552    write(2, szMsg, cchMsg);
     553    return 0;
     554}
     555
     556static bool patchExtSym(mach_header_64_t *pHdr, const char *pszSymbol, uintptr_t uNewValue)
     557{
     558    /*
     559     * First do some basic header checks and the scan the load
     560     * commands for the symbol table info.
     561     */
     562    AssertLogRelMsgReturn(pHdr->magic == (ARCH_BITS == 64 ? MH_MAGIC_64 : MH_MAGIC),
     563                          ("%p: magic=%#x\n", pHdr, pHdr->magic), false);
     564    uint32_t const cCmds = pHdr->ncmds;
     565    uint32_t const cbCmds = pHdr->sizeofcmds;
     566    AssertLogRelMsgReturn(cCmds < 16384 && cbCmds < _2M, ("%p: ncmds=%u sizeofcmds=%u\n", pHdr, cCmds, cbCmds), false);
     567
     568    /*
     569     * First command pass: Locate the symbol table and dynamic symbol table info
     570     *                     commands, also calc the slide (load addr - link addr).
     571     */
     572    dysymtab_command_t const   *pDySymTab = NULL;
     573    symtab_command_t const     *pSymTab   = NULL;
     574    segment_command_64_t const *pFirstSeg = NULL;
     575    uintptr_t                   offSlide  = 0;
     576    uint32_t                    offCmd    = 0;
     577    for (uint32_t iCmd = 0; iCmd < cCmds; iCmd++)
     578    {
     579        AssertLogRelMsgReturn(offCmd + sizeof(load_command_t) <= cbCmds,
     580                              ("%p: iCmd=%u offCmd=%#x cbCmds=%#x\n", pHdr, iCmd, offCmd, cbCmds), false);
     581        load_command_t const * const pCmd = (load_command_t const *)((uintptr_t)(pHdr + 1) + offCmd);
     582        uint32_t const cbCurCmd = pCmd->cmdsize;
     583        AssertLogRelMsgReturn(offCmd + cbCurCmd <= cbCmds && cbCurCmd <= cbCmds,
     584                              ("%p: iCmd=%u offCmd=%#x cbCurCmd=%#x cbCmds=%#x\n", pHdr, iCmd, offCmd, cbCurCmd, cbCmds), false);
     585        offCmd += cbCurCmd;
     586
     587        if (pCmd->cmd == LC_SYMTAB)
     588        {
     589            AssertLogRelMsgReturn(!pSymTab, ("%p: pSymTab=%p pCmd=%p\n", pHdr, pSymTab, pCmd), false);
     590            pSymTab = (symtab_command_t const *)pCmd;
     591            AssertLogRelMsgReturn(cbCurCmd == sizeof(*pSymTab), ("%p: pSymTab=%p cbCurCmd=%#x\n", pHdr, pCmd, cbCurCmd), false);
     592
     593        }
     594        else if (pCmd->cmd == LC_DYSYMTAB)
     595        {
     596            AssertLogRelMsgReturn(!pDySymTab, ("%p: pDySymTab=%p pCmd=%p\n", pHdr, pDySymTab, pCmd), false);
     597            pDySymTab = (dysymtab_command_t const *)pCmd;
     598            AssertLogRelMsgReturn(cbCurCmd == sizeof(*pDySymTab), ("%p: pDySymTab=%p cbCurCmd=%#x\n", pHdr, pCmd, cbCurCmd),
     599                                  false);
     600        }
     601        else if (pCmd->cmd == LC_SEGMENT_64 && !pFirstSeg) /* ASSUMES the first seg is the one with the header and stuff. */
     602        {
     603            /* Note! the fileoff and vmaddr seems to be modified. */
     604            pFirstSeg = (segment_command_64_t const *)pCmd;
     605            AssertLogRelMsgReturn(cbCurCmd >= sizeof(*pFirstSeg), ("%p: iCmd=%u cbCurCmd=%#x\n", pHdr, iCmd, cbCurCmd), false);
     606            AssertLogRelMsgReturn(/*pFirstSeg->fileoff == 0 && */ pFirstSeg->vmsize >= sizeof(*pHdr) + cbCmds,
     607                                  ("%p: iCmd=%u fileoff=%llx vmsize=%#llx cbCmds=%#x name=%.16s\n",
     608                                   pHdr, iCmd, pFirstSeg->fileoff, pFirstSeg->vmsize, cbCmds, pFirstSeg->segname), false);
     609            offSlide = (uintptr_t)pHdr - pFirstSeg->vmaddr;
     610        }
     611    }
     612    AssertLogRelMsgReturn(pSymTab, ("%p: no LC_SYMTAB\n", pHdr), false);
     613    AssertLogRelMsgReturn(pDySymTab, ("%p: no LC_DYSYMTAB\n", pHdr), false);
     614    AssertLogRelMsgReturn(pFirstSeg, ("%p: no LC_SEGMENT_64\n", pHdr), false);
     615
     616    /*
     617     * Second command pass: Locate the memory locations of the symbol table, string
     618     *                      table and the indirect symbol table by checking LC_SEGMENT_xx.
     619     */
     620    macho_nlist_64_t const *paSymbols  = NULL;
     621    uint32_t const          offSymbols = pSymTab->symoff;
     622    uint32_t const          cSymbols   = pSymTab->nsyms;
     623    AssertLogRelMsgReturn(cSymbols > 0 && offSymbols >= sizeof(pHdr) + cbCmds,
     624                          ("%p: cSymbols=%#x offSymbols=%#x\n", pHdr, cSymbols, offSymbols), false);
     625
     626    const char    *pchStrTab = NULL;
     627    uint32_t const offStrTab = pSymTab->stroff;
     628    uint32_t const cbStrTab  = pSymTab->strsize;
     629    AssertLogRelMsgReturn(cbStrTab > 0 && offStrTab >= sizeof(pHdr) + cbCmds,
     630                          ("%p: cbStrTab=%#x offStrTab=%#x\n", pHdr, cbStrTab, offStrTab), false);
     631
     632    uint32_t const *paidxIndirSymbols = NULL;
     633    uint32_t const  offIndirSymbols = pDySymTab->indirectsymboff;
     634    uint32_t const  cIndirSymbols   = pDySymTab->nindirectsymb;
     635    AssertLogRelMsgReturn(cIndirSymbols > 0 && offIndirSymbols >= sizeof(pHdr) + cbCmds,
     636                          ("%p: cIndirSymbols=%#x offIndirSymbols=%#x\n", pHdr, cIndirSymbols, offIndirSymbols), false);
     637
     638    offCmd = 0;
     639    for (uint32_t iCmd = 0; iCmd < cCmds; iCmd++)
     640    {
     641        load_command_t const * const pCmd = (load_command_t const *)((uintptr_t)(pHdr + 1) + offCmd);
     642        uint32_t const cbCurCmd = pCmd->cmdsize;
     643        AssertLogRelMsgReturn(offCmd + cbCurCmd <= cbCmds && cbCurCmd <= cbCmds,
     644                              ("%p: iCmd=%u offCmd=%#x cbCurCmd=%#x cbCmds=%#x\n", pHdr, iCmd, offCmd, cbCurCmd, cbCmds), false);
     645        offCmd += cbCurCmd;
     646
     647        if (pCmd->cmd == LC_SEGMENT_64)
     648        {
     649            segment_command_64_t const *pSeg = (segment_command_64_t const *)pCmd;
     650            AssertLogRelMsgReturn(cbCurCmd >= sizeof(*pSeg), ("%p: iCmd=%u cbCurCmd=%#x\n", pHdr, iCmd, cbCurCmd), false);
     651            uintptr_t const uPtrSeg = pSeg->vmaddr + offSlide;
     652            uint64_t const  cbSeg   = pSeg->vmsize;
     653            uint64_t const  offFile = pSeg->fileoff;
     654
     655            uint64_t offSeg = offSymbols - offFile;
     656            if (offSeg < cbSeg)
     657            {
     658                AssertLogRelMsgReturn(!paSymbols, ("%p: paSymbols=%p uPtrSeg=%p off=%#llx\n", pHdr, paSymbols, uPtrSeg, offSeg),
     659                                      false);
     660                AssertLogRelMsgReturn(offSeg + cSymbols * sizeof(paSymbols[0]) <= cbSeg,
     661                                      ("%p: offSeg=%#llx cSymbols=%#x cbSeg=%llx\n", pHdr, offSeg, cSymbols, cbSeg), false);
     662                paSymbols = (macho_nlist_64_t const *)(uPtrSeg + offSeg);
     663            }
     664
     665            offSeg = offStrTab - offFile;
     666            if (offSeg < cbSeg)
     667            {
     668                AssertLogRelMsgReturn(!pchStrTab, ("%p: paSymbols=%p uPtrSeg=%p\n", pHdr, pchStrTab, uPtrSeg), false);
     669                AssertLogRelMsgReturn(offSeg + cbStrTab <= cbSeg,
     670                                      ("%p: offSeg=%#llx cbStrTab=%#x cbSeg=%llx\n", pHdr, offSeg, cbStrTab, cbSeg), false);
     671                pchStrTab = (const char *)(uPtrSeg + offSeg);
     672            }
     673
     674            offSeg = offIndirSymbols - offFile;
     675            if (offSeg < cbSeg)
     676            {
     677                AssertLogRelMsgReturn(!paidxIndirSymbols,
     678                                      ("%p: paidxIndirSymbols=%p uPtrSeg=%p\n", pHdr, paidxIndirSymbols, uPtrSeg), false);
     679                AssertLogRelMsgReturn(offSeg + cIndirSymbols * sizeof(paidxIndirSymbols[0]) <= cbSeg,
     680                                      ("%p: offSeg=%#llx cIndirSymbols=%#x cbSeg=%llx\n", pHdr, offSeg, cIndirSymbols, cbSeg),
     681                                      false);
     682                paidxIndirSymbols = (uint32_t const *)(uPtrSeg + offSeg);
     683            }
     684        }
     685    }
     686
     687    AssertLogRelMsgReturn(paSymbols, ("%p: offSymbols=%#x\n", pHdr, offSymbols), false);
     688    AssertLogRelMsgReturn(pchStrTab, ("%p: offStrTab=%#x\n", pHdr, offStrTab), false);
     689    AssertLogRelMsgReturn(paidxIndirSymbols, ("%p: offIndirSymbols=%#x\n", pHdr, offIndirSymbols), false);
     690
     691    /*
     692     * Third command pass: Process sections of types S_NON_LAZY_SYMBOL_POINTERS
     693     *                     and S_LAZY_SYMBOL_POINTERS
     694     */
     695    bool fFound = false;
     696    offCmd = 0;
     697    for (uint32_t iCmd = 0; iCmd < cCmds; iCmd++)
     698    {
     699        load_command_t const * const pCmd = (load_command_t const *)((uintptr_t)(pHdr + 1) + offCmd);
     700        uint32_t const cbCurCmd = pCmd->cmdsize;
     701        AssertLogRelMsgReturn(offCmd + cbCurCmd <= cbCmds && cbCurCmd <= cbCmds,
     702                              ("%p: iCmd=%u offCmd=%#x cbCurCmd=%#x cbCmds=%#x\n", pHdr, iCmd, offCmd, cbCurCmd, cbCmds), false);
     703        offCmd += cbCurCmd;
     704        if (pCmd->cmd == LC_SEGMENT_64)
     705        {
     706            segment_command_64_t const *pSeg = (segment_command_64_t const *)pCmd;
     707            AssertLogRelMsgReturn(cbCurCmd >= sizeof(*pSeg), ("%p: iCmd=%u cbCurCmd=%#x\n", pHdr, iCmd, cbCurCmd), false);
     708            uint64_t const  uSegAddr = pSeg->vmaddr;
     709            uint64_t const  cbSeg    = pSeg->vmsize;
     710
     711            uint32_t const             cSections  = pSeg->nsects;
     712            section_64_t const * const paSections = (section_64_t const *)(pSeg + 1);
     713            AssertLogRelMsgReturn(cSections < _256K && sizeof(*pSeg) + cSections * sizeof(paSections[0]) <= cbCurCmd,
     714                                  ("%p: iCmd=%u cSections=%#x cbCurCmd=%#x\n", pHdr, iCmd, cSections, cbCurCmd), false);
     715            for (uint32_t iSection = 0; iSection < cSections; iSection++)
     716            {
     717                if (   paSections[iSection].flags == S_NON_LAZY_SYMBOL_POINTERS
     718                    || paSections[iSection].flags == S_LAZY_SYMBOL_POINTERS)
     719                {
     720                    uint32_t const idxIndirBase = paSections[iSection].reserved1;
     721                    uint32_t const cEntries     = paSections[iSection].size / sizeof(uintptr_t);
     722                    AssertLogRelMsgReturn(idxIndirBase <= cIndirSymbols && idxIndirBase + cEntries <= cIndirSymbols,
     723                                          ("%p: idxIndirBase=%#x cEntries=%#x cIndirSymbols=%#x\n",
     724                                           pHdr, idxIndirBase, cEntries, cIndirSymbols), false);
     725                    uint64_t const uSecAddr = paSections[iSection].addr;
     726                    uint64_t const offInSeg = uSecAddr - uSegAddr;
     727                    AssertLogRelMsgReturn(offInSeg < cbSeg && offInSeg + cEntries * sizeof(uintptr_t) <= cbSeg,
     728                                          ("%p: offInSeg=%#llx cEntries=%#x cbSeg=%#llx\n", pHdr, offInSeg, cEntries, cbSeg),
     729                                          false);
     730                    uintptr_t *pauPtrs = (uintptr_t *)(uSecAddr + offSlide);
     731                    for (uint32_t iEntry = 0; iEntry < cEntries; iEntry++)
     732                    {
     733                        uint32_t const idxSym = paidxIndirSymbols[idxIndirBase + iEntry];
     734                        if (idxSym < cSymbols)
     735                        {
     736                            macho_nlist_64_t const * const pSym    = &paSymbols[idxSym];
     737                            const char * const             pszName = pSym->n_un.n_strx < cbStrTab
     738                                                                   ? &pchStrTab[pSym->n_un.n_strx] : "!invalid symtab offset!";
     739                            if (strcmp(pszName, pszSymbol) == 0)
     740                            {
     741                                pauPtrs[iEntry] = uNewValue;
     742                                fFound = true;
     743                                break;
     744                            }
     745                        }
     746                        else
     747                            AssertMsg(idxSym == INDIRECT_SYMBOL_LOCAL || idxSym == INDIRECT_SYMBOL_ABS, ("%#x\n", idxSym));
     748                    }
     749                }
     750            }
     751        }
     752    }
     753    AssertLogRel(fFound);
     754    return fFound;
     755}
     756
    531757/**
    532758 * Mac OS X: Really ugly hack to bypass a set-uid check in AppKit.
     
    540766static void hideSetUidRootFromAppKit()
    541767{
     768    void *pvAddr;
    542769    /* Find issetguid() and make it always return 0 by modifying the code: */
    543     void *pvAddr = dlsym(RTLD_DEFAULT, "issetugid");
     770# if 0
     771    pvAddr = dlsym(RTLD_DEFAULT, "issetugid");
    544772    int rc = mprotect((void *)((uintptr_t)pvAddr & ~(uintptr_t)0xfff), 0x2000, PROT_WRITE | PROT_READ | PROT_EXEC);
    545773    if (!rc)
    546774        ASMAtomicWriteU32((volatile uint32_t *)pvAddr, 0xccc3c031); /* xor eax, eax; ret; int3 */
     775    else
     776# endif
     777    {
     778        /* Failing that, find AppKit and patch its import table: */
     779        void *pvAppKit = dlopen("/System/Library/Frameworks/AppKit.framework/AppKit", RTLD_NOLOAD);
     780        pvAddr = dlsym(pvAppKit, "NSApplicationMain");
     781        Dl_info Info = {0};
     782        if (   dladdr(pvAddr, &Info)
     783            && Info.dli_fbase != NULL)
     784        {
     785            if (!patchExtSym((mach_header_64_t *)Info.dli_fbase, "_issetugid", (uintptr_t)&issetugid_for_AppKit))
     786                write(2, RT_STR_TUPLE("WARNING: Failed to patch issetugid in AppKit! (patchExtSym)\n"));
     787# ifdef DEBUG
     788            else
     789                write(2, RT_STR_TUPLE("INFO: Successfully patched _issetugid import for AppKit!\n"));
     790# endif
     791        }
     792        else
     793            write(2, RT_STR_TUPLE("WARNING: Failed to patch issetugid in AppKit! (dladdr)\n"));
     794    }
     795
    547796}
     797
    548798#endif /* RT_OS_DARWIN */
    549799
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