From: Jeff Xu jeffxu@chromium.org
Add selftest to mremap across VMA boundaries, i.e. mremap will fail.
Signed-off-by: Jeff Xu jeffxu@chromium.org --- tools/testing/selftests/mm/mseal_test.c | 293 +++++++++++++++++++++++- 1 file changed, 292 insertions(+), 1 deletion(-)
diff --git a/tools/testing/selftests/mm/mseal_test.c b/tools/testing/selftests/mm/mseal_test.c index 5bce2fe102ab..422cf90fb56c 100644 --- a/tools/testing/selftests/mm/mseal_test.c +++ b/tools/testing/selftests/mm/mseal_test.c @@ -1482,6 +1482,47 @@ static void test_seal_mremap_move_dontunmap_anyaddr(bool seal) REPORT_TEST_PASS(); }
+static void test_seal_mremap_move_dontunmap_allocated(bool seal) +{ + void *ptr, *ptr2; + unsigned long page_size = getpagesize(); + unsigned long size = 4 * page_size; + int ret; + void *ret2; + + setup_single_address(size, &ptr); + FAIL_TEST_IF_FALSE(ptr != (void *)-1); + + if (seal) { + ret = sys_mseal(ptr, size); + FAIL_TEST_IF_FALSE(!ret); + } + + /* + * The new address is allocated. + */ + setup_single_address(size, &ptr2); + FAIL_TEST_IF_FALSE(ptr2 != (void *)-1); + + /* + * remap to allocated address. + */ + ret2 = sys_mremap(ptr, size, size, MREMAP_MAYMOVE | MREMAP_DONTUNMAP, + (void *) ptr2); + if (seal) { + FAIL_TEST_IF_FALSE(ret2 == MAP_FAILED); + FAIL_TEST_IF_FALSE(errno == EPERM); + } else { + /* remap success and but it won't be ptr2 */ + FAIL_TEST_IF_FALSE(!(ret2 == MAP_FAILED)); + FAIL_TEST_IF_FALSE(ret2 != ptr2); + } + + REPORT_TEST_PASS(); +} + + + static void test_seal_merge_and_split(void) { void *ptr; @@ -1746,6 +1787,239 @@ static void test_seal_discard_ro_anon(bool seal) 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); + 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 == 0x0); + } 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); + if (seal) { + 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 == 0x4); + + size = get_vma_size(ptr + 4 * page_size, &prot); + FAIL_TEST_IF_FALSE(size == 4 * page_size); + FAIL_TEST_IF_FALSE(prot == 0x0); + } else { + 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); + if (seal) { + 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 == 0x4); + + size = get_vma_size(ptr + 4 * page_size, &prot); + FAIL_TEST_IF_FALSE(size == 4 * page_size); + FAIL_TEST_IF_FALSE(prot == 0x0); + } else { + 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 == 0x4); + + size = get_vma_size(ptr + 4 * page_size, &prot); + FAIL_TEST_IF_FALSE(size == 4 * page_size); + FAIL_TEST_IF_FALSE(prot == 0x0); + } + + 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); + 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 == 4); + + size = get_vma_size(ptr + 4 * page_size, &prot); + FAIL_TEST_IF_FALSE(size == 4 * page_size); + FAIL_TEST_IF_FALSE(prot == 0); + } else { + 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(); @@ -1758,7 +2032,7 @@ int main(int argc, char **argv) if (!pkey_supported()) ksft_print_msg("PKEY not supported\n");
- ksft_set_plan(80); + ksft_set_plan(91);
test_seal_addseal(); test_seal_unmapped_start(); @@ -1835,8 +2109,12 @@ int main(int argc, char **argv) test_seal_mremap_move_dontunmap(true); test_seal_mremap_move_fixed_zero(false); test_seal_mremap_move_fixed_zero(true); + test_seal_mremap_move_dontunmap_anyaddr(false); test_seal_mremap_move_dontunmap_anyaddr(true); + test_seal_mremap_move_dontunmap_allocated(false); + test_seal_mremap_move_dontunmap_allocated(true); + test_seal_discard_ro_anon(false); test_seal_discard_ro_anon(true); test_seal_discard_ro_anon_on_rw(false); @@ -1858,5 +2136,18 @@ int main(int argc, char **argv) test_seal_discard_ro_anon_on_pkey(false); test_seal_discard_ro_anon_on_pkey(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(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(); }