Skip to content

Commit c0a16ba

Browse files
committed
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 <dave.scott@docker.com>
1 parent 04f7bc8 commit c0a16ba

File tree

1 file changed

+42
-1
lines changed

1 file changed

+42
-1
lines changed

Diff for: src/lib/vmm/vmm_mem.c

+42-1
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,55 @@
2929

3030
#include <stdint.h>
3131
#include <stdlib.h>
32+
#include <errno.h>
3233
#include <Hypervisor/hv.h>
3334
#include <Hypervisor/hv_vmx.h>
3435
#include <xhyve/support/misc.h>
3536
#include <xhyve/vmm/vmm_mem.h>
3637
#include <sys/mman.h>
38+
#include <sys/types.h>
39+
#include <sys/sysctl.h>
40+
41+
/* According to the mono project
42+
https://github.com/mono/mono/commit/a502768b3a24f4251de6a48ba78a27c898968e63
43+
using MAP_JIT causes problems with older macOS versions so we should use it
44+
on Mojave or later. */
45+
46+
static int mmap_flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_JIT;
47+
48+
#define OSRELEASE "kern.osrelease"
49+
#define OSRELEASE_MOJAVE 18
50+
51+
static long
52+
vmm_get_kern_osrelease()
53+
{
54+
char *s;
55+
size_t len;
56+
long v;
57+
if (sysctlbyname(OSRELEASE, NULL, &len, NULL, 0)) {
58+
xhyve_abort("vmm_get_kern_osrelease failed to query sysctl kern.osrelease\n");
59+
}
60+
s = malloc(len);
61+
if (!s) {
62+
xhyve_abort("vmm_get_kern_osrelease failed to allocate memory for kern.osrelease\n");
63+
}
64+
if (sysctlbyname(OSRELEASE, s, &len, NULL, 0)){
65+
xhyve_abort("vmm_get_kern_osrelease failed to query sysctl kern.osrelease\n");
66+
}
67+
v = strtol(s, NULL, 10);
68+
if ((v == 0) && (errno != 0)) {
69+
xhyve_abort("vmm_get_kern_osrelease failed to parse sysctl kern.osrelease value\n");
70+
}
71+
return v;
72+
}
73+
3774
int
3875
vmm_mem_init(void)
3976
{
77+
if (vmm_get_kern_osrelease() < OSRELEASE_MOJAVE) {
78+
fprintf(stderr, "Detected macOS older than Mojave, cannot use MAP_JIT\n");
79+
mmap_flags &= ~MAP_JIT;
80+
}
4081
return (0);
4182
}
4283

@@ -46,7 +87,7 @@ vmm_mem_alloc(uint64_t gpa, size_t size)
4687
{
4788
void *object;
4889

49-
object = mmap(0, size, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
90+
object = mmap(0, size, PROT_READ|PROT_WRITE|PROT_EXEC, mmap_flags, -1, 0);
5091
if (object == MAP_FAILED) {
5192
xhyve_abort("vmm_mem_alloc failed in mmap\n");
5293
}

0 commit comments

Comments
 (0)