Skip to content

Commit 0cfcfc9

Browse files
committed
[Sanitizers][Apple] Fix logic bugs that break RestrictMemoryToMaxAddress
There are two logic bugs breaking RestrictMemoryToMaxAddress -- adding left_padding within MapDynamicShadow. There is also an issue with the expectation of hitting KERN_INVALID_ADDRESS when we are beyond the addressable regions. For most embedded scenarios, we exceed vm_max_address and setting max_occupied address to a memory region the process doesn't have access to. Because of this, our check if (new_max_vm < max_occupied_addr) { will always fail and we will never restrict the address on smaller devices. rdar://66603866
1 parent b968fd9 commit 0cfcfc9

File tree

1 file changed

+11
-5
lines changed

1 file changed

+11
-5
lines changed

compiler-rt/lib/sanitizer_common/sanitizer_mac.cpp

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1203,13 +1203,14 @@ uptr MapDynamicShadow(uptr shadow_size_bytes, uptr shadow_scale,
12031203
const uptr left_padding =
12041204
Max<uptr>(granularity, 1ULL << min_shadow_base_alignment);
12051205

1206-
uptr space_size = shadow_size_bytes + left_padding;
1206+
uptr space_size = shadow_size_bytes;
12071207

12081208
uptr largest_gap_found = 0;
12091209
uptr max_occupied_addr = 0;
1210+
12101211
VReport(2, "FindDynamicShadowStart, space_size = %p\n", (void *)space_size);
12111212
uptr shadow_start =
1212-
FindAvailableMemoryRange(space_size, alignment, granularity,
1213+
FindAvailableMemoryRange(space_size, alignment, left_padding,
12131214
&largest_gap_found, &max_occupied_addr);
12141215
// If the shadow doesn't fit, restrict the address space to make it fit.
12151216
if (shadow_start == 0) {
@@ -1229,9 +1230,9 @@ uptr MapDynamicShadow(uptr shadow_size_bytes, uptr shadow_scale,
12291230
}
12301231
RestrictMemoryToMaxAddress(new_max_vm);
12311232
high_mem_end = new_max_vm - 1;
1232-
space_size = (high_mem_end >> shadow_scale) + left_padding;
1233+
space_size = (high_mem_end >> shadow_scale);
12331234
VReport(2, "FindDynamicShadowStart, space_size = %p\n", (void *)space_size);
1234-
shadow_start = FindAvailableMemoryRange(space_size, alignment, granularity,
1235+
shadow_start = FindAvailableMemoryRange(space_size, alignment, left_padding,
12351236
nullptr, nullptr);
12361237
if (shadow_start == 0) {
12371238
Report("Unable to find a memory range after restricting VM.\n");
@@ -1272,10 +1273,15 @@ uptr FindAvailableMemoryRange(uptr size, uptr alignment, uptr left_padding,
12721273
mach_msg_type_number_t count = kRegionInfoSize;
12731274
kr = mach_vm_region_recurse(mach_task_self(), &address, &vmsize, &depth,
12741275
(vm_region_info_t)&vminfo, &count);
1275-
if (kr == KERN_INVALID_ADDRESS) {
1276+
1277+
// There are cases where going beyond the processes' max vm does
1278+
// not return KERN_INVALID_ADDRESS so we check for going beyond that
1279+
// max address as well.
1280+
if (kr == KERN_INVALID_ADDRESS || address > max_vm_address) {
12761281
// No more regions beyond "address", consider the gap at the end of VM.
12771282
address = max_vm_address;
12781283
vmsize = 0;
1284+
kr = -1; // break after this iteration.
12791285
} else {
12801286
if (max_occupied_addr) *max_occupied_addr = address + vmsize;
12811287
}

0 commit comments

Comments
 (0)