On 09/01/2024 13:04, Chaitanya S Prakash wrote:
From: Chaitanya S Prakash chaitanyas.prakash@arm.com
Attempting to remap a range larger than what is owned by the capability triggers a -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 triggers the -ENOMEM error. Within the bounds of a reservation, mremap() can be used to grow the mappings in-place. Tests to verify this behaviour have been added.
Signed-off-by: Chaitanya S Prakash chaitanyas.prakash@arm.com
tools/testing/selftests/arm64/morello/mmap.c | 57 ++++++++++++++++++++ 1 file changed, 57 insertions(+)
diff --git a/tools/testing/selftests/arm64/morello/mmap.c b/tools/testing/selftests/arm64/morello/mmap.c index 727937b49c11..610ba12a35ff 100644 --- a/tools/testing/selftests/arm64/morello/mmap.c +++ b/tools/testing/selftests/arm64/morello/mmap.c @@ -343,6 +343,62 @@ TEST(test_mmap_bounds_check) ASSERT_EQ(retval, 0); } +/* test to verify mremap() behaviour when capability bounds are modified */ +TEST(test_mremap_bounds_check) +{
- void *addr, *ptr, *new_ptr;
- int retval;
- int prot = PROT_READ | PROT_WRITE;
- int flags = MAP_PRIVATE | MAP_ANONYMOUS;
- /* moving a mapping with MREMAP_MAYMOVE flag specified */
- ptr = mmap(NULL, MMAP_SIZE_REDUCED, prot, flags, -1, 0);
- ASSERT_FALSE(IS_ERR_VALUE(ptr));
- new_ptr = mremap(ptr, MMAP_SIZE_REDUCED, MMAP_SIZE, MREMAP_MAYMOVE, NULL);
- ASSERT_FALSE(IS_ERR_VALUE(new_ptr));
- ASSERT_NE((unsigned long)ptr, (unsigned long)new_ptr);
No need for the casts.
- EXPECT_EQ(0, probe_mem_range(new_ptr, MMAP_SIZE,
PROBE_MODE_TOUCH | PROBE_MODE_VERIFY));
- retval = munmap(new_ptr, MMAP_SIZE);
- ASSERT_EQ(retval, 0);
- /* moving a mapping without MREMAP_MAYMOVE flag triggers an ENOMEM error */
This is a bit confusing, because as such the mremap() call below doesn't ask for the mapping to be moved. It is only because of reservation restrictions that it would be necessary to move it. Maybe "expanding a mapping"? That would also make sense in the comment above.
- ptr = mmap(NULL, MMAP_SIZE_REDUCED, prot, flags, -1, 0);
- ASSERT_FALSE(IS_ERR_VALUE(ptr));
- new_ptr = mremap(ptr, MMAP_SIZE_REDUCED, MMAP_SIZE, 0, 0);
- EXPECT_EQ((unsigned long)new_ptr, (unsigned long)-ENOMEM);
- retval = munmap(ptr, MMAP_SIZE_REDUCED);
- ASSERT_EQ(retval, 0);
- /* attempt to resize a mapping range greater than what the capability owns */
- ptr = mmap(NULL, MMAP_SIZE_REDUCED, prot, flags, -1, 0);
- ASSERT_FALSE(IS_ERR_VALUE(ptr));
- new_ptr = mremap(ptr, MMAP_SIZE, MMAP_SIZE, MREMAP_MAYMOVE, 0);
- EXPECT_EQ((unsigned long)new_ptr, (unsigned long)-EINVAL);
- retval = munmap(ptr, MMAP_SIZE_REDUCED);
- ASSERT_EQ(retval, 0);
- /* attempt to grow mappings in-place */
- ptr = mmap(NULL, MMAP_SIZE, prot, flags, -1, 0);
- ASSERT_FALSE(IS_ERR_VALUE(ptr));
- addr = (void *)(uintptr_t)(ptr + MMAP_SIZE_REDUCED);
It doesn't look like you need the temporary and casts, just pass ptr + MMAP_SIZE_REDUCED to munmap() directly?
Kevin
- retval = munmap(addr, MMAP_SIZE_REDUCED);
- ASSERT_EQ(retval, 0);
- new_ptr = mremap(ptr, MMAP_SIZE_REDUCED, MMAP_SIZE, 0, 0);
- ASSERT_FALSE(IS_ERR_VALUE(new_ptr));
- retval = munmap(new_ptr, MMAP_SIZE);
- EXPECT_EQ(retval, 0);
+}
int main(__unused int argc, __unused char **argv, __unused char **envp, struct morello_auxv *auxv) { pagesize = get_pagesize(auxv); @@ -353,5 +409,6 @@ int main(__unused int argc, __unused char **argv, __unused char **envp, struct m test_validity_tag_check(); test_range_check(); test_mmap_bounds_check();
- test_mremap_bounds_check(); return 0;
}