VirtualBox

Ignore:
Timestamp:
Oct 26, 2021 7:41:11 AM (3 years ago)
Author:
vboxsync
Message:

FE/VBoxHeadless: Disable patching the AppKit import table for the issetuid() hack as it should be done already in the hardened startup library and it crashes on macOS Monterey [Remove the code as test worked out]

File:
1 edited

Legend:

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

    r92060 r92063  
    484484}
    485485#endif /* VBOX_WITH_RECORDING defined */
    486 
    487 /* This should be done in the hardening code already and it fails on Monterey. */
    488 #if 0 //def RT_OS_DARWIN
    489 
    490 # include <unistd.h>
    491 # include <stdio.h>
    492 # include <dlfcn.h>
    493 # include <iprt/formats/mach-o.h>
    494 
    495 /**
    496  * Override this one to try hide the fact that we're setuid to root
    497  * orginially.
    498  */
    499 int issetugid_for_AppKit(void)
    500 {
    501     Dl_info Info = {0};
    502     char szMsg[512];
    503     size_t cchMsg;
    504     const void * uCaller = __builtin_return_address(0);
    505     if (dladdr(uCaller, &Info))
    506         cchMsg = snprintf(szMsg, sizeof(szMsg), "DEBUG: issetugid_for_AppKit was called by %p %s::%s+%p\n",
    507                           uCaller, Info.dli_fname, Info.dli_sname, (void *)((uintptr_t)uCaller - (uintptr_t)Info.dli_saddr));
    508     else
    509         cchMsg = snprintf(szMsg, sizeof(szMsg), "DEBUG: issetugid_for_AppKit was called by %p\n", uCaller);
    510     write(2, szMsg, cchMsg);
    511     return 0;
    512 }
    513 
    514 static bool patchExtSym(mach_header_64_t *pHdr, const char *pszSymbol, uintptr_t uNewValue)
    515 {
    516     /*
    517      * First do some basic header checks and the scan the load
    518      * commands for the symbol table info.
    519      */
    520     AssertLogRelMsgReturn(pHdr->magic == (ARCH_BITS == 64 ? MH_MAGIC_64 : MH_MAGIC),
    521                           ("%p: magic=%#x\n", pHdr, pHdr->magic), false);
    522     uint32_t const cCmds = pHdr->ncmds;
    523     uint32_t const cbCmds = pHdr->sizeofcmds;
    524     AssertLogRelMsgReturn(cCmds < 16384 && cbCmds < _2M, ("%p: ncmds=%u sizeofcmds=%u\n", pHdr, cCmds, cbCmds), false);
    525 
    526     /*
    527      * First command pass: Locate the symbol table and dynamic symbol table info
    528      *                     commands, also calc the slide (load addr - link addr).
    529      */
    530     dysymtab_command_t const   *pDySymTab = NULL;
    531     symtab_command_t const     *pSymTab   = NULL;
    532     segment_command_64_t const *pFirstSeg = NULL;
    533     uintptr_t                   offSlide  = 0;
    534     uint32_t                    offCmd    = 0;
    535     for (uint32_t iCmd = 0; iCmd < cCmds; iCmd++)
    536     {
    537         AssertLogRelMsgReturn(offCmd + sizeof(load_command_t) <= cbCmds,
    538                               ("%p: iCmd=%u offCmd=%#x cbCmds=%#x\n", pHdr, iCmd, offCmd, cbCmds), false);
    539         load_command_t const * const pCmd = (load_command_t const *)((uintptr_t)(pHdr + 1) + offCmd);
    540         uint32_t const cbCurCmd = pCmd->cmdsize;
    541         AssertLogRelMsgReturn(offCmd + cbCurCmd <= cbCmds && cbCurCmd <= cbCmds,
    542                               ("%p: iCmd=%u offCmd=%#x cbCurCmd=%#x cbCmds=%#x\n", pHdr, iCmd, offCmd, cbCurCmd, cbCmds), false);
    543         offCmd += cbCurCmd;
    544 
    545         if (pCmd->cmd == LC_SYMTAB)
    546         {
    547             AssertLogRelMsgReturn(!pSymTab, ("%p: pSymTab=%p pCmd=%p\n", pHdr, pSymTab, pCmd), false);
    548             pSymTab = (symtab_command_t const *)pCmd;
    549             AssertLogRelMsgReturn(cbCurCmd == sizeof(*pSymTab), ("%p: pSymTab=%p cbCurCmd=%#x\n", pHdr, pCmd, cbCurCmd), false);
    550 
    551         }
    552         else if (pCmd->cmd == LC_DYSYMTAB)
    553         {
    554             AssertLogRelMsgReturn(!pDySymTab, ("%p: pDySymTab=%p pCmd=%p\n", pHdr, pDySymTab, pCmd), false);
    555             pDySymTab = (dysymtab_command_t const *)pCmd;
    556             AssertLogRelMsgReturn(cbCurCmd == sizeof(*pDySymTab), ("%p: pDySymTab=%p cbCurCmd=%#x\n", pHdr, pCmd, cbCurCmd),
    557                                   false);
    558         }
    559         else if (pCmd->cmd == LC_SEGMENT_64 && !pFirstSeg) /* ASSUMES the first seg is the one with the header and stuff. */
    560         {
    561             /* Note! the fileoff and vmaddr seems to be modified. */
    562             pFirstSeg = (segment_command_64_t const *)pCmd;
    563             AssertLogRelMsgReturn(cbCurCmd >= sizeof(*pFirstSeg), ("%p: iCmd=%u cbCurCmd=%#x\n", pHdr, iCmd, cbCurCmd), false);
    564             AssertLogRelMsgReturn(/*pFirstSeg->fileoff == 0 && */ pFirstSeg->vmsize >= sizeof(*pHdr) + cbCmds,
    565                                   ("%p: iCmd=%u fileoff=%llx vmsize=%#llx cbCmds=%#x name=%.16s\n",
    566                                    pHdr, iCmd, pFirstSeg->fileoff, pFirstSeg->vmsize, cbCmds, pFirstSeg->segname), false);
    567             offSlide = (uintptr_t)pHdr - pFirstSeg->vmaddr;
    568         }
    569     }
    570     AssertLogRelMsgReturn(pSymTab, ("%p: no LC_SYMTAB\n", pHdr), false);
    571     AssertLogRelMsgReturn(pDySymTab, ("%p: no LC_DYSYMTAB\n", pHdr), false);
    572     AssertLogRelMsgReturn(pFirstSeg, ("%p: no LC_SEGMENT_64\n", pHdr), false);
    573 
    574     /*
    575      * Second command pass: Locate the memory locations of the symbol table, string
    576      *                      table and the indirect symbol table by checking LC_SEGMENT_xx.
    577      */
    578     macho_nlist_64_t const *paSymbols  = NULL;
    579     uint32_t const          offSymbols = pSymTab->symoff;
    580     uint32_t const          cSymbols   = pSymTab->nsyms;
    581     AssertLogRelMsgReturn(cSymbols > 0 && offSymbols >= sizeof(pHdr) + cbCmds,
    582                           ("%p: cSymbols=%#x offSymbols=%#x\n", pHdr, cSymbols, offSymbols), false);
    583 
    584     const char    *pchStrTab = NULL;
    585     uint32_t const offStrTab = pSymTab->stroff;
    586     uint32_t const cbStrTab  = pSymTab->strsize;
    587     AssertLogRelMsgReturn(cbStrTab > 0 && offStrTab >= sizeof(pHdr) + cbCmds,
    588                           ("%p: cbStrTab=%#x offStrTab=%#x\n", pHdr, cbStrTab, offStrTab), false);
    589 
    590     uint32_t const *paidxIndirSymbols = NULL;
    591     uint32_t const  offIndirSymbols = pDySymTab->indirectsymboff;
    592     uint32_t const  cIndirSymbols   = pDySymTab->nindirectsymb;
    593     AssertLogRelMsgReturn(cIndirSymbols > 0 && offIndirSymbols >= sizeof(pHdr) + cbCmds,
    594                           ("%p: cIndirSymbols=%#x offIndirSymbols=%#x\n", pHdr, cIndirSymbols, offIndirSymbols), false);
    595 
    596     offCmd = 0;
    597     for (uint32_t iCmd = 0; iCmd < cCmds; iCmd++)
    598     {
    599         load_command_t const * const pCmd = (load_command_t const *)((uintptr_t)(pHdr + 1) + offCmd);
    600         uint32_t const cbCurCmd = pCmd->cmdsize;
    601         AssertLogRelMsgReturn(offCmd + cbCurCmd <= cbCmds && cbCurCmd <= cbCmds,
    602                               ("%p: iCmd=%u offCmd=%#x cbCurCmd=%#x cbCmds=%#x\n", pHdr, iCmd, offCmd, cbCurCmd, cbCmds), false);
    603         offCmd += cbCurCmd;
    604 
    605         if (pCmd->cmd == LC_SEGMENT_64)
    606         {
    607             segment_command_64_t const *pSeg = (segment_command_64_t const *)pCmd;
    608             AssertLogRelMsgReturn(cbCurCmd >= sizeof(*pSeg), ("%p: iCmd=%u cbCurCmd=%#x\n", pHdr, iCmd, cbCurCmd), false);
    609             uintptr_t const uPtrSeg = pSeg->vmaddr + offSlide;
    610             uint64_t const  cbSeg   = pSeg->vmsize;
    611             uint64_t const  offFile = pSeg->fileoff;
    612 
    613             uint64_t offSeg = offSymbols - offFile;
    614             if (offSeg < cbSeg)
    615             {
    616                 AssertLogRelMsgReturn(!paSymbols, ("%p: paSymbols=%p uPtrSeg=%p off=%#llx\n", pHdr, paSymbols, uPtrSeg, offSeg),
    617                                       false);
    618                 AssertLogRelMsgReturn(offSeg + cSymbols * sizeof(paSymbols[0]) <= cbSeg,
    619                                       ("%p: offSeg=%#llx cSymbols=%#x cbSeg=%llx\n", pHdr, offSeg, cSymbols, cbSeg), false);
    620                 paSymbols = (macho_nlist_64_t const *)(uPtrSeg + offSeg);
    621             }
    622 
    623             offSeg = offStrTab - offFile;
    624             if (offSeg < cbSeg)
    625             {
    626                 AssertLogRelMsgReturn(!pchStrTab, ("%p: paSymbols=%p uPtrSeg=%p\n", pHdr, pchStrTab, uPtrSeg), false);
    627                 AssertLogRelMsgReturn(offSeg + cbStrTab <= cbSeg,
    628                                       ("%p: offSeg=%#llx cbStrTab=%#x cbSeg=%llx\n", pHdr, offSeg, cbStrTab, cbSeg), false);
    629                 pchStrTab = (const char *)(uPtrSeg + offSeg);
    630             }
    631 
    632             offSeg = offIndirSymbols - offFile;
    633             if (offSeg < cbSeg)
    634             {
    635                 AssertLogRelMsgReturn(!paidxIndirSymbols,
    636                                       ("%p: paidxIndirSymbols=%p uPtrSeg=%p\n", pHdr, paidxIndirSymbols, uPtrSeg), false);
    637                 AssertLogRelMsgReturn(offSeg + cIndirSymbols * sizeof(paidxIndirSymbols[0]) <= cbSeg,
    638                                       ("%p: offSeg=%#llx cIndirSymbols=%#x cbSeg=%llx\n", pHdr, offSeg, cIndirSymbols, cbSeg),
    639                                       false);
    640                 paidxIndirSymbols = (uint32_t const *)(uPtrSeg + offSeg);
    641             }
    642         }
    643     }
    644 
    645     AssertLogRelMsgReturn(paSymbols, ("%p: offSymbols=%#x\n", pHdr, offSymbols), false);
    646     AssertLogRelMsgReturn(pchStrTab, ("%p: offStrTab=%#x\n", pHdr, offStrTab), false);
    647     AssertLogRelMsgReturn(paidxIndirSymbols, ("%p: offIndirSymbols=%#x\n", pHdr, offIndirSymbols), false);
    648 
    649     /*
    650      * Third command pass: Process sections of types S_NON_LAZY_SYMBOL_POINTERS
    651      *                     and S_LAZY_SYMBOL_POINTERS
    652      */
    653     bool fFound = false;
    654     offCmd = 0;
    655     for (uint32_t iCmd = 0; iCmd < cCmds; iCmd++)
    656     {
    657         load_command_t const * const pCmd = (load_command_t const *)((uintptr_t)(pHdr + 1) + offCmd);
    658         uint32_t const cbCurCmd = pCmd->cmdsize;
    659         AssertLogRelMsgReturn(offCmd + cbCurCmd <= cbCmds && cbCurCmd <= cbCmds,
    660                               ("%p: iCmd=%u offCmd=%#x cbCurCmd=%#x cbCmds=%#x\n", pHdr, iCmd, offCmd, cbCurCmd, cbCmds), false);
    661         offCmd += cbCurCmd;
    662         if (pCmd->cmd == LC_SEGMENT_64)
    663         {
    664             segment_command_64_t const *pSeg = (segment_command_64_t const *)pCmd;
    665             AssertLogRelMsgReturn(cbCurCmd >= sizeof(*pSeg), ("%p: iCmd=%u cbCurCmd=%#x\n", pHdr, iCmd, cbCurCmd), false);
    666             uint64_t const  uSegAddr = pSeg->vmaddr;
    667             uint64_t const  cbSeg    = pSeg->vmsize;
    668 
    669             uint32_t const             cSections  = pSeg->nsects;
    670             section_64_t const * const paSections = (section_64_t const *)(pSeg + 1);
    671             AssertLogRelMsgReturn(cSections < _256K && sizeof(*pSeg) + cSections * sizeof(paSections[0]) <= cbCurCmd,
    672                                   ("%p: iCmd=%u cSections=%#x cbCurCmd=%#x\n", pHdr, iCmd, cSections, cbCurCmd), false);
    673             for (uint32_t iSection = 0; iSection < cSections; iSection++)
    674             {
    675                 if (   paSections[iSection].flags == S_NON_LAZY_SYMBOL_POINTERS
    676                     || paSections[iSection].flags == S_LAZY_SYMBOL_POINTERS)
    677                 {
    678                     uint32_t const idxIndirBase = paSections[iSection].reserved1;
    679                     uint32_t const cEntries     = paSections[iSection].size / sizeof(uintptr_t);
    680                     AssertLogRelMsgReturn(idxIndirBase <= cIndirSymbols && idxIndirBase + cEntries <= cIndirSymbols,
    681                                           ("%p: idxIndirBase=%#x cEntries=%#x cIndirSymbols=%#x\n",
    682                                            pHdr, idxIndirBase, cEntries, cIndirSymbols), false);
    683                     uint64_t const uSecAddr = paSections[iSection].addr;
    684                     uint64_t const offInSeg = uSecAddr - uSegAddr;
    685                     AssertLogRelMsgReturn(offInSeg < cbSeg && offInSeg + cEntries * sizeof(uintptr_t) <= cbSeg,
    686                                           ("%p: offInSeg=%#llx cEntries=%#x cbSeg=%#llx\n", pHdr, offInSeg, cEntries, cbSeg),
    687                                           false);
    688                     uintptr_t *pauPtrs = (uintptr_t *)(uSecAddr + offSlide);
    689                     for (uint32_t iEntry = 0; iEntry < cEntries; iEntry++)
    690                     {
    691                         uint32_t const idxSym = paidxIndirSymbols[idxIndirBase + iEntry];
    692                         if (idxSym < cSymbols)
    693                         {
    694                             macho_nlist_64_t const * const pSym    = &paSymbols[idxSym];
    695                             const char * const             pszName = pSym->n_un.n_strx < cbStrTab
    696                                                                    ? &pchStrTab[pSym->n_un.n_strx] : "!invalid symtab offset!";
    697                             if (strcmp(pszName, pszSymbol) == 0)
    698                             {
    699                                 pauPtrs[iEntry] = uNewValue;
    700                                 fFound = true;
    701                                 break;
    702                             }
    703                         }
    704                         else
    705                             AssertMsg(idxSym == INDIRECT_SYMBOL_LOCAL || idxSym == INDIRECT_SYMBOL_ABS, ("%#x\n", idxSym));
    706                     }
    707                 }
    708             }
    709         }
    710     }
    711     AssertLogRel(fFound);
    712     return fFound;
    713 }
    714 
    715 /**
    716  * Mac OS X: Really ugly hack to bypass a set-uid check in AppKit.
    717  *
    718  * This will modify the issetugid() function to always return zero.  This must
    719  * be done _before_ AppKit is initialized, otherwise it will refuse to play ball
    720  * with us as it distrusts set-uid processes since Snow Leopard.  We, however,
    721  * have carefully dropped all root privileges at this point and there should be
    722  * no reason for any security concern here.
    723  */
    724 static void hideSetUidRootFromAppKit()
    725 {
    726     void *pvAddr;
    727     /* Find issetguid() and make it always return 0 by modifying the code: */
    728 # if 0
    729     pvAddr = dlsym(RTLD_DEFAULT, "issetugid");
    730     int rc = mprotect((void *)((uintptr_t)pvAddr & ~(uintptr_t)0xfff), 0x2000, PROT_WRITE | PROT_READ | PROT_EXEC);
    731     if (!rc)
    732         ASMAtomicWriteU32((volatile uint32_t *)pvAddr, 0xccc3c031); /* xor eax, eax; ret; int3 */
    733     else
    734 # endif
    735     {
    736         /* Failing that, find AppKit and patch its import table: */
    737         void *pvAppKit = dlopen("/System/Library/Frameworks/AppKit.framework/AppKit", RTLD_NOLOAD);
    738         pvAddr = dlsym(pvAppKit, "NSApplicationMain");
    739         Dl_info Info = {0};
    740         if (   dladdr(pvAddr, &Info)
    741             && Info.dli_fbase != NULL)
    742         {
    743             if (!patchExtSym((mach_header_64_t *)Info.dli_fbase, "_issetugid", (uintptr_t)&issetugid_for_AppKit))
    744                 write(2, RT_STR_TUPLE("WARNING: Failed to patch issetugid in AppKit! (patchExtSym)\n"));
    745 # ifdef DEBUG
    746             else
    747                 write(2, RT_STR_TUPLE("INFO: Successfully patched _issetugid import for AppKit!\n"));
    748 # endif
    749         }
    750         else
    751             write(2, RT_STR_TUPLE("WARNING: Failed to patch issetugid in AppKit! (dladdr)\n"));
    752     }
    753 
    754 }
    755 
    756 #endif /* RT_OS_DARWIN */
    757486
    758487
     
    1161890    const char *pcszNameOrUUID = NULL;
    1162891
    1163 #if 0 //def RT_OS_DARWIN - see above
    1164     hideSetUidRootFromAppKit();
    1165 #endif
    1166 
    1167892    // parse the command line
    1168893    int ch;
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