On 17/07/2023 07:11, Chaitanya S Prakash wrote:
The length of the initial mapping using an mmap() call has the ability to be reduced in a subsequent mmap() call without first being unmapped. Whereas, trying to increase the length of the initial mapping would
I have trouble making sense of this: mappings can only be enlarged or shrunk using mremap(), and these tests are not about mremap(). Rather using mmap(MAP_FIXED) in the middle of an existing mapping overwrites part of it.
result in failure as the capability is not permitted to access a range that it does not own.
Address space management syscalls that manipulate a given mapping are restricted to the range owned by the capability. Any attempt to modify or access memory beyond this range will result in failure of syscall.
It would be good to clarify that the mm syscalls do not access memory, but rather manage mappings.
Signed-off-by: Chaitanya S Prakash chaitanyas.prakash@arm.com
tools/testing/selftests/arm64/morello/mmap.c | 132 +++++++++++++++++++ 1 file changed, 132 insertions(+)
diff --git a/tools/testing/selftests/arm64/morello/mmap.c b/tools/testing/selftests/arm64/morello/mmap.c index 184dcf4ddc92..4a2a552d47dc 100644 --- a/tools/testing/selftests/arm64/morello/mmap.c +++ b/tools/testing/selftests/arm64/morello/mmap.c @@ -198,6 +198,132 @@ static inline void purecap_param_check(void) ASSERT_EQ(retval, 0); } +/* test to verify address space management syscall behaviour when capability
- range is modified */
+static inline void purecap_range_check(void) +{
- void *addr, *ret;
- int retval;
- int prot = PROT_READ | PROT_WRITE;
- int flags = MAP_PRIVATE | MAP_ANONYMOUS;
- unsigned char vec[MMAP_SIZE / PAGE_SIZE];
- /* mapping a smaller range at prev mmap addr in a subsequent mmap()
* call without first unmapping */
- addr = mmap(NULL, MMAP_SIZE, prot, flags, -1, 0);
- ASSERT_GT((unsigned long)addr, 0);
- ret = mmap(addr, MMAP_SIZE_REDUCED, prot, flags | MAP_FIXED, -1, 0);
- ASSERT_GT((unsigned long)ret, 0);
- EXPECT_EQ(0, probe_mem_range(addr, MMAP_SIZE_REDUCED,
PROBE_MODE_TOUCH | PROBE_MODE_VERIFY));
- retval = munmap(addr, MMAP_SIZE_REDUCED);
- ASSERT_EQ(retval, 0);
- /* mapping a larger range at prev mmap addr in a subsequent mmap()
* call without first unmapping */
- addr = mmap(NULL, MMAP_SIZE, prot, flags, -1, 0);
- ASSERT_GT((unsigned long)addr, 0);
- ret = mmap(addr, 2 * MMAP_SIZE, prot, flags | MAP_FIXED, -1, 0);
- ASSERT_EQ((unsigned long)ret, (unsigned long)-EINVAL);
- retval = munmap(addr, MMAP_SIZE);
- ASSERT_EQ(retval, 0);
- /* positive madvise() range test */
- addr = mmap(NULL, MMAP_SIZE, prot, flags, -1, 0);
- ASSERT_GT((unsigned long)addr, 0);
- retval = madvise(addr, MMAP_SIZE, MADV_WILLNEED);
- ASSERT_NE(retval, -EINVAL);
- EXPECT_EQ(0, probe_mem_range(addr, MMAP_SIZE,
PROBE_MODE_TOUCH | PROBE_MODE_VERIFY));
- retval = munmap(addr, MMAP_SIZE);
- ASSERT_EQ(retval, 0);
- /* negative madvise() range test */
- addr = mmap(NULL, MMAP_SIZE_REDUCED, prot, flags, -1, 0);
- ASSERT_GT((unsigned long)addr, 0);
- retval = madvise(addr, MMAP_SIZE, MADV_NORMAL);
- ASSERT_EQ(retval, -EINVAL);
- retval = munmap(addr, MMAP_SIZE_REDUCED);
- ASSERT_EQ(retval, 0);
- /* positive mincore() range test */
- addr = mmap(NULL, MMAP_SIZE, prot, flags, -1, 0);
- ASSERT_GT((unsigned long)addr, 0);
- retval = mincore(addr, MMAP_SIZE, vec);
- ASSERT_EQ(retval, 0);
- EXPECT_EQ(0, probe_mem_range(addr, MMAP_SIZE,
PROBE_MODE_TOUCH | PROBE_MODE_VERIFY));
- retval = munmap(addr, MMAP_SIZE);
- ASSERT_EQ(retval, 0);
- /* negative mincore() range test */
- addr = mmap(NULL, MMAP_SIZE_REDUCED, prot, flags, -1, 0);
- ASSERT_GT((unsigned long)addr, 0);
- retval = mincore(addr, MMAP_SIZE, vec);
- ASSERT_EQ(retval, -EINVAL);
- retval = munmap(addr, MMAP_SIZE_REDUCED);
- ASSERT_EQ(retval, 0);
- /* positive mlock() range test */
- addr = mmap(NULL, MMAP_SIZE, prot, flags, -1, 0);
- ASSERT_GT((unsigned long)addr, 0);
- retval = mlock(addr, MMAP_SIZE);
- EXPECT_EQ(0, probe_mem_range(addr, MMAP_SIZE,
PROBE_MODE_TOUCH | PROBE_MODE_VERIFY));
- retval = munlock(addr, MMAP_SIZE);
- ASSERT_EQ(retval, 0);
- retval = munmap(addr, MMAP_SIZE);
- ASSERT_EQ(retval, 0);
- /* negative mlock() range test */
- addr = mmap(NULL, MMAP_SIZE_REDUCED, prot, flags, -1, 0);
- ASSERT_GT((unsigned long)addr, 0);
- retval = mlock(addr, MMAP_SIZE);
- ASSERT_EQ(retval, -EINVAL);
- retval = munmap(addr, MMAP_SIZE_REDUCED);
- ASSERT_EQ(retval, 0);
- /* negative munlock() range test */
- addr = mmap(NULL, MMAP_SIZE_REDUCED, prot, flags, -1, 0);
- ASSERT_GT((unsigned long)addr, 0);
- EXPECT_EQ(0, mlock2(addr, MMAP_SIZE_REDUCED, MLOCK_ONFAULT));
- EXPECT_EQ(0, probe_mem_range(addr, MMAP_SIZE_REDUCED,
PROBE_MODE_TOUCH | PROBE_MODE_VERIFY));
- retval = munlock(addr, MMAP_SIZE);
- ASSERT_EQ(retval, -EINVAL);
- retval = munmap(addr, MMAP_SIZE_REDUCED);
- ASSERT_EQ(retval, 0);
- /* positive msync() range test */
- addr = mmap(NULL, MMAP_SIZE, prot, flags, -1, 0);
- ASSERT_GT((unsigned long)addr, 0);
- retval = msync(addr, MMAP_SIZE, MS_SYNC);
- ASSERT_EQ(retval, 0);
- EXPECT_EQ(0, probe_mem_range(addr, MMAP_SIZE,
PROBE_MODE_TOUCH | PROBE_MODE_VERIFY));
- retval = munmap(addr, MMAP_SIZE);
- ASSERT_EQ(retval, 0);
- /* negative msync() range test */
- addr = mmap(NULL, MMAP_SIZE_REDUCED, prot, flags, -1, 0);
- ASSERT_GT((unsigned long)addr, 0);
- retval = msync(addr, MMAP_SIZE, MS_SYNC);
- ASSERT_EQ(retval, -EINVAL);
These madvise/mincore/mlock/munlock/msync testcases will indeed fail in PCuABI (and only in PCuABI), but that is purely because the length they are passed is greater than the length of addr, not because the mapping is smaller. It would be clearer to reduce the bounds of addr instead of passing a length that is larger than the mapping. Also, given that the tests are the same regardless of the particular syscall, it would be good to refactor them to reduce duplication.
Kevin