On 7/18/23 21:13, Tudor Cretu wrote:
On 17-07-2023 06: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 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.
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 */
Block comments use a trailing */ on a separate line. You have a few other instances in the following patches.
I'll correct it.
+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);
You probably want to munmap the whole MMAP_SIZE here. Otherwise there's a memory leak.
I'll change that.
Tudor
+ 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);
+ retval = munmap(addr, MMAP_SIZE_REDUCED); + ASSERT_EQ(retval, 0); +}
TEST(test_syscall_mmap) { syscall_mmap(); @@ -218,11 +344,17 @@ TEST(test_purecap_param_check) purecap_param_check(); } +TEST(test_purecap_range_check) +{ + purecap_range_check(); +}
int main(void) { test_syscall_mmap(); test_syscall_mmap2(); test_purecap_map_growsdown(); test_purecap_param_check(); + test_purecap_range_check(); return 0; }