On Wed, Oct 16, 2024 at 7:26 PM <jeffxu@xxxxxxxxxxxx> wrote: > > From: Jeff Xu <jeffxu@xxxxxxxxxx> > > It appears there is a regression on the latest mm, > when munmap seals memory, it can cause an unexpected VMA split. > E.g. repro use this test. It appears that this test has some dependency tests that haven't been merged, so can't be run as is. This is the repro step: - Allocate 12 pages (0-11). - Seal middle 4 pages (4567) - munmap (2345) - this will fail Seeing VMA for page (0123) is split as 2 VMAs (01)-(23), those 2 VMA have the same attribute, and should be merged as one. > --- > tools/testing/selftests/mm/mseal_test.c | 76 +++++++++++++++++++++++++ > 1 file changed, 76 insertions(+) > > diff --git a/tools/testing/selftests/mm/mseal_test.c b/tools/testing/selftests/mm/mseal_test.c > index fa74dbe4a684..0af33e13b606 100644 > --- a/tools/testing/selftests/mm/mseal_test.c > +++ b/tools/testing/selftests/mm/mseal_test.c > @@ -1969,6 +1969,79 @@ static void test_madvise_filebacked_was_writable(bool seal) > REPORT_TEST_PASS(); > } > > +static void test_munmap_free_multiple_ranges_with_split(bool seal) > +{ > + void *ptr; > + unsigned long page_size = getpagesize(); > + unsigned long size = 12 * page_size; > + int ret; > + int prot; > + > + setup_single_address(size, &ptr); > + FAIL_TEST_IF_FALSE(ptr != (void *)-1); > + > + /* seal the middle 4 page */ > + if (seal) { > + ret = sys_mseal(ptr + 4 * page_size, 4 * page_size); > + 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 == 4); > + > + size = get_vma_size(ptr + 8 * page_size, &prot); > + FAIL_TEST_IF_FALSE(size == 4 * page_size); > + FAIL_TEST_IF_FALSE(prot == 4); > + } > + > + /* munmap 4 pages from the third page */ > + ret = sys_munmap(ptr + 2 * page_size, 4 * page_size); > + if (seal) { > + FAIL_TEST_IF_FALSE(ret); > + 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 == 4); > + > + size = get_vma_size(ptr + 8 * page_size, &prot); > + FAIL_TEST_IF_FALSE(size == 4 * page_size); > + FAIL_TEST_IF_FALSE(prot == 4); > + } else > + FAIL_TEST_IF_FALSE(!ret); > + > + /* munmap 4 pages from the sealed page */ > + ret = sys_munmap(ptr + 6 * page_size, 4 * page_size); > + if (seal) { > + FAIL_TEST_IF_FALSE(ret); > + FAIL_TEST_IF_FALSE(errno == EPERM); > + > + size = get_vma_size(ptr + 4 * page_size, &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 == 4); > + > + size = get_vma_size(ptr + 8 * page_size, &prot); > + FAIL_TEST_IF_FALSE(size == 4 * page_size); > + FAIL_TEST_IF_FALSE(prot == 4); > + } else > + FAIL_TEST_IF_FALSE(!ret); > + > + REPORT_TEST_PASS(); > +} > + > + > int main(int argc, char **argv) > { > bool test_seal = seal_support(); > @@ -2099,5 +2172,8 @@ int main(int argc, char **argv) > test_madvise_filebacked_was_writable(false); > test_madvise_filebacked_was_writable(true); > > + test_munmap_free_multiple_ranges_with_split(false); > + test_munmap_free_multiple_ranges_with_split(true); > + > ksft_finished(); > } > -- > 2.47.0.rc1.288.g06298d1525-goog >