Changeset 97188 in vbox
- Timestamp:
- Oct 18, 2022 7:42:50 AM (2 years ago)
- svn:sync-xref-src-repo-rev:
- 154163
- Location:
- trunk/src/VBox
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/HostDrivers/Support/darwin/SUPR3HardenedEntitlementsVM.plist
r97177 r97188 4 4 <dict> 5 5 <!-- <key>com.apple.security.cs.allow-jit</key> <true/> --> 6 <!-- <key>com.apple.security.cs.allow-unsigned-executable-memory</key> <true/> --> 7 <!-- <key>com.apple.security.cs.disable-executable-page-protection</key> <true/> --> 6 <!-- 7 The following two entitlements are required for using AppleHV on Catalina. 8 The first entitlement allows us to have unsigned executable memory in the guests 9 address space like the BIOS code (and essentially all the guests address space which 10 is mapped as RWX). 11 The second entitlement is required in order to map guest memory as RWX into the 12 guests address space. 13 These entitlements are not required starting with BigSur+ where Apple has clearly 14 changed something in their entitlement scheme without properly documenting it. 15 --> 16 <key>com.apple.security.cs.allow-unsigned-executable-memory</key> <true/> 17 <key>com.apple.security.cs.disable-executable-page-protection</key> <true/> 8 18 <!-- For audio input --> 9 19 <key>com.apple.security.device.audio-input</key> <true/> -
trunk/src/VBox/VMM/VMMAll/VMXAllTemplate.cpp.h
r97183 r97188 9423 9423 */ 9424 9424 NEMHCDARWINHMACPCCSTATE State = { RT_BOOL(pVmxTransient->uExitQual & VMX_EXIT_QUAL_EPT_ACCESS_WRITE), 9425 RT_BOOL(pVmxTransient->uExitQual & VMX_EXIT_QUAL_EPT_ACCESS_INSTR_FETCH),9426 9425 false, 9427 9426 false }; -
trunk/src/VBox/VMM/VMMR3/NEMR3.cpp
r97175 r97188 101 101 "|VmxPleWindow" 102 102 "|VmxLbr" 103 "|CatalinaWxWorkaround"104 103 #endif 105 104 , -
trunk/src/VBox/VMM/VMMR3/NEMR3Native-darwin.cpp
r97174 r97188 293 293 /** VMX: Set if swapping EFER is supported. */ 294 294 static bool g_fHmVmxSupportsVmcsEfer = false; 295 /** Flag whether the AppleHV code suffers from a bug preventing WX mappings and we need to296 * ping pong between RX and RW mappings depending on what the guest is doing. */297 static bool g_fAppleHvNoWX = false;298 295 /** @name APIs imported from Hypervisor.framework. 299 296 * @{ */ … … 562 559 if (fPageProt & NEM_PAGE_PROT_WRITE) 563 560 fHvMemProt |= HV_MEMORY_WRITE; 564 if ( fPageProt & NEM_PAGE_PROT_EXECUTE 565 && ( !g_fAppleHvNoWX 566 || !(fPageProt & NEM_PAGE_PROT_WRITE))) 561 if (fPageProt & NEM_PAGE_PROT_EXECUTE) 567 562 fHvMemProt |= HV_MEMORY_EXEC; 568 563 569 564 hv_return_t hrc; 570 #if 0 /* Simulates the error path on Catalina without requiring signed binaries. */571 if ( (fHvMemProt & HV_MEMORY_WRITE)572 && (fHvMemProt & HV_MEMORY_EXEC))573 hrc = HV_ERROR;574 else575 {576 if (pVM->nem.s.fCreatedAsid)577 hrc = hv_vm_map_space(pVM->nem.s.uVmAsid, pvRam, GCPhys, cb, fHvMemProt);578 else579 hrc = hv_vm_map(pvRam, GCPhys, cb, fHvMemProt);580 }581 #else582 565 if (pVM->nem.s.fCreatedAsid) 583 566 hrc = hv_vm_map_space(pVM->nem.s.uVmAsid, pvRam, GCPhys, cb, fHvMemProt); 584 567 else 585 568 hrc = hv_vm_map(pvRam, GCPhys, cb, fHvMemProt); 586 #endif587 569 if (hrc == HV_SUCCESS) 588 570 { … … 594 576 } 595 577 596 if ( hrc == HV_ERROR597 && (fHvMemProt & HV_MEMORY_WRITE)598 && (fHvMemProt & HV_MEMORY_EXEC))599 {600 /*601 * On Catalina 10.15.7 it is impossible to have WX permissions with a properly signed602 * process due to some bug(?), it works starting with BigSur. So to work around that603 * we will never have WX mappings but only RW and RX and switch between them on demand for the604 * guest region in question. This can have a huge negative performance impact if the guest605 * writes to the same page frequently and executes code there.606 */607 Assert(!g_fAppleHvNoWX); /* We should come here only once. */608 609 /*610 * Try unmapping the region first (the code on Catalina doesn't remove it form the map if vm_map_protect() fails and611 * causes the following hv_vm_map call to fail...).612 */613 hv_vm_unmap(GCPhys, cb);614 615 /* Start with an RW mapping (most of the time the guest needs to write something there before it can execute code). */616 fHvMemProt &= ~HV_MEMORY_EXEC;617 g_fAppleHvNoWX = true;618 LogRel(("NEM: AppleHV refuses RWX mappings for the guest, activating workaround, expect decreased performance\n"));619 if (pVM->nem.s.fCreatedAsid)620 hrc = hv_vm_map_space(pVM->nem.s.uVmAsid, pvRam, GCPhys, cb, fHvMemProt);621 else622 hrc = hv_vm_map(pvRam, GCPhys, cb, fHvMemProt);623 if (hrc == HV_SUCCESS)624 {625 if (pu2State)626 *pu2State = NEM_DARWIN_PAGE_STATE_WRITABLE; /* Writable without exec. */627 return VINF_SUCCESS;628 }629 }630 631 578 return nemR3DarwinHvSts2Rc(hrc); 632 579 } 633 580 634 581 #if 0 /* unused */ 635 582 DECLINLINE(int) nemR3DarwinProtectPage(PVM pVM, RTGCPHYS GCPhys, size_t cb, uint32_t fPageProt) 636 583 { 637 Assert( !g_fAppleHvNoWX638 || ( (fPageProt & NEM_PAGE_PROT_WRITE)639 && !(fPageProt & NEM_PAGE_PROT_EXECUTE))640 || ( !(fPageProt & NEM_PAGE_PROT_WRITE)641 && (fPageProt & NEM_PAGE_PROT_EXECUTE)));642 643 584 hv_memory_flags_t fHvMemProt = 0; 644 585 if (fPageProt & NEM_PAGE_PROT_READ) … … 657 598 return nemR3DarwinHvSts2Rc(hrc); 658 599 } 659 600 #endif 660 601 661 602 DECLINLINE(int) nemR3NativeGCPhys2R3PtrReadOnly(PVM pVM, RTGCPHYS GCPhys, const void **ppv) … … 1210 1151 /** 1211 1152 * State to pass between vmxHCExitEptViolation 1212 * and nem HCWinHandleMemoryAccessPageCheckerCallback.1153 * and nemR3DarwinHandleMemoryAccessPageCheckerCallback. 1213 1154 */ 1214 1155 typedef struct NEMHCDARWINHMACPCCSTATE … … 1216 1157 /** Input: Write access. */ 1217 1158 bool fWriteAccess; 1218 /** Input: Instruction fetch access. */1219 bool fInsnFetch;1220 1159 /** Output: Set if we did something. */ 1221 1160 bool fDidSomething; … … 1264 1203 1265 1204 int rc = VINF_SUCCESS; 1266 if ( pInfo->fNemProt & NEM_PAGE_PROT_WRITE 1267 && !pState->fInsnFetch) 1205 if (pInfo->fNemProt & NEM_PAGE_PROT_WRITE) 1268 1206 { 1269 1207 void *pvPage; 1270 1208 rc = nemR3NativeGCPhys2R3PtrWriteable(pVM, GCPhys, &pvPage); 1271 1209 if (RT_SUCCESS(rc)) 1272 { 1273 uint32_t fProt = pInfo->fNemProt; 1274 if (g_fAppleHvNoWX) 1275 fProt &= ~NEM_PAGE_PROT_EXECUTE; /* Start with RW mapping. */ 1276 rc = nemR3DarwinMap(pVM, GCPhys & ~(RTGCPHYS)X86_PAGE_OFFSET_MASK, pvPage, X86_PAGE_SIZE, fProt, &u2State); 1277 } 1210 rc = nemR3DarwinMap(pVM, GCPhys & ~(RTGCPHYS)X86_PAGE_OFFSET_MASK, pvPage, X86_PAGE_SIZE, pInfo->fNemProt, &u2State); 1278 1211 } 1279 1212 else if (pInfo->fNemProt & NEM_PAGE_PROT_READ) … … 1282 1215 rc = nemR3NativeGCPhys2R3PtrReadOnly(pVM, GCPhys, &pvPage); 1283 1216 if (RT_SUCCESS(rc)) 1284 rc = nemR3DarwinMap(pVM, GCPhys & ~(RTGCPHYS)X86_PAGE_OFFSET_MASK, pvPage, X86_PAGE_SIZE, pInfo->fNemProt & ~NEM_PAGE_PROT_WRITE, &u2State);1217 rc = nemR3DarwinMap(pVM, GCPhys & ~(RTGCPHYS)X86_PAGE_OFFSET_MASK, pvPage, X86_PAGE_SIZE, pInfo->fNemProt, &u2State); 1285 1218 } 1286 1219 else /* Only EXECUTE doesn't work. */ … … 1295 1228 } 1296 1229 case NEM_DARWIN_PAGE_STATE_READABLE: 1297 if ( g_fAppleHvNoWX1298 && pState->fWriteAccess1299 && (pInfo->fNemProt & NEM_PAGE_PROT_WRITE))1300 {1301 /* Write access to an RWX page which we set to RX due to Catalina woes, convert to RW. */1302 int rc = nemR3DarwinProtectPage(pVM, GCPhys & ~(RTGCPHYS)X86_PAGE_OFFSET_MASK, X86_PAGE_SIZE, NEM_PAGE_PROT_READ | NEM_PAGE_PROT_WRITE);1303 1304 pInfo->u2NemState = NEM_DARWIN_PAGE_STATE_WRITABLE;1305 Log4(("nemR3DarwinHandleMemoryAccessPageCheckerCallback: %RGp - RX => RW + %Rrc\n", GCPhys, rc));1306 pState->fDidSomething = true;1307 /*1308 * We will emulate that single instruction in case the instruction writes to the same page as it executes from to avoid1309 * an endless loop switching between RW and RX mappings without making any progress.1310 */1311 pState->fCanResume = false;1312 return rc;1313 }1314 1315 1230 if ( !(pInfo->fNemProt & NEM_PAGE_PROT_WRITE) 1316 1231 && (pInfo->fNemProt & (NEM_PAGE_PROT_READ | NEM_PAGE_PROT_EXECUTE))) … … 1323 1238 1324 1239 case NEM_DARWIN_PAGE_STATE_WRITABLE: 1325 if ( g_fAppleHvNoWX1326 && pState->fInsnFetch1327 && (pInfo->fNemProt & NEM_PAGE_PROT_EXECUTE))1328 {1329 /* Write access to an RWX page which we set to RW due to Catalina woes, convert to RX. */1330 int rc = nemR3DarwinProtectPage(pVM, GCPhys & ~(RTGCPHYS)X86_PAGE_OFFSET_MASK, X86_PAGE_SIZE, NEM_PAGE_PROT_READ | NEM_PAGE_PROT_EXECUTE);1331 1332 pInfo->u2NemState = NEM_DARWIN_PAGE_STATE_READABLE;1333 Log4(("nemR3DarwinHandleMemoryAccessPageCheckerCallback: %RGp - RW => RX + %Rrc\n", GCPhys, rc));1334 pState->fDidSomething = true;1335 /* Just resume with execution, no emulation in case the instruction being executed is something we don't emulate right now (AVX for example). */1336 pState->fCanResume = true;1337 return rc;1338 }1339 1340 1240 if (pInfo->fNemProt & NEM_PAGE_PROT_WRITE) 1341 1241 { … … 1345 1245 return VINF_SUCCESS; 1346 1246 } 1347 1348 1247 break; 1349 1248 … … 2993 2892 * useful while debugging and enabling it causes a noticeable performance hit. */ 2994 2893 rc = CFGMR3QueryBoolDef(pCfgNem, "VmxLbr", &pVM->nem.s.fLbr, false); 2995 AssertRCReturn(rc, rc);2996 2997 /** @cfgm{/NEM/CatalinaWxWorkaround, bool, false}2998 * Whether to allow only W^X guest mappings due to a bug in the Catalina AppleHV2999 * driver refusing RWX when a properly signed binary is used.3000 */3001 rc = CFGMR3QueryBoolDef(pCfgNem, "CatalinaWxWorkaround", &g_fAppleHvNoWX, false);3002 2894 AssertRCReturn(rc, rc); 3003 2895
Note:
See TracChangeset
for help on using the changeset viewer.