Changeset 83070 in vbox for trunk/src/VBox/Runtime/r0drv/darwin/memobj-r0drv-darwin.cpp
- Timestamp:
- Feb 13, 2020 9:21:02 PM (5 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/r0drv/darwin/memobj-r0drv-darwin.cpp
r82968 r83070 44 44 #include <iprt/param.h> 45 45 #include <iprt/process.h> 46 #include <iprt/semaphore.h> 46 47 #include <iprt/string.h> 47 48 #include <iprt/thread.h> … … 72 73 IOMemoryMap *pMemMap; 73 74 } RTR0MEMOBJDARWIN, *PRTR0MEMOBJDARWIN; 75 76 /** 77 * Common thread_call_allocate/thread_call_enter argument package. 78 */ 79 typedef struct RTR0MEMOBJDARWINTHREADARGS 80 { 81 int32_t volatile rc; 82 RTSEMEVENTMULTI hEvent; 83 } RTR0MEMOBJDARWINTHREADARGS; 84 85 86 /** 87 * Arguments for rtR0MemObjNativeAllockWorkOnKernelThread. 88 */ 89 typedef struct RTR0MEMOBJDARWINALLOCARGS 90 { 91 RTR0MEMOBJDARWINTHREADARGS Core; 92 PPRTR0MEMOBJINTERNAL ppMem; 93 size_t cb; 94 bool fExecutable; 95 bool fContiguous; 96 mach_vm_address_t PhysMask; 97 uint64_t MaxPhysAddr; 98 RTR0MEMOBJTYPE enmType; 99 size_t uAlignment; 100 } RTR0MEMOBJDARWINALLOCARGS; 101 102 /** 103 * Arguments for rtR0MemObjNativeProtectWorkOnKernelThread. 104 */ 105 typedef struct RTR0MEMOBJDARWINPROTECTARGS 106 { 107 RTR0MEMOBJDARWINTHREADARGS Core; 108 PRTR0MEMOBJINTERNAL pMem; 109 size_t offSub; 110 size_t cbSub; 111 uint32_t fProt; 112 } RTR0MEMOBJDARWINPROTECTARGS; 113 114 115 /********************************************************************************************************************************* 116 * Internal Functions * 117 *********************************************************************************************************************************/ 118 static void rtR0MemObjNativeAllockWorkerOnKernelThread(void *pvUser0, void *pvUser1); 119 static int rtR0MemObjNativeProtectWorker(PRTR0MEMOBJINTERNAL pMem, size_t offSub, size_t cbSub, uint32_t fProt); 120 static void rtR0MemObjNativeProtectWorkerOnKernelThread(void *pvUser0, void *pvUser1); 74 121 75 122 … … 440 487 441 488 489 /** 490 * This is a helper function to executes @a pfnWorker in the context of the 491 * kernel_task 492 * 493 * @returns IPRT status code - result from pfnWorker or dispatching error. 494 * @param pfnWorker The function to call. 495 * @param pArgs The arguments to pass to the function. 496 */ 497 static int rtR0MemObjDarwinDoInKernelTaskThread(thread_call_func_t pfnWorker, RTR0MEMOBJDARWINTHREADARGS *pArgs) 498 { 499 pArgs->rc = VERR_IPE_UNINITIALIZED_STATUS; 500 pArgs->hEvent = NIL_RTSEMEVENTMULTI; 501 int rc = RTSemEventMultiCreate(&pArgs->hEvent); 502 if (RT_SUCCESS(rc)) 503 { 504 thread_call_t hCall = thread_call_allocate(pfnWorker, (void *)pArgs); 505 if (hCall) 506 { 507 boolean_t fRc = thread_call_enter(hCall); 508 AssertLogRel(fRc == FALSE); 509 510 rc = RTSemEventMultiWaitEx(pArgs->hEvent, RTSEMWAIT_FLAGS_INDEFINITE | RTSEMWAIT_FLAGS_UNINTERRUPTIBLE, 511 RT_INDEFINITE_WAIT); 512 AssertLogRelRC(rc); 513 514 rc = pArgs->rc; 515 thread_call_free(hCall); 516 } 517 else 518 rc = VERR_NO_MEMORY; 519 RTSemEventMultiDestroy(pArgs->hEvent); 520 } 521 return rc; 522 } 523 524 525 /** 526 * Signals result to thread waiting in rtR0MemObjDarwinDoInKernelTaskThread. 527 * 528 * @param pArgs The argument structure. 529 * @param rc The IPRT status code to signal. 530 */ 531 static void rtR0MemObjDarwinSignalThreadWaitinOnTask(RTR0MEMOBJDARWINTHREADARGS volatile *pArgs, int rc) 532 { 533 if (ASMAtomicCmpXchgS32(&pArgs->rc, rc, VERR_IPE_UNINITIALIZED_STATUS)) 534 { 535 rc = RTSemEventMultiSignal(pArgs->hEvent); 536 AssertLogRelRC(rc); 537 } 538 } 539 442 540 443 541 /** … … 457 555 * @param enmType The object type. 458 556 * @param uAlignment The allocation alignment (in bytes). 557 * @param fOnKernelThread Set if we're already on the kernel thread. 459 558 */ 460 559 static int rtR0MemObjNativeAllocWorker(PPRTR0MEMOBJINTERNAL ppMem, size_t cb, 461 560 bool fExecutable, bool fContiguous, 462 561 mach_vm_address_t PhysMask, uint64_t MaxPhysAddr, 463 RTR0MEMOBJTYPE enmType, size_t uAlignment )562 RTR0MEMOBJTYPE enmType, size_t uAlignment, bool fOnKernelThread) 464 563 { 465 564 int rc; 565 566 /* 567 * Because of process code signing properties leaking into kernel space in 568 * in XNU's vm_fault.c code, we have to defer allocations of exec memory to 569 * a thread running in the kernel_task to get consistent results here. 570 * Believing is trouble is caused by the page_nx() + exec check, it was 571 * introduced in 10.10.5 (or 10.11.0). 572 * (PS. Doubt this is in anyway intentional behaviour, but rather unforseen 573 * consequences from a pragmatic approach to modifying the complicate VM code.) 574 */ 575 if (!fExecutable || fOnKernelThread) 576 { /* likely */ } 577 else 578 { 579 RTR0MEMOBJDARWINALLOCARGS Args; 580 Args.ppMem = ppMem; 581 Args.cb = cb; 582 Args.fExecutable = fExecutable; 583 Args.fContiguous = fContiguous; 584 Args.PhysMask = PhysMask; 585 Args.MaxPhysAddr = MaxPhysAddr; 586 Args.enmType = enmType; 587 Args.uAlignment = uAlignment; 588 return rtR0MemObjDarwinDoInKernelTaskThread(rtR0MemObjNativeAllockWorkerOnKernelThread, &Args.Core); 589 } 466 590 467 591 /* … … 494 618 if (version_major >= 12 /* 12 = 10.8.x = Mountain Kitten */) 495 619 fOptions |= kIOMemoryMapperNone; 620 621 #if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 && 0 /* enable when/if necessary */ 622 /* Paranoia: Don't misrepresent our intentions, we won't map kernel executable memory into ring-0. */ 623 if (fExecutable && version_major >= 11 /* 10.7.x = Lion, as below */) 624 { 625 fOptions &= ~kIOMemoryKernelUserShared; 626 if (uAlignment < PAGE_SIZE) 627 uAlignment = PAGE_SIZE; 628 } 629 #endif 496 630 497 631 /* The public initWithPhysicalMask virtual method appeared in 10.7.0, in … … 618 752 } 619 753 620 #if 1 /* Experimental code. */621 754 if (fExecutable) 622 755 { 623 rc = rtR0MemObjNativeProtect(&pMemDarwin->Core, 0, cb, RTMEM_PROT_READ | RTMEM_PROT_WRITE | RTMEM_PROT_EXEC); 624 # ifdef RT_STRICT 625 /* check that the memory is actually mapped. */ 626 RTTHREADPREEMPTSTATE State2 = RTTHREADPREEMPTSTATE_INITIALIZER; 627 RTThreadPreemptDisable(&State2); 628 rtR0MemObjDarwinTouchPages(pv, cb); 629 RTThreadPreemptRestore(&State2); 630 # endif 631 756 rc = rtR0MemObjNativeProtectWorker(&pMemDarwin->Core, 0, cb, 757 RTMEM_PROT_READ | RTMEM_PROT_WRITE | RTMEM_PROT_EXEC); 758 #ifdef RT_STRICT 759 if (RT_SUCCESS(rc)) 760 { 761 /* check that the memory is actually mapped. */ 762 RTTHREADPREEMPTSTATE State2 = RTTHREADPREEMPTSTATE_INITIALIZER; 763 RTThreadPreemptDisable(&State2); 764 rtR0MemObjDarwinTouchPages(pv, cb); 765 RTThreadPreemptRestore(&State2); 766 } 767 #endif 632 768 /* Bug 6226: Ignore KERN_PROTECTION_FAILURE on Leopard and older. */ 633 769 if ( rc == VERR_PERMISSION_DENIED … … 636 772 } 637 773 else 638 #endif639 774 rc = VINF_SUCCESS; 640 775 if (RT_SUCCESS(rc)) … … 673 808 674 809 810 /** 811 * rtR0MemObjNativeAllocWorker kernel_task wrapper function. 812 */ 813 static void rtR0MemObjNativeAllockWorkerOnKernelThread(void *pvUser0, void *pvUser1) 814 { 815 AssertPtr(pvUser0); Assert(pvUser1 == NULL); NOREF(pvUser1); 816 RTR0MEMOBJDARWINALLOCARGS volatile *pArgs = (RTR0MEMOBJDARWINALLOCARGS volatile *)pvUser0; 817 int rc = rtR0MemObjNativeAllocWorker(pArgs->ppMem, pArgs->cb, pArgs->fExecutable, pArgs->fContiguous, pArgs->PhysMask, 818 pArgs->MaxPhysAddr, pArgs->enmType, pArgs->uAlignment, true /*fOnKernelThread*/); 819 rtR0MemObjDarwinSignalThreadWaitinOnTask(&pArgs->Core, rc); 820 } 821 822 675 823 DECLHIDDEN(int) rtR0MemObjNativeAllocPage(PPRTR0MEMOBJINTERNAL ppMem, size_t cb, bool fExecutable) 676 824 { 677 825 IPRT_DARWIN_SAVE_EFL_AC(); 678 826 679 int rc = rtR0MemObjNativeAllocWorker(ppMem, cb, fExecutable, false /* fContiguous */, 680 0 /* PhysMask */, UINT64_MAX, RTR0MEMOBJTYPE_PAGE, PAGE_SIZE);827 int rc = rtR0MemObjNativeAllocWorker(ppMem, cb, fExecutable, false /* fContiguous */, 0 /* PhysMask */, UINT64_MAX, 828 RTR0MEMOBJTYPE_PAGE, PAGE_SIZE, false /*fOnKernelThread*/); 681 829 682 830 IPRT_DARWIN_RESTORE_EFL_AC(); … … 696 844 * (See bug comment in the worker and IOBufferMemoryDescriptor::initWithPhysicalMask.) 697 845 */ 698 int rc = rtR0MemObjNativeAllocWorker(ppMem, cb, fExecutable, false /* fContiguous */, 699 ~(uint32_t)PAGE_OFFSET_MASK, _4G - PAGE_SIZE, RTR0MEMOBJTYPE_LOW, PAGE_SIZE);846 int rc = rtR0MemObjNativeAllocWorker(ppMem, cb, fExecutable, false /* fContiguous */, ~(uint32_t)PAGE_OFFSET_MASK, 847 _4G - PAGE_SIZE, RTR0MEMOBJTYPE_LOW, PAGE_SIZE, false /*fOnKernelThread*/); 700 848 if (rc == VERR_ADDRESS_TOO_BIG) 701 rc = rtR0MemObjNativeAllocWorker(ppMem, cb, fExecutable, false /* fContiguous */, 702 0 /* PhysMask */, _4G - PAGE_SIZE, RTR0MEMOBJTYPE_LOW, PAGE_SIZE);849 rc = rtR0MemObjNativeAllocWorker(ppMem, cb, fExecutable, false /* fContiguous */, 0 /* PhysMask */, 850 _4G - PAGE_SIZE, RTR0MEMOBJTYPE_LOW, PAGE_SIZE, false /*fOnKernelThread*/); 703 851 704 852 IPRT_DARWIN_RESTORE_EFL_AC(); … … 713 861 int rc = rtR0MemObjNativeAllocWorker(ppMem, cb, fExecutable, true /* fContiguous */, 714 862 ~(uint32_t)PAGE_OFFSET_MASK, _4G - PAGE_SIZE, 715 RTR0MEMOBJTYPE_CONT, PAGE_SIZE );863 RTR0MEMOBJTYPE_CONT, PAGE_SIZE, false /*fOnKernelThread*/); 716 864 717 865 /* … … 722 870 rc = rtR0MemObjNativeAllocWorker(ppMem, cb + PAGE_SIZE, fExecutable, true /* fContiguous */, 723 871 ~(uint32_t)PAGE_OFFSET_MASK, _4G - PAGE_SIZE, 724 RTR0MEMOBJTYPE_CONT, PAGE_SIZE );872 RTR0MEMOBJTYPE_CONT, PAGE_SIZE, false /*fOnKernelThread*/); 725 873 IPRT_DARWIN_RESTORE_EFL_AC(); 726 874 return rc; … … 746 894 rc = rtR0MemObjNativeAllocWorker(ppMem, cb, false /* fExecutable */, true /* fContiguous */, 747 895 uAlignment <= PAGE_SIZE ? 0 : ~(mach_vm_address_t)(uAlignment - 1) /* PhysMask*/, 748 UINT64_MAX, RTR0MEMOBJTYPE_PHYS, uAlignment );896 UINT64_MAX, RTR0MEMOBJTYPE_PHYS, uAlignment, false /*fOnKernelThread*/); 749 897 else 750 898 { … … 757 905 758 906 rc = rtR0MemObjNativeAllocWorker(ppMem, cb, false /* fExecutable */, true /* fContiguous */, 759 PhysMask, PhysHighest, RTR0MEMOBJTYPE_PHYS, uAlignment );907 PhysMask, PhysHighest, RTR0MEMOBJTYPE_PHYS, uAlignment, false /*fOnKernelThread*/); 760 908 } 761 909 … … 1160 1308 1161 1309 1162 DECLHIDDEN(int) rtR0MemObjNativeProtect(PRTR0MEMOBJINTERNAL pMem, size_t offSub, size_t cbSub, uint32_t fProt) 1310 /** 1311 * Worker for rtR0MemObjNativeProtect that's typically called in a different 1312 * context. 1313 */ 1314 static int rtR0MemObjNativeProtectWorker(PRTR0MEMOBJINTERNAL pMem, size_t offSub, size_t cbSub, uint32_t fProt) 1163 1315 { 1164 1316 IPRT_DARWIN_SAVE_EFL_AC(); … … 1261 1413 1262 1414 1415 /** 1416 * rtR0MemObjNativeProtect kernel_task wrapper function. 1417 */ 1418 static void rtR0MemObjNativeProtectWorkerOnKernelThread(void *pvUser0, void *pvUser1) 1419 { 1420 AssertPtr(pvUser0); Assert(pvUser1 == NULL); NOREF(pvUser1); 1421 RTR0MEMOBJDARWINPROTECTARGS *pArgs = (RTR0MEMOBJDARWINPROTECTARGS *)pvUser0; 1422 int rc = rtR0MemObjNativeProtectWorker(pArgs->pMem, pArgs->offSub, pArgs->cbSub, pArgs->fProt); 1423 rtR0MemObjDarwinSignalThreadWaitinOnTask(&pArgs->Core, rc); 1424 } 1425 1426 1427 DECLHIDDEN(int) rtR0MemObjNativeProtect(PRTR0MEMOBJINTERNAL pMem, size_t offSub, size_t cbSub, uint32_t fProt) 1428 { 1429 /* 1430 * The code won't work right because process codesigning properties leaks 1431 * into kernel_map memory management. So, if the user process we're running 1432 * in has CS restrictions active, we cannot play around with the EXEC 1433 * protection because some vm_fault.c think we're modifying the process map 1434 * or something. Looks like this problem was introduced in 10.10.5 or/and 1435 * 10.11.0, so for for Yosemite and up we'll just push the work off to a thread 1436 * running in the kernel_task context and hope it has be better chance of 1437 * consistent results. 1438 */ 1439 int rc; 1440 if ( version_major >= 14 /* 10.10 = Yosemite */ 1441 && rtR0MemObjDarwinGetMap(pMem) == kernel_map) 1442 { 1443 RTR0MEMOBJDARWINPROTECTARGS Args; 1444 Args.pMem = pMem; 1445 Args.offSub = offSub; 1446 Args.cbSub = cbSub; 1447 Args.fProt = fProt; 1448 rc = rtR0MemObjDarwinDoInKernelTaskThread(rtR0MemObjNativeProtectWorkerOnKernelThread, &Args.Core); 1449 } 1450 else 1451 rc = rtR0MemObjNativeProtectWorker(pMem, offSub, cbSub, fProt); 1452 return rc; 1453 } 1454 1455 1263 1456 DECLHIDDEN(RTHCPHYS) rtR0MemObjNativeGetPagePhysAddr(PRTR0MEMOBJINTERNAL pMem, size_t iPage) 1264 1457 {
Note:
See TracChangeset
for help on using the changeset viewer.