diff --git a/runtime/memory-map/src/lib.rs b/runtime/memory-map/src/lib.rs index fbfbc70fc..61db1f4a0 100644 --- a/runtime/memory-map/src/lib.rs +++ b/runtime/memory-map/src/lib.rs @@ -337,6 +337,28 @@ pub extern "C" fn memory_map_region_get_prot(map: &MemoryMap, needle: Range) -> /** memory_map_region_get_prot found no or multiple protections in the given range */ pub const PROT_INDETERMINATE: u32 = 0xFFFFFFFFu32; +const PKEY_MULTIPLE: u8 = 255; +const PKEY_NONE: u8 = 254; + +/// return the pkey (0-15) that covers the given range, or PKEY_MULTIPLE or +/// PKEY_NONE if the entire range is not protected by exactly one pkey +#[no_mangle] +pub extern "C" fn memory_map_region_get_owner_pkey(map: &MemoryMap, needle: Range) -> u8 { + let mut pkey = None; + let same = map.all_overlapping_regions(needle, |region| match pkey { + None => { + pkey = Some(region.state.owner_pkey); + true + } + Some(pkey) => region.state.owner_pkey == pkey, + }); + if same { + pkey.unwrap_or(PKEY_NONE) // all same (return pkey) or no pkey + } else { + PKEY_MULTIPLE // multiple pkeys + } +} + #[no_mangle] pub extern "C" fn memory_map_unmap_region(map: &mut MemoryMap, needle: Range) -> bool { map.split_out_region(needle).is_some() diff --git a/runtime/memory_map.h b/runtime/memory_map.h index ac1aef96a..51e3635ef 100644 --- a/runtime/memory_map.h +++ b/runtime/memory_map.h @@ -43,6 +43,8 @@ bool memory_map_all_overlapping_regions_mprotected(const struct memory_map *map, uint32_t memory_map_region_get_prot(const struct memory_map *map, struct range needle); +uint8_t memory_map_region_get_owner_pkey(const struct memory_map *map, struct range needle); + bool memory_map_unmap_region(struct memory_map *map, struct range needle); bool memory_map_add_region(struct memory_map *map, diff --git a/runtime/mmap_event.h b/runtime/mmap_event.h index 7810c8610..3ff1da976 100644 --- a/runtime/mmap_event.h +++ b/runtime/mmap_event.h @@ -78,4 +78,28 @@ static const char *event_name(enum mmap_event event) { return event_names[event]; } +static inline const struct range *event_target_range(enum mmap_event event, const union event_info *info) { + switch (event) { + case EVENT_MMAP: + return &info->mmap.range; + case EVENT_MUNMAP: + return &info->munmap.range; + case EVENT_MREMAP: + return &info->mremap.old_range; + case EVENT_MADVISE: + return &info->madvise.range; + case EVENT_MPROTECT: + return &info->mprotect.range; + case EVENT_PKEY_MPROTECT: + return &info->pkey_mprotect.range; + case EVENT_CLONE: + return NULL; + case EVENT_EXEC: + return NULL; + case EVENT_NONE: + return NULL; + break; + } +} + enum mmap_event event_from_syscall(uint64_t rax); diff --git a/runtime/track_memory_map.c b/runtime/track_memory_map.c index 3d02b709d..f3d7b403f 100644 --- a/runtime/track_memory_map.c +++ b/runtime/track_memory_map.c @@ -839,6 +839,10 @@ bool track_memory_map(pid_t pid, int *exit_status_out, enum trace_mode mode) { } else if (!is_op_permitted(map, event, &event_info)) { fprintf(stderr, "forbidden operation requested: "); print_event(event, &event_info); + const struct range *range = event_target_range(event, &event_info); + if (range != NULL) { + printf("region pkey: %d\n", memory_map_region_get_owner_pkey(map, *range)); + } return_syscall_eperm(waited_pid); if (ptrace(continue_request, waited_pid, 0, 0) < 0) { perror("could not PTRACE_SYSCALL");