Attempting to remap a range larger than what is owned by the capability trigger an -EINVAL error. Additionally, mappings that have to be moved in order to satisfy the new constraints, expect the MREMAP_MAYMOVE flag to be specified. Failure to do so also triggers the -ERESERVATION error. Tests to verify this behaviour has been added.
Signed-off-by: Chaitanya S Prakash chaitanyas.prakash@arm.com --- tools/testing/selftests/arm64/morello/mmap.c | 44 ++++++++++++++++++++ 1 file changed, 44 insertions(+)
diff --git a/tools/testing/selftests/arm64/morello/mmap.c b/tools/testing/selftests/arm64/morello/mmap.c index c7f1ddb395c5..aa552c8affba 100644 --- a/tools/testing/selftests/arm64/morello/mmap.c +++ b/tools/testing/selftests/arm64/morello/mmap.c @@ -434,6 +434,44 @@ static inline void purecap_mmap_bounds_check(void) TH_LOG("Segmenation fault caused by invalid memory access has been handled."); }
+/* test to verify mremap() behaviour when capability bounds are modified */ +static inline void purecap_mremap_bounds_check(void) +{ + void *addr, *new_addr; + int retval; + int prot = PROT_READ | PROT_WRITE; + int flags = MAP_PRIVATE | MAP_ANONYMOUS; + + /* moving a mapping with MREMAP_MAYMOVE flag specified */ + addr = mmap(NULL, MMAP_SIZE_REDUCED, prot, flags, -1, 0); + ASSERT_GT((unsigned long)addr, 0); + new_addr = mremap(addr, MMAP_SIZE_REDUCED, MMAP_SIZE, MREMAP_MAYMOVE, 0); + ASSERT_GT((unsigned long)new_addr, 0); + EXPECT_EQ(0, probe_mem_range(new_addr, MMAP_SIZE, + PROBE_MODE_TOUCH | PROBE_MODE_VERIFY)); + + retval = munmap(new_addr, MMAP_SIZE); + ASSERT_EQ(retval, 0); + + /* moving a mapping without MREMAP_MAYMOVE flag triggers a reservation error */ + addr = mmap(NULL, MMAP_SIZE_REDUCED, prot, flags, -1, 0); + ASSERT_GT((unsigned long)addr, 0); + new_addr = mremap(addr, MMAP_SIZE_REDUCED, MMAP_SIZE, 0, 0); + ASSERT_EQ((unsigned long)new_addr, (unsigned long)-ERESERVATION); + + retval = munmap(addr, MMAP_SIZE_REDUCED); + ASSERT_EQ(retval, 0); + + /* attempt to resize a mapping range greater than what the capability owns */ + addr = mmap(NULL, MMAP_SIZE_REDUCED, prot, flags, -1, 0); + ASSERT_GT((unsigned long)addr, 0); + new_addr = mremap(addr, MMAP_SIZE, MMAP_SIZE, MREMAP_MAYMOVE, 0); + ASSERT_EQ((unsigned long)new_addr, (unsigned long)-EINVAL); + + retval = munmap(addr, MMAP_SIZE_REDUCED); + ASSERT_EQ(retval, 0); +} + TEST(test_syscall_mmap) { syscall_mmap(); @@ -464,6 +502,11 @@ TEST(test_purecap_mmap_bounds_check) purecap_mmap_bounds_check(); }
+TEST(test_purecap_mremap_bounds_check) +{ + purecap_mremap_bounds_check(); +} + int main(void) { test_syscall_mmap(); @@ -472,5 +515,6 @@ int main(void) test_purecap_param_check(); test_purecap_range_check(); test_purecap_mmap_bounds_check(); + test_purecap_mremap_bounds_check(); return 0; }