- Timestamp:
- Feb 3, 2020 12:45:15 PM (5 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Frontends/VirtualBox/src/main.cpp
r79365 r82955 124 124 125 125 #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 */ 136 int 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 151 static 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 126 352 /** 127 353 * Mac OS X: Really ugly hack to bypass a set-uid check in AppKit. … … 135 361 static void HideSetUidRootFromAppKit() 136 362 { 363 void *pvAddr; 137 364 /* 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"); 139 367 int rc = mprotect((void *)((uintptr_t)pvAddr & ~(uintptr_t)0xfff), 0x2000, PROT_WRITE | PROT_READ | PROT_EXEC); 140 368 if (!rc) 141 369 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 142 391 } 392 143 393 #endif /* VBOX_WS_MAC */ 144 394
Note:
See TracChangeset
for help on using the changeset viewer.