From 04f7bc8d1b60d1827a0b7a71517f9d1adb4c3d86 Mon Sep 17 00:00:00 2001 From: David Scott Date: Mon, 19 Aug 2019 17:39:05 +0100 Subject: [PATCH 1/2] Use `mmap` rather than `valloc` in `vmm_mem_alloc` This will allow us to customise the flags in a later patch. Signed-off-by: David Scott --- src/lib/vmm/vmm_mem.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/lib/vmm/vmm_mem.c b/src/lib/vmm/vmm_mem.c index 2c5c858b..c98316be 100644 --- a/src/lib/vmm/vmm_mem.c +++ b/src/lib/vmm/vmm_mem.c @@ -33,7 +33,7 @@ #include #include #include - +#include int vmm_mem_init(void) { @@ -46,10 +46,9 @@ vmm_mem_alloc(uint64_t gpa, size_t size) { void *object; - object = valloc(size); - - if (!object) { - xhyve_abort("vmm_mem_alloc failed\n"); + object = mmap(0, size, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); + if (object == MAP_FAILED) { + xhyve_abort("vmm_mem_alloc failed in mmap\n"); } if (hv_vm_map(object, gpa, size, From c0a16ba041afc4fa6751040e9de14a076a44bc4b Mon Sep 17 00:00:00 2001 From: David Scott Date: Tue, 20 Aug 2019 11:49:32 +0100 Subject: [PATCH 2/2] On Majave and later, allocate with MAP_JIT The VM requires writeable + executable memory which is blocked when the "hardened runtime" is enabled at the codesigning stage. If we pass the `MAP_JIT` flag then we can add the capability com.apple.security.cs.allow-jit [1] to permit the allocation. The alternative is to globally enable write+execute for all allocations in the process which seems worse [2] [1] https://developer.apple.com/documentation/bundleresources/entitlements/com_apple_security_cs_allow-jit [2] https://developer.apple.com/documentation/bundleresources/entitlements/com_apple_security_cs_allow-unsigned-executable-memory Signed-off-by: David Scott --- src/lib/vmm/vmm_mem.c | 43 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/src/lib/vmm/vmm_mem.c b/src/lib/vmm/vmm_mem.c index c98316be..dd6f5681 100644 --- a/src/lib/vmm/vmm_mem.c +++ b/src/lib/vmm/vmm_mem.c @@ -29,14 +29,55 @@ #include #include +#include #include #include #include #include #include +#include +#include + +/* According to the mono project + https://github.com/mono/mono/commit/a502768b3a24f4251de6a48ba78a27c898968e63 + using MAP_JIT causes problems with older macOS versions so we should use it + on Mojave or later. */ + +static int mmap_flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_JIT; + +#define OSRELEASE "kern.osrelease" +#define OSRELEASE_MOJAVE 18 + +static long +vmm_get_kern_osrelease() +{ + char *s; + size_t len; + long v; + if (sysctlbyname(OSRELEASE, NULL, &len, NULL, 0)) { + xhyve_abort("vmm_get_kern_osrelease failed to query sysctl kern.osrelease\n"); + } + s = malloc(len); + if (!s) { + xhyve_abort("vmm_get_kern_osrelease failed to allocate memory for kern.osrelease\n"); + } + if (sysctlbyname(OSRELEASE, s, &len, NULL, 0)){ + xhyve_abort("vmm_get_kern_osrelease failed to query sysctl kern.osrelease\n"); + } + v = strtol(s, NULL, 10); + if ((v == 0) && (errno != 0)) { + xhyve_abort("vmm_get_kern_osrelease failed to parse sysctl kern.osrelease value\n"); + } + return v; +} + int vmm_mem_init(void) { + if (vmm_get_kern_osrelease() < OSRELEASE_MOJAVE) { + fprintf(stderr, "Detected macOS older than Mojave, cannot use MAP_JIT\n"); + mmap_flags &= ~MAP_JIT; + } return (0); } @@ -46,7 +87,7 @@ vmm_mem_alloc(uint64_t gpa, size_t size) { void *object; - object = mmap(0, size, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); + object = mmap(0, size, PROT_READ|PROT_WRITE|PROT_EXEC, mmap_flags, -1, 0); if (object == MAP_FAILED) { xhyve_abort("vmm_mem_alloc failed in mmap\n"); }