[compiler-rt] [sanitizer-common][Darwin] gracefully handle mach_vm_region_recurse error (PR #194436)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Apr 27 11:54:47 PDT 2026
https://github.com/SharonXSharon created https://github.com/llvm/llvm-project/pull/194436
`[sanitizer-common][Darwin] Improve mach_vm_region_recurse error handling (#158670)`) added specific error messages for non-`KERN_SUCCESS` return codes from `mach_vm_region_recurse` in `FindAvailableMemoryRange`. It also changed the behavior of the `KERN_DENIED` case to call `Die()` and the catch-all `else` case to call `break`, both of which prevent the gap-checking code from running and cause a fatal crash instead of attempting shadow placement.
On iOS App extensions (e.g. widgets), the sandbox can block `mach_vm_region_recurse`, returning `KERN_DENIED` or other error codes during early memprof initialization, causing app extension crash.
The patch keeps the newly added error messages added by #158670, but instead of `Die()` or `break`, set `address = max_vm_address` , the same as how the code is handling `KERN_INVALID_ADDRESS`, so the code will attempt to check the gap and let the subsequent code handle if the gap is useable.
>From fbe4e1f30a84043a2697f27cc59e1decc9c73c0c Mon Sep 17 00:00:00 2001
From: Sharon Xu <sharonxu at fb.com>
Date: Mon, 27 Apr 2026 11:09:24 -0700
Subject: [PATCH] [sanitizer-common][Darwin] gracefully handle
mach_vm_region_recurse error
8fb02fae9957 (`[sanitizer-common][Darwin] Improve mach_vm_region_recurse
error handling (#158670)`) added specific error messages for
non-`KERN_SUCCESS` return codes from `mach_vm_region_recurse` in
`FindAvailableMemoryRange`. However, the `KERN_DENIED` case calls
`Die()` and the catch-all `else` case calls `break`, both of which
prevent the gap-checking code from running and cause a fatal crash
instead of attempting shadow placement.
On iOS/macOS app extensions (e.g. widgets), the sandbox can block
`mach_vm_region_recurse`, returning `KERN_DENIED` or other error codes
during early memprof initialization. This causes a `SIGABRT` crash
during `libSystem_initializer`.
Keep the error messages added by that commit, but instead of `Die()` or
`break`, set `address = max_vm_address` so the remaining address space
is treated as free and the gap-checking code can still attempt to place
the shadow.
---
compiler-rt/lib/sanitizer_common/sanitizer_mac.cpp | 10 ++++++----
.../TestCases/Darwin/sandbox-vm-region-recurse.cpp | 5 +++--
2 files changed, 9 insertions(+), 6 deletions(-)
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_mac.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_mac.cpp
index 6fafc04f557b4..ee67fab73f3df 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_mac.cpp
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_mac.cpp
@@ -1363,14 +1363,16 @@ uptr FindAvailableMemoryRange(uptr size, uptr alignment, uptr left_padding,
} else if (kr == KERN_DENIED) {
Report("ERROR: Unable to find a memory range for dynamic shadow.\n");
Report("HINT: Ensure mach_vm_region_recurse is allowed under sandbox.\n");
- Die();
+ address = max_vm_address;
+
+ // We will break after this iteration since kr != KERN_SUCCESS
} else {
Report(
"WARNING: mach_vm_region_recurse returned unexpected code %d (%s)\n",
kr, mach_error_string(kr));
- DCHECK(false && "mach_vm_region_recurse returned unexpected code");
- break; // address is not valid unless KERN_SUCCESS, therefore we must not
- // use it.
+ address = max_vm_address;
+
+ // We will break after this iteration since kr != KERN_SUCCESS
}
if (free_begin != address) {
diff --git a/compiler-rt/test/asan/TestCases/Darwin/sandbox-vm-region-recurse.cpp b/compiler-rt/test/asan/TestCases/Darwin/sandbox-vm-region-recurse.cpp
index c496d822a7fb8..58ee270361b19 100644
--- a/compiler-rt/test/asan/TestCases/Darwin/sandbox-vm-region-recurse.cpp
+++ b/compiler-rt/test/asan/TestCases/Darwin/sandbox-vm-region-recurse.cpp
@@ -1,4 +1,5 @@
-// Check that if mach_vm_region_recurse is disallowed by sandbox, we report a message saying so.
+// Check that if mach_vm_region_recurse is disallowed by sandbox, we report a
+// hint but still gracefully proceed with shadow placement and detect errors.
// RUN: %clangxx_asan -O0 %s -o %t
// RUN: not %run sandbox-exec -p '(version 1)(allow default)(deny syscall-mig (kernel-mig-routine mach_vm_region_recurse))' %t 2>&1 | FileCheck --check-prefix=CHECK-DENY %s
@@ -20,7 +21,6 @@ int main() {
free(x);
return x[5];
// CHECK-ALLOW: {{.*ERROR: AddressSanitizer: heap-use-after-free on address}}
- // CHECK-DENY-NOT: {{.*ERROR: AddressSanitizer: heap-use-after-free on address}}
// CHECK-ALLOW: {{READ of size 1 at 0x.* thread T0}}
// CHECK-ALLOW: {{ #0 0x.* in main}}
// CHECK-ALLOW: {{freed by thread T0 here:}}
@@ -30,4 +30,5 @@ int main() {
// CHECK-ALLOW: {{ #0 0x.* in malloc}}
// CHECK-ALLOW: {{ #1 0x.* in main}}
// CHECK-DENY: {{.*HINT: Ensure mach_vm_region_recurse is allowed under sandbox}}
+ // CHECK-DENY: {{.*ERROR: AddressSanitizer: heap-use-after-free on address}}
}
More information about the llvm-commits
mailing list