On Wed, Oct 16, 2024 at 7:26 PM jeffxu@chromium.org wrote:
From: Jeff Xu jeffxu@google.com
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