Skip to content

Commit 13e6cb5

Browse files
committed
qemu: new JIT workaround for iOS 26
We map the JIT region originally as RX and also mirror map it as RX. Then we use attached debugger to flag the mirror mapping as debugger owned. Finally, we change the original map to RW which should not invalidate code-signing as the mirror is debugger owned. Thanks to @JJTech0130 for this workaround.
1 parent 5423e6d commit 13e6cb5

File tree

1 file changed

+112
-0
lines changed

1 file changed

+112
-0
lines changed

patches/qemu-10.0.2-utm.patch

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -427,3 +427,115 @@ index 6c91e2d292..86978f4671 100644
427427
--
428428
2.41.0
429429

430+
From 9a800289e762e543d23d73846668221bc9c59f65 Mon Sep 17 00:00:00 2001
431+
From: osy <[email protected]>
432+
Date: Sun, 14 Sep 2025 00:55:51 -0700
433+
Subject: [PATCH] tcg: new JIT workaround for iOS 26
434+
435+
We map the JIT region originally as RX and also mirror map it
436+
as RX. Then we use attached debugger to flag the mirror
437+
mapping as debugger owned. Finally, we change the original map
438+
to RW which should not invalidate code-signing as the mirror
439+
is debugger owned.
440+
441+
Thanks to @JJTech0130 for this workaround.
442+
---
443+
tcg/region.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++--
444+
1 file changed, 60 insertions(+), 2 deletions(-)
445+
446+
diff --git a/tcg/region.c b/tcg/region.c
447+
index 70996b5ab1..231438c58e 100644
448+
--- a/tcg/region.c
449+
+++ b/tcg/region.c
450+
@@ -610,6 +610,8 @@ static int alloc_code_gen_buffer_splitwx_memfd(size_t size, Error **errp)
451+
452+
#ifdef CONFIG_DARWIN
453+
#include <mach/mach.h>
454+
+#include <sys/types.h>
455+
+#include <sys/sysctl.h>
456+
457+
extern kern_return_t mach_vm_remap(vm_map_t target_task,
458+
mach_vm_address_t *target_address,
459+
@@ -623,14 +625,50 @@ extern kern_return_t mach_vm_remap(vm_map_t target_task,
460+
vm_prot_t *max_protection,
461+
vm_inherit_t inheritance);
462+
463+
+static int is_debugger_attached(void)
464+
+{
465+
+ int mib[4];
466+
+ struct kinfo_proc info;
467+
+ size_t size;
468+
+
469+
+ info.kp_proc.p_flag = 0;
470+
+
471+
+ /* Initialize MIB for sysctl call */
472+
+ mib[0] = CTL_KERN;
473+
+ mib[1] = KERN_PROC;
474+
+ mib[2] = KERN_PROC_PID;
475+
+ mib[3] = getpid();
476+
+
477+
+ size = sizeof(info);
478+
+
479+
+ if (sysctl(mib, 4, &info, &size, NULL, 0) == -1) {
480+
+ return 0; // sysctl failed, be conservative
481+
+ }
482+
+
483+
+ /* P_TRACED means the process is being debugged */
484+
+ return (info.kp_proc.p_flag & P_TRACED) != 0;
485+
+}
486+
+
487+
+static void break_prepare_jit_region(mach_vm_address_t addr, size_t len)
488+
+{
489+
+ asm ("mov x0, %0\n"
490+
+ "mov x1, %1\n"
491+
+ "brk #0x69" :: "r" (addr), "r" (len) : "x0", "x1");
492+
+}
493+
+
494+
static int alloc_code_gen_buffer_splitwx_vmremap(size_t size, Error **errp)
495+
{
496+
kern_return_t ret;
497+
mach_vm_address_t buf_rw, buf_rx;
498+
vm_prot_t cur_prot, max_prot;
499+
+ int orig_prot = PROT_READ | PROT_WRITE;
500+
+
501+
+ /* iOS 26 with TXM requires new workaround*/
502+
+ if (__builtin_available(iOS 26, visionOS 26, *)) {
503+
+ orig_prot = PROT_READ | PROT_EXEC;
504+
+ }
505+
506+
- /* Map the read-write portion via normal anon memory. */
507+
- if (!alloc_code_gen_buffer_anon(size, PROT_READ | PROT_WRITE,
508+
+ if (!alloc_code_gen_buffer_anon(size, orig_prot,
509+
MAP_PRIVATE | MAP_ANONYMOUS, errp)) {
510+
return -1;
511+
}
512+
@@ -662,6 +700,26 @@ static int alloc_code_gen_buffer_splitwx_vmremap(size_t size, Error **errp)
513+
return -1;
514+
}
515+
516+
+ if (__builtin_available(iOS 26, visionOS 26, *)) {
517+
+ if (!is_debugger_attached()) {
518+
+ error_setg(errp, "debugger must be attached for jit workaround");
519+
+ munmap((void *)buf_rx, size);
520+
+ munmap((void *)buf_rw, size);
521+
+ return -1;
522+
+ }
523+
+
524+
+ /* give let debugger modify the page permission */
525+
+ break_prepare_jit_region(buf_rx, size);
526+
+
527+
+ /* finally mark the read-write portion as RW */
528+
+ if (mprotect((void *)buf_rw, size, PROT_READ | PROT_WRITE) != 0) {
529+
+ error_setg_errno(errp, errno, "mprotect for jit splitwx (rw)");
530+
+ munmap((void *)buf_rx, size);
531+
+ munmap((void *)buf_rw, size);
532+
+ return -1;
533+
+ }
534+
+ }
535+
+
536+
tcg_splitwx_diff = buf_rx - buf_rw;
537+
return PROT_READ | PROT_WRITE;
538+
}
539+
--
540+
2.41.0
541+

0 commit comments

Comments
 (0)