From 332c1bd17422c1aa59e18513042e56ea5aac4051 Mon Sep 17 00:00:00 2001 From: Danish Khateeb Date: Thu, 22 Oct 2026 07:18:37 -0500 Subject: [PATCH] selftests/mm: merge: keep the far mremap() targets in the carveout The merge tests map their areas at fixed addresses within a 30-page PROT_NONE carveout. Several mremap() tests move an area 1000 or 2000 pages away to separate it from the others, but those targets are outside the carveout, and MREMAP_FIXED unmaps whatever is mapped there. Under virtme-ng, the shared libraries are packed right above the carveout and the dynamic linker starts about 4 MiB above it. The moves then replace part of its text with an anonymous mapping, and the test crashes in its next lazily bound call: merge[6980]: segfault at 7f7ebb3c1e60 ip 00007f7ebb3c1e60 sp 00007ffd35fbaec8 error 14 Two to four of the mremap() tests then fail with "Test terminated unexpectedly by signal 11", depending on the exact layout. On a host where libc is mapped at a 2 MiB aligned address, the targets happen to land above the dynamic linker and the tests pass. Since the areas are all within the first 30 pages, moving one by 30 pages is enough to keep it apart from the others. Add FAR_PAGES for that distance, move areas by FAR_PAGES or 2 * FAR_PAGES pages, and make the carveout 3 * FAR_PAGES pages so that it covers every target. Link: https://lore.kernel.org/20261022121837.28723-1-danishkhateeb03@gmail.com Fixes: 4e25f85b9f85 ("tools/testing/selftests: add mremap() unfaulted/faulted test cases") Signed-off-by: Danish Khateeb Signed-off-by: Andrew Morton Reviewed-by: Lorenzo Stoakes (ARM) Reviewed-by: Gregory Price (Meta) Cc: Liam R. Howlett Cc: Vlastimil Babka Cc: Jann Horn Cc: Pedro Falcato Cc: David Hildenbrand Cc: Mike Rapoport Cc: Suren Baghdasaryan Cc: Michal Hocko Cc: Shuah Khan --- tools/testing/selftests/mm/merge.c | 33 ++++++++++++++++-------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/tools/testing/selftests/mm/merge.c b/tools/testing/selftests/mm/merge.c index 7dd2933417c1..6def490186a9 100644 --- a/tools/testing/selftests/mm/merge.c +++ b/tools/testing/selftests/mm/merge.c @@ -22,9 +22,12 @@ FIXTURE(merge) struct procmap_fd procmap; }; +#define FAR_PAGES 30 +#define CARVEOUT_PAGES (3 * FAR_PAGES) + static char *map_carveout(unsigned int page_size) { - return mmap(NULL, 30 * page_size, PROT_NONE, + return mmap(NULL, CARVEOUT_PAGES * page_size, PROT_NONE, MAP_ANON | MAP_PRIVATE, -1, 0); } @@ -73,7 +76,7 @@ FIXTURE_SETUP(merge) FIXTURE_TEARDOWN(merge) { - ASSERT_EQ(munmap(self->carveout, 30 * self->page_size), 0); + ASSERT_EQ(munmap(self->carveout, CARVEOUT_PAGES * self->page_size), 0); /* May fail for parent of forked process. */ close_procmap(&self->procmap); /* @@ -115,7 +118,7 @@ FIXTURE_SETUP(merge_with_fork) FIXTURE_TEARDOWN(merge_with_fork) { - ASSERT_EQ(munmap(self->carveout, 30 * self->page_size), 0); + ASSERT_EQ(munmap(self->carveout, CARVEOUT_PAGES * self->page_size), 0); ASSERT_EQ(close_procmap(&self->procmap), 0); /* See above. */ prctl(PR_SET_MEMORY_MERGE, 0, 0, 0, 0); @@ -660,7 +663,7 @@ TEST_F(merge, mremap_unfaulted_to_faulted) /* Offset ptr2 further away. */ ptr2 = sys_mremap(ptr2, 5 * page_size, 5 * page_size, - MREMAP_MAYMOVE | MREMAP_FIXED, ptr2 + page_size * 1000); + MREMAP_MAYMOVE | MREMAP_FIXED, ptr2 + FAR_PAGES * page_size); ASSERT_NE(ptr2, MAP_FAILED); /* @@ -721,7 +724,7 @@ TEST_F(merge, mremap_unfaulted_behind_faulted) /* Offset ptr2 further away. */ ptr2 = sys_mremap(ptr2, 5 * page_size, 5 * page_size, - MREMAP_MAYMOVE | MREMAP_FIXED, ptr2 + page_size * 1000); + MREMAP_MAYMOVE | MREMAP_FIXED, ptr2 + FAR_PAGES * page_size); ASSERT_NE(ptr2, MAP_FAILED); /* @@ -785,12 +788,12 @@ TEST_F(merge, mremap_unfaulted_between_faulted) /* Offset ptr3 further away. */ ptr3 = sys_mremap(ptr3, 5 * page_size, 5 * page_size, - MREMAP_MAYMOVE | MREMAP_FIXED, ptr3 + page_size * 2000); + MREMAP_MAYMOVE | MREMAP_FIXED, ptr3 + 2 * FAR_PAGES * page_size); ASSERT_NE(ptr3, MAP_FAILED); /* Offset ptr2 further away. */ ptr2 = sys_mremap(ptr2, 5 * page_size, 5 * page_size, - MREMAP_MAYMOVE | MREMAP_FIXED, ptr2 + page_size * 1000); + MREMAP_MAYMOVE | MREMAP_FIXED, ptr2 + FAR_PAGES * page_size); ASSERT_NE(ptr2, MAP_FAILED); /* @@ -870,13 +873,13 @@ TEST_F(merge, mremap_unfaulted_between_faulted_unfaulted) /* Offset ptr3 further away. */ ptr3 = sys_mremap(ptr3, 5 * page_size, 5 * page_size, - MREMAP_MAYMOVE | MREMAP_FIXED, ptr3 + page_size * 2000); + MREMAP_MAYMOVE | MREMAP_FIXED, ptr3 + 2 * FAR_PAGES * page_size); ASSERT_NE(ptr3, MAP_FAILED); /* Offset ptr2 further away. */ ptr2 = sys_mremap(ptr2, 5 * page_size, 5 * page_size, - MREMAP_MAYMOVE | MREMAP_FIXED, ptr2 + page_size * 1000); + MREMAP_MAYMOVE | MREMAP_FIXED, ptr2 + FAR_PAGES * page_size); ASSERT_NE(ptr2, MAP_FAILED); /* @@ -1035,11 +1038,11 @@ TEST_F(merge, mremap_correct_placed_faulted) */ ptr3 = &ptr[10 * page_size]; ptr3 = sys_mremap(ptr3, 5 * page_size, 5 * page_size, - MREMAP_MAYMOVE | MREMAP_FIXED, ptr3 + page_size * 2000); + MREMAP_MAYMOVE | MREMAP_FIXED, ptr3 + 2 * FAR_PAGES * page_size); ASSERT_NE(ptr3, MAP_FAILED); ptr2 = &ptr[5 * page_size]; ptr2 = sys_mremap(ptr2, 5 * page_size, 5 * page_size, - MREMAP_MAYMOVE | MREMAP_FIXED, ptr2 + page_size * 1000); + MREMAP_MAYMOVE | MREMAP_FIXED, ptr2 + FAR_PAGES * page_size); ASSERT_NE(ptr2, MAP_FAILED); /* @@ -1075,7 +1078,7 @@ TEST_F(merge, mremap_correct_placed_faulted) * ptr2 \ ptr \ ptr3 */ ptr = sys_mremap(ptr, 5 * page_size, 5 * page_size, - MREMAP_MAYMOVE | MREMAP_FIXED, ptr + page_size * 1000); + MREMAP_MAYMOVE | MREMAP_FIXED, ptr + FAR_PAGES * page_size); ASSERT_NE(ptr, MAP_FAILED); /* @@ -1110,7 +1113,7 @@ TEST_F(merge, mremap_correct_placed_faulted) * ptr2 \ ptr \ ptr3 */ ptr = sys_mremap(ptr, 5 * page_size, 5 * page_size, - MREMAP_MAYMOVE | MREMAP_FIXED, ptr + page_size * 1000); + MREMAP_MAYMOVE | MREMAP_FIXED, ptr + FAR_PAGES * page_size); ASSERT_NE(ptr, MAP_FAILED); /* @@ -1168,7 +1171,7 @@ TEST_F(merge, mremap_correct_placed_faulted) * ptr ptr3 \ ptr2 */ ptr2 = sys_mremap(ptr2, 5 * page_size, 5 * page_size, - MREMAP_MAYMOVE | MREMAP_FIXED, ptr2 + page_size * 1000); + MREMAP_MAYMOVE | MREMAP_FIXED, ptr2 + FAR_PAGES * page_size); ASSERT_NE(ptr2, MAP_FAILED); /* @@ -1203,7 +1206,7 @@ TEST_F(merge, mremap_correct_placed_faulted) * ptr \ ptr3 */ ptr3 = sys_mremap(ptr3, 5 * page_size, 5 * page_size, - MREMAP_MAYMOVE | MREMAP_FIXED, ptr3 + page_size * 1000); + MREMAP_MAYMOVE | MREMAP_FIXED, ptr3 + FAR_PAGES * page_size); ASSERT_NE(ptr3, MAP_FAILED); /*