From: Jeff Xu jeffxu@chromium.org
mmap(MAP_FIXED) should return EPERM when memory is sealed.
Fixes: 4205a39e06da ("mm/munmap: replace can_modify_mm with can_modify_vma") Signed-off-by: Jeff Xu jeffxu@chromium.org --- mm/mmap.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/mm/mmap.c b/mm/mmap.c index 80d70ed099cf..0cd0c0ef03c7 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -1386,7 +1386,10 @@ unsigned long mmap_region(struct file *file, unsigned long addr, mt_on_stack(mt_detach); mas_init(&mas_detach, &mt_detach, /* addr = */ 0); /* Prepare to unmap any existing mapping in the area */ - if (vms_gather_munmap_vmas(&vms, &mas_detach)) + error = vms_gather_munmap_vmas(&vms, &mas_detach); + if (error == -EPERM) + return -EPERM; + if (error) return -ENOMEM;
vmg.next = vms.next;
From: Jeff Xu jeffxu@chromium.org
Add more testcases and increase test coverage, e.g. add get_vma_size to check VMA size and prot bits.
Signed-off-by: Jeff Xu jeffxu@chromium.org --- tools/testing/selftests/mm/mseal_test.c | 826 ++++++++++++++++++++++-- 1 file changed, 759 insertions(+), 67 deletions(-)
diff --git a/tools/testing/selftests/mm/mseal_test.c b/tools/testing/selftests/mm/mseal_test.c index e7991e5fdcf3..4b3f883aae17 100644 --- a/tools/testing/selftests/mm/mseal_test.c +++ b/tools/testing/selftests/mm/mseal_test.c @@ -170,18 +170,30 @@ static void set_pkey(int pkey, unsigned long pkey_value) static void setup_single_address(int size, void **ptrOut) { void *ptr; + unsigned long page_size = getpagesize();
- ptr = mmap(NULL, size, PROT_READ, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); - *ptrOut = ptr; + *ptrOut = (void *)-1; + ptr = mmap(NULL, size + 2 * page_size, PROT_READ, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); + if (ptr != (void *) -1) { + sys_mprotect(ptr, page_size, PROT_NONE); + sys_mprotect(ptr + size + page_size, page_size, PROT_NONE); + *ptrOut = ptr + page_size; + } }
static void setup_single_address_rw(int size, void **ptrOut) { void *ptr; unsigned long mapflags = MAP_ANONYMOUS | MAP_PRIVATE; + unsigned long page_size = getpagesize();
- ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, mapflags, -1, 0); - *ptrOut = ptr; + *ptrOut = (void *)-1; + ptr = mmap(NULL, size + 2 * page_size, PROT_READ | PROT_WRITE, mapflags, -1, 0); + if (ptr != (void *) -1) { + sys_mprotect(ptr, page_size, PROT_NONE); + sys_mprotect(ptr + size + page_size, page_size, PROT_NONE); + *ptrOut = ptr + page_size; + } }
static int clean_single_address(void *ptr, int size) @@ -226,6 +238,21 @@ bool pkey_supported(void) return false; }
+bool get_vma_size_supported(void) +{ + void *ptr; + unsigned long page_size = getpagesize(); + unsigned long size = 4 * page_size; + int prot; + + setup_single_address(size, &ptr); + size = get_vma_size(ptr, &prot); + if (size == 4 * page_size && prot == 0x4) + return true; + + return false; +} + static void test_seal_addseal(void) { int ret; @@ -419,11 +446,17 @@ static void test_seal_invalid_input(void) unsigned long size = 4 * page_size; int ret;
- setup_single_address(8 * page_size, &ptr); + setup_single_address(9 * page_size, &ptr); FAIL_TEST_IF_FALSE(ptr != (void *)-1); - ret = clean_single_address(ptr + 4 * page_size, 4 * page_size); + + ret = clean_single_address(ptr, page_size); + FAIL_TEST_IF_FALSE(!ret); + + ret = clean_single_address(ptr + 5 * page_size, 4 * page_size); FAIL_TEST_IF_FALSE(!ret);
+ ptr = ptr + page_size; + /* invalid flag */ ret = syscall(__NR_mseal, ptr, size, 0x20); FAIL_TEST_IF_FALSE(ret < 0); @@ -523,6 +556,7 @@ static void test_seal_mprotect(bool seal) unsigned long page_size = getpagesize(); unsigned long size = 4 * page_size; int ret; + int prot;
setup_single_address(size, &ptr); FAIL_TEST_IF_FALSE(ptr != (void *)-1); @@ -533,9 +567,14 @@ static void test_seal_mprotect(bool seal) }
ret = sys_mprotect(ptr, size, PROT_READ | PROT_WRITE); - if (seal) + if (seal) { FAIL_TEST_IF_FALSE(ret < 0); - else + FAIL_TEST_IF_FALSE(errno == EPERM); + + size = get_vma_size(ptr, &prot); + FAIL_TEST_IF_FALSE(size == 4 * page_size); + FAIL_TEST_IF_FALSE(prot == 0x4); + } else FAIL_TEST_IF_FALSE(!ret);
REPORT_TEST_PASS(); @@ -547,6 +586,7 @@ static void test_seal_start_mprotect(bool seal) unsigned long page_size = getpagesize(); unsigned long size = 4 * page_size; int ret; + int prot;
setup_single_address(size, &ptr); FAIL_TEST_IF_FALSE(ptr != (void *)-1); @@ -558,9 +598,14 @@ static void test_seal_start_mprotect(bool seal)
/* the first page is sealed. */ ret = sys_mprotect(ptr, page_size, PROT_READ | PROT_WRITE); - if (seal) + if (seal) { FAIL_TEST_IF_FALSE(ret < 0); - else + FAIL_TEST_IF_FALSE(errno == EPERM); + + size = get_vma_size(ptr, &prot); + FAIL_TEST_IF_FALSE(size == page_size); + FAIL_TEST_IF_FALSE(prot == 0x4); + } else FAIL_TEST_IF_FALSE(!ret);
/* pages after the first page is not sealed. */ @@ -577,6 +622,7 @@ static void test_seal_end_mprotect(bool seal) unsigned long page_size = getpagesize(); unsigned long size = 4 * page_size; int ret; + int prot;
setup_single_address(size, &ptr); FAIL_TEST_IF_FALSE(ptr != (void *)-1); @@ -593,9 +639,14 @@ static void test_seal_end_mprotect(bool seal) /* last 3 page are sealed */ ret = sys_mprotect(ptr + page_size, page_size * 3, PROT_READ | PROT_WRITE); - if (seal) + if (seal) { FAIL_TEST_IF_FALSE(ret < 0); - else + FAIL_TEST_IF_FALSE(errno == EPERM); + + size = get_vma_size(ptr + page_size, &prot); + FAIL_TEST_IF_FALSE(size == 3 * page_size); + FAIL_TEST_IF_FALSE(prot == 0x4); + } else FAIL_TEST_IF_FALSE(!ret);
REPORT_TEST_PASS(); @@ -607,6 +658,7 @@ static void test_seal_mprotect_unalign_len(bool seal) unsigned long page_size = getpagesize(); unsigned long size = 4 * page_size; int ret; + int prot;
setup_single_address(size, &ptr); FAIL_TEST_IF_FALSE(ptr != (void *)-1); @@ -618,9 +670,14 @@ static void test_seal_mprotect_unalign_len(bool seal)
/* 2 pages are sealed. */ ret = sys_mprotect(ptr, page_size * 2, PROT_READ | PROT_WRITE); - if (seal) + if (seal) { FAIL_TEST_IF_FALSE(ret < 0); - else + FAIL_TEST_IF_FALSE(errno == EPERM); + + size = get_vma_size(ptr, &prot); + FAIL_TEST_IF_FALSE(size == 2 * page_size); + FAIL_TEST_IF_FALSE(prot == 0x4); + } else FAIL_TEST_IF_FALSE(!ret);
ret = sys_mprotect(ptr + page_size * 2, page_size, @@ -636,6 +693,7 @@ static void test_seal_mprotect_unalign_len_variant_2(bool seal) unsigned long page_size = getpagesize(); unsigned long size = 4 * page_size; int ret; + int prot;
setup_single_address(size, &ptr); FAIL_TEST_IF_FALSE(ptr != (void *)-1); @@ -646,9 +704,14 @@ static void test_seal_mprotect_unalign_len_variant_2(bool seal)
/* 3 pages are sealed. */ ret = sys_mprotect(ptr, page_size * 3, PROT_READ | PROT_WRITE); - if (seal) + if (seal) { FAIL_TEST_IF_FALSE(ret < 0); - else + FAIL_TEST_IF_FALSE(errno == EPERM); + + size = get_vma_size(ptr, &prot); + FAIL_TEST_IF_FALSE(size == 3 * page_size); + FAIL_TEST_IF_FALSE(prot == 0x4); + } else FAIL_TEST_IF_FALSE(!ret);
ret = sys_mprotect(ptr + page_size * 3, page_size, @@ -664,6 +727,7 @@ static void test_seal_mprotect_two_vma(bool seal) unsigned long page_size = getpagesize(); unsigned long size = 4 * page_size; int ret; + int prot;
setup_single_address(size, &ptr); FAIL_TEST_IF_FALSE(ptr != (void *)-1); @@ -678,16 +742,26 @@ static void test_seal_mprotect_two_vma(bool seal) }
ret = sys_mprotect(ptr, page_size * 2, PROT_READ | PROT_WRITE); - if (seal) + if (seal) { FAIL_TEST_IF_FALSE(ret < 0); - else + FAIL_TEST_IF_FALSE(errno == EPERM); + + size = get_vma_size(ptr, &prot); + FAIL_TEST_IF_FALSE(size == 2 * page_size); + FAIL_TEST_IF_FALSE(prot == 0x6); + } else FAIL_TEST_IF_FALSE(!ret);
ret = sys_mprotect(ptr + page_size * 2, page_size * 2, PROT_READ | PROT_WRITE); - if (seal) + if (seal) { FAIL_TEST_IF_FALSE(ret < 0); - else + FAIL_TEST_IF_FALSE(errno == EPERM); + + size = get_vma_size(ptr + page_size * 2, &prot); + FAIL_TEST_IF_FALSE(size == 2 * page_size); + FAIL_TEST_IF_FALSE(prot == 0x4); + } else FAIL_TEST_IF_FALSE(!ret);
REPORT_TEST_PASS(); @@ -699,6 +773,7 @@ static void test_seal_mprotect_two_vma_with_split(bool seal) unsigned long page_size = getpagesize(); unsigned long size = 4 * page_size; int ret; + int prot;
setup_single_address(size, &ptr); FAIL_TEST_IF_FALSE(ptr != (void *)-1); @@ -719,17 +794,27 @@ static void test_seal_mprotect_two_vma_with_split(bool seal)
/* the second page is sealed. */ ret = sys_mprotect(ptr + page_size, page_size, PROT_READ | PROT_WRITE); - if (seal) + if (seal) { FAIL_TEST_IF_FALSE(ret < 0); - else + FAIL_TEST_IF_FALSE(errno == EPERM); + + size = get_vma_size(ptr, &prot); + FAIL_TEST_IF_FALSE(size == 1 * page_size); + FAIL_TEST_IF_FALSE(prot == 0x6); + } else FAIL_TEST_IF_FALSE(!ret);
/* the third page is sealed. */ ret = sys_mprotect(ptr + 2 * page_size, page_size, PROT_READ | PROT_WRITE); - if (seal) + if (seal) { FAIL_TEST_IF_FALSE(ret < 0); - else + FAIL_TEST_IF_FALSE(errno == EPERM); + + size = get_vma_size(ptr + 2 * page_size, &prot); + FAIL_TEST_IF_FALSE(size == 1 * page_size); + FAIL_TEST_IF_FALSE(prot == 0x4); + } else FAIL_TEST_IF_FALSE(!ret);
/* the fouth page is not sealed. */ @@ -746,6 +831,7 @@ static void test_seal_mprotect_partial_mprotect(bool seal) unsigned long page_size = getpagesize(); unsigned long size = 4 * page_size; int ret; + int prot;
setup_single_address(size, &ptr); FAIL_TEST_IF_FALSE(ptr != (void *)-1); @@ -758,9 +844,14 @@ static void test_seal_mprotect_partial_mprotect(bool seal)
/* mprotect first 2 page will fail, since the first page are sealed. */ ret = sys_mprotect(ptr, 2 * page_size, PROT_READ | PROT_WRITE); - if (seal) + if (seal) { FAIL_TEST_IF_FALSE(ret < 0); - else + FAIL_TEST_IF_FALSE(errno == EPERM); + + size = get_vma_size(ptr, &prot); + FAIL_TEST_IF_FALSE(size == 1 * page_size); + FAIL_TEST_IF_FALSE(prot == 0x4); + } else FAIL_TEST_IF_FALSE(!ret);
REPORT_TEST_PASS(); @@ -783,15 +874,15 @@ static void test_seal_mprotect_partial_mprotect_tail(bool seal) }
ret = sys_mprotect(ptr, size, PROT_EXEC); - if (seal) + if (seal) { FAIL_TEST_IF_FALSE(ret < 0); - else - FAIL_TEST_IF_FALSE(!ret); + FAIL_TEST_IF_FALSE(errno == EPERM);
- if (seal) { - FAIL_TEST_IF_FALSE(get_vma_size(ptr + page_size, &prot) > 0); + size = get_vma_size(ptr + page_size, &prot); + FAIL_TEST_IF_FALSE(size == 1 * page_size); FAIL_TEST_IF_FALSE(prot == 0x4); - } + } else + FAIL_TEST_IF_FALSE(!ret);
REPORT_TEST_PASS(); } @@ -846,6 +937,7 @@ static void test_seal_mprotect_split(bool seal) unsigned long page_size = getpagesize(); unsigned long size = 4 * page_size; int ret; + int prot;
setup_single_address(size, &ptr); FAIL_TEST_IF_FALSE(ptr != (void *)-1); @@ -862,16 +954,34 @@ static void test_seal_mprotect_split(bool seal)
/* mprotect is sealed. */ ret = sys_mprotect(ptr, 2 * page_size, PROT_READ); - if (seal) + if (seal) { FAIL_TEST_IF_FALSE(ret < 0); - else + FAIL_TEST_IF_FALSE(errno == EPERM); + + size = get_vma_size(ptr, &prot); + FAIL_TEST_IF_FALSE(size == 1 * page_size); + FAIL_TEST_IF_FALSE(prot == 0x6); + + size = get_vma_size(ptr + page_size, &prot); + FAIL_TEST_IF_FALSE(size == 3 * page_size); + FAIL_TEST_IF_FALSE(prot == 0x4); + } else FAIL_TEST_IF_FALSE(!ret);
ret = sys_mprotect(ptr + 2 * page_size, 2 * page_size, PROT_READ); - if (seal) + if (seal) { FAIL_TEST_IF_FALSE(ret < 0); - else + FAIL_TEST_IF_FALSE(errno == EPERM); + + size = get_vma_size(ptr, &prot); + FAIL_TEST_IF_FALSE(size == 1 * page_size); + FAIL_TEST_IF_FALSE(prot == 0x6); + + size = get_vma_size(ptr + page_size, &prot); + FAIL_TEST_IF_FALSE(size == 3 * page_size); + FAIL_TEST_IF_FALSE(prot == 0x4); + } else FAIL_TEST_IF_FALSE(!ret);
REPORT_TEST_PASS(); @@ -883,6 +993,7 @@ static void test_seal_mprotect_merge(bool seal) unsigned long page_size = getpagesize(); unsigned long size = 4 * page_size; int ret; + int prot;
setup_single_address(size, &ptr); FAIL_TEST_IF_FALSE(ptr != (void *)-1); @@ -899,9 +1010,18 @@ static void test_seal_mprotect_merge(bool seal)
/* 2 pages are sealed. */ ret = sys_mprotect(ptr, 2 * page_size, PROT_READ); - if (seal) + if (seal) { FAIL_TEST_IF_FALSE(ret < 0); - else + FAIL_TEST_IF_FALSE(errno == EPERM); + + size = get_vma_size(ptr, &prot); + FAIL_TEST_IF_FALSE(size == 1 * page_size); + FAIL_TEST_IF_FALSE(prot == 0x6); + + size = get_vma_size(ptr + page_size, &prot); + FAIL_TEST_IF_FALSE(size == 1 * page_size); + FAIL_TEST_IF_FALSE(prot == 0x4); + } else FAIL_TEST_IF_FALSE(!ret);
/* last 2 pages are not sealed. */ @@ -917,6 +1037,7 @@ static void test_seal_munmap(bool seal) unsigned long page_size = getpagesize(); unsigned long size = 4 * page_size; int ret; + int prot;
setup_single_address(size, &ptr); FAIL_TEST_IF_FALSE(ptr != (void *)-1); @@ -928,9 +1049,14 @@ static void test_seal_munmap(bool seal)
/* 4 pages are sealed. */ ret = sys_munmap(ptr, size); - if (seal) + if (seal) { FAIL_TEST_IF_FALSE(ret < 0); - else + FAIL_TEST_IF_FALSE(errno == EPERM); + + size = get_vma_size(ptr, &prot); + FAIL_TEST_IF_FALSE(size == 4 * page_size); + FAIL_TEST_IF_FALSE(prot == 0x4); + } else FAIL_TEST_IF_FALSE(!ret);
REPORT_TEST_PASS(); @@ -948,6 +1074,7 @@ static void test_seal_munmap_two_vma(bool seal) unsigned long page_size = getpagesize(); unsigned long size = 4 * page_size; int ret; + int prot;
setup_single_address(size, &ptr); FAIL_TEST_IF_FALSE(ptr != (void *)-1); @@ -962,15 +1089,33 @@ static void test_seal_munmap_two_vma(bool seal) }
ret = sys_munmap(ptr, page_size * 2); - if (seal) + if (seal) { FAIL_TEST_IF_FALSE(ret < 0); - else + FAIL_TEST_IF_FALSE(errno == EPERM); + + size = get_vma_size(ptr, &prot); + FAIL_TEST_IF_FALSE(size == 2 * page_size); + FAIL_TEST_IF_FALSE(prot == 0x6); + + size = get_vma_size(ptr + 2 * page_size, &prot); + FAIL_TEST_IF_FALSE(size == 2 * page_size); + FAIL_TEST_IF_FALSE(prot == 0x4); + } else FAIL_TEST_IF_FALSE(!ret);
ret = sys_munmap(ptr + page_size, page_size * 2); - if (seal) + if (seal) { FAIL_TEST_IF_FALSE(ret < 0); - else + FAIL_TEST_IF_FALSE(errno == EPERM); + + size = get_vma_size(ptr, &prot); + FAIL_TEST_IF_FALSE(size == 2 * page_size); + FAIL_TEST_IF_FALSE(prot == 0x6); + + size = get_vma_size(ptr + 2 * page_size, &prot); + FAIL_TEST_IF_FALSE(size == 2 * page_size); + FAIL_TEST_IF_FALSE(prot == 0x4); + } else FAIL_TEST_IF_FALSE(!ret);
REPORT_TEST_PASS(); @@ -1018,33 +1163,75 @@ static void test_seal_munmap_partial_across_vmas(bool seal) { void *ptr; unsigned long page_size = getpagesize(); - unsigned long size = 2 * page_size; + unsigned long size = 12 * page_size; int ret; int prot;
- /* - * Check if a partial mseal (that results in two vmas) works correctly. - * It might unmap the first, but it'll never unmap the second (msealed) vma. - */ - setup_single_address(size, &ptr); FAIL_TEST_IF_FALSE(ptr != (void *)-1);
if (seal) { - ret = sys_mseal(ptr + page_size, page_size); + ret = sys_mseal(ptr + 4 * page_size, 4 * page_size); FAIL_TEST_IF_FALSE(!ret); }
- ret = sys_munmap(ptr, size); - if (seal) + ret = sys_munmap(ptr, 12 * page_size); + if (seal) { FAIL_TEST_IF_FALSE(ret < 0); - else + FAIL_TEST_IF_FALSE(errno == EPERM); + + size = get_vma_size(ptr, &prot); + FAIL_TEST_IF_FALSE(size == 4 * page_size); + FAIL_TEST_IF_FALSE(prot == 0x4); + + size = get_vma_size(ptr + 4 * page_size, &prot); + FAIL_TEST_IF_FALSE(size == 4 * page_size); + FAIL_TEST_IF_FALSE(prot == 0x4); + + size = get_vma_size(ptr + 8 * page_size, &prot); + FAIL_TEST_IF_FALSE(size == 4 * page_size); + FAIL_TEST_IF_FALSE(prot == 0x4); + } else FAIL_TEST_IF_FALSE(!ret);
+ + ret = sys_munmap(ptr, 6 * page_size); if (seal) { - FAIL_TEST_IF_FALSE(get_vma_size(ptr + page_size, &prot) > 0); + FAIL_TEST_IF_FALSE(ret < 0); + FAIL_TEST_IF_FALSE(errno == EPERM); + + size = get_vma_size(ptr, &prot); + FAIL_TEST_IF_FALSE(size == 4 * page_size); + FAIL_TEST_IF_FALSE(prot == 0x4); + + size = get_vma_size(ptr + 4 * page_size, &prot); + FAIL_TEST_IF_FALSE(size == 4 * page_size); + FAIL_TEST_IF_FALSE(prot == 0x4); + + size = get_vma_size(ptr + 8 * page_size, &prot); + FAIL_TEST_IF_FALSE(size == 4 * page_size); + FAIL_TEST_IF_FALSE(prot == 0x4); + } else + FAIL_TEST_IF_FALSE(!ret); + + ret = sys_munmap(ptr + 6 * page_size, 6 * page_size); + if (seal) { + FAIL_TEST_IF_FALSE(ret < 0); + FAIL_TEST_IF_FALSE(errno == EPERM); + + size = get_vma_size(ptr, &prot); + FAIL_TEST_IF_FALSE(size == 4 * page_size); + FAIL_TEST_IF_FALSE(prot == 0x4); + + size = get_vma_size(ptr + 4 * page_size, &prot); + FAIL_TEST_IF_FALSE(size == 4 * page_size); FAIL_TEST_IF_FALSE(prot == 0x4); - } + + size = get_vma_size(ptr + 8 * page_size, &prot); + FAIL_TEST_IF_FALSE(size == 4 * page_size); + FAIL_TEST_IF_FALSE(prot == 0x4); + } else + FAIL_TEST_IF_FALSE(!ret);
REPORT_TEST_PASS(); } @@ -1074,9 +1261,11 @@ static void test_munmap_start_freed(bool seal) ret = sys_munmap(ptr, size); if (seal) { FAIL_TEST_IF_FALSE(ret < 0); + FAIL_TEST_IF_FALSE(errno == EPERM);
size = get_vma_size(ptr + page_size, &prot); - FAIL_TEST_IF_FALSE(size == page_size * 3); + FAIL_TEST_IF_FALSE(size == 3 * page_size); + FAIL_TEST_IF_FALSE(prot == 0x4); } else { /* note: this will be OK, even the first page is */ /* already unmapped. */ @@ -1095,6 +1284,7 @@ static void test_munmap_end_freed(bool seal) unsigned long page_size = getpagesize(); unsigned long size = 4 * page_size; int ret; + int prot;
setup_single_address(size, &ptr); FAIL_TEST_IF_FALSE(ptr != (void *)-1); @@ -1111,9 +1301,14 @@ static void test_munmap_end_freed(bool seal)
/* unmap all pages. */ ret = sys_munmap(ptr, size); - if (seal) + if (seal) { FAIL_TEST_IF_FALSE(ret < 0); - else + FAIL_TEST_IF_FALSE(errno == EPERM); + + size = get_vma_size(ptr, &prot); + FAIL_TEST_IF_FALSE(size == 3 * page_size); + FAIL_TEST_IF_FALSE(prot == 0x4); + } else FAIL_TEST_IF_FALSE(!ret);
REPORT_TEST_PASS(); @@ -1144,12 +1339,15 @@ static void test_munmap_middle_freed(bool seal) ret = sys_munmap(ptr, size); if (seal) { FAIL_TEST_IF_FALSE(ret < 0); + FAIL_TEST_IF_FALSE(errno == EPERM);
size = get_vma_size(ptr, &prot); FAIL_TEST_IF_FALSE(size == page_size); + FAIL_TEST_IF_FALSE(prot == 0x4);
size = get_vma_size(ptr + page_size * 3, &prot); FAIL_TEST_IF_FALSE(size == page_size); + FAIL_TEST_IF_FALSE(prot == 0x4); } else { FAIL_TEST_IF_FALSE(!ret);
@@ -1170,6 +1368,7 @@ static void test_seal_mremap_shrink(bool seal) unsigned long size = 4 * page_size; int ret; void *ret2; + int prot;
setup_single_address(size, &ptr); FAIL_TEST_IF_FALSE(ptr != (void *)-1); @@ -1184,6 +1383,10 @@ static void test_seal_mremap_shrink(bool seal) if (seal) { FAIL_TEST_IF_FALSE(ret2 == (void *) MAP_FAILED); FAIL_TEST_IF_FALSE(errno == EPERM); + + size = get_vma_size(ptr, &prot); + FAIL_TEST_IF_FALSE(size == 4 * page_size); + FAIL_TEST_IF_FALSE(prot == 0x4); } else { FAIL_TEST_IF_FALSE(ret2 != (void *) MAP_FAILED);
@@ -1199,6 +1402,7 @@ static void test_seal_mremap_expand(bool seal) unsigned long size = 4 * page_size; int ret; void *ret2; + int prot;
setup_single_address(size, &ptr); FAIL_TEST_IF_FALSE(ptr != (void *)-1); @@ -1216,6 +1420,10 @@ static void test_seal_mremap_expand(bool seal) if (seal) { FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED); FAIL_TEST_IF_FALSE(errno == EPERM); + + size = get_vma_size(ptr, &prot); + FAIL_TEST_IF_FALSE(size == 2 * page_size); + FAIL_TEST_IF_FALSE(prot == 0x4); } else { FAIL_TEST_IF_FALSE(ret2 == ptr);
@@ -1231,6 +1439,7 @@ static void test_seal_mremap_move(bool seal) unsigned long size = page_size; int ret; void *ret2; + int prot;
setup_single_address(size, &ptr); FAIL_TEST_IF_FALSE(ptr != (void *)-1); @@ -1249,10 +1458,12 @@ static void test_seal_mremap_move(bool seal) if (seal) { FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED); FAIL_TEST_IF_FALSE(errno == EPERM); - } else { - FAIL_TEST_IF_FALSE(ret2 != MAP_FAILED);
- } + size = get_vma_size(ptr, &prot); + FAIL_TEST_IF_FALSE(size == page_size); + FAIL_TEST_IF_FALSE(prot == 0x4); + } else + FAIL_TEST_IF_FALSE(ret2 != MAP_FAILED);
REPORT_TEST_PASS(); } @@ -1264,6 +1475,7 @@ static void test_seal_mmap_overwrite_prot(bool seal) unsigned long size = page_size; int ret; void *ret2; + int prot;
setup_single_address(size, &ptr); FAIL_TEST_IF_FALSE(ptr != (void *)-1); @@ -1279,6 +1491,10 @@ static void test_seal_mmap_overwrite_prot(bool seal) if (seal) { FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED); FAIL_TEST_IF_FALSE(errno == EPERM); + + size = get_vma_size(ptr, &prot); + FAIL_TEST_IF_FALSE(size == page_size); + FAIL_TEST_IF_FALSE(prot == 0x4); } else FAIL_TEST_IF_FALSE(ret2 == ptr);
@@ -1292,6 +1508,7 @@ static void test_seal_mmap_expand(bool seal) unsigned long size = 12 * page_size; int ret; void *ret2; + int prot;
setup_single_address(size, &ptr); FAIL_TEST_IF_FALSE(ptr != (void *)-1); @@ -1310,6 +1527,10 @@ static void test_seal_mmap_expand(bool seal) if (seal) { FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED); FAIL_TEST_IF_FALSE(errno == EPERM); + + size = get_vma_size(ptr, &prot); + FAIL_TEST_IF_FALSE(size == 8 * page_size); + FAIL_TEST_IF_FALSE(prot == 0x4); } else FAIL_TEST_IF_FALSE(ret2 == ptr);
@@ -1323,6 +1544,7 @@ static void test_seal_mmap_shrink(bool seal) unsigned long size = 12 * page_size; int ret; void *ret2; + int prot;
setup_single_address(size, &ptr); FAIL_TEST_IF_FALSE(ptr != (void *)-1); @@ -1338,6 +1560,10 @@ static void test_seal_mmap_shrink(bool seal) if (seal) { FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED); FAIL_TEST_IF_FALSE(errno == EPERM); + + size = get_vma_size(ptr, &prot); + FAIL_TEST_IF_FALSE(size == 12 * page_size); + FAIL_TEST_IF_FALSE(prot == 0x4); } else FAIL_TEST_IF_FALSE(ret2 == ptr);
@@ -1352,6 +1578,7 @@ static void test_seal_mremap_shrink_fixed(bool seal) unsigned long size = 4 * page_size; int ret; void *ret2; + int prot;
setup_single_address(size, &ptr); FAIL_TEST_IF_FALSE(ptr != (void *)-1); @@ -1369,6 +1596,10 @@ static void test_seal_mremap_shrink_fixed(bool seal) if (seal) { FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED); FAIL_TEST_IF_FALSE(errno == EPERM); + + size = get_vma_size(ptr, &prot); + FAIL_TEST_IF_FALSE(size == 4 * page_size); + FAIL_TEST_IF_FALSE(prot == 0x4); } else FAIL_TEST_IF_FALSE(ret2 == newAddr);
@@ -1383,6 +1614,7 @@ static void test_seal_mremap_expand_fixed(bool seal) unsigned long size = 4 * page_size; int ret; void *ret2; + int prot;
setup_single_address(page_size, &ptr); FAIL_TEST_IF_FALSE(ptr != (void *)-1); @@ -1400,6 +1632,10 @@ static void test_seal_mremap_expand_fixed(bool seal) if (seal) { FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED); FAIL_TEST_IF_FALSE(errno == EPERM); + + size = get_vma_size(newAddr, &prot); + FAIL_TEST_IF_FALSE(size == 4 * page_size); + FAIL_TEST_IF_FALSE(prot == 0x4); } else FAIL_TEST_IF_FALSE(ret2 == newAddr);
@@ -1414,6 +1650,7 @@ static void test_seal_mremap_move_fixed(bool seal) unsigned long size = 4 * page_size; int ret; void *ret2; + int prot;
setup_single_address(size, &ptr); FAIL_TEST_IF_FALSE(ptr != (void *)-1); @@ -1430,6 +1667,10 @@ static void test_seal_mremap_move_fixed(bool seal) if (seal) { FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED); FAIL_TEST_IF_FALSE(errno == EPERM); + + size = get_vma_size(newAddr, &prot); + FAIL_TEST_IF_FALSE(size == 4 * page_size); + FAIL_TEST_IF_FALSE(prot == 0x4); } else FAIL_TEST_IF_FALSE(ret2 == newAddr);
@@ -1443,6 +1684,7 @@ static void test_seal_mremap_move_fixed_zero(bool seal) unsigned long size = 4 * page_size; int ret; void *ret2; + int prot;
setup_single_address(size, &ptr); FAIL_TEST_IF_FALSE(ptr != (void *)-1); @@ -1460,9 +1702,12 @@ static void test_seal_mremap_move_fixed_zero(bool seal) if (seal) { FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED); FAIL_TEST_IF_FALSE(errno == EPERM); - } else { + + size = get_vma_size(ptr, &prot); + FAIL_TEST_IF_FALSE(size == 4 * page_size); + FAIL_TEST_IF_FALSE(prot == 0x4); + } else FAIL_TEST_IF_FALSE(ret2 == 0); - }
REPORT_TEST_PASS(); } @@ -1474,6 +1719,7 @@ static void test_seal_mremap_move_dontunmap(bool seal) unsigned long size = 4 * page_size; int ret; void *ret2; + int prot;
setup_single_address(size, &ptr); FAIL_TEST_IF_FALSE(ptr != (void *)-1); @@ -1488,6 +1734,10 @@ static void test_seal_mremap_move_dontunmap(bool seal) if (seal) { FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED); FAIL_TEST_IF_FALSE(errno == EPERM); + + size = get_vma_size(ptr, &prot); + FAIL_TEST_IF_FALSE(size == 4 * page_size); + FAIL_TEST_IF_FALSE(prot == 0x4); } else { /* kernel will allocate a new address */ FAIL_TEST_IF_FALSE(ret2 != MAP_FAILED); @@ -1503,6 +1753,7 @@ static void test_seal_mremap_move_dontunmap_anyaddr(bool seal) unsigned long size = 4 * page_size; int ret; void *ret2; + int prot;
setup_single_address(size, &ptr); FAIL_TEST_IF_FALSE(ptr != (void *)-1); @@ -1529,6 +1780,10 @@ static void test_seal_mremap_move_dontunmap_anyaddr(bool seal) if (seal) { FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED); FAIL_TEST_IF_FALSE(errno == EPERM); + + size = get_vma_size(ptr, &prot); + FAIL_TEST_IF_FALSE(size == 4 * page_size); + FAIL_TEST_IF_FALSE(prot == 0x4); } else { /* remap success and return ptr2 */ FAIL_TEST_IF_FALSE(ret2 == ptr2); @@ -1690,9 +1945,10 @@ static void test_seal_discard_ro_anon_on_pkey(bool seal) /* sealing will take effect if PKRU deny write. */ set_pkey(pkey, PKEY_DISABLE_WRITE); ret = sys_madvise(ptr, size, MADV_DONTNEED); - if (seal) + if (seal) { FAIL_TEST_IF_FALSE(ret < 0); - else + FAIL_TEST_IF_FALSE(errno == EPERM); + } else FAIL_TEST_IF_FALSE(!ret);
/* base seal still apply. */ @@ -1864,6 +2120,413 @@ static void test_seal_madvise_nodiscard(bool seal) REPORT_TEST_PASS(); }
+static void test_seal_discard_madvise_advice(void) +{ + void *ptr; + unsigned long page_size = getpagesize(); + unsigned long size = 4 * page_size; + int ret; + int sealed_advice[] = {MADV_FREE, MADV_DONTNEED, + MADV_DONTNEED_LOCKED, MADV_REMOVE, + MADV_DONTFORK, MADV_WIPEONFORK}; + int size_sealed_advice = sizeof(sealed_advice) / sizeof(int); + + setup_single_address(size, &ptr); + FAIL_TEST_IF_FALSE(ptr != (void *)-1); + + ret = seal_single_address(ptr, size); + FAIL_TEST_IF_FALSE(!ret); + + for (int i = 0; i < size_sealed_advice; i++) { + ret = sys_madvise(ptr, size, sealed_advice[i]); + FAIL_TEST_IF_FALSE(ret < 0); + FAIL_TEST_IF_FALSE(errno == EPERM); + } + + REPORT_TEST_PASS(); +} + +static void test_munmap_free_multiple_ranges(bool seal) +{ + void *ptr; + unsigned long page_size = getpagesize(); + unsigned long size = 8 * page_size; + int ret; + int prot; + + setup_single_address(size, &ptr); + FAIL_TEST_IF_FALSE(ptr != (void *)-1); + + /* unmap one page from beginning. */ + ret = sys_munmap(ptr, page_size); + FAIL_TEST_IF_FALSE(!ret); + + /* unmap one page from middle. */ + ret = sys_munmap(ptr + 4 * page_size, page_size); + FAIL_TEST_IF_FALSE(!ret); + + size = get_vma_size(ptr + page_size, &prot); + FAIL_TEST_IF_FALSE(size == 3 * page_size); + FAIL_TEST_IF_FALSE(prot == 4); + + size = get_vma_size(ptr + 5 * page_size, &prot); + FAIL_TEST_IF_FALSE(size == 3 * page_size); + FAIL_TEST_IF_FALSE(prot == 4); + + + /* seal the last page */ + if (seal) { + ret = sys_mseal(ptr + 7 * page_size, page_size); + FAIL_TEST_IF_FALSE(!ret); + + size = get_vma_size(ptr + 1 * page_size, &prot); + FAIL_TEST_IF_FALSE(size == 3 * page_size); + FAIL_TEST_IF_FALSE(prot == 4); + + size = get_vma_size(ptr + 5 * page_size, &prot); + FAIL_TEST_IF_FALSE(size == 2 * page_size); + FAIL_TEST_IF_FALSE(prot == 4); + + size = get_vma_size(ptr + 7 * page_size, &prot); + FAIL_TEST_IF_FALSE(size == 1 * page_size); + FAIL_TEST_IF_FALSE(prot == 4); + } + + /* munmap all 8 pages from beginning */ + ret = sys_munmap(ptr, 8 * page_size); + if (seal) { + FAIL_TEST_IF_FALSE(ret); + + size = get_vma_size(ptr + 1 * page_size, &prot); + FAIL_TEST_IF_FALSE(size == 3 * page_size); + FAIL_TEST_IF_FALSE(prot == 4); + + size = get_vma_size(ptr + 5 * page_size, &prot); + FAIL_TEST_IF_FALSE(size == 2 * page_size); + FAIL_TEST_IF_FALSE(prot == 4); + + size = get_vma_size(ptr + 7 * page_size, &prot); + FAIL_TEST_IF_FALSE(size == 1 * page_size); + FAIL_TEST_IF_FALSE(prot == 4); + } else { + FAIL_TEST_IF_FALSE(!ret); + + for (int i = 0; i < 8; i++) { + size = get_vma_size(ptr, &prot); + FAIL_TEST_IF_FALSE(size == 0); + } + } + + REPORT_TEST_PASS(); +} + +static void test_seal_mmap_expand_seal_middle(bool seal) +{ + void *ptr; + unsigned long page_size = getpagesize(); + unsigned long size = 12 * page_size; + int ret; + void *ret2; + int prot; + + setup_single_address(size, &ptr); + FAIL_TEST_IF_FALSE(ptr != (void *)-1); + /* ummap last 4 pages. */ + ret = sys_munmap(ptr + 8 * page_size, 4 * page_size); + FAIL_TEST_IF_FALSE(!ret); + + size = get_vma_size(ptr, &prot); + FAIL_TEST_IF_FALSE(size == 8 * page_size); + FAIL_TEST_IF_FALSE(prot == 0x4); + + if (seal) { + ret = sys_mseal(ptr + 4 * page_size, 4 * page_size); + FAIL_TEST_IF_FALSE(!ret); + } + + /* use mmap to expand. */ + ret2 = mmap(ptr, 12 * page_size, PROT_READ, + MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0); + if (seal) { + FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED); + FAIL_TEST_IF_FALSE(errno == EPERM); + + size = get_vma_size(ptr, &prot); + FAIL_TEST_IF_FALSE(size == 4 * page_size); + FAIL_TEST_IF_FALSE(prot == 0x4); + + size = get_vma_size(ptr + 4 * page_size, &prot); + FAIL_TEST_IF_FALSE(size == 4 * page_size); + FAIL_TEST_IF_FALSE(prot == 0x4); + } else + FAIL_TEST_IF_FALSE(ret2 == ptr); + + REPORT_TEST_PASS(); +} + +static void test_seal_mmap_shrink_seal_middle(bool seal) +{ + void *ptr; + unsigned long page_size = getpagesize(); + unsigned long size = 12 * page_size; + int ret; + void *ret2; + int prot; + + setup_single_address(size, &ptr); + FAIL_TEST_IF_FALSE(ptr != (void *)-1); + + if (seal) { + ret = sys_mseal(ptr + 4 * page_size, 4 * page_size); + FAIL_TEST_IF_FALSE(!ret); + } + + /* use mmap to shrink. */ + ret2 = mmap(ptr, 7 * page_size, PROT_READ, + MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0); + if (seal) { + FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED); + FAIL_TEST_IF_FALSE(errno == EPERM); + + size = get_vma_size(ptr, &prot); + FAIL_TEST_IF_FALSE(size == 4 * page_size); + FAIL_TEST_IF_FALSE(prot == 0x4); + + size = get_vma_size(ptr + 4 * page_size, &prot); + FAIL_TEST_IF_FALSE(size == 4 * page_size); + FAIL_TEST_IF_FALSE(prot == 0x4); + + size = get_vma_size(ptr + 4 * page_size, &prot); + FAIL_TEST_IF_FALSE(size == 4 * page_size); + FAIL_TEST_IF_FALSE(prot == 0x4); + } else + FAIL_TEST_IF_FALSE(ret2 == ptr); + + REPORT_TEST_PASS(); +} + +static void test_seal_mmap_overwrite_addr(bool seal) +{ + void *ptr; + unsigned long page_size = getpagesize(); + unsigned long size = page_size; + int ret; + void *ret2; + int prot; + + setup_single_address(size, &ptr); + FAIL_TEST_IF_FALSE(ptr != (void *)-1); + + if (seal) { + ret = sys_mseal(ptr, size); + FAIL_TEST_IF_FALSE(!ret); + } + + /* use mmap to change protection. */ + ret2 = mmap(ptr, size, PROT_NONE, + MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); + + FAIL_TEST_IF_FALSE(!(ret2 == MAP_FAILED)); + FAIL_TEST_IF_FALSE(ret2 != ptr); + + size = get_vma_size(ptr, &prot); + FAIL_TEST_IF_FALSE(size == page_size); + FAIL_TEST_IF_FALSE(prot == 0x4); + + REPORT_TEST_PASS(); +} + +static void test_seal_mremap_shrink_multiple_vmas(bool seal) +{ + void *ptr; + unsigned long page_size = getpagesize(); + unsigned long size = 12 * page_size; + int ret; + void *ret2; + int prot; + + setup_single_address(size, &ptr); + FAIL_TEST_IF_FALSE(ptr != (void *)-1); + + ret = sys_mprotect(ptr + 4 * page_size, 4 * page_size, PROT_NONE); + FAIL_TEST_IF_FALSE(!ret); + + size = get_vma_size(ptr, &prot); + FAIL_TEST_IF_FALSE(size == 4 * page_size); + + size = get_vma_size(ptr + 4 * page_size, &prot); + FAIL_TEST_IF_FALSE(size == 4 * page_size); + + if (seal) { + ret = sys_mseal(ptr + 4 * page_size, 4 * page_size); + FAIL_TEST_IF_FALSE(!ret); + } + + ret2 = sys_mremap(ptr, 12 * page_size, 6 * page_size, 0, 0); + if (seal) { + FAIL_TEST_IF_FALSE(ret2 == (void *) MAP_FAILED); + FAIL_TEST_IF_FALSE(errno == EPERM); + + size = get_vma_size(ptr, &prot); + FAIL_TEST_IF_FALSE(size == 4 * page_size); + + size = get_vma_size(ptr + 4 * page_size, &prot); + FAIL_TEST_IF_FALSE(size == 4 * page_size); + } else { + FAIL_TEST_IF_FALSE(ret2 == ptr); + + size = get_vma_size(ptr, &prot); + FAIL_TEST_IF_FALSE(size == 4 * page_size); + + size = get_vma_size(ptr + 4 * page_size, &prot); + FAIL_TEST_IF_FALSE(size == 2 * page_size); + } + + REPORT_TEST_PASS(); +} + +static void test_seal_mremap_expand_multiple_vmas(bool seal) +{ + void *ptr; + unsigned long page_size = getpagesize(); + unsigned long size = 12 * page_size; + int ret; + void *ret2; + int prot; + + setup_single_address(size, &ptr); + FAIL_TEST_IF_FALSE(ptr != (void *)-1); + + ret = sys_mprotect(ptr + 4 * page_size, 4 * page_size, PROT_NONE); + FAIL_TEST_IF_FALSE(!ret); + + /* ummap last 4 pages. */ + ret = sys_munmap(ptr + 8 * page_size, 4 * page_size); + FAIL_TEST_IF_FALSE(!ret); + + size = get_vma_size(ptr, &prot); + FAIL_TEST_IF_FALSE(size == 4 * page_size); + + size = get_vma_size(ptr + 4 * page_size, &prot); + FAIL_TEST_IF_FALSE(size == 4 * page_size); + + if (seal) { + ret = sys_mseal(ptr + 4 * page_size, 4 * page_size); + FAIL_TEST_IF_FALSE(!ret); + } + + ret2 = sys_mremap(ptr, 8 * page_size, 12 * page_size, 0, 0); + FAIL_TEST_IF_FALSE(ret2 == (void *) MAP_FAILED); + + size = get_vma_size(ptr, &prot); + FAIL_TEST_IF_FALSE(size == 4 * page_size); + + size = get_vma_size(ptr + 4 * page_size, &prot); + FAIL_TEST_IF_FALSE(size == 4 * page_size); + + REPORT_TEST_PASS(); +} + +static void test_seal_mremap_move_expand_multiple_vmas(bool seal) +{ + void *ptr; + unsigned long page_size = getpagesize(); + unsigned long size = 12 * page_size; + int ret; + void *ret2; + int prot; + void *ptr2; + + setup_single_address(size, &ptr); + FAIL_TEST_IF_FALSE(ptr != (void *)-1); + + setup_single_address(size, &ptr2); + FAIL_TEST_IF_FALSE(ptr2 != (void *)-1); + + ret = sys_munmap(ptr2, 12 * page_size); + FAIL_TEST_IF_FALSE(!ret); + + ret = sys_mprotect(ptr + 4 * page_size, 4 * page_size, PROT_NONE); + FAIL_TEST_IF_FALSE(!ret); + + /* ummap last 4 pages. */ + ret = sys_munmap(ptr + 8 * page_size, 4 * page_size); + FAIL_TEST_IF_FALSE(!ret); + + size = get_vma_size(ptr, &prot); + FAIL_TEST_IF_FALSE(size == 4 * page_size); + + size = get_vma_size(ptr + 4 * page_size, &prot); + FAIL_TEST_IF_FALSE(size == 4 * page_size); + + if (seal) { + ret = sys_mseal(ptr + 4 * page_size, 4 * page_size); + FAIL_TEST_IF_FALSE(!ret); + } + + /* move and expand cross VMA boundary will fail */ + ret2 = sys_mremap(ptr, 8 * page_size, 10 * page_size, MREMAP_FIXED | MREMAP_MAYMOVE, ptr2); + FAIL_TEST_IF_FALSE(ret2 == (void *) MAP_FAILED); + + size = get_vma_size(ptr, &prot); + FAIL_TEST_IF_FALSE(size == 4 * page_size); + + size = get_vma_size(ptr + 4 * page_size, &prot); + FAIL_TEST_IF_FALSE(size == 4 * page_size); + + REPORT_TEST_PASS(); +} + +static void test_seal_mremap_move_shrink_multiple_vmas(bool seal) +{ + void *ptr; + unsigned long page_size = getpagesize(); + unsigned long size = 12 * page_size; + int ret; + void *ret2; + int prot; + void *ptr2; + + setup_single_address(size, &ptr); + FAIL_TEST_IF_FALSE(ptr != (void *)-1); + + setup_single_address(size, &ptr2); + FAIL_TEST_IF_FALSE(ptr2 != (void *)-1); + + ret = sys_munmap(ptr2, 12 * page_size); + FAIL_TEST_IF_FALSE(!ret); + + ret = sys_mprotect(ptr + 4 * page_size, 4 * page_size, PROT_NONE); + FAIL_TEST_IF_FALSE(!ret); + + size = get_vma_size(ptr, &prot); + FAIL_TEST_IF_FALSE(size == 4 * page_size); + FAIL_TEST_IF_FALSE(prot == 4); + + size = get_vma_size(ptr + 4 * page_size, &prot); + FAIL_TEST_IF_FALSE(size == 4 * page_size); + FAIL_TEST_IF_FALSE(prot == 0); + + if (seal) { + ret = sys_mseal(ptr + 4 * page_size, 4 * page_size); + FAIL_TEST_IF_FALSE(!ret); + } + + /* move and shrink cross VMA boundary is NOK */ + ret2 = sys_mremap(ptr, 12 * page_size, 8 * page_size, MREMAP_FIXED | MREMAP_MAYMOVE, ptr2); + FAIL_TEST_IF_FALSE(ret2 == (void *) MAP_FAILED); + + size = get_vma_size(ptr, &prot); + FAIL_TEST_IF_FALSE(size == 4 * page_size); + FAIL_TEST_IF_FALSE(prot == 4); + + size = get_vma_size(ptr + 4 * page_size, &prot); + FAIL_TEST_IF_FALSE(size == 4 * page_size); + FAIL_TEST_IF_FALSE(prot == 0); + + REPORT_TEST_PASS(); +} + int main(int argc, char **argv) { bool test_seal = seal_support(); @@ -1876,7 +2539,15 @@ int main(int argc, char **argv) if (!pkey_supported()) ksft_print_msg("PKEY not supported\n");
- ksft_set_plan(88); + /* + * possible reasons: + * - unable to read /proc/pid/maps + * - parsing error when reading /proc/pid/maps,e.g. len is not expected. + */ + if (!get_vma_size_supported()) + ksft_exit_skip("get_vma_size not supported\n"); + + ksft_set_plan(105);
test_seal_addseal(); test_seal_unmapped_start(); @@ -1985,5 +2656,26 @@ int main(int argc, char **argv) test_seal_discard_ro_anon_on_pkey(false); test_seal_discard_ro_anon_on_pkey(true);
+ test_seal_discard_madvise_advice(); + + test_munmap_free_multiple_ranges(false); + test_munmap_free_multiple_ranges(true); + + test_seal_mmap_expand_seal_middle(false); + test_seal_mmap_expand_seal_middle(true); + test_seal_mmap_shrink_seal_middle(false); + test_seal_mmap_shrink_seal_middle(true); + test_seal_mmap_overwrite_addr(false); + test_seal_mmap_overwrite_addr(true); + + test_seal_mremap_shrink_multiple_vmas(false); + test_seal_mremap_shrink_multiple_vmas(true); + test_seal_mremap_expand_multiple_vmas(false); + test_seal_mremap_expand_multiple_vmas(true); + test_seal_mremap_move_expand_multiple_vmas(false); + test_seal_mremap_move_expand_multiple_vmas(true); + test_seal_mremap_move_shrink_multiple_vmas(false); + test_seal_mremap_move_shrink_multiple_vmas(true); + ksft_finished(); }
HI Andrew
On Wed, Aug 28, 2024 at 3:55 PM jeffxu@chromium.org wrote:
From: Jeff Xu jeffxu@chromium.org
Add more testcases and increase test coverage, e.g. add get_vma_size to check VMA size and prot bits.
Could you please pull the self-test part of this patch series to mm-unstable ? It will help to prevent regression.
The first part ([PATCH v1 1/2] mseal: fix mmap(FIXED) error code) can be ignored as Liam proposed to fix it differently.
Thanks -Jeff
-Jeff
Signed-off-by: Jeff Xu jeffxu@chromium.org
tools/testing/selftests/mm/mseal_test.c | 826 ++++++++++++++++++++++-- 1 file changed, 759 insertions(+), 67 deletions(-)
diff --git a/tools/testing/selftests/mm/mseal_test.c b/tools/testing/selftests/mm/mseal_test.c index e7991e5fdcf3..4b3f883aae17 100644 --- a/tools/testing/selftests/mm/mseal_test.c +++ b/tools/testing/selftests/mm/mseal_test.c
On Thu, Aug 29, 2024 at 07:45:56AM GMT, Jeff Xu wrote:
HI Andrew
On Wed, Aug 28, 2024 at 3:55 PM jeffxu@chromium.org wrote:
From: Jeff Xu jeffxu@chromium.org
Add more testcases and increase test coverage, e.g. add get_vma_size to check VMA size and prot bits.
This commit message is ridiculously short for such a massive change, even for test code.
Could you please pull the self-test part of this patch series to mm-unstable ? It will help to prevent regression.
No, please don't.
This needs review.
These tests establish a precedent as to how mseal should behave, this is something that needs community review, not to just be taken.
There's already been a great deal of confusion/contentious discussion around mseal() and its implementation.
Pushing in ~800 lines of test code asserting how mseal() should behave without review isn't helping things.
Also, this is a really unusual way to send a series - why is this a 2/2 in reply to the 1/2 and no cover letter? Why is this change totally unrelated to the other patch?
Can you send this as a separate patch, preferably as an RFC so we can ensure that we all agree on how mseal() should behave?
Sorry to be contentious here, but I think we need to find a more constructive, collaborative way forward with mseal() and to act with a little more caution, given the problems that the original series has caused I'd think this is in the best interests of all.
Thanks for understanding!
The first part ([PATCH v1 1/2] mseal: fix mmap(FIXED) error code) can be ignored as Liam proposed to fix it differently.
Thanks -Jeff
-Jeff
Signed-off-by: Jeff Xu jeffxu@chromium.org
tools/testing/selftests/mm/mseal_test.c | 826 ++++++++++++++++++++++-- 1 file changed, 759 insertions(+), 67 deletions(-)
diff --git a/tools/testing/selftests/mm/mseal_test.c b/tools/testing/selftests/mm/mseal_test.c index e7991e5fdcf3..4b3f883aae17 100644 --- a/tools/testing/selftests/mm/mseal_test.c +++ b/tools/testing/selftests/mm/mseal_test.c
Hi Lorenzo
On Thu, Aug 29, 2024 at 8:14 AM Lorenzo Stoakes lorenzo.stoakes@oracle.com wrote:
On Thu, Aug 29, 2024 at 07:45:56AM GMT, Jeff Xu wrote:
HI Andrew
On Wed, Aug 28, 2024 at 3:55 PM jeffxu@chromium.org wrote:
From: Jeff Xu jeffxu@chromium.org
Add more testcases and increase test coverage, e.g. add get_vma_size to check VMA size and prot bits.
This commit message is ridiculously short for such a massive change, even for test code.
Could you please pull the self-test part of this patch series to mm-unstable ? It will help to prevent regression.
No, please don't.
This needs review.
These tests establish a precedent as to how mseal should behave, this is something that needs community review, not to just be taken.
There's already been a great deal of confusion/contentious discussion around mseal() and its implementation.
Pushing in ~800 lines of test code asserting how mseal() should behave without review isn't helping things.
Also, this is a really unusual way to send a series - why is this a 2/2 in reply to the 1/2 and no cover letter? Why is this change totally unrelated to the other patch?
Can you send this as a separate patch, preferably as an RFC so we can ensure that we all agree on how mseal() should behave?
Sorry to be contentious here, but I think we need to find a more constructive, collaborative way forward with mseal() and to act with a little more caution, given the problems that the original series has caused I'd think this is in the best interests of all.
Thanks for understanding!
There have been two bugs I found recently on mseal. One during V2 of in-loop change and the other mentioned in 1/2 of this patch.
These additional tests will increase the test coverage of mseal and ensure the functionality of in-loop change is correct, also help to detect future regression.
If you feel it will take time to review the test case, please do so and comment on the tests itself directly, I will send V2 after that.
Thanks -Jeff
The first part ([PATCH v1 1/2] mseal: fix mmap(FIXED) error code) can be ignored as Liam proposed to fix it differently.
Thanks -Jeff
-Jeff
Signed-off-by: Jeff Xu jeffxu@chromium.org
tools/testing/selftests/mm/mseal_test.c | 826 ++++++++++++++++++++++-- 1 file changed, 759 insertions(+), 67 deletions(-)
diff --git a/tools/testing/selftests/mm/mseal_test.c b/tools/testing/selftests/mm/mseal_test.c index e7991e5fdcf3..4b3f883aae17 100644 --- a/tools/testing/selftests/mm/mseal_test.c +++ b/tools/testing/selftests/mm/mseal_test.c
On Thu, Aug 29, 2024 at 08:30:11AM GMT, Jeff Xu wrote:
Hi Lorenzo
On Thu, Aug 29, 2024 at 8:14 AM Lorenzo Stoakes lorenzo.stoakes@oracle.com wrote:
On Thu, Aug 29, 2024 at 07:45:56AM GMT, Jeff Xu wrote:
HI Andrew
On Wed, Aug 28, 2024 at 3:55 PM jeffxu@chromium.org wrote:
From: Jeff Xu jeffxu@chromium.org
Add more testcases and increase test coverage, e.g. add get_vma_size to check VMA size and prot bits.
This commit message is ridiculously short for such a massive change, even for test code.
Could you please pull the self-test part of this patch series to mm-unstable ? It will help to prevent regression.
No, please don't.
This needs review.
These tests establish a precedent as to how mseal should behave, this is something that needs community review, not to just be taken.
There's already been a great deal of confusion/contentious discussion around mseal() and its implementation.
Pushing in ~800 lines of test code asserting how mseal() should behave without review isn't helping things.
Also, this is a really unusual way to send a series - why is this a 2/2 in reply to the 1/2 and no cover letter? Why is this change totally unrelated to the other patch?
Can you send this as a separate patch, preferably as an RFC so we can ensure that we all agree on how mseal() should behave?
Sorry to be contentious here, but I think we need to find a more constructive, collaborative way forward with mseal() and to act with a little more caution, given the problems that the original series has caused I'd think this is in the best interests of all.
Thanks for understanding!
There have been two bugs I found recently on mseal. One during V2 of in-loop change and the other mentioned in 1/2 of this patch.
Jeff you've ignored pretty much everything I've said here. This is not collaboration. And you keep doing this + causing disharmony among other devleopers. It's getting tiresome, and you need to do better.
If you insist on review for this patch as it stands - NACK.
The commit message is ludicriously short, you've not sent the series correctly, and you are ignoring feedback.
Resend this with a substantially improved commit message and ideally some actual comments in your tests rather than a giant lump of code which constitutes 'how Jeff feels mseal() should work'.
Then when people give feedback - listen.
Hi Lorenzo
On Thu, Aug 29, 2024 at 8:44 AM Lorenzo Stoakes lorenzo.stoakes@oracle.com wrote:
Also, this is a really unusual way to send a series - why is this a 2/2 in reply to the 1/2 and no cover letter? Why is this change totally unrelated to the other patch?
1/2 has a fix that 2/2 is depending on. That is the reason they are together.
Can you send this as a separate patch, preferably as an RFC so we can ensure that we all agree on how mseal() should behave?
It is not an RFC because it doesn't change any semanic to mseal. The updated test will pass on linux main as well as 6.10. The increased coverage will help to prevent future regression, i.e. during refactoring.
I will add a cover letter, split the tests and add more comments to help the review.
Thanks -Jeff
On Thu, Aug 29, 2024 at 12:54:09PM -0700, Jeff Xu wrote:
Hi Lorenzo
On Thu, Aug 29, 2024 at 8:44 AM Lorenzo Stoakes lorenzo.stoakes@oracle.com wrote:
Also, this is a really unusual way to send a series - why is this a 2/2 in reply to the 1/2 and no cover letter? Why is this change totally unrelated to the other patch?
1/2 has a fix that 2/2 is depending on. That is the reason they are together.
The normal way to send out these patches is as three emails; a 0/2 cover letter, 1/2 replying to 0/2 and 2/2 also replying to 0/2. That's what has Lorenzo confused.
Can you send this as a separate patch, preferably as an RFC so we can ensure that we all agree on how mseal() should behave?
It is not an RFC because it doesn't change any semanic to mseal. The updated test will pass on linux main as well as 6.10. The increased coverage will help to prevent future regression, i.e. during refactoring.
You seem to not understand that there is disagreement on the semantics of mseal(). I mean, ther's been a lot of arguing about that over the last week. There's understanable reluctance to accept a large pile of tests saying "this just ensures that mseal behaves the way I think it should", when there is substantial disagreement that the way you think it should behave is in fact the way it should behave. Be prepared to argue for each semantic that you think it should have.
I will add a cover letter, split the tests and add more comments to help the review.
Thank you.
Hi Matthew
On Thu, Aug 29, 2024 at 12:58 PM Matthew Wilcox willy@infradead.org wrote:
Can you send this as a separate patch, preferably as an RFC so we can ensure that we all agree on how mseal() should behave?
It is not an RFC because it doesn't change any semanic to mseal. The updated test will pass on linux main as well as 6.10. The increased coverage will help to prevent future regression, i.e. during refactoring.
You seem to not understand that there is disagreement on the semantics of mseal(). I mean, ther's been a lot of arguing about that over the last week. There's understanable reluctance to accept a large pile of tests saying "this just ensures that mseal behaves the way I think it should", when there is substantial disagreement that the way you think it should behave is in fact the way it should behave. Be prepared to argue for each semantic that you think it should have.
If this is about in-loop discussion, this patch also passes the latest mm-unstable branch which has in-loop change (pending Liam's fix on mmap). The increased test coverage also helps to ensure the in-loop change's correctness on sealing.
I'm not aware there are other semantic changes on mseal, we can continue this discussion on V2 patch, if necessary.
Thanks -Jeff
On Wed, Aug 28, 2024 at 10:55:22PM +0000, jeffxu@chromium.org wrote:
Add more testcases and increase test coverage, e.g. add get_vma_size to check VMA size and prot bits.
I think this needs to be split into multiple patches, for example the new test cases done separately to the additions to the existing ones, possibly as multiple patches (eg, should the size changes be split from the prot ones?).
On Thu, Aug 29, 2024 at 05:16:50PM GMT, Mark Brown wrote:
On Wed, Aug 28, 2024 at 10:55:22PM +0000, jeffxu@chromium.org wrote:
Add more testcases and increase test coverage, e.g. add get_vma_size to check VMA size and prot bits.
I think this needs to be split into multiple patches, for example the new test cases done separately to the additions to the existing ones, possibly as multiple patches (eg, should the size changes be split from the prot ones?).
Agree wholeheartedly.
Hi Mark
On Thu, Aug 29, 2024 at 9:16 AM Mark Brown broonie@kernel.org wrote:
On Wed, Aug 28, 2024 at 10:55:22PM +0000, jeffxu@chromium.org wrote:
Add more testcases and increase test coverage, e.g. add get_vma_size to check VMA size and prot bits.
I think this needs to be split into multiple patches, for example the new test cases done separately to the additions to the existing ones, possibly as multiple patches (eg, should the size changes be split from the prot ones?).
The size check should go with prot., because it is part of verifying the sealed VMAs. I will split the patch into updating existing tests and adding new tests.
Thanks -Jeff
+CC vma reviewers On Wed, Aug 28, 2024 at 10:55:21PM GMT, jeffxu@chromium.org wrote:
From: Jeff Xu jeffxu@chromium.org
mmap(MAP_FIXED) should return EPERM when memory is sealed.
Fixes: 4205a39e06da ("mm/munmap: replace can_modify_mm with can_modify_vma")
Thank you for the patch! This Fixes: is wrong, the bug was added during Liam's rebasing of his munmap patch set on mine.
Signed-off-by: Jeff Xu jeffxu@chromium.org
mm/mmap.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/mm/mmap.c b/mm/mmap.c index 80d70ed099cf..0cd0c0ef03c7 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -1386,7 +1386,10 @@ unsigned long mmap_region(struct file *file, unsigned long addr, mt_on_stack(mt_detach); mas_init(&mas_detach, &mt_detach, /* addr = */ 0); /* Prepare to unmap any existing mapping in the area */
if (vms_gather_munmap_vmas(&vms, &mas_detach))
error = vms_gather_munmap_vmas(&vms, &mas_detach);
if (error == -EPERM)
return -EPERM;
Not sure if it makes sense to special case this. We should probably deal with this inside vms_gather_munmap_vmas and just pass through the error we get.
Otherwise LGTM. Liam?
(we should also squash this into the offending commit)
* Pedro Falcato pedro.falcato@gmail.com [240828 19:38]:
+CC vma reviewers On Wed, Aug 28, 2024 at 10:55:21PM GMT, jeffxu@chromium.org wrote:
From: Jeff Xu jeffxu@chromium.org
mmap(MAP_FIXED) should return EPERM when memory is sealed.
Thanks for the fix and finding the issue. Please email the maintainers of the file as well as the patch author next time.
Fixes: 4205a39e06da ("mm/munmap: replace can_modify_mm with can_modify_vma")
Thank you for the patch! This Fixes: is wrong, the bug was added during Liam's rebasing of his munmap patch set on mine.
Right now, the akpm/mm-unstable git id of the patch this needs to squash into is 5887a7ac23836. Although, this will leave intermittent patches to return the incorrect error code.
Initially it was introduced in commit c2eb22189bbc9, so I'd like to fix this in the series so that it doesn't show up in any bisection.
Signed-off-by: Jeff Xu jeffxu@chromium.org
mm/mmap.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/mm/mmap.c b/mm/mmap.c index 80d70ed099cf..0cd0c0ef03c7 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -1386,7 +1386,10 @@ unsigned long mmap_region(struct file *file, unsigned long addr, mt_on_stack(mt_detach); mas_init(&mas_detach, &mt_detach, /* addr = */ 0); /* Prepare to unmap any existing mapping in the area */
if (vms_gather_munmap_vmas(&vms, &mas_detach))
error = vms_gather_munmap_vmas(&vms, &mas_detach);
if (error == -EPERM)
return -EPERM;
Not sure if it makes sense to special case this. We should probably deal with this inside vms_gather_munmap_vmas and just pass through the error we get.
Otherwise LGTM. Liam?
(we should also squash this into the offending commit)
All code paths that exist today in vms_gather_munmap_vmas() can only return -EPERM and -ENOMEM. So filtering isn't really necessary right now. But then again, vms_gather_munmap_vmas() is only used in two places and this filters one return, but not the other.
I think it best to address this in vms_gather_munmap_vmas() to only return -ENOMEM or -EPERM.
I will fix this in my series, thanks Jeff.
Regards, Liam
On Thu, Aug 29, 2024 at 7:03 AM Liam R. Howlett Liam.Howlett@oracle.com wrote:
I will fix this in my series, thanks Jeff.
Sure.
-Jeff
Regards, Liam
On Wed, Aug 28, 2024 at 4:38 PM Pedro Falcato pedro.falcato@gmail.com wrote:
+CC vma reviewers On Wed, Aug 28, 2024 at 10:55:21PM GMT, jeffxu@chromium.org wrote:
From: Jeff Xu jeffxu@chromium.org
mmap(MAP_FIXED) should return EPERM when memory is sealed.
Fixes: 4205a39e06da ("mm/munmap: replace can_modify_mm with can_modify_vma")
Thank you for the patch! This Fixes: is wrong, the bug was added during Liam's rebasing of his munmap patch set on mine.
ok.
Signed-off-by: Jeff Xu jeffxu@chromium.org
mm/mmap.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/mm/mmap.c b/mm/mmap.c index 80d70ed099cf..0cd0c0ef03c7 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -1386,7 +1386,10 @@ unsigned long mmap_region(struct file *file, unsigned long addr, mt_on_stack(mt_detach); mas_init(&mas_detach, &mt_detach, /* addr = */ 0); /* Prepare to unmap any existing mapping in the area */
if (vms_gather_munmap_vmas(&vms, &mas_detach))
error = vms_gather_munmap_vmas(&vms, &mas_detach);
if (error == -EPERM)
return -EPERM;
Not sure if it makes sense to special case this. We should probably deal with this inside vms_gather_munmap_vmas and just pass through the error we get.
Otherwise LGTM. Liam?
(we should also squash this into the offending commit)
-- Pedro
Jeff... come on now.
Please cc- the reviewers of mm/mmap.c on these patches - that's me, Vlastimil and Liam. Same for mm/vma.c, mm/vma.h, mm/vma_internal.h.
And it seems like it should be pretty obvious you should cc- Liam when it's quite literally his code you're changing!
Relevant section from MAINTAINERS:
MEMORY MAPPING M: Andrew Morton akpm@linux-foundation.org R: Liam R. Howlett Liam.Howlett@oracle.com R: Vlastimil Babka vbabka@suse.cz R: Lorenzo Stoakes lorenzo.stoakes@oracle.com L: linux-mm@kvack.org S: Maintained W: http://www.linux-mm.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm F: mm/mmap.c
On Wed, Aug 28, 2024 at 10:55:21PM GMT, jeffxu@chromium.org wrote:
From: Jeff Xu jeffxu@chromium.org
mmap(MAP_FIXED) should return EPERM when memory is sealed.
Fixes: 4205a39e06da ("mm/munmap: replace can_modify_mm with can_modify_vma") Signed-off-by: Jeff Xu jeffxu@chromium.org
mm/mmap.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/mm/mmap.c b/mm/mmap.c index 80d70ed099cf..0cd0c0ef03c7 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -1386,7 +1386,10 @@ unsigned long mmap_region(struct file *file, unsigned long addr, mt_on_stack(mt_detach); mas_init(&mas_detach, &mt_detach, /* addr = */ 0); /* Prepare to unmap any existing mapping in the area */
if (vms_gather_munmap_vmas(&vms, &mas_detach))
error = vms_gather_munmap_vmas(&vms, &mas_detach);
if (error == -EPERM)
return -EPERM;
if (error) return -ENOMEM;
Can't we just return the error here?
This is one for Liam, but I'm ostensibly in favour, this does seem valid!
vmg.next = vms.next;
-- 2.46.0.295.g3b9ea8a38a-goog
On Thu, Aug 29, 2024 at 5:09 AM Lorenzo Stoakes lorenzo.stoakes@oracle.com wrote:
Jeff... come on now.
Please cc- the reviewers of mm/mmap.c on these patches - that's me, Vlastimil and Liam. Same for mm/vma.c, mm/vma.h, mm/vma_internal.h.
sure, that was a small fix and I thought introduced by Pedro's commit (which was wrong)
And it seems like it should be pretty obvious you should cc- Liam when it's quite literally his code you're changing!
Relevant section from MAINTAINERS:
MEMORY MAPPING M: Andrew Morton akpm@linux-foundation.org R: Liam R. Howlett Liam.Howlett@oracle.com R: Vlastimil Babka vbabka@suse.cz R: Lorenzo Stoakes lorenzo.stoakes@oracle.com L: linux-mm@kvack.org S: Maintained W: http://www.linux-mm.org T: git git://git.kernel.org/pub/scm/linux/kernel/git/akpm/mm F: mm/mmap.c
On Wed, Aug 28, 2024 at 10:55:21PM GMT, jeffxu@chromium.org wrote:
From: Jeff Xu jeffxu@chromium.org
mmap(MAP_FIXED) should return EPERM when memory is sealed.
Fixes: 4205a39e06da ("mm/munmap: replace can_modify_mm with can_modify_vma") Signed-off-by: Jeff Xu jeffxu@chromium.org
mm/mmap.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/mm/mmap.c b/mm/mmap.c index 80d70ed099cf..0cd0c0ef03c7 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -1386,7 +1386,10 @@ unsigned long mmap_region(struct file *file, unsigned long addr, mt_on_stack(mt_detach); mas_init(&mas_detach, &mt_detach, /* addr = */ 0); /* Prepare to unmap any existing mapping in the area */
if (vms_gather_munmap_vmas(&vms, &mas_detach))
error = vms_gather_munmap_vmas(&vms, &mas_detach);
if (error == -EPERM)
return -EPERM;
if (error) return -ENOMEM;
Can't we just return the error here?
This is one for Liam, but I'm ostensibly in favour, this does seem valid!
vmg.next = vms.next;
-- 2.46.0.295.g3b9ea8a38a-goog
On Thu, 29 Aug 2024 13:09:41 +0100 Lorenzo Stoakes lorenzo.stoakes@oracle.com wrote:
Relevant section from MAINTAINERS:
MEMORY MAPPING
I always thought it meant "memory management" ;)
On Fri, Aug 30, 2024 at 06:15:46PM GMT, Andrew Morton wrote:
On Thu, 29 Aug 2024 13:09:41 +0100 Lorenzo Stoakes lorenzo.stoakes@oracle.com wrote:
Relevant section from MAINTAINERS:
MEMORY MAPPING
I always thought it meant "memory management" ;)
Ha ha no, I leave the managing to you, we just map and pray! ;)
linux-kselftest-mirror@lists.linaro.org