From: Chaitanya S Prakash chaitanyas.prakash@arm.com
Reservations are contiguous ranges of virtual addresses that exactly match the bounds of an owning capability. When an owning capability is passed to a syscall, it's bounds are first verified against the existing reservation. If the bounds of a null-derived capability are found to overlap with any existing reservation, the syscall fails with an -ERESERVATION error code. A partial unmap within a particular reservation still allows the rest of the region to be accessible. Tests to verify the same have been added.
Signed-off-by: Chaitanya S Prakash chaitanyas.prakash@arm.com --- tools/testing/selftests/arm64/morello/mmap.c | 39 ++++++++++++++++++++ 1 file changed, 39 insertions(+)
diff --git a/tools/testing/selftests/arm64/morello/mmap.c b/tools/testing/selftests/arm64/morello/mmap.c index daf69633e182..727937b49c11 100644 --- a/tools/testing/selftests/arm64/morello/mmap.c +++ b/tools/testing/selftests/arm64/morello/mmap.c @@ -305,6 +305,44 @@ TEST(test_range_check) EXPECT_EQ(retval, -EINVAL); }
+/* test to verify mmap() behaviour when capability bounds are modified */ +TEST(test_mmap_bounds_check) +{ + void *addr, *ptr, *new_ptr; + size_t size; + int retval; + int prot = PROT_READ | PROT_WRITE; + int flags = MAP_PRIVATE | MAP_ANONYMOUS; + + /* test to verify rest of reservation region is accessible after a partial + * unmap + */ + ptr = mmap(NULL, MMAP_SIZE, prot, flags, -1, 0); + ASSERT_FALSE(IS_ERR_VALUE(ptr)); + + retval = munmap(ptr, pagesize); + ASSERT_EQ(retval, 0); + ptr = ptr + pagesize; + size = MMAP_SIZE - pagesize; + EXPECT_EQ(0, probe_mem_range(ptr, size, + PROBE_MODE_TOUCH | PROBE_MODE_VERIFY)); + + retval = munmap(ptr, size); + ASSERT_EQ(retval, 0); + + /* null-derived ptr overlaps with an existing resservation */ + addr = (void *)(uintptr_t)(pagesize * 8); + ptr = mmap(addr, MMAP_SIZE, prot, flags, -1, 0); + ASSERT_FALSE(IS_ERR_VALUE(ptr)); + + new_ptr = mmap(addr + MMAP_SIZE_REDUCED, MMAP_SIZE, prot, + flags | MAP_FIXED, -1, 0); + EXPECT_EQ((unsigned long)new_ptr, (unsigned long)-ERESERVATION); + + retval = munmap(ptr, MMAP_SIZE); + ASSERT_EQ(retval, 0); +} + int main(__unused int argc, __unused char **argv, __unused char **envp, struct morello_auxv *auxv) { pagesize = get_pagesize(auxv); @@ -314,5 +352,6 @@ int main(__unused int argc, __unused char **argv, __unused char **envp, struct m test_map_growsdown(); test_validity_tag_check(); test_range_check(); + test_mmap_bounds_check(); return 0; }