AI Trajectory


Trajectory: (Expand/Collapse All)
Seq Timestamp Type Name Duration
0/0 2026/11/02 21:06 flow patch-triage
0m Args:
null

Results:
{
  "EnableConfigs": null,
  "FocusSymbols": [],
  "KMSANReasoning": "",
  "NeedsKMSAN": false,
  "Reasoning": "The patch only modifies user-space selftest code (tools/testing/selftests/mm/mremap_test.c) and does not affect the compiled kernel image or any kernel-space executable code.",
  "WorthFuzzing": false
}

1/1 2026/11/02 21:06 action read-patch-diff
0m Args:
null

Results:
{
  "PatchDiff": "commit f5ed3e338e82ef1f7bdfff316667eb25cc2666f8\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate:   Mon Nov 2 21:06:19 2026 +0000\n\n    syz-cluster: applied patch under review\n\ndiff --git a/tools/testing/selftests/mm/mremap_test.c b/tools/testing/selftests/mm/mremap_test.c\nindex 31b484517bda61..b83c5797a2d8a5 100644\n--- a/tools/testing/selftests/mm/mremap_test.c\n+++ b/tools/testing/selftests/mm/mremap_test.c\n@@ -13,8 +13,8 @@\n #include \u003csys/ioctl.h\u003e\n #include \u003csys/mman.h\u003e\n #include \u003csyscall.h\u003e\n-#include \u003ctime.h\u003e\n #include \u003cstdbool.h\u003e\n+#include \u003cstdint.h\u003e\n \n #include \"kselftest.h\"\n \n@@ -22,14 +22,7 @@\n #define EXPECT_FAILURE 1\n #define NON_OVERLAPPING 0\n #define OVERLAPPING 1\n-#define NS_PER_SEC 1000000000ULL\n-#define VALIDATION_DEFAULT_THRESHOLD 4\t/* 4MB */\n-#define VALIDATION_NO_THRESHOLD 0\t/* Verify the entire region */\n-\n-#ifndef MIN\n-#define MIN(X, Y) ((X) \u003c (Y) ? (X) : (Y))\n-#define MAX(X, Y) ((X) \u003e (Y) ? (X) : (Y))\n-#endif\n+\n #define SIZE_MB(m) ((size_t)m * (1024 * 1024))\n #define SIZE_KB(k) ((size_t)k * 1024)\n \n@@ -129,13 +122,14 @@ static unsigned long long get_mmap_min_addr(void)\n }\n \n /*\n- * Using /proc/self/maps, assert that the specified address range is contained\n- * within a single mapping.\n+ * Using /proc/self/maps, check whether the specified address range is contained\n+ * within a single mapping with the expected permissions, if supplied.\n  */\n-static bool is_range_mapped(FILE *maps_fp, unsigned long start,\n-\t\t\t    unsigned long end)\n+static bool is_range_mapped_with_perms(FILE *maps_fp, unsigned long start,\n+\t\tunsigned long end, const char *expected_perms)\n {\n \tchar *line = NULL;\n+\tchar perms[5];\n \tsize_t len = 0;\n \tbool success = false;\n \tunsigned long first_val, second_val;\n@@ -143,12 +137,13 @@ static bool is_range_mapped(FILE *maps_fp, unsigned long start,\n \trewind(maps_fp);\n \n \twhile (getline(\u0026line, \u0026len, maps_fp) != -1) {\n-\t\tif (sscanf(line, \"%lx-%lx\", \u0026first_val, \u0026second_val) != 2) {\n+\t\tif (sscanf(line, \"%lx-%lx %4s\", \u0026first_val, \u0026second_val, perms) != 3) {\n \t\t\tksft_exit_fail_msg(\"cannot parse /proc/self/maps\\n\");\n \t\t\tbreak;\n \t\t}\n \n-\t\tif (first_val \u003c= start \u0026\u0026 second_val \u003e= end) {\n+\t\tif (first_val \u003c= start \u0026\u0026 second_val \u003e= end \u0026\u0026\n+\t\t    (!expected_perms || !strcmp(perms, expected_perms))) {\n \t\t\tsuccess = true;\n \t\t\tfflush(maps_fp);\n \t\t\tbreak;\n@@ -159,6 +154,12 @@ static bool is_range_mapped(FILE *maps_fp, unsigned long start,\n \treturn success;\n }\n \n+static bool is_range_mapped(FILE *maps_fp, unsigned long start,\n+\t\t\t    unsigned long end)\n+{\n+\treturn is_range_mapped_with_perms(maps_fp, start, end, NULL);\n+}\n+\n /* Check if [ptr, ptr + size) mapped in /proc/self/maps. */\n static bool is_ptr_mapped(FILE *maps_fp, void *ptr, unsigned long size)\n {\n@@ -168,6 +169,20 @@ static bool is_ptr_mapped(FILE *maps_fp, void *ptr, unsigned long size)\n \treturn is_range_mapped(maps_fp, start, end);\n }\n \n+/*\n+ * Check if [ptr, ptr + size) is mapped with the required permissions in\n+ * /proc/self/maps.\n+ */\n+static bool is_ptr_mapped_with_perms(FILE *maps_fp, void *ptr,\n+\t\t\t\t     unsigned long size,\n+\t\t\t\t     const char *expected_perms)\n+{\n+\tunsigned long start = (unsigned long)ptr;\n+\tunsigned long end = start + size;\n+\n+\treturn is_range_mapped_with_perms(maps_fp, start, end, expected_perms);\n+}\n+\n /*\n  * Returns the start address of the mapping on success, else returns\n  * NULL on failure.\n@@ -257,10 +272,7 @@ static void mremap_expand_merge(FILE *maps_fp, unsigned long page_size)\n \tmunmap(start, 3 * page_size);\n \n out:\n-\tif (success)\n-\t\tksft_test_result_pass(\"%s\\n\", test_name);\n-\telse\n-\t\tksft_test_result_fail(\"%s\\n\", test_name);\n+\tksft_test_result(success, \"%s\\n\", test_name);\n }\n \n /*\n@@ -297,10 +309,7 @@ static void mremap_expand_merge_offset(FILE *maps_fp, unsigned long page_size)\n \tmunmap(start, 3 * page_size);\n \n out:\n-\tif (success)\n-\t\tksft_test_result_pass(\"%s\\n\", test_name);\n-\telse\n-\t\tksft_test_result_fail(\"%s\\n\", test_name);\n+\tksft_test_result(success, \"%s\\n\", test_name);\n }\n \n /*\n@@ -317,17 +326,17 @@ static void mremap_expand_merge_offset(FILE *maps_fp, unsigned long page_size)\n  *\n  * |DDDDddddSSSSssss|\n  */\n-static void mremap_move_within_range(unsigned int pattern_seed, char *rand_addr)\n+static void mremap_move_within_range(char *pattern_addr)\n {\n-\tchar *test_name = \"mremap mremap move within range\";\n+\tchar *test_name = \"mremap move within range\";\n \tvoid *src, *dest;\n-\tunsigned int i, success = 1;\n+\tunsigned int success = 1;\n \n \tsize_t size = SIZE_MB(20);\n \tvoid *ptr = mmap(NULL, size, PROT_READ | PROT_WRITE,\n \t\t\t MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);\n \tif (ptr == MAP_FAILED) {\n-\t\tperror(\"mmap\");\n+\t\tksft_perror(\"mmap\");\n \t\tsuccess = 0;\n \t\tgoto out;\n \t}\n@@ -337,68 +346,71 @@ static void mremap_move_within_range(unsigned int pattern_seed, char *rand_addr)\n \tsrc = (void *)((unsigned long)src \u0026 ~(SIZE_MB(2) - 1));\n \n \t/* Set byte pattern for source block. */\n-\tmemcpy(src, rand_addr, SIZE_MB(2));\n+\tmemcpy(src, pattern_addr + SIZE_MB(2), SIZE_MB(2));\n \n \tdest = src - SIZE_MB(2);\n \n \tvoid *new_ptr = mremap(src + SIZE_MB(1), SIZE_MB(1), SIZE_MB(1),\n-\t\t\t\t\t\t   MREMAP_MAYMOVE | MREMAP_FIXED, dest + SIZE_MB(1));\n+\t\t\t       MREMAP_MAYMOVE | MREMAP_FIXED, dest + SIZE_MB(1));\n \tif (new_ptr == MAP_FAILED) {\n-\t\tperror(\"mremap\");\n+\t\tksft_perror(\"mremap\");\n \t\tsuccess = 0;\n-\t\tgoto out;\n+\t\tgoto out_unmap;\n \t}\n \n \t/* Verify byte pattern after remapping */\n-\tsrand(pattern_seed);\n-\tfor (i = 0; i \u003c SIZE_MB(1); i++) {\n-\t\tchar c = (char) rand();\n-\n-\t\tif (((char *)src)[i] != c) {\n-\t\t\tksft_print_msg(\"Data at src at %d got corrupted due to unrelated mremap\\n\",\n-\t\t\t\t       i);\n-\t\t\tksft_print_msg(\"Expected: %#x\\t Got: %#x\\n\", c \u0026 0xff,\n-\t\t\t\t\t((char *) src)[i] \u0026 0xff);\n-\t\t\tsuccess = 0;\n-\t\t}\n+\tif (memcmp(src, pattern_addr + SIZE_MB(2), SIZE_MB(1))) {\n+\t\tksft_print_msg(\"Source data was corrupted\\n\");\n+\t\tsuccess = 0;\n \t}\n \n+out_unmap:\n+\tmunmap(ptr, size);\n out:\n-\tif (munmap(ptr, size) == -1)\n-\t\tperror(\"munmap\");\n-\n-\tif (success)\n-\t\tksft_test_result_pass(\"%s\\n\", test_name);\n-\telse\n-\t\tksft_test_result_fail(\"%s\\n\", test_name);\n+\tksft_test_result(success, \"%s\\n\", test_name);\n }\n \n-static bool is_multiple_vma_range_ok(unsigned int pattern_seed,\n-\t\t\t\t     char *ptr, unsigned long page_size)\n+static bool is_multiple_vma_range_ok(FILE *maps_fp, char *pattern_addr,\n+\t\t\t\t     char *ptr, unsigned long page_size,\n+\t\t\t\t     bool expect_gaps_mapped)\n {\n-\tint i;\n+\tfor (int i = 0; i \u003c= 10; i++) {\n \n-\tsrand(pattern_seed);\n-\tfor (i = 0; i \u003c= 10; i += 2) {\n-\t\tint j;\n-\t\tchar *buf = \u0026ptr[i * page_size];\n-\t\tsize_t size = i == 4 ? 2 * page_size : page_size;\n-\n-\t\tfor (j = 0; j \u003c size; j++) {\n-\t\t\tchar chr = rand();\n+\t\tif (i == 5)\n+\t\t\tcontinue;\n \n-\t\t\tif (chr != buf[j]) {\n-\t\t\t\tksft_print_msg(\"page %d offset %d corrupted, expected %d got %d\\n\",\n-\t\t\t\t\t       i, j, chr, buf[j]);\n+\t\t/* Odd pages correspond to gaps between the source VMAs. */\n+\t\tif (i \u0026 1) {\n+\t\t\tif (expect_gaps_mapped) {\n+\t\t\t\tif (!is_ptr_mapped_with_perms(maps_fp,\n+\t\t\t\t\t\t\t      ptr + i * page_size,\n+\t\t\t\t\t\t\t      page_size, \"---p\")) {\n+\t\t\t\t\tksft_print_msg(\"Page %d PROT_NONE mapping overwritten\\n\",\n+\t\t\t\t\t\t       i);\n+\t\t\t\t\treturn false;\n+\t\t\t\t}\n+\t\t\t} else if (is_ptr_mapped(maps_fp, ptr + i * page_size,\n+\t\t\t\t\t\t page_size)) {\n+\t\t\t\tksft_print_msg(\"Page %d is unexpectedly mapped\\n\", i);\n \t\t\t\treturn false;\n \t\t\t}\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\tsize_t size = i == 4 ? 2 * page_size : page_size;\n+\n+\t\tif (memcmp(ptr + i * page_size, pattern_addr + i * page_size,\n+\t\t\t   size)) {\n+\t\t\tksft_print_msg(\"Data in VMA starting at page %d got corrupted\\n\",\n+\t\t\t\t       i);\n+\t\t\treturn false;\n \t\t}\n \t}\n \n \treturn true;\n }\n \n-static void mremap_move_multiple_vmas(unsigned int pattern_seed,\n+static void mremap_move_multiple_vmas(FILE *maps_fp, char *pattern_addr,\n \t\t\t\t      unsigned long page_size,\n \t\t\t\t      bool dont_unmap)\n {\n@@ -415,7 +427,7 @@ static void mremap_move_multiple_vmas(unsigned int pattern_seed,\n \tptr = mmap(NULL, size, PROT_READ | PROT_WRITE,\n \t\t   MAP_PRIVATE | MAP_ANON, -1, 0);\n \tif (ptr == MAP_FAILED) {\n-\t\tperror(\"mmap\");\n+\t\tksft_perror(\"mmap\");\n \t\tsuccess = false;\n \t\tgoto out;\n \t}\n@@ -423,55 +435,46 @@ static void mremap_move_multiple_vmas(unsigned int pattern_seed,\n \ttgt_ptr = mmap(NULL, 2 * size, PROT_READ | PROT_WRITE,\n \t\t       MAP_PRIVATE | MAP_ANON, -1, 0);\n \tif (tgt_ptr == MAP_FAILED) {\n-\t\tperror(\"mmap\");\n+\t\tksft_perror(\"mmap\");\n \t\tsuccess = false;\n-\t\tgoto out;\n+\t\tgoto out_unmap_src;\n \t}\n \tif (munmap(tgt_ptr, 2 * size)) {\n-\t\tperror(\"munmap\");\n+\t\tksft_perror(\"munmap\");\n \t\tsuccess = false;\n \t\tgoto out_unmap;\n \t}\n \n+\tmemcpy(ptr, pattern_addr, size);\n+\n \t/*\n \t * Unmap so we end up with:\n \t *\n \t *  0   2   4 5 6   8   10 offset in buffer\n \t * |*| |*| |*****| |*| |*|\n \t * |*| |*| |*****| |*| |*|\n-\t *  0   1   2 3 4   5   6  pattern offset\n+\t *  0   2   4 5 6   8   10  pattern offset\n \t */\n \tfor (i = 1; i \u003c 10; i += 2) {\n \t\tif (i == 5)\n \t\t\tcontinue;\n \n \t\tif (munmap(\u0026ptr[i * page_size], page_size)) {\n-\t\t\tperror(\"munmap\");\n+\t\t\tksft_perror(\"munmap\");\n \t\t\tsuccess = false;\n \t\t\tgoto out_unmap;\n \t\t}\n \t}\n \n-\tsrand(pattern_seed);\n-\n-\t/* Set up random patterns. */\n-\tfor (i = 0; i \u003c= 10; i += 2) {\n-\t\tint j;\n-\t\tsize_t size = i == 4 ? 2 * page_size : page_size;\n-\t\tchar *buf = \u0026ptr[i * page_size];\n-\n-\t\tfor (j = 0; j \u003c size; j++)\n-\t\t\tbuf[j] = rand();\n-\t}\n-\n \t/* First, just move the whole thing. */\n \tif (mremap(ptr, size, size, mremap_flags, tgt_ptr) == MAP_FAILED) {\n-\t\tperror(\"mremap\");\n+\t\tksft_perror(\"mremap\");\n \t\tsuccess = false;\n \t\tgoto out_unmap;\n \t}\n \t/* Check move was ok. */\n-\tif (!is_multiple_vma_range_ok(pattern_seed, tgt_ptr, page_size)) {\n+\tif (!is_multiple_vma_range_ok(maps_fp, pattern_addr, tgt_ptr,\n+\t\t\t\t      page_size, false)) {\n \t\tsuccess = false;\n \t\tgoto out_unmap;\n \t}\n@@ -479,12 +482,13 @@ static void mremap_move_multiple_vmas(unsigned int pattern_seed,\n \t/* Move next to itself. */\n \tif (mremap(tgt_ptr, size, size, mremap_flags,\n \t\t   \u0026tgt_ptr[size]) == MAP_FAILED) {\n-\t\tperror(\"mremap\");\n+\t\tksft_perror(\"mremap\");\n \t\tsuccess = false;\n \t\tgoto out_unmap;\n \t}\n \t/* Check that the move is ok. */\n-\tif (!is_multiple_vma_range_ok(pattern_seed, \u0026tgt_ptr[size], page_size)) {\n+\tif (!is_multiple_vma_range_ok(maps_fp, pattern_addr, \u0026tgt_ptr[size],\n+\t\t\t\t      page_size, false)) {\n \t\tsuccess = false;\n \t\tgoto out_unmap;\n \t}\n@@ -492,36 +496,30 @@ static void mremap_move_multiple_vmas(unsigned int pattern_seed,\n \t/* Map a range to overwrite. */\n \tif (mmap(tgt_ptr, size, PROT_NONE,\n \t\t MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0) == MAP_FAILED) {\n-\t\tperror(\"mmap tgt\");\n+\t\tksft_perror(\"mmap tgt\");\n \t\tsuccess = false;\n \t\tgoto out_unmap;\n \t}\n \t/* Move and overwrite. */\n \tif (mremap(\u0026tgt_ptr[size], size, size,\n \t\t   mremap_flags, tgt_ptr) == MAP_FAILED) {\n-\t\tperror(\"mremap\");\n+\t\tksft_perror(\"mremap\");\n \t\tsuccess = false;\n \t\tgoto out_unmap;\n \t}\n \t/* Check that the move is ok. */\n-\tif (!is_multiple_vma_range_ok(pattern_seed, tgt_ptr, page_size)) {\n+\tif (!is_multiple_vma_range_ok(maps_fp, pattern_addr, tgt_ptr,\n+\t\t\t\t      page_size, true)) {\n \t\tsuccess = false;\n \t\tgoto out_unmap;\n \t}\n \n out_unmap:\n-\tif (munmap(tgt_ptr, 2 * size))\n-\t\tperror(\"munmap tgt\");\n-\tif (munmap(ptr, size))\n-\t\tperror(\"munmap src\");\n-\n+\tmunmap(tgt_ptr, 2 * size);\n+out_unmap_src:\n+\tmunmap(ptr, size);\n out:\n-\tif (success)\n-\t\tksft_test_result_pass(\"%s%s\\n\", test_name,\n-\t\t\t\t      dont_unmap ? \" [dontunnmap]\" : \"\");\n-\telse\n-\t\tksft_test_result_fail(\"%s%s\\n\", test_name,\n-\t\t\t\t      dont_unmap ? \" [dontunnmap]\" : \"\");\n+\tksft_test_result(success, \"%s%s\\n\", test_name, dont_unmap ? \" [dontunmap]\" : \"\");\n }\n \n static void mremap_shrink_multiple_vmas(unsigned long page_size,\n@@ -537,7 +535,7 @@ static void mremap_shrink_multiple_vmas(unsigned long page_size,\n \tptr = mmap(NULL, size, PROT_READ | PROT_WRITE,\n \t\t   MAP_PRIVATE | MAP_ANON, -1, 0);\n \tif (ptr == MAP_FAILED) {\n-\t\tperror(\"mmap\");\n+\t\tksft_perror(\"mmap\");\n \t\tsuccess = false;\n \t\tgoto out;\n \t}\n@@ -545,12 +543,12 @@ static void mremap_shrink_multiple_vmas(unsigned long page_size,\n \ttgt_ptr = mmap(NULL, size, PROT_READ | PROT_WRITE,\n \t\t       MAP_PRIVATE | MAP_ANON, -1, 0);\n \tif (tgt_ptr == MAP_FAILED) {\n-\t\tperror(\"mmap\");\n+\t\tksft_perror(\"mmap\");\n \t\tsuccess = false;\n-\t\tgoto out;\n+\t\tgoto out_unmap_src;\n \t}\n \tif (munmap(tgt_ptr, size)) {\n-\t\tperror(\"munmap\");\n+\t\tksft_perror(\"munmap\");\n \t\tsuccess = false;\n \t\tgoto out_unmap;\n \t}\n@@ -564,7 +562,7 @@ static void mremap_shrink_multiple_vmas(unsigned long page_size,\n \t */\n \tfor (i = 1; i \u003c 10; i += 2) {\n \t\tif (munmap(\u0026ptr[i * page_size], page_size)) {\n-\t\t\tperror(\"munmap\");\n+\t\t\tksft_perror(\"munmap\");\n \t\t\tsuccess = false;\n \t\t\tgoto out_unmap;\n \t\t}\n@@ -584,26 +582,21 @@ static void mremap_shrink_multiple_vmas(unsigned long page_size,\n \t\t\t     tgt_ptr);\n \n \tif (res == MAP_FAILED) {\n-\t\tperror(\"mremap\");\n+\t\tksft_perror(\"mremap\");\n \t\tsuccess = false;\n \t\tgoto out_unmap;\n \t}\n \n out_unmap:\n-\tif (munmap(tgt_ptr, size))\n-\t\tperror(\"munmap tgt\");\n-\tif (munmap(ptr, size))\n-\t\tperror(\"munmap src\");\n+\tmunmap(tgt_ptr, size);\n+out_unmap_src:\n+\tmunmap(ptr, size);\n out:\n-\tif (success)\n-\t\tksft_test_result_pass(\"%s%s\\n\", test_name,\n-\t\t\t\t      inplace ? \" [inplace]\" : \"\");\n-\telse\n-\t\tksft_test_result_fail(\"%s%s\\n\", test_name,\n-\t\t\t\t      inplace ? \" [inplace]\" : \"\");\n+\tksft_test_result(success, \"%s%s\\n\", test_name, inplace ? \" [inplace]\" : \"\");\n }\n \n-static void mremap_move_multiple_vmas_split(unsigned int pattern_seed,\n+static void mremap_move_multiple_vmas_split(FILE *maps_fp,\n+\t\t\t\t\t    char *pattern_addr,\n \t\t\t\t\t    unsigned long page_size,\n \t\t\t\t\t    bool dont_unmap)\n {\n@@ -620,7 +613,7 @@ static void mremap_move_multiple_vmas_split(unsigned int pattern_seed,\n \tptr = mmap(NULL, size, PROT_READ | PROT_WRITE,\n \t\t   MAP_PRIVATE | MAP_ANON, -1, 0);\n \tif (ptr == MAP_FAILED) {\n-\t\tperror(\"mmap\");\n+\t\tksft_perror(\"mmap\");\n \t\tsuccess = false;\n \t\tgoto out;\n \t}\n@@ -628,43 +621,32 @@ static void mremap_move_multiple_vmas_split(unsigned int pattern_seed,\n \ttgt_ptr = mmap(NULL, size, PROT_READ | PROT_WRITE,\n \t\t       MAP_PRIVATE | MAP_ANON, -1, 0);\n \tif (tgt_ptr == MAP_FAILED) {\n-\t\tperror(\"mmap\");\n+\t\tksft_perror(\"mmap\");\n \t\tsuccess = false;\n-\t\tgoto out;\n+\t\tgoto out_unmap_src;\n \t}\n \tif (munmap(tgt_ptr, size)) {\n-\t\tperror(\"munmap\");\n+\t\tksft_perror(\"munmap\");\n \t\tsuccess = false;\n \t\tgoto out_unmap;\n \t}\n \n+\tmemcpy(ptr, pattern_addr, size);\n+\n \t/*\n \t * Unmap so we end up with:\n \t *\n \t *  0 1 2 3 4 5 6 7 8 9 10 offset in buffer\n \t * |**********| |*******|\n \t * |**********| |*******|\n-\t *  0 1 2 3 4   5 6 7 8 9  pattern offset\n+\t *  0 1 2 3 4 5 6 7 8 9 10 pattern offset\n \t */\n \tif (munmap(\u0026ptr[5 * page_size], page_size)) {\n-\t\tperror(\"munmap\");\n+\t\tksft_perror(\"munmap\");\n \t\tsuccess = false;\n \t\tgoto out_unmap;\n \t}\n \n-\t/* Set up random patterns. */\n-\tsrand(pattern_seed);\n-\tfor (i = 0; i \u003c 10; i++) {\n-\t\tint j;\n-\t\tchar *buf = \u0026ptr[i * page_size];\n-\n-\t\tif (i == 5)\n-\t\t\tcontinue;\n-\n-\t\tfor (j = 0; j \u003c page_size; j++)\n-\t\t\tbuf[j] = rand();\n-\t}\n-\n \t/*\n \t * Move the below:\n \t *\n@@ -672,58 +654,48 @@ static void mremap_move_multiple_vmas_split(unsigned int pattern_seed,\n \t *  0 1 2 3 4 5 6 7 8 9 10 offset in buffer\n \t * |**********| |*******|\n \t * |**********| |*******|\n-\t *  0 1 2 3 4   5 6 7 8 9  pattern offset\n+\t *  0 1 2 3 4 5 6 7 8 9 10  pattern offset\n \t *\n \t * Into:\n \t *\n \t * 0 1 2 3 4 5 6 7 offset in buffer\n \t * |*****| |*****|\n \t * |*****| |*****|\n-\t * 2 3 4   5 6 7   pattern offset\n+\t * 2 3 4 5 6 7 8 9 pattern offset\n \t */\n \tif (mremap(\u0026ptr[2 * page_size], size - 3 * page_size, size - 3 * page_size,\n \t\t   mremap_flags, tgt_ptr) == MAP_FAILED) {\n-\t\tperror(\"mremap\");\n+\t\tksft_perror(\"mremap\");\n \t\tsuccess = false;\n \t\tgoto out_unmap;\n \t}\n \n-\t/* Offset into random pattern. */\n-\tsrand(pattern_seed);\n-\tfor (i = 0; i \u003c 2 * page_size; i++)\n-\t\trand();\n-\n \t/* Check pattern. */\n \tfor (i = 0; i \u003c 7; i++) {\n-\t\tint j;\n-\t\tchar *buf = \u0026tgt_ptr[i * page_size];\n-\n-\t\tif (i == 3)\n-\t\t\tcontinue;\n-\n-\t\tfor (j = 0; j \u003c page_size; j++) {\n-\t\t\tchar chr = rand();\n-\n-\t\t\tif (chr != buf[j]) {\n-\t\t\t\tksft_print_msg(\"page %d offset %d corrupted, expected %d got %d\\n\",\n-\t\t\t\t\t       i, j, chr, buf[j]);\n+\t\tif (i == 3) {\n+\t\t\tif (is_ptr_mapped(maps_fp, tgt_ptr + i * page_size,\n+\t\t\t\t\t  page_size)) {\n+\t\t\t\tksft_print_msg(\"Page %d is unexpectedly mapped\\n\", i);\n+\t\t\t\tsuccess = false;\n \t\t\t\tgoto out_unmap;\n \t\t\t}\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\tif (memcmp(tgt_ptr + i * page_size,\n+\t\t\t   pattern_addr + (i + 2) * page_size, page_size)) {\n+\t\t\tksft_print_msg(\"Data in page %d got corrupted\\n\", i + 2);\n+\t\t\tsuccess = false;\n+\t\t\tgoto out_unmap;\n \t\t}\n \t}\n \n out_unmap:\n-\tif (munmap(tgt_ptr, size))\n-\t\tperror(\"munmap tgt\");\n-\tif (munmap(ptr, size))\n-\t\tperror(\"munmap src\");\n+\tmunmap(tgt_ptr, size);\n+out_unmap_src:\n+\tmunmap(ptr, size);\n out:\n-\tif (success)\n-\t\tksft_test_result_pass(\"%s%s\\n\", test_name,\n-\t\t\t\t      dont_unmap ? \" [dontunnmap]\" : \"\");\n-\telse\n-\t\tksft_test_result_fail(\"%s%s\\n\", test_name,\n-\t\t\t\t      dont_unmap ? \" [dontunnmap]\" : \"\");\n+\tksft_test_result(success, \"%s%s\\n\", test_name, dont_unmap ? \" [dontunmap]\" : \"\");\n }\n \n #ifdef __NR_userfaultfd\n@@ -734,7 +706,7 @@ static void mremap_move_multi_invalid_vmas(FILE *maps_fp,\n \tconst size_t size = 10 * page_size;\n \tbool success = true;\n \tchar *ptr, *tgt_ptr;\n-\tint uffd, err, i;\n+\tint uffd, i;\n \tvoid *res;\n \tstruct uffdio_api api = {\n \t\t.api = UFFD_API,\n@@ -743,17 +715,16 @@ static void mremap_move_multi_invalid_vmas(FILE *maps_fp,\n \n \tuffd = syscall(__NR_userfaultfd, O_NONBLOCK);\n \tif (uffd == -1) {\n-\t\terr = errno;\n-\t\tperror(\"userfaultfd\");\n-\t\tif (err == EPERM) {\n-\t\t\tksft_test_result_skip(\"%s - missing uffd\", test_name);\n+\t\tif (errno == EPERM || errno == ENOSYS) {\n+\t\t\tksft_test_result_skip(\"%s - missing uffd\\n\", test_name);\n \t\t\treturn;\n \t\t}\n+\t\tksft_perror(\"userfaultfd\");\n \t\tsuccess = false;\n \t\tgoto out;\n \t}\n \tif (ioctl(uffd, UFFDIO_API, \u0026api)) {\n-\t\tperror(\"ioctl UFFDIO_API\");\n+\t\tksft_perror(\"ioctl UFFDIO_API\");\n \t\tsuccess = false;\n \t\tgoto out_close_uffd;\n \t}\n@@ -761,19 +732,19 @@ static void mremap_move_multi_invalid_vmas(FILE *maps_fp,\n \tptr = mmap(NULL, size, PROT_READ | PROT_WRITE,\n \t\t   MAP_PRIVATE | MAP_ANON, -1, 0);\n \tif (ptr == MAP_FAILED) {\n-\t\tperror(\"mmap\");\n+\t\tksft_perror(\"mmap\");\n \t\tsuccess = false;\n \t\tgoto out_close_uffd;\n \t}\n \n \ttgt_ptr = mmap(NULL, size, PROT_NONE, MAP_PRIVATE | MAP_ANON, -1, 0);\n \tif (tgt_ptr == MAP_FAILED) {\n-\t\tperror(\"mmap\");\n+\t\tksft_perror(\"mmap\");\n \t\tsuccess = false;\n-\t\tgoto out_close_uffd;\n+\t\tgoto out_unmap_src;\n \t}\n \tif (munmap(tgt_ptr, size)) {\n-\t\tperror(\"munmap\");\n+\t\tksft_perror(\"munmap\");\n \t\tsuccess = false;\n \t\tgoto out_unmap;\n \t}\n@@ -799,12 +770,12 @@ static void mremap_move_multi_invalid_vmas(FILE *maps_fp,\n \t\t};\n \n \t\tif (ioctl(uffd, UFFDIO_REGISTER, \u0026reg) == -1) {\n-\t\t\tperror(\"ioctl UFFDIO_REGISTER\");\n+\t\t\tksft_perror(\"ioctl UFFDIO_REGISTER\");\n \t\t\tsuccess = false;\n \t\t\tgoto out_unmap;\n \t\t}\n \t\tif (munmap(unmap_ptr, page_size)) {\n-\t\t\tperror(\"munmap\");\n+\t\t\tksft_perror(\"munmap\");\n \t\t\tsuccess = false;\n \t\t\tgoto out_unmap;\n \t\t}\n@@ -817,21 +788,18 @@ static void mremap_move_multi_invalid_vmas(FILE *maps_fp,\n \t * time.\n \t */\n \tres = mremap(ptr, size, size, MREMAP_MAYMOVE | MREMAP_FIXED, tgt_ptr);\n-\terr = errno;\n \tif (res != MAP_FAILED) {\n-\t\tfprintf(stderr, \"mremap() succeeded for multi VMA uffd armed\\n\");\n+\t\tksft_print_msg(\"mremap() succeeded for multi VMA uffd armed\\n\");\n \t\tsuccess = false;\n \t\tgoto out_unmap;\n \t}\n-\tif (err != EFAULT) {\n-\t\terrno = err;\n-\t\tperror(\"mremap() unexpected error\");\n+\tif (errno != EFAULT) {\n+\t\tksft_perror(\"mremap() unexpected error\");\n \t\tsuccess = false;\n \t\tgoto out_unmap;\n \t}\n \tif (is_ptr_mapped(maps_fp, tgt_ptr, page_size)) {\n-\t\tfprintf(stderr,\n-\t\t\t\"Invalid uffd-armed VMA at start of multi range moved\\n\");\n+\t\tksft_print_msg(\"Invalid uffd-armed VMA at start of multi range moved\\n\");\n \t\tsuccess = false;\n \t\tgoto out_unmap;\n \t}\n@@ -843,7 +811,7 @@ static void mremap_move_multi_invalid_vmas(FILE *maps_fp,\n \tres = mremap(ptr, page_size, page_size,\n \t\t     MREMAP_MAYMOVE | MREMAP_FIXED, tgt_ptr);\n \tif (res == MAP_FAILED) {\n-\t\tperror(\"mremap single invalid-multi VMA\");\n+\t\tksft_perror(\"mremap single invalid-multi VMA\");\n \t\tsuccess = false;\n \t\tgoto out_unmap;\n \t}\n@@ -853,14 +821,14 @@ static void mremap_move_multi_invalid_vmas(FILE *maps_fp,\n \t * move valid) VMA at the start of ptr range.\n \t */\n \tif (munmap(tgt_ptr, page_size)) {\n-\t\tperror(\"munmap\");\n+\t\tksft_perror(\"munmap\");\n \t\tsuccess = false;\n \t\tgoto out_unmap;\n \t}\n \tres = mmap(ptr, page_size, PROT_READ | PROT_WRITE,\n \t\t   MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);\n \tif (res == MAP_FAILED) {\n-\t\tperror(\"mmap\");\n+\t\tksft_perror(\"mmap\");\n \t\tsuccess = false;\n \t\tgoto out_unmap;\n \t}\n@@ -870,20 +838,18 @@ static void mremap_move_multi_invalid_vmas(FILE *maps_fp,\n \t * first VMA, but no others, and report a failure.\n \t */\n \tres = mremap(ptr, size, size, MREMAP_MAYMOVE | MREMAP_FIXED, tgt_ptr);\n-\terr = errno;\n \tif (res != MAP_FAILED) {\n-\t\tfprintf(stderr, \"mremap() succeeded for multi VMA uffd armed\\n\");\n+\t\tksft_print_msg(\"mremap() succeeded for multi VMA uffd armed\\n\");\n \t\tsuccess = false;\n \t\tgoto out_unmap;\n \t}\n-\tif (err != EFAULT) {\n-\t\terrno = err;\n-\t\tperror(\"mremap() unexpected error\");\n+\tif (errno != EFAULT) {\n+\t\tksft_perror(\"mremap() unexpected error\");\n \t\tsuccess = false;\n \t\tgoto out_unmap;\n \t}\n \tif (!is_ptr_mapped(maps_fp, tgt_ptr, page_size)) {\n-\t\tfprintf(stderr, \"Valid VMA not moved\\n\");\n+\t\tksft_print_msg(\"Valid VMA not moved\\n\");\n \t\tsuccess = false;\n \t\tgoto out_unmap;\n \t}\n@@ -894,12 +860,12 @@ static void mremap_move_multi_invalid_vmas(FILE *maps_fp,\n \t * multi-move VMAs.\n \t */\n \tif (munmap(tgt_ptr, page_size)) {\n-\t\tperror(\"munmap\");\n+\t\tksft_perror(\"munmap\");\n \t\tsuccess = false;\n \t\tgoto out_unmap;\n \t}\n \tif (munmap(ptr, size - 2 * page_size)) {\n-\t\tperror(\"munmap\");\n+\t\tksft_perror(\"munmap\");\n \t\tsuccess = false;\n \t\tgoto out_unmap;\n \t}\n@@ -908,7 +874,7 @@ static void mremap_move_multi_invalid_vmas(FILE *maps_fp,\n \t\t\t   PROT_READ | PROT_WRITE,\n \t\t\t   MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);\n \t\tif (res == MAP_FAILED) {\n-\t\t\tperror(\"mmap\");\n+\t\t\tksft_perror(\"mmap\");\n \t\t\tsuccess = false;\n \t\t\tgoto out_unmap;\n \t\t}\n@@ -919,69 +885,102 @@ static void mremap_move_multi_invalid_vmas(FILE *maps_fp,\n \t * the last VMA, and report a failure.\n \t */\n \tres = mremap(ptr, size, size, MREMAP_MAYMOVE | MREMAP_FIXED, tgt_ptr);\n-\terr = errno;\n \tif (res != MAP_FAILED) {\n-\t\tfprintf(stderr, \"mremap() succeeded for multi VMA uffd armed\\n\");\n+\t\tksft_print_msg(\"mremap() succeeded for multi VMA uffd armed\\n\");\n \t\tsuccess = false;\n \t\tgoto out_unmap;\n \t}\n-\tif (err != EFAULT) {\n-\t\terrno = err;\n-\t\tperror(\"mremap() unexpected error\");\n+\tif (errno != EFAULT) {\n+\t\tksft_perror(\"mremap() unexpected error\");\n \t\tsuccess = false;\n \t\tgoto out_unmap;\n \t}\n \n-\tfor (i = 0; i \u003c 10; i += 2) {\n+\tfor (i = 0; i \u003c 10; i++) {\n \t\tbool is_mapped = is_ptr_mapped(maps_fp,\n \t\t\t\t\u0026tgt_ptr[i * page_size], page_size);\n \n+\t\tif (i \u0026 1) {\n+\t\t\tif (is_mapped) {\n+\t\t\t\tksft_print_msg(\"Gap unexpectedly mapped at %d\\n\", i);\n+\t\t\t\tsuccess = false;\n+\t\t\t\tgoto out_unmap;\n+\t\t\t}\n+\t\t\tcontinue;\n+\t\t}\n+\n \t\tif (i \u003c 8 \u0026\u0026 !is_mapped) {\n-\t\t\tfprintf(stderr, \"Valid VMA not moved at %d\\n\", i);\n+\t\t\tksft_print_msg(\"Valid VMA not moved at %d\\n\", i);\n \t\t\tsuccess = false;\n \t\t\tgoto out_unmap;\n \t\t} else if (i == 8 \u0026\u0026 is_mapped) {\n-\t\t\tfprintf(stderr, \"Invalid VMA moved at %d\\n\", i);\n+\t\t\tksft_print_msg(\"Invalid VMA moved at %d\\n\", i);\n \t\t\tsuccess = false;\n \t\t\tgoto out_unmap;\n \t\t}\n \t}\n \n out_unmap:\n-\tif (munmap(tgt_ptr, size))\n-\t\tperror(\"munmap tgt\");\n-\tif (munmap(ptr, size))\n-\t\tperror(\"munmap src\");\n+\tmunmap(tgt_ptr, size);\n+out_unmap_src:\n+\tmunmap(ptr, size);\n out_close_uffd:\n \tclose(uffd);\n out:\n-\tif (success)\n-\t\tksft_test_result_pass(\"%s\\n\", test_name);\n-\telse\n-\t\tksft_test_result_fail(\"%s\\n\", test_name);\n+\tksft_test_result(success, \"%s\\n\", test_name);\n }\n #else\n static void mremap_move_multi_invalid_vmas(FILE *maps_fp, unsigned long page_size)\n {\n \tchar *test_name = \"mremap move multiple invalid vmas\";\n \n-\tksft_test_result_skip(\"%s - missing uffd\", test_name);\n+\tksft_test_result_skip(\"%s - missing uffd\\n\", test_name);\n }\n #endif /* __NR_userfaultfd */\n \n-/* Returns the time taken for the remap on success else returns -1. */\n-static long long remap_region(struct config c, unsigned int threshold_mb,\n-\t\t\t      char *rand_addr)\n+static void populate_test_data(char *addr, size_t size, char *pattern_addr,\n+\t\tsize_t pattern_size, size_t page_size)\n {\n-\tvoid *addr, *tmp_addr, *src_addr, *dest_addr, *dest_preamble_addr = NULL;\n-\tstruct timespec t_start = {0, 0}, t_end = {0, 0};\n-\tlong long  start_ns, end_ns, align_mask, ret, offset;\n-\tunsigned long long threshold;\n+\tsize_t mid, end;\n+\tsize_t len = 10 * page_size;\n \n-\tif (threshold_mb == VALIDATION_NO_THRESHOLD)\n-\t\tthreshold = c.region_size;\n-\telse\n-\t\tthreshold = MIN(threshold_mb * _1MB, c.region_size);\n+\tif (size \u003c= pattern_size) {\n+\t\tmemcpy(addr, pattern_addr, size);\n+\t\treturn;\n+\t}\n+\n+\tend = size - len;\n+\tmid = end / 2;\n+\n+\tmemcpy(addr, pattern_addr, len);\n+\tmemcpy(addr + mid, pattern_addr + len, len);\n+\tmemcpy(addr + end, pattern_addr + 2 * len, len);\n+}\n+\n+static bool validate_test_data(char *addr, size_t size, char *pattern_addr,\n+\t\tsize_t pattern_size, size_t page_size)\n+{\n+\tsize_t mid, end;\n+\tsize_t len = 10 * page_size;\n+\n+\tif (size \u003c= pattern_size)\n+\t\treturn !memcmp(addr, pattern_addr, size);\n+\n+\tend = size - len;\n+\tmid = end / 2;\n+\n+\treturn !memcmp(addr, pattern_addr, len) \u0026\u0026\n+\t       !memcmp(addr + mid, pattern_addr + len, len) \u0026\u0026\n+\t       !memcmp(addr + end, pattern_addr + 2 * len, len);\n+}\n+\n+static int remap_region(struct config c, char *pattern_addr, size_t pattern_size,\n+\t\tsize_t page_size)\n+{\n+\tvoid *addr, *tmp_addr, *src_addr, *dest_addr, *dest_preamble_addr = NULL;\n+\tlong long align_mask, offset;\n+\tchar *preamble_pattern = NULL;\n+\tint ret = 0;\n \n \tsrc_addr = get_source_mapping(c);\n \tif (!src_addr) {\n@@ -990,7 +989,8 @@ static long long remap_region(struct config c, unsigned int threshold_mb,\n \t}\n \n \t/* Set byte pattern for source block. */\n-\tmemcpy(src_addr, rand_addr, threshold);\n+\tpopulate_test_data(src_addr, c.region_size, pattern_addr,\n+\t\t\t   pattern_size, page_size);\n \n \t/* Mask to zero out lower bits of address for alignment */\n \talign_mask = ~(c.dest_alignment - 1);\n@@ -1032,14 +1032,13 @@ static long long remap_region(struct config c, unsigned int threshold_mb,\n \t\t\tgoto clean_up_src;\n \t\t}\n \n+\t\tpreamble_pattern = pattern_addr + pattern_size - c.dest_preamble_size;\n \t\t/* Set byte pattern for the dest preamble block. */\n-\t\tmemcpy(dest_preamble_addr, rand_addr, c.dest_preamble_size);\n+\t\tmemcpy(dest_preamble_addr, preamble_pattern, c.dest_preamble_size);\n \t}\n \n-\tclock_gettime(CLOCK_MONOTONIC, \u0026t_start);\n \tdest_addr = mremap(src_addr, c.region_size, c.region_size,\n-\t\t\t\t\t  MREMAP_MAYMOVE|MREMAP_FIXED, (char *) addr);\n-\tclock_gettime(CLOCK_MONOTONIC, \u0026t_end);\n+\t\t\t   MREMAP_MAYMOVE | MREMAP_FIXED, (char *)addr);\n \n \tif (dest_addr == MAP_FAILED) {\n \t\tksft_print_msg(\"mremap failed: %s\\n\", strerror(errno));\n@@ -1048,7 +1047,8 @@ static long long remap_region(struct config c, unsigned int threshold_mb,\n \t}\n \n \t/* Verify byte pattern after remapping */\n-\tif (memcmp(dest_addr, rand_addr, threshold)) {\n+\tif (!validate_test_data(dest_addr, c.region_size, pattern_addr,\n+\t\t\t\tpattern_size, page_size)) {\n \t\tksft_print_msg(\"Data after remap doesn't match\\n\");\n \t\tret = -1;\n \t\tgoto clean_up_dest;\n@@ -1056,22 +1056,12 @@ static long long remap_region(struct config c, unsigned int threshold_mb,\n \n \t/* Verify the dest preamble byte pattern after remapping */\n \tif (c.dest_preamble_size \u0026\u0026\n-\t    memcmp(dest_preamble_addr, rand_addr, c.dest_preamble_size)) {\n+\t    memcmp(dest_preamble_addr, preamble_pattern, c.dest_preamble_size)) {\n \t\tksft_print_msg(\"Preamble data after remap doesn't match\\n\");\n \t\tret = -1;\n \t\tgoto clean_up_dest;\n \t}\n \n-\tstart_ns = t_start.tv_sec * NS_PER_SEC + t_start.tv_nsec;\n-\tend_ns = t_end.tv_sec * NS_PER_SEC + t_end.tv_nsec;\n-\tret = end_ns - start_ns;\n-\n-/*\n- * Since the destination address is specified using MREMAP_FIXED, subsequent\n- * mremap will unmap any previous mapping at the address range specified by\n- * dest_addr and region_size. This significantly affects the remap time of\n- * subsequent tests. So we clean up mappings after each test.\n- */\n clean_up_dest:\n \tmunmap(dest_addr, c.region_size);\n clean_up_dest_preamble:\n@@ -1088,12 +1078,11 @@ static long long remap_region(struct config c, unsigned int threshold_mb,\n  * the beginning of the mapping just because the aligned\n  * down address landed on a mapping that maybe does not exist.\n  */\n-static void mremap_move_1mb_from_start(unsigned int pattern_seed,\n-\t\t\t\t       char *rand_addr)\n+static void mremap_move_1mb_from_start(char *pattern_addr)\n {\n \tchar *test_name = \"mremap move 1mb from start at 1MB+256KB aligned src\";\n \tvoid *src = NULL, *dest = NULL;\n-\tunsigned int i, success = 1;\n+\tunsigned int success = 1;\n \n \t/* Config to reuse get_source_mapping() to do an aligned mmap. */\n \tstruct config c = {\n@@ -1115,7 +1104,7 @@ static void mremap_move_1mb_from_start(unsigned int pattern_seed,\n \t}\n \n \t/* Set byte pattern for source block. */\n-\tmemcpy(src, rand_addr, SIZE_MB(2));\n+\tmemcpy(src, pattern_addr, SIZE_MB(2));\n \n \t/*\n \t * Unmap the beginning of dest so that the aligned address\n@@ -1124,177 +1113,97 @@ static void mremap_move_1mb_from_start(unsigned int pattern_seed,\n \tmunmap(dest, SIZE_MB(1));\n \n \tvoid *new_ptr = mremap(src + SIZE_MB(1), SIZE_MB(1), SIZE_MB(1),\n-\t\t\t\t\t\t   MREMAP_MAYMOVE | MREMAP_FIXED, dest + SIZE_MB(1));\n+\t\t\t       MREMAP_MAYMOVE | MREMAP_FIXED, dest + SIZE_MB(1));\n \tif (new_ptr == MAP_FAILED) {\n-\t\tperror(\"mremap\");\n+\t\tksft_perror(\"mremap\");\n \t\tsuccess = 0;\n \t\tgoto out;\n \t}\n \n \t/* Verify byte pattern after remapping */\n-\tsrand(pattern_seed);\n-\tfor (i = 0; i \u003c SIZE_MB(1); i++) {\n-\t\tchar c = (char) rand();\n-\n-\t\tif (((char *)src)[i] != c) {\n-\t\t\tksft_print_msg(\"Data at src at %d got corrupted due to unrelated mremap\\n\",\n-\t\t\t\t       i);\n-\t\t\tksft_print_msg(\"Expected: %#x\\t Got: %#x\\n\", c \u0026 0xff,\n-\t\t\t\t\t((char *) src)[i] \u0026 0xff);\n-\t\t\tsuccess = 0;\n-\t\t}\n+\tif (memcmp(src, pattern_addr, SIZE_MB(1))) {\n+\t\tksft_print_msg(\"Data before the remapped range was corrupted\\n\");\n+\t\tsuccess = 0;\n \t}\n \n out:\n-\tif (src \u0026\u0026 munmap(src, c.region_size) == -1)\n-\t\tperror(\"munmap src\");\n+\tif (src)\n+\t\tmunmap(src, c.region_size);\n \n-\tif (dest \u0026\u0026 munmap(dest, c.region_size) == -1)\n-\t\tperror(\"munmap dest\");\n+\tif (dest)\n+\t\tmunmap(dest, c.region_size);\n \n-\tif (success)\n-\t\tksft_test_result_pass(\"%s\\n\", test_name);\n-\telse\n-\t\tksft_test_result_fail(\"%s\\n\", test_name);\n+\tksft_test_result(success, \"%s\\n\", test_name);\n }\n \n-static void run_mremap_test_case(struct test test_case, int *failures,\n-\t\t\t\t unsigned int threshold_mb,\n-\t\t\t\t char *rand_addr)\n+static void run_mremap_test_case(struct test test_case,\n+\t\t\t\t char *pattern_addr,\n+\t\t\t\t size_t pattern_size,\n+\t\t\t\t size_t page_size)\n {\n-\tlong long remap_time = remap_region(test_case.config, threshold_mb,\n-\t\t\t\t\t    rand_addr);\n-\n-\tif (remap_time \u003c 0) {\n-\t\tif (test_case.expect_failure) {\n-\t\t\tksft_print_msg(\"%s: expected mremap failure\\n\",\n-\t\t\t\t       test_case.name);\n-\t\t\tksft_test_result_xfail(\"%s\\n\", test_case.name);\n-\t\t} else {\n+\tint ret = remap_region(test_case.config, pattern_addr, pattern_size, page_size);\n+\n+\tif (ret \u003c 0) {\n+\t\tif (test_case.expect_failure)\n+\t\t\tksft_test_result_xfail(\"%s: expected mremap failure\\n\",\n+\t\t\t\t\t       test_case.name);\n+\t\telse\n \t\t\tksft_test_result_fail(\"%s\\n\", test_case.name);\n-\t\t\t*failures += 1;\n-\t\t}\n \t} else {\n-\t\t/*\n-\t\t * Comparing mremap time is only applicable if entire region\n-\t\t * was faulted in.\n-\t\t */\n-\t\tif (threshold_mb == VALIDATION_NO_THRESHOLD ||\n-\t\t    test_case.config.region_size \u003c= threshold_mb * _1MB) {\n-\t\t\tksft_print_msg(\"%s: mremap time: %12lldns\\n\",\n-\t\t\t\t       test_case.name, remap_time);\n-\t\t\tksft_test_result_pass(\"%s\\n\", test_case.name);\n-\t\t} else {\n+\t\tif (test_case.expect_failure)\n+\t\t\tksft_test_result_fail(\"%s: unexpected mremap success\\n\",\n+\t\t\t\t\t      test_case.name);\n+\t\telse\n \t\t\tksft_test_result_pass(\"%s\\n\", test_case.name);\n-\t\t}\n \t}\n }\n \n-static void usage(const char *cmd)\n-{\n-\tfprintf(stderr,\n-\t\t\"Usage: %s [[-t \u003cthreshold_mb\u003e] [-p \u003cpattern_seed\u003e]]\\n\"\n-\t\t\"-t\\t only validate threshold_mb of the remapped region\\n\"\n-\t\t\"  \\t if 0 is supplied no threshold is used; all tests\\n\"\n-\t\t\"  \\t are run and remapped regions validated fully.\\n\"\n-\t\t\"  \\t The default threshold used is 4MB.\\n\"\n-\t\t\"-p\\t provide a seed to generate the random pattern for\\n\"\n-\t\t\"  \\t validating the remapped region.\\n\", cmd);\n-}\n-\n-static int parse_args(int argc, char **argv, unsigned int *threshold_mb,\n-\t\t      unsigned int *pattern_seed)\n+static void fill_pattern(char *pattern_addr, size_t pattern_size, size_t page_size)\n {\n-\tconst char *optstr = \"t:p:\";\n-\tint opt;\n+\tsize_t nr_pages = pattern_size / page_size;\n+\tsize_t words_per_page = page_size / sizeof(uint32_t);\n+\tsize_t page, word;\n \n-\twhile ((opt = getopt(argc, argv, optstr)) != -1) {\n-\t\tswitch (opt) {\n-\t\tcase 't':\n-\t\t\t*threshold_mb = atoi(optarg);\n-\t\t\tbreak;\n-\t\tcase 'p':\n-\t\t\t*pattern_seed = atoi(optarg);\n-\t\t\tbreak;\n-\t\tdefault:\n-\t\t\tusage(argv[0]);\n-\t\t\treturn -1;\n-\t\t}\n-\t}\n+\tfor (page = 0; page \u003c nr_pages; page++) {\n+\t\tuint32_t *page_addr = (uint32_t *)pattern_addr + page * words_per_page;\n+\t\tuint32_t val = page + 1;\n \n-\tif (optind \u003c argc) {\n-\t\tusage(argv[0]);\n-\t\treturn -1;\n+\t\tfor (word = 0; word \u003c words_per_page; word++)\n+\t\t\tpage_addr[word] = val;\n \t}\n-\n-\treturn 0;\n }\n \n #define MAX_TEST 15\n-#define MAX_PERF_TEST 3\n-int main(int argc, char **argv)\n+int main(void)\n {\n-\tint failures = 0;\n \tunsigned int i;\n-\tint run_perf_tests;\n-\tunsigned int threshold_mb = VALIDATION_DEFAULT_THRESHOLD;\n-\n-\t/* hard-coded test configs */\n-\tsize_t max_test_variable_region_size = _2GB;\n-\tsize_t max_test_constant_region_size = _2MB;\n-\tsize_t dest_preamble_size = 10 * _4MB;\n \n-\tunsigned int pattern_seed;\n-\tchar *rand_addr;\n-\tsize_t rand_size;\n+\tchar *pattern_addr;\n+\tsize_t pattern_size;\n \tint num_expand_tests = 2;\n \tint num_misc_tests = 9;\n \tstruct test test_cases[MAX_TEST] = {};\n-\tstruct test perf_test_cases[MAX_PERF_TEST];\n \tint page_size;\n-\ttime_t t;\n \tFILE *maps_fp;\n \n \tksft_print_header();\n \n \tget_mmap_min_addr();\n \n-\tpattern_seed = (unsigned int) time(\u0026t);\n-\n-\tif (parse_args(argc, argv, \u0026threshold_mb, \u0026pattern_seed) \u003c 0)\n-\t\texit(EXIT_FAILURE);\n-\n-\tksft_print_msg(\"Test configs:\\n\");\n-\tksft_print_msg(\"threshold_mb=%u\\n\", threshold_mb);\n-\tksft_print_msg(\"pattern_seed=%u\\n\", pattern_seed);\n-\n \t/*\n-\t * set preallocated random array according to test configs; see the\n-\t * functions for the logic of setting the size\n+\t * The 40MB destination preamble determines the pattern buffer size\n \t */\n-\tif (!threshold_mb)\n-\t\trand_size = MAX(max_test_variable_region_size,\n-\t\t\t\tmax_test_constant_region_size);\n-\telse\n-\t\trand_size = MAX(MIN(threshold_mb * _1MB,\n-\t\t\t\t    max_test_variable_region_size),\n-\t\t\t\tmax_test_constant_region_size);\n-\trand_size = MAX(dest_preamble_size, rand_size);\n-\n-\trand_addr = (char *)mmap(NULL, rand_size, PROT_READ | PROT_WRITE,\n-\t\t\t\t MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);\n-\tif (rand_addr == MAP_FAILED) {\n-\t\tperror(\"mmap\");\n-\t\tksft_exit_fail_msg(\"cannot mmap rand_addr\\n\");\n-\t}\n+\tpattern_size = 10 * _4MB;\n \n-\t/* fill stream of random bytes */\n-\tsrand(pattern_seed);\n-\tfor (unsigned long i = 0; i \u003c rand_size; ++i)\n-\t\trand_addr[i] = (char) rand();\n+\tpattern_addr = (char *)mmap(NULL, pattern_size, PROT_READ | PROT_WRITE,\n+\t\t\t\t    MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);\n+\tif (pattern_addr == MAP_FAILED)\n+\t\tksft_exit_fail_perror(\"cannot mmap pattern_addr\");\n \n \tpage_size = sysconf(_SC_PAGESIZE);\n \n+\tfill_pattern(pattern_addr, pattern_size, page_size);\n+\n \t/* Expected mremap failures */\n \ttest_cases[0] =\tMAKE_TEST(page_size, page_size, page_size,\n \t\t\t\t  OVERLAPPING, EXPECT_FAILURE,\n@@ -1345,62 +1254,34 @@ int main(int argc, char **argv)\n \t\t\t\t  \"5MB mremap - Source 1MB-aligned, Dest 1MB-aligned with 40MB Preamble\");\n \ttest_cases[14].config.dest_preamble_size = 10 * _4MB;\n \n-\tperf_test_cases[0] =  MAKE_TEST(page_size, page_size, _1GB, NON_OVERLAPPING, EXPECT_SUCCESS,\n-\t\t\t\t\t\"1GB mremap - Source PTE-aligned, Destination PTE-aligned\");\n-\t/*\n-\t * mremap 1GB region - Page table level aligned time\n-\t * comparison.\n-\t */\n-\tperf_test_cases[1] = MAKE_TEST(PMD, PMD, _1GB, NON_OVERLAPPING, EXPECT_SUCCESS,\n-\t\t\t\t       \"1GB mremap - Source PMD-aligned, Destination PMD-aligned\");\n-\tperf_test_cases[2] = MAKE_TEST(PUD, PUD, _1GB, NON_OVERLAPPING, EXPECT_SUCCESS,\n-\t\t\t\t       \"1GB mremap - Source PUD-aligned, Destination PUD-aligned\");\n-\n-\trun_perf_tests =  (threshold_mb == VALIDATION_NO_THRESHOLD) ||\n-\t\t\t\t(threshold_mb * _1MB \u003e= _1GB);\n-\n-\tksft_set_plan(ARRAY_SIZE(test_cases) + (run_perf_tests ?\n-\t\t      ARRAY_SIZE(perf_test_cases) : 0) + num_expand_tests + num_misc_tests);\n+\tksft_set_plan(ARRAY_SIZE(test_cases) + num_expand_tests + num_misc_tests);\n \n \tfor (i = 0; i \u003c ARRAY_SIZE(test_cases); i++)\n-\t\trun_mremap_test_case(test_cases[i], \u0026failures, threshold_mb,\n-\t\t\t\t     rand_addr);\n+\t\trun_mremap_test_case(test_cases[i], pattern_addr, pattern_size, page_size);\n \n \tmaps_fp = fopen(\"/proc/self/maps\", \"r\");\n \n \tif (maps_fp == NULL) {\n-\t\tmunmap(rand_addr, rand_size);\n+\t\tmunmap(pattern_addr, pattern_size);\n \t\tksft_exit_fail_msg(\"Failed to read /proc/self/maps: %s\\n\", strerror(errno));\n \t}\n \n \tmremap_expand_merge(maps_fp, page_size);\n \tmremap_expand_merge_offset(maps_fp, page_size);\n \n-\tmremap_move_within_range(pattern_seed, rand_addr);\n-\tmremap_move_1mb_from_start(pattern_seed, rand_addr);\n+\tmremap_move_within_range(pattern_addr);\n+\tmremap_move_1mb_from_start(pattern_addr);\n \tmremap_shrink_multiple_vmas(page_size, /* inplace= */true);\n \tmremap_shrink_multiple_vmas(page_size, /* inplace= */false);\n-\tmremap_move_multiple_vmas(pattern_seed, page_size, /* dontunmap= */ false);\n-\tmremap_move_multiple_vmas(pattern_seed, page_size, /* dontunmap= */ true);\n-\tmremap_move_multiple_vmas_split(pattern_seed, page_size, /* dontunmap= */ false);\n-\tmremap_move_multiple_vmas_split(pattern_seed, page_size, /* dontunmap= */ true);\n+\tmremap_move_multiple_vmas(maps_fp, pattern_addr, page_size, /* dontunmap= */ false);\n+\tmremap_move_multiple_vmas(maps_fp, pattern_addr, page_size, /* dontunmap= */ true);\n+\tmremap_move_multiple_vmas_split(maps_fp, pattern_addr, page_size, /* dontunmap= */ false);\n+\tmremap_move_multiple_vmas_split(maps_fp, pattern_addr, page_size, /* dontunmap= */ true);\n \tmremap_move_multi_invalid_vmas(maps_fp, page_size);\n \n \tfclose(maps_fp);\n \n-\tif (run_perf_tests) {\n-\t\tksft_print_msg(\"\\n%s\\n\",\n-\t\t \"mremap HAVE_MOVE_PMD/PUD optimization time comparison for 1GB region:\");\n-\t\tfor (i = 0; i \u003c ARRAY_SIZE(perf_test_cases); i++)\n-\t\t\trun_mremap_test_case(perf_test_cases[i], \u0026failures,\n-\t\t\t\t\t     threshold_mb,\n-\t\t\t\t\t     rand_addr);\n-\t}\n-\n-\tmunmap(rand_addr, rand_size);\n+\tmunmap(pattern_addr, pattern_size);\n \n-\tif (failures \u003e 0)\n-\t\tksft_exit_fail();\n-\telse\n-\t\tksft_exit_pass();\n+\tksft_finished();\n }\n"
}

2/1 2026/11/02 21:06 agent patch-evaluator
0m Model:
core

Args:
null

Results:
{
  "EnableConfigs": null,
  "FocusSymbols": [],
  "Reasoning": "The patch only modifies user-space selftest code (tools/testing/selftests/mm/mremap_test.c) and does not affect the compiled kernel image or any kernel-space executable code.",
  "WorthFuzzing": false
}

Instruction:
You are an expert Linux kernel maintainer and security engineer.
Your job is to review a provided patch series and evaluate whether it warrants fuzzing with syzkaller.

IMPORTANT: The changes have ALREADY been applied and committed as the HEAD commit in
your workspace. Do NOT rely on internal assumptions. You must actively use your code access
tools to inspect the actual source code, callers, and surrounding context.

================================================================================
1. CORE TRIAGE PHILOSOPHY
================================================================================
The goal of patch fuzzing is to discover crashes, regressions, exposed latent bugs,
and newly triggered assertions introduced by the patch series.

- REACHABILITY IS THE PRIMARY GATE:
  Fuzzing can only discover bugs in code that can actually execute in standard virtualized
  environments (GCE or QEMU, utilizing software-emulated devices like USB gadgets, netdev, tun/tap).
  If the modified code is structurally unreachable (see Section 2), it MUST NOT be fuzzed,
  regardless of whether it adds assertions or complex logic.

- DO NOT BLINDLY TRUST "NO FUNCTIONAL CHANGE" (NFCI) OR "REFACTORING" CLAIMS:
  Patch authors routinely label changes as "cleanups", "refactorings", or state
  "No functional change intended". Do NOT take these claims at face value.
  Code refactorings that rearrange logic, introduce helper functions, or alter state management
  in core subsystems frequently introduce subtle semantic shifts or uncover latent kernel bugs.
  If reachable executable code is modified or refactored, it MUST be fuzzed.

- NEW OR MODIFIED ASSERTIONS IN REACHABLE CODE MUST BE FUZZED:
  When a patch introduces or modifies runtime checks or assertions (e.g., WARN_ON*, VM_WARN_ON*,
  BUG_ON*, lockdep_assert*) in reachable code paths, it enforces new or stricter invariants.
  Even if the author believes the invariant always holds, fuzzing is essential to verify whether
  an unusual sequence of operations can violate it.

================================================================================
2. WHEN TO RETURN WorthFuzzing=false (NEGATIVE CRITERIA)
================================================================================
Return WorthFuzzing=false ONLY IF all modified code falls strictly into one or more of these categories:

- Non-kernel and non-executable changes:
  * Modifications to Documentation/, comments, or spelling fixes.
  * User-space directories, self-tests, samples, or scripts (e.g., tools/, samples/, scripts/, usr/)
    that do not affect the compiled kernel image (vmlinux) or kernel modules.
  * Purely decorative logging (e.g., message strings in pr_err, printk, dev_info) or tracepoints
    that do not alter control flow or data structures.
  * Build system or Kconfig changes that do not alter compiled C logic.
- Structurally unreachable hardware:
  * Vendor-specific PCIe switches, SmartNICs, or GPU drivers (e.g., mlxsw, pds_core, qed,
    ionic, amdgpu) requiring physical ASIC/PCIe cards not emulated in standard QEMU.
- Unreachable execution paths:
  * Driver teardown callbacks (.remove, .shutdown, pci_unregister_driver) executed only during
    physical PCI hot-unplug or manual sysfs driver unbinding.
  * Code paths exclusive to architectures other than the target architecture.

================================================================================
3. WHEN TO RETURN WorthFuzzing=true (POSITIVE CRITERIA)
================================================================================
Return WorthFuzzing=true whenever the patch touches reachable executable code, including:
- Core Subsystems:
  * Any logic modifications in memory management (mm/), synchronization/locking (kernel/locking/),
    BPF, scheduler, core networking, VFS, or syscall handling.
- Refactorings and Code Cleanups:
  * Any restructuring of reachable data structures, helper abstractions, or algorithm flows.
- Runtime Assertions and Defensive Checks:
  * Any introduction or alteration of assertions (WARN_ON*, VM_WARN_ON*, BUG_ON*, etc.) in reachable paths.
- Reachable Drivers and Protocols:
  * Drivers accessible via virtual buses (virtio, USB gadget, loopback, netlink, binder, sockets, etc.).

================================================================================
4. EXTRACTING FocusSymbols (PREVENTING DILUTION)
================================================================================
When WorthFuzzing=true, you must extract specific kernel functions into FocusSymbols to guide the fuzzer:

- AVOID UBIQUITOUS LIFECYCLE HOT-PATHS:
  Do NOT list generic, ubiquitous functions called by almost every program in the corpus
  (including, but not limited to: general memory allocators and deallocators, page fault
  and trap handlers, or core synchronization primitives; this is not an exhaustive list).
  Listing ubiquitous functions causes the fuzzer to classify thousands of unrelated tests as "focused",
  which severely dilutes fuzzing effort away from the actual changes.

- TARGET SPECIFIC FEATURE LOGIC AND ENTRYPOINTS:
  List functions that specifically implement the logic being added or altered, or direct API entrypoints
  for the subsystem feature under review.

- HANDLING STATIC INLINE FUNCTIONS IN HEADERS (.h):
  Compiler-inlined static functions (such as static inlines in mm/*.h or include/linux/*.h) lack
  distinct symbol addresses in vmlinux and cannot be targeted directly by symbol coverage filters.
  If the changes are primarily in static inline helpers, identify non-static, feature-specific caller
  functions in .c files that exercise them (avoiding ubiquitous lifecycle wrappers).

================================================================================
5. IDENTIFYING EnableConfigs
================================================================================
Identify any specific CONFIG_ options required to properly compile and reach the modified code:
- Inspect Kconfig files and #ifdef guards; do not make assumptions.
- Check "depends on" lines in Kconfig to include any non-standard parent subsystem configs needed.
- Strip any 'CONFIG_' prefix (e.g., return "NET_IPV4" instead of "CONFIG_NET_IPV4").
Prefer calling several tools at the same time to save round-trips.


Use set-results tool to provide results of the analysis.
It must be called exactly once before the final reply.
Ignore results of this tool.

Prompt:
Target architecture: amd64

For your convenience, here is the diff of the changes:
commit f5ed3e338e82ef1f7bdfff316667eb25cc2666f8
Author: syz-cluster <triage@syzkaller.com>
Date:   Mon Nov 2 21:06:19 2026 +0000

    syz-cluster: applied patch under review

diff --git a/tools/testing/selftests/mm/mremap_test.c b/tools/testing/selftests/mm/mremap_test.c
index 31b484517bda61..b83c5797a2d8a5 100644
--- a/tools/testing/selftests/mm/mremap_test.c
+++ b/tools/testing/selftests/mm/mremap_test.c
@@ -13,8 +13,8 @@
 #include <sys/ioctl.h>
 #include <sys/mman.h>
 #include <syscall.h>
-#include <time.h>
 #include <stdbool.h>
+#include <stdint.h>
 
 #include "kselftest.h"
 
@@ -22,14 +22,7 @@
 #define EXPECT_FAILURE 1
 #define NON_OVERLAPPING 0
 #define OVERLAPPING 1
-#define NS_PER_SEC 1000000000ULL
-#define VALIDATION_DEFAULT_THRESHOLD 4	/* 4MB */
-#define VALIDATION_NO_THRESHOLD 0	/* Verify the entire region */
-
-#ifndef MIN
-#define MIN(X, Y) ((X) < (Y) ? (X) : (Y))
-#define MAX(X, Y) ((X) > (Y) ? (X) : (Y))
-#endif
+
 #define SIZE_MB(m) ((size_t)m * (1024 * 1024))
 #define SIZE_KB(k) ((size_t)k * 1024)
 
@@ -129,13 +122,14 @@ static unsigned long long get_mmap_min_addr(void)
 }
 
 /*
- * Using /proc/self/maps, assert that the specified address range is contained
- * within a single mapping.
+ * Using /proc/self/maps, check whether the specified address range is contained
+ * within a single mapping with the expected permissions, if supplied.
  */
-static bool is_range_mapped(FILE *maps_fp, unsigned long start,
-			    unsigned long end)
+static bool is_range_mapped_with_perms(FILE *maps_fp, unsigned long start,
+		unsigned long end, const char *expected_perms)
 {
 	char *line = NULL;
+	char perms[5];
 	size_t len = 0;
 	bool success = false;
 	unsigned long first_val, second_val;
@@ -143,12 +137,13 @@ static bool is_range_mapped(FILE *maps_fp, unsigned long start,
 	rewind(maps_fp);
 
 	while (getline(&line, &len, maps_fp) != -1) {
-		if (sscanf(line, "%lx-%lx", &first_val, &second_val) != 2) {
+		if (sscanf(line, "%lx-%lx %4s", &first_val, &second_val, perms) != 3) {
 			ksft_exit_fail_msg("cannot parse /proc/self/maps\n");
 			break;
 		}
 
-		if (first_val <= start && second_val >= end) {
+		if (first_val <= start && second_val >= end &&
+		    (!expected_perms || !strcmp(perms, expected_perms))) {
 			success = true;
 			fflush(maps_fp);
 			break;
@@ -159,6 +154,12 @@ static bool is_range_mapped(FILE *maps_fp, unsigned long start,
 	return success;
 }
 
+static bool is_range_mapped(FILE *maps_fp, unsigned long start,
+			    unsigned long end)
+{
+	return is_range_mapped_with_perms(maps_fp, start, end, NULL);
+}
+
 /* Check if [ptr, ptr + size) mapped in /proc/self/maps. */
 static bool is_ptr_mapped(FILE *maps_fp, void *ptr, unsigned long size)
 {
@@ -168,6 +169,20 @@ static bool is_ptr_mapped(FILE *maps_fp, void *ptr, unsigned long size)
 	return is_range_mapped(maps_fp, start, end);
 }
 
+/*
+ * Check if [ptr, ptr + size) is mapped with the required permissions in
+ * /proc/self/maps.
+ */
+static bool is_ptr_mapped_with_perms(FILE *maps_fp, void *ptr,
+				     unsigned long size,
+				     const char *expected_perms)
+{
+	unsigned long start = (unsigned long)ptr;
+	unsigned long end = start + size;
+
+	return is_range_mapped_with_perms(maps_fp, start, end, expected_perms);
+}
+
 /*
  * Returns the start address of the mapping on success, else returns
  * NULL on failure.
@@ -257,10 +272,7 @@ static void mremap_expand_merge(FILE *maps_fp, unsigned long page_size)
 	munmap(start, 3 * page_size);
 
 out:
-	if (success)
-		ksft_test_result_pass("%s\n", test_name);
-	else
-		ksft_test_result_fail("%s\n", test_name);
+	ksft_test_result(success, "%s\n", test_name);
 }
 
 /*
@@ -297,10 +309,7 @@ static void mremap_expand_merge_offset(FILE *maps_fp, unsigned long page_size)
 	munmap(start, 3 * page_size);
 
 out:
-	if (success)
-		ksft_test_result_pass("%s\n", test_name);
-	else
-		ksft_test_result_fail("%s\n", test_name);
+	ksft_test_result(success, "%s\n", test_name);
 }
 
 /*
@@ -317,17 +326,17 @@ static void mremap_expand_merge_offset(FILE *maps_fp, unsigned long page_size)
  *
  * |DDDDddddSSSSssss|
  */
-static void mremap_move_within_range(unsigned int pattern_seed, char *rand_addr)
+static void mremap_move_within_range(char *pattern_addr)
 {
-	char *test_name = "mremap mremap move within range";
+	char *test_name = "mremap move within range";
 	void *src, *dest;
-	unsigned int i, success = 1;
+	unsigned int success = 1;
 
 	size_t size = SIZE_MB(20);
 	void *ptr = mmap(NULL, size, PROT_READ | PROT_WRITE,
 			 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
 	if (ptr == MAP_FAILED) {
-		perror("mmap");
+		ksft_perror("mmap");
 		success = 0;
 		goto out;
 	}
@@ -337,68 +346,71 @@ static void mremap_move_within_range(unsigned int pattern_seed, char *rand_addr)
 	src = (void *)((unsigned long)src & ~(SIZE_MB(2) - 1));
 
 	/* Set byte pattern for source block. */
-	memcpy(src, rand_addr, SIZE_MB(2));
+	memcpy(src, pattern_addr + SIZE_MB(2), SIZE_MB(2));
 
 	dest = src - SIZE_MB(2);
 
 	void *new_ptr = mremap(src + SIZE_MB(1), SIZE_MB(1), SIZE_MB(1),
-						   MREMAP_MAYMOVE | MREMAP_FIXED, dest + SIZE_MB(1));
+			       MREMAP_MAYMOVE | MREMAP_FIXED, dest + SIZE_MB(1));
 	if (new_ptr == MAP_FAILED) {
-		perror("mremap");
+		ksft_perror("mremap");
 		success = 0;
-		goto out;
+		goto out_unmap;
 	}
 
 	/* Verify byte pattern after remapping */
-	srand(pattern_seed);
-	for (i = 0; i < SIZE_MB(1); i++) {
-		char c = (char) rand();
-
-		if (((char *)src)[i] != c) {
-			ksft_print_msg("Data at src at %d got corrupted due to unrelated mremap\n",
-				       i);
-			ksft_print_msg("Expected: %#x\t Got: %#x\n", c & 0xff,
-					((char *) src)[i] & 0xff);
-			success = 0;
-		}
+	if (memcmp(src, pattern_addr + SIZE_MB(2), SIZE_MB(1))) {
+		ksft_print_msg("Source data was corrupted\n");
+		success = 0;
 	}
 
+out_unmap:
+	munmap(ptr, size);
 out:
-	if (munmap(ptr, size) == -1)
-		perror("munmap");
-
-	if (success)
-		ksft_test_result_pass("%s\n", test_name);
-	else
-		ksft_test_result_fail("%s\n", test_name);
+	ksft_test_result(success, "%s\n", test_name);
 }
 
-static bool is_multiple_vma_range_ok(unsigned int pattern_seed,
-				     char *ptr, unsigned long page_size)
+static bool is_multiple_vma_range_ok(FILE *maps_fp, char *pattern_addr,
+				     char *ptr, unsigned long page_size,
+				     bool expect_gaps_mapped)
 {
-	int i;
+	for (int i = 0; i <= 10; i++) {
 
-	srand(pattern_seed);
-	for (i = 0; i <= 10; i += 2) {
-		int j;
-		char *buf = &ptr[i * page_size];
-		size_t size = i == 4 ? 2 * page_size : page_size;
-
-		for (j = 0; j < size; j++) {
-			char chr = rand();
+		if (i == 5)
+			continue;
 
-			if (chr != buf[j]) {
-				ksft_print_msg("page %d offset %d corrupted, expected %d got %d\n",
-					       i, j, chr, buf[j]);
+		/* Odd pages correspond to gaps between the source VMAs. */
+		if (i & 1) {
+			if (expect_gaps_mapped) {
+				if (!is_ptr_mapped_with_perms(maps_fp,
+							      ptr + i * page_size,
+							      page_size, "---p")) {
+					ksft_print_msg("Page %d PROT_NONE mapping overwritten\n",
+						       i);
+					return false;
+				}
+			} else if (is_ptr_mapped(maps_fp, ptr + i * page_size,
+						 page_size)) {
+				ksft_print_msg("Page %d is unexpectedly mapped\n", i);
 				return false;
 			}
+			continue;
+		}
+
+		size_t size = i == 4 ? 2 * page_size : page_size;
+
+		if (memcmp(ptr + i * page_size, pattern_addr + i * page_size,
+			   size)) {
+			ksft_print_msg("Data in VMA starting at page %d got corrupted\n",
+				       i);
+			return false;
 		}
 	}
 
 	return true;
 }
 
-static void mremap_move_multiple_vmas(unsigned int pattern_seed,
+static void mremap_move_multiple_vmas(FILE *maps_fp, char *pattern_addr,
 				      unsigned long page_size,
 				      bool dont_unmap)
 {
@@ -415,7 +427,7 @@ static void mremap_move_multiple_vmas(unsigned int pattern_seed,
 	ptr = mmap(NULL, size, PROT_READ | PROT_WRITE,
 		   MAP_PRIVATE | MAP_ANON, -1, 0);
 	if (ptr == MAP_FAILED) {
-		perror("mmap");
+		ksft_perror("mmap");
 		success = false;
 		goto out;
 	}
@@ -423,55 +435,46 @@ static void mremap_move_multiple_vmas(unsigned int pattern_seed,
 	tgt_ptr = mmap(NULL, 2 * size, PROT_READ | PROT_WRITE,
 		       MAP_PRIVATE | MAP_ANON, -1, 0);
 	if (tgt_ptr == MAP_FAILED) {
-		perror("mmap");
+		ksft_perror("mmap");
 		success = false;
-		goto out;
+		goto out_unmap_src;
 	}
 	if (munmap(tgt_ptr, 2 * size)) {
-		perror("munmap");
+		ksft_perror("munmap");
 		success = false;
 		goto out_unmap;
 	}
 
+	memcpy(ptr, pattern_addr, size);
+
 	/*
 	 * Unmap so we end up with:
 	 *
 	 *  0   2   4 5 6   8   10 offset in buffer
 	 * |*| |*| |*****| |*| |*|
 	 * |*| |*| |*****| |*| |*|
-	 *  0   1   2 3 4   5   6  pattern offset
+	 *  0   2   4 5 6   8   10  pattern offset
 	 */
 	for (i = 1; i < 10; i += 2) {
 		if (i == 5)
 			continue;
 
 		if (munmap(&ptr[i * page_size], page_size)) {
-			perror("munmap");
+			ksft_perror("munmap");
 			success = false;
 			goto out_unmap;
 		}
 	}
 
-	srand(pattern_seed);
-
-	/* Set up random patterns. */
-	for (i = 0; i <= 10; i += 2) {
-		int j;
-		size_t size = i == 4 ? 2 * page_size : page_size;
-		char *buf = &ptr[i * page_size];
-
-		for (j = 0; j < size; j++)
-			buf[j] = rand();
-	}
-
 	/* First, just move the whole thing. */
 	if (mremap(ptr, size, size, mremap_flags, tgt_ptr) == MAP_FAILED) {
-		perror("mremap");
+		ksft_perror("mremap");
 		success = false;
 		goto out_unmap;
 	}
 	/* Check move was ok. */
-	if (!is_multiple_vma_range_ok(pattern_seed, tgt_ptr, page_size)) {
+	if (!is_multiple_vma_range_ok(maps_fp, pattern_addr, tgt_ptr,
+				      page_size, false)) {
 		success = false;
 		goto out_unmap;
 	}
@@ -479,12 +482,13 @@ static void mremap_move_multiple_vmas(unsigned int pattern_seed,
 	/* Move next to itself. */
 	if (mremap(tgt_ptr, size, size, mremap_flags,
 		   &tgt_ptr[size]) == MAP_FAILED) {
-		perror("mremap");
+		ksft_perror("mremap");
 		success = false;
 		goto out_unmap;
 	}
 	/* Check that the move is ok. */
-	if (!is_multiple_vma_range_ok(pattern_seed, &tgt_ptr[size], page_size)) {
+	if (!is_multiple_vma_range_ok(maps_fp, pattern_addr, &tgt_ptr[size],
+				      page_size, false)) {
 		success = false;
 		goto out_unmap;
 	}
@@ -492,36 +496,30 @@ static void mremap_move_multiple_vmas(unsigned int pattern_seed,
 	/* Map a range to overwrite. */
 	if (mmap(tgt_ptr, size, PROT_NONE,
 		 MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0) == MAP_FAILED) {
-		perror("mmap tgt");
+		ksft_perror("mmap tgt");
 		success = false;
 		goto out_unmap;
 	}
 	/* Move and overwrite. */
 	if (mremap(&tgt_ptr[size], size, size,
 		   mremap_flags, tgt_ptr) == MAP_FAILED) {
-		perror("mremap");
+		ksft_perror("mremap");
 		success = false;
 		goto out_unmap;
 	}
 	/* Check that the move is ok. */
-	if (!is_multiple_vma_range_ok(pattern_seed, tgt_ptr, page_size)) {
+	if (!is_multiple_vma_range_ok(maps_fp, pattern_addr, tgt_ptr,
+				      page_size, true)) {
 		success = false;
 		goto out_unmap;
 	}
 
 out_unmap:
-	if (munmap(tgt_ptr, 2 * size))
-		perror("munmap tgt");
-	if (munmap(ptr, size))
-		perror("munmap src");
-
+	munmap(tgt_ptr, 2 * size);
+out_unmap_src:
+	munmap(ptr, size);
 out:
-	if (success)
-		ksft_test_result_pass("%s%s\n", test_name,
-				      dont_unmap ? " [dontunnmap]" : "");
-	else
-		ksft_test_result_fail("%s%s\n", test_name,
-				      dont_unmap ? " [dontunnmap]" : "");
+	ksft_test_result(success, "%s%s\n", test_name, dont_unmap ? " [dontunmap]" : "");
 }
 
 static void mremap_shrink_multiple_vmas(unsigned long page_size,
@@ -537,7 +535,7 @@ static void mremap_shrink_multiple_vmas(unsigned long page_size,
 	ptr = mmap(NULL, size, PROT_READ | PROT_WRITE,
 		   MAP_PRIVATE | MAP_ANON, -1, 0);
 	if (ptr == MAP_FAILED) {
-		perror("mmap");
+		ksft_perror("mmap");
 		success = false;
 		goto out;
 	}
@@ -545,12 +543,12 @@ static void mremap_shrink_multiple_vmas(unsigned long page_size,
 	tgt_ptr = mmap(NULL, size, PROT_READ | PROT_WRITE,
 		       MAP_PRIVATE | MAP_ANON, -1, 0);
 	if (tgt_ptr == MAP_FAILED) {
-		perror("mmap");
+		ksft_perror("mmap");
 		success = false;
-		goto out;
+		goto out_unmap_src;
 	}
 	if (munmap(tgt_ptr, size)) {
-		perror("munmap");
+		ksft_perror("munmap");
 		success = false;
 		goto out_unmap;
 	}
@@ -564,7 +562,7 @@ static void mremap_shrink_multiple_vmas(unsigned long page_size,
 	 */
 	for (i = 1; i < 10; i += 2) {
 		if (munmap(&ptr[i * page_size], page_size)) {
-			perror("munmap");
+			ksft_perror("munmap");
 			success = false;
 			goto out_unmap;
 		}
@@ -584,26 +582,21 @@ static void mremap_shrink_multiple_vmas(unsigned long page_size,
 			     tgt_ptr);
 
 	if (res == MAP_FAILED) {
-		perror("mremap");
+		ksft_perror("mremap");
 		success = false;
 		goto out_unmap;
 	}
 
 out_unmap:
-	if (munmap(tgt_ptr, size))
-		perror("munmap tgt");
-	if (munmap(ptr, size))
-		perror("munmap src");
+	munmap(tgt_ptr, size);
+out_unmap_src:
+	munmap(ptr, size);
 out:
-	if (success)
-		ksft_test_result_pass("%s%s\n", test_name,
-				      inplace ? " [inplace]" : "");
-	else
-		ksft_test_result_fail("%s%s\n", test_name,
-				      inplace ? " [inplace]" : "");
+	ksft_test_result(success, "%s%s\n", test_name, inplace ? " [inplace]" : "");
 }
 
-static void mremap_move_multiple_vmas_split(unsigned int pattern_seed,
+static void mremap_move_multiple_vmas_split(FILE *maps_fp,
+					    char *pattern_addr,
 					    unsigned long page_size,
 					    bool dont_unmap)
 {
@@ -620,7 +613,7 @@ static void mremap_move_multiple_vmas_split(unsigned int pattern_seed,
 	ptr = mmap(NULL, size, PROT_READ | PROT_WRITE,
 		   MAP_PRIVATE | MAP_ANON, -1, 0);
 	if (ptr == MAP_FAILED) {
-		perror("mmap");
+		ksft_perror("mmap");
 		success = false;
 		goto out;
 	}
@@ -628,43 +621,32 @@ static void mremap_move_multiple_vmas_split(unsigned int pattern_seed,
 	tgt_ptr = mmap(NULL, size, PROT_READ | PROT_WRITE,
 		       MAP_PRIVATE | MAP_ANON, -1, 0);
 	if (tgt_ptr == MAP_FAILED) {
-		perror("mmap");
+		ksft_perror("mmap");
 		success = false;
-		goto out;
+		goto out_unmap_src;
 	}
 	if (munmap(tgt_ptr, size)) {
-		perror("munmap");
+		ksft_perror("munmap");
 		success = false;
 		goto out_unmap;
 	}
 
+	memcpy(ptr, pattern_addr, size);
+
 	/*
 	 * Unmap so we end up with:
 	 *
 	 *  0 1 2 3 4 5 6 7 8 9 10 offset in buffer
 	 * |**********| |*******|
 	 * |**********| |*******|
-	 *  0 1 2 3 4   5 6 7 8 9  pattern offset
+	 *  0 1 2 3 4 5 6 7 8 9 10 pattern offset
 	 */
 	if (munmap(&ptr[5 * page_size], page_size)) {
-		perror("munmap");
+		ksft_perror("munmap");
 		success = false;
 		goto out_unmap;
 	}
 
-	/* Set up random patterns. */
-	srand(pattern_seed);
-	for (i = 0; i < 10; i++) {
-		int j;
-		char *buf = &ptr[i * page_size];
-
-		if (i == 5)
-			continue;
-
-		for (j = 0; j < page_size; j++)
-			buf[j] = rand();
-	}
-
 	/*
 	 * Move the below:
 	 *
@@ -672,58 +654,48 @@ static void mremap_move_multiple_vmas_split(unsigned int pattern_seed,
 	 *  0 1 2 3 4 5 6 7 8 9 10 offset in buffer
 	 * |**********| |*******|
 	 * |**********| |*******|
-	 *  0 1 2 3 4   5 6 7 8 9  pattern offset
+	 *  0 1 2 3 4 5 6 7 8 9 10  pattern offset
 	 *
 	 * Into:
 	 *
 	 * 0 1 2 3 4 5 6 7 offset in buffer
 	 * |*****| |*****|
 	 * |*****| |*****|
-	 * 2 3 4   5 6 7   pattern offset
+	 * 2 3 4 5 6 7 8 9 pattern offset
 	 */
 	if (mremap(&ptr[2 * page_size], size - 3 * page_size, size - 3 * page_size,
 		   mremap_flags, tgt_ptr) == MAP_FAILED) {
-		perror("mremap");
+		ksft_perror("mremap");
 		success = false;
 		goto out_unmap;
 	}
 
-	/* Offset into random pattern. */
-	srand(pattern_seed);
-	for (i = 0; i < 2 * page_size; i++)
-		rand();
-
 	/* Check pattern. */
 	for (i = 0; i < 7; i++) {
-		int j;
-		char *buf = &tgt_ptr[i * page_size];
-
-		if (i == 3)
-			continue;
-
-		for (j = 0; j < page_size; j++) {
-			char chr = rand();
-
-			if (chr != buf[j]) {
-				ksft_print_msg("page %d offset %d corrupted, expected %d got %d\n",
-					       i, j, chr, buf[j]);
+		if (i == 3) {
+			if (is_ptr_mapped(maps_fp, tgt_ptr + i * page_size,
+					  page_size)) {
+				ksft_print_msg("Page %d is unexpectedly mapped\n", i);
+				success = false;
 				goto out_unmap;
 			}
+			continue;
+		}
+
+		if (memcmp(tgt_ptr + i * page_size,
+			   pattern_addr + (i + 2) * page_size, page_size)) {
+			ksft_print_msg("Data in page %d got corrupted\n", i + 2);
+			success = false;
+			goto out_unmap;
 		}
 	}
 
 out_unmap:
-	if (munmap(tgt_ptr, size))
-		perror("munmap tgt");
-	if (munmap(ptr, size))
-		perror("munmap src");
+	munmap(tgt_ptr, size);
+out_unmap_src:
+	munmap(ptr, size);
 out:
-	if (success)
-		ksft_test_result_pass("%s%s\n", test_name,
-				      dont_unmap ? " [dontunnmap]" : "");
-	else
-		ksft_test_result_fail("%s%s\n", test_name,
-				      dont_unmap ? " [dontunnmap]" : "");
+	ksft_test_result(success, "%s%s\n", test_name, dont_unmap ? " [dontunmap]" : "");
 }
 
 #ifdef __NR_userfaultfd
@@ -734,7 +706,7 @@ static void mremap_move_multi_invalid_vmas(FILE *maps_fp,
 	const size_t size = 10 * page_size;
 	bool success = true;
 	char *ptr, *tgt_ptr;
-	int uffd, err, i;
+	int uffd, i;
 	void *res;
 	struct uffdio_api api = {
 		.api = UFFD_API,
@@ -743,17 +715,16 @@ static void mremap_move_multi_invalid_vmas(FILE *maps_fp,
 
 	uffd = syscall(__NR_userfaultfd, O_NONBLOCK);
 	if (uffd == -1) {
-		err = errno;
-		perror("userfaultfd");
-		if (err == EPERM) {
-			ksft_test_result_skip("%s - missing uffd", test_name);
+		if (errno == EPERM || errno == ENOSYS) {
+			ksft_test_result_skip("%s - missing uffd\n", test_name);
 			return;
 		}
+		ksft_perror("userfaultfd");
 		success = false;
 		goto out;
 	}
 	if (ioctl(uffd, UFFDIO_API, &api)) {
-		perror("ioctl UFFDIO_API");
+		ksft_perror("ioctl UFFDIO_API");
 		success = false;
 		goto out_close_uffd;
 	}
@@ -761,19 +732,19 @@ static void mremap_move_multi_invalid_vmas(FILE *maps_fp,
 	ptr = mmap(NULL, size, PROT_READ | PROT_WRITE,
 		   MAP_PRIVATE | MAP_ANON, -1, 0);
 	if (ptr == MAP_FAILED) {
-		perror("mmap");
+		ksft_perror("mmap");
 		success = false;
 		goto out_close_uffd;
 	}
 
 	tgt_ptr = mmap(NULL, size, PROT_NONE, MAP_PRIVATE | MAP_ANON, -1, 0);
 	if (tgt_ptr == MAP_FAILED) {
-		perror("mmap");
+		ksft_perror("mmap");
 		success = false;
-		goto out_close_uffd;
+		goto out_unmap_src;
 	}
 	if (munmap(tgt_ptr, size)) {
-		perror("munmap");
+		ksft_perror("munmap");
 		success = false;
 		goto out_unmap;
 	}
@@ -799,12 +770,12 @@ static void mremap_move_multi_invalid_vmas(FILE *maps_fp,
 		};
 
 		if (ioctl(uffd, UFFDIO_REGISTER, &reg) == -1) {
-			perror("ioctl UFFDIO_REGISTER");
+			ksft_perror("ioctl UFFDIO_REGISTER");
 			success = false;
 			goto out_unmap;
 		}
 		if (munmap(unmap_ptr, page_size)) {
-			perror("munmap");
+			ksft_perror("munmap");
 			success = false;
 			goto out_unmap;
 		}
@@ -817,21 +788,18 @@ static void mremap_move_multi_invalid_vmas(FILE *maps_fp,
 	 * time.
 	 */
 	res = mremap(ptr, size, size, MREMAP_MAYMOVE | MREMAP_FIXED, tgt_ptr);
-	err = errno;
 	if (res != MAP_FAILED) {
-		fprintf(stderr, "mremap() succeeded for multi VMA uffd armed\n");
+		ksft_print_msg("mremap() succeeded for multi VMA uffd armed\n");
 		success = false;
 		goto out_unmap;
 	}
-	if (err != EFAULT) {
-		errno = err;
-		perror("mremap() unexpected error");
+	if (errno != EFAULT) {
+		ksft_perror("mremap() unexpected error");
 		success = false;
 		goto out_unmap;
 	}
 	if (is_ptr_mapped(maps_fp, tgt_ptr, page_size)) {
-		fprintf(stderr,
-			"Invalid uffd-armed VMA at start of multi range moved\n");
+		ksft_print_msg("Invalid uffd-armed VMA at start of multi range moved\n");
 		success = false;
 		goto out_unmap;
 	}
@@ -843,7 +811,7 @@ static void mremap_move_multi_invalid_vmas(FILE *maps_fp,
 	res = mremap(ptr, page_size, page_size,
 		     MREMAP_MAYMOVE | MREMAP_FIXED, tgt_ptr);
 	if (res == MAP_FAILED) {
-		perror("mremap single invalid-multi VMA");
+		ksft_perror("mremap single invalid-multi VMA");
 		success = false;
 		goto out_unmap;
 	}
@@ -853,14 +821,14 @@ static void mremap_move_multi_invalid_vmas(FILE *maps_fp,
 	 * move valid) VMA at the start of ptr range.
 	 */
 	if (munmap(tgt_ptr, page_size)) {
-		perror("munmap");
+		ksft_perror("munmap");
 		success = false;
 		goto out_unmap;
 	}
 	res = mmap(ptr, page_size, PROT_READ | PROT_WRITE,
 		   MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
 	if (res == MAP_FAILED) {
-		perror("mmap");
+		ksft_perror("mmap");
 		success = false;
 		goto out_unmap;
 	}
@@ -870,20 +838,18 @@ static void mremap_move_multi_invalid_vmas(FILE *maps_fp,
 	 * first VMA, but no others, and report a failure.
 	 */
 	res = mremap(ptr, size, size, MREMAP_MAYMOVE | MREMAP_FIXED, tgt_ptr);
-	err = errno;
 	if (res != MAP_FAILED) {
-		fprintf(stderr, "mremap() succeeded for multi VMA uffd armed\n");
+		ksft_print_msg("mremap() succeeded for multi VMA uffd armed\n");
 		success = false;
 		goto out_unmap;
 	}
-	if (err != EFAULT) {
-		errno = err;
-		perror("mremap() unexpected error");
+	if (errno != EFAULT) {
+		ksft_perror("mremap() unexpected error");
 		success = false;
 		goto out_unmap;
 	}
 	if (!is_ptr_mapped(maps_fp, tgt_ptr, page_size)) {
-		fprintf(stderr, "Valid VMA not moved\n");
+		ksft_print_msg("Valid VMA not moved\n");
 		success = false;
 		goto out_unmap;
 	}
@@ -894,12 +860,12 @@ static void mremap_move_multi_invalid_vmas(FILE *maps_fp,
 	 * multi-move VMAs.
 	 */
 	if (munmap(tgt_ptr, page_size)) {
-		perror("munmap");
+		ksft_perror("munmap");
 		success = false;
 		goto out_unmap;
 	}
 	if (munmap(ptr, size - 2 * page_size)) {
-		perror("munmap");
+		ksft_perror("munmap");
 		success = false;
 		goto out_unmap;
 	}
@@ -908,7 +874,7 @@ static void mremap_move_multi_invalid_vmas(FILE *maps_fp,
 			   PROT_READ | PROT_WRITE,
 			   MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
 		if (res == MAP_FAILED) {
-			perror("mmap");
+			ksft_perror("mmap");
 			success = false;
 			goto out_unmap;
 		}
@@ -919,69 +885,102 @@ static void mremap_move_multi_invalid_vmas(FILE *maps_fp,
 	 * the last VMA, and report a failure.
 	 */
 	res = mremap(ptr, size, size, MREMAP_MAYMOVE | MREMAP_FIXED, tgt_ptr);
-	err = errno;
 	if (res != MAP_FAILED) {
-		fprintf(stderr, "mremap() succeeded for multi VMA uffd armed\n");
+		ksft_print_msg("mremap() succeeded for multi VMA uffd armed\n");
 		success = false;
 		goto out_unmap;
 	}
-	if (err != EFAULT) {
-		errno = err;
-		perror("mremap() unexpected error");
+	if (errno != EFAULT) {
+		ksft_perror("mremap() unexpected error");
 		success = false;
 		goto out_unmap;
 	}
 
-	for (i = 0; i < 10; i += 2) {
+	for (i = 0; i < 10; i++) {
 		bool is_mapped = is_ptr_mapped(maps_fp,
 				&tgt_ptr[i * page_size], page_size);
 
+		if (i & 1) {
+			if (is_mapped) {
+				ksft_print_msg("Gap unexpectedly mapped at %d\n", i);
+				success = false;
+				goto out_unmap;
+			}
+			continue;
+		}
+
 		if (i < 8 && !is_mapped) {
-			fprintf(stderr, "Valid VMA not moved at %d\n", i);
+			ksft_print_msg("Valid VMA not moved at %d\n", i);
 			success = false;
 			goto out_unmap;
 		} else if (i == 8 && is_mapped) {
-			fprintf(stderr, "Invalid VMA moved at %d\n", i);
+			ksft_print_msg("Invalid VMA moved at %d\n", i);
 			success = false;
 			goto out_unmap;
 		}
 	}
 
 out_unmap:
-	if (munmap(tgt_ptr, size))
-		perror("munmap tgt");
-	if (munmap(ptr, size))
-		perror("munmap src");
+	munmap(tgt_ptr, size);
+out_unmap_src:
+	munmap(ptr, size);
 out_close_uffd:
 	close(uffd);
 out:
-	if (success)
-		ksft_test_result_pass("%s\n", test_name);
-	else
-		ksft_test_result_fail("%s\n", test_name);
+	ksft_test_result(success, "%s\n", test_name);
 }
 #else
 static void mremap_move_multi_invalid_vmas(FILE *maps_fp, unsigned long page_size)
 {
 	char *test_name = "mremap move multiple invalid vmas";
 
-	ksft_test_result_skip("%s - missing uffd", test_name);
+	ksft_test_result_skip("%s - missing uffd\n", test_name);
 }
 #endif /* __NR_userfaultfd */
 
-/* Returns the time taken for the remap on success else returns -1. */
-static long long remap_region(struct config c, unsigned int threshold_mb,
-			      char *rand_addr)
+static void populate_test_data(char *addr, size_t size, char *pattern_addr,
+		size_t pattern_size, size_t page_size)
 {
-	void *addr, *tmp_addr, *src_addr, *dest_addr, *dest_preamble_addr = NULL;
-	struct timespec t_start = {0, 0}, t_end = {0, 0};
-	long long  start_ns, end_ns, align_mask, ret, offset;
-	unsigned long long threshold;
+	size_t mid, end;
+	size_t len = 10 * page_size;
 
-	if (threshold_mb == VALIDATION_NO_THRESHOLD)
-		threshold = c.region_size;
-	else
-		threshold = MIN(threshold_mb * _1MB, c.region_size);
+	if (size <= pattern_size) {
+		memcpy(addr, pattern_addr, size);
+		return;
+	}
+
+	end = size - len;
+	mid = end / 2;
+
+	memcpy(addr, pattern_addr, len);
+	memcpy(addr + mid, pattern_addr + len, len);
+	memcpy(addr + end, pattern_addr + 2 * len, len);
+}
+
+static bool validate_test_data(char *addr, size_t size, char *pattern_addr,
+		size_t pattern_size, size_t page_size)
+{
+	size_t mid, end;
+	size_t len = 10 * page_size;
+
+	if (size <= pattern_size)
+		return !memcmp(addr, pattern_addr, size);
+
+	end = size - len;
+	mid = end / 2;
+
+	return !memcmp(addr, pattern_addr, len) &&
+	       !memcmp(addr + mid, pattern_addr + len, len) &&
+	       !memcmp(addr + end, pattern_addr + 2 * len, len);
+}
+
+static int remap_region(struct config c, char *pattern_addr, size_t pattern_size,
+		size_t page_size)
+{
+	void *addr, *tmp_addr, *src_addr, *dest_addr, *dest_preamble_addr = NULL;
+	long long align_mask, offset;
+	char *preamble_pattern = NULL;
+	int ret = 0;
 
 	src_addr = get_source_mapping(c);
 	if (!src_addr) {
@@ -990,7 +989,8 @@ static long long remap_region(struct config c, unsigned int threshold_mb,
 	}
 
 	/* Set byte pattern for source block. */
-	memcpy(src_addr, rand_addr, threshold);
+	populate_test_data(src_addr, c.region_size, pattern_addr,
+			   pattern_size, page_size);
 
 	/* Mask to zero out lower bits of address for alignment */
 	align_mask = ~(c.dest_alignment - 1);
@@ -1032,14 +1032,13 @@ static long long remap_region(struct config c, unsigned int threshold_mb,
 			goto clean_up_src;
 		}
 
+		preamble_pattern = pattern_addr + pattern_size - c.dest_preamble_size;
 		/* Set byte pattern for the dest preamble block. */
-		memcpy(dest_preamble_addr, rand_addr, c.dest_preamble_size);
+		memcpy(dest_preamble_addr, preamble_pattern, c.dest_preamble_size);
 	}
 
-	clock_gettime(CLOCK_MONOTONIC, &t_start);
 	dest_addr = mremap(src_addr, c.region_size, c.region_size,
-					  MREMAP_MAYMOVE|MREMAP_FIXED, (char *) addr);
-	clock_gettime(CLOCK_MONOTONIC, &t_end);
+			   MREMAP_MAYMOVE | MREMAP_FIXED, (char *)addr);
 
 	if (dest_addr == MAP_FAILED) {
 		ksft_print_msg("mremap failed: %s\n", strerror(errno));
@@ -1048,7 +1047,8 @@ static long long remap_region(struct config c, unsigned int threshold_mb,
 	}
 
 	/* Verify byte pattern after remapping */
-	if (memcmp(dest_addr, rand_addr, threshold)) {
+	if (!validate_test_data(dest_addr, c.region_size, pattern_addr,
+				pattern_size, page_size)) {
 		ksft_print_msg("Data after remap doesn't match\n");
 		ret = -1;
 		goto clean_up_dest;
@@ -1056,22 +1056,12 @@ static long long remap_region(struct config c, unsigned int threshold_mb,
 
 	/* Verify the dest preamble byte pattern after remapping */
 	if (c.dest_preamble_size &&
-	    memcmp(dest_preamble_addr, rand_addr, c.dest_preamble_size)) {
+	    memcmp(dest_preamble_addr, preamble_pattern, c.dest_preamble_size)) {
 		ksft_print_msg("Preamble data after remap doesn't match\n");
 		ret = -1;
 		goto clean_up_dest;
 	}
 
-	start_ns = t_start.tv_sec * NS_PER_SEC + t_start.tv_nsec;
-	end_ns = t_end.tv_sec * NS_PER_SEC + t_end.tv_nsec;
-	ret = end_ns - start_ns;
-
-/*
- * Since the destination address is specified using MREMAP_FIXED, subsequent
- * mremap will unmap any previous mapping at the address range specified by
- * dest_addr and region_size. This significantly affects the remap time of
- * subsequent tests. So we clean up mappings after each test.
- */
 clean_up_dest:
 	munmap(dest_addr, c.region_size);
 clean_up_dest_preamble:
@@ -1088,12 +1078,11 @@ static long long remap_region(struct config c, unsigned int threshold_mb,
  * the beginning of the mapping just because the aligned
  * down address landed on a mapping that maybe does not exist.
  */
-static void mremap_move_1mb_from_start(unsigned int pattern_seed,
-				       char *rand_addr)
+static void mremap_move_1mb_from_start(char *pattern_addr)
 {
 	char *test_name = "mremap move 1mb from start at 1MB+256KB aligned src";
 	void *src = NULL, *dest = NULL;
-	unsigned int i, success = 1;
+	unsigned int success = 1;
 
 	/* Config to reuse get_source_mapping() to do an aligned mmap. */
 	struct config c = {
@@ -1115,7 +1104,7 @@ static void mremap_move_1mb_from_start(unsigned int pattern_seed,
 	}
 
 	/* Set byte pattern for source block. */
-	memcpy(src, rand_addr, SIZE_MB(2));
+	memcpy(src, pattern_addr, SIZE_MB(2));
 
 	/*
 	 * Unmap the beginning of dest so that the aligned address
@@ -1124,177 +1113,97 @@ static void mremap_move_1mb_from_start(unsigned int pattern_seed,
 	munmap(dest, SIZE_MB(1));
 
 	void *new_ptr = mremap(src + SIZE_MB(1), SIZE_MB(1), SIZE_MB(1),
-						   MREMAP_MAYMOVE | MREMAP_FIXED, dest + SIZE_MB(1));
+			       MREMAP_MAYMOVE | MREMAP_FIXED, dest + SIZE_MB(1));
 	if (new_ptr == MAP_FAILED) {
-		perror("mremap");
+		ksft_perror("mremap");
 		success = 0;
 		goto out;
 	}
 
 	/* Verify byte pattern after remapping */
-	srand(pattern_seed);
-	for (i = 0; i < SIZE_MB(1); i++) {
-		char c = (char) rand();
-
-		if (((char *)src)[i] != c) {
-			ksft_print_msg("Data at src at %d got corrupted due to unrelated mremap\n",
-				       i);
-			ksft_print_msg("Expected: %#x\t Got: %#x\n", c & 0xff,
-					((char *) src)[i] & 0xff);
-			success = 0;
-		}
+	if (memcmp(src, pattern_addr, SIZE_MB(1))) {
+		ksft_print_msg("Data before the remapped range was corrupted\n");
+		success = 0;
 	}
 
 out:
-	if (src && munmap(src, c.region_size) == -1)
-		perror("munmap src");
+	if (src)
+		munmap(src, c.region_size);
 
-	if (dest && munmap(dest, c.region_size) == -1)
-		perror("munmap dest");
+	if (dest)
+		munmap(dest, c.region_size);
 
-	if (success)
-		ksft_test_result_pass("%s\n", test_name);
-	else
-		ksft_test_result_fail("%s\n", test_name);
+	ksft_test_result(success, "%s\n", test_name);
 }
 
-static void run_mremap_test_case(struct test test_case, int *failures,
-				 unsigned int threshold_mb,
-				 char *rand_addr)
+static void run_mremap_test_case(struct test test_case,
+				 char *pattern_addr,
+				 size_t pattern_size,
+				 size_t page_size)
 {
-	long long remap_time = remap_region(test_case.config, threshold_mb,
-					    rand_addr);
-
-	if (remap_time < 0) {
-		if (test_case.expect_failure) {
-			ksft_print_msg("%s: expected mremap failure\n",
-				       test_case.name);
-			ksft_test_result_xfail("%s\n", test_case.name);
-		} else {
+	int ret = remap_region(test_case.config, pattern_addr, pattern_size, page_size);
+
+	if (ret < 0) {
+		if (test_case.expect_failure)
+			ksft_test_result_xfail("%s: expected mremap failure\n",
+					       test_case.name);
+		else
 			ksft_test_result_fail("%s\n", test_case.name);
-			*failures += 1;
-		}
 	} else {
-		/*
-		 * Comparing mremap time is only applicable if entire region
-		 * was faulted in.
-		 */
-		if (threshold_mb == VALIDATION_NO_THRESHOLD ||
-		    test_case.config.region_size <= threshold_mb * _1MB) {
-			ksft_print_msg("%s: mremap time: %12lldns\n",
-				       test_case.name, remap_time);
-			ksft_test_result_pass("%s\n", test_case.name);
-		} else {
+		if (test_case.expect_failure)
+			ksft_test_result_fail("%s: unexpected mremap success\n",
+					      test_case.name);
+		else
 			ksft_test_result_pass("%s\n", test_case.name);
-		}
 	}
 }
 
-static void usage(const char *cmd)
-{
-	fprintf(stderr,
-		"Usage: %s [[-t <threshold_mb>] [-p <pattern_seed>]]\n"
-		"-t\t only validate threshold_mb of the remapped region\n"
-		"  \t if 0 is supplied no threshold is used; all tests\n"
-		"  \t are run and remapped regions validated fully.\n"
-		"  \t The default threshold used is 4MB.\n"
-		"-p\t provide a seed to generate the random pattern for\n"
-		"  \t validating the remapped region.\n", cmd);
-}
-
-static int parse_args(int argc, char **argv, unsigned int *threshold_mb,
-		      unsigned int *pattern_seed)
+static void fill_pattern(char *pattern_addr, size_t pattern_size, size_t page_size)
 {
-	const char *optstr = "t:p:";
-	int opt;
+	size_t nr_pages = pattern_size / page_size;
+	size_t words_per_page = page_size / sizeof(uint32_t);
+	size_t page, word;
 
-	while ((opt = getopt(argc, argv, optstr)) != -1) {
-		switch (opt) {
-		case 't':
-			*threshold_mb = atoi(optarg);
-			break;
-		case 'p':
-			*pattern_seed = atoi(optarg);
-			break;
-		default:
-			usage(argv[0]);
-			return -1;
-		}
-	}
+	for (page = 0; page < nr_pages; page++) {
+		uint32_t *page_addr = (uint32_t *)pattern_addr + page * words_per_page;
+		uint32_t val = page + 1;
 
-	if (optind < argc) {
-		usage(argv[0]);
-		return -1;
+		for (word = 0; word < words_per_page; word++)
+			page_addr[word] = val;
 	}
-
-	return 0;
 }
 
 #define MAX_TEST 15
-#define MAX_PERF_TEST 3
-int main(int argc, char **argv)
+int main(void)
 {
-	int failures = 0;
 	unsigned int i;
-	int run_perf_tests;
-	unsigned int threshold_mb = VALIDATION_DEFAULT_THRESHOLD;
-
-	/* hard-coded test configs */
-	size_t max_test_variable_region_size = _2GB;
-	size_t max_test_constant_region_size = _2MB;
-	size_t dest_preamble_size = 10 * _4MB;
 
-	unsigned int pattern_seed;
-	char *rand_addr;
-	size_t rand_size;
+	char *pattern_addr;
+	size_t pattern_size;
 	int num_expand_tests = 2;
 	int num_misc_tests = 9;
 	struct test test_cases[MAX_TEST] = {};
-	struct test perf_test_cases[MAX_PERF_TEST];
 	int page_size;
-	time_t t;
 	FILE *maps_fp;
 
 	ksft_print_header();
 
 	get_mmap_min_addr();
 
-	pattern_seed = (unsigned int) time(&t);
-
-	if (parse_args(argc, argv, &threshold_mb, &pattern_seed) < 0)
-		exit(EXIT_FAILURE);
-
-	ksft_print_msg("Test configs:\n");
-	ksft_print_msg("threshold_mb=%u\n", threshold_mb);
-	ksft_print_msg("pattern_seed=%u\n", pattern_seed);
-
 	/*
-	 * set preallocated random array according to test configs; see the
-	 * functions for the logic of setting the size
+	 * The 40MB destination preamble determines the pattern buffer size
 	 */
-	if (!threshold_mb)
-		rand_size = MAX(max_test_variable_region_size,
-				max_test_constant_region_size);
-	else
-		rand_size = MAX(MIN(threshold_mb * _1MB,
-				    max_test_variable_region_size),
-				max_test_constant_region_size);
-	rand_size = MAX(dest_preamble_size, rand_size);
-
-	rand_addr = (char *)mmap(NULL, rand_size, PROT_READ | PROT_WRITE,
-				 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
-	if (rand_addr == MAP_FAILED) {
-		perror("mmap");
-		ksft_exit_fail_msg("cannot mmap rand_addr\n");
-	}
+	pattern_size = 10 * _4MB;
 
-	/* fill stream of random bytes */
-	srand(pattern_seed);
-	for (unsigned long i = 0; i < rand_size; ++i)
-		rand_addr[i] = (char) rand();
+	pattern_addr = (char *)mmap(NULL, pattern_size, PROT_READ | PROT_WRITE,
+				    MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+	if (pattern_addr == MAP_FAILED)
+		ksft_exit_fail_perror("cannot mmap pattern_addr");
 
 	page_size = sysconf(_SC_PAGESIZE);
 
+	fill_pattern(pattern_addr, pattern_size, page_size);
+
 	/* Expected mremap failures */
 	test_cases[0] =	MAKE_TEST(page_size, page_size, page_size,
 				  OVERLAPPING, EXPECT_FAILURE,
@@ -1345,62 +1254,34 @@ int main(int argc, char **argv)
 				  "5MB mremap - Source 1MB-aligned, Dest 1MB-aligned with 40MB Preamble");
 	test_cases[14].config.dest_preamble_size = 10 * _4MB;
 
-	perf_test_cases[0] =  MAKE_TEST(page_size, page_size, _1GB, NON_OVERLAPPING, EXPECT_SUCCESS,
-					"1GB mremap - Source PTE-aligned, Destination PTE-aligned");
-	/*
-	 * mremap 1GB region - Page table level aligned time
-	 * comparison.
-	 */
-	perf_test_cases[1] = MAKE_TEST(PMD, PMD, _1GB, NON_OVERLAPPING, EXPECT_SUCCESS,
-				       "1GB mremap - Source PMD-aligned, Destination PMD-aligned");
-	perf_test_cases[2] = MAKE_TEST(PUD, PUD, _1GB, NON_OVERLAPPING, EXPECT_SUCCESS,
-				       "1GB mremap - Source PUD-aligned, Destination PUD-aligned");
-
-	run_perf_tests =  (threshold_mb == VALIDATION_NO_THRESHOLD) ||
-				(threshold_mb * _1MB >= _1GB);
-
-	ksft_set_plan(ARRAY_SIZE(test_cases) + (run_perf_tests ?
-		      ARRAY_SIZE(perf_test_cases) : 0) + num_expand_tests + num_misc_tests);
+	ksft_set_plan(ARRAY_SIZE(test_cases) + num_expand_tests + num_misc_tests);
 
 	for (i = 0; i < ARRAY_SIZE(test_cases); i++)
-		run_mremap_test_case(test_cases[i], &failures, threshold_mb,
-				     rand_addr);
+		run_mremap_test_case(test_cases[i], pattern_addr, pattern_size, page_size);
 
 	maps_fp = fopen("/proc/self/maps", "r");
 
 	if (maps_fp == NULL) {
-		munmap(rand_addr, rand_size);
+		munmap(pattern_addr, pattern_size);
 		ksft_exit_fail_msg("Failed to read /proc/self/maps: %s\n", strerror(errno));
 	}
 
 	mremap_expand_merge(maps_fp, page_size);
 	mremap_expand_merge_offset(maps_fp, page_size);
 
-	mremap_move_within_range(pattern_seed, rand_addr);
-	mremap_move_1mb_from_start(pattern_seed, rand_addr);
+	mremap_move_within_range(pattern_addr);
+	mremap_move_1mb_from_start(pattern_addr);
 	mremap_shrink_multiple_vmas(page_size, /* inplace= */true);
 	mremap_shrink_multiple_vmas(page_size, /* inplace= */false);
-	mremap_move_multiple_vmas(pattern_seed, page_size, /* dontunmap= */ false);
-	mremap_move_multiple_vmas(pattern_seed, page_size, /* dontunmap= */ true);
-	mremap_move_multiple_vmas_split(pattern_seed, page_size, /* dontunmap= */ false);
-	mremap_move_multiple_vmas_split(pattern_seed, page_size, /* dontunmap= */ true);
+	mremap_move_multiple_vmas(maps_fp, pattern_addr, page_size, /* dontunmap= */ false);
+	mremap_move_multiple_vmas(maps_fp, pattern_addr, page_size, /* dontunmap= */ true);
+	mremap_move_multiple_vmas_split(maps_fp, pattern_addr, page_size, /* dontunmap= */ false);
+	mremap_move_multiple_vmas_split(maps_fp, pattern_addr, page_size, /* dontunmap= */ true);
 	mremap_move_multi_invalid_vmas(maps_fp, page_size);
 
 	fclose(maps_fp);
 
-	if (run_perf_tests) {
-		ksft_print_msg("\n%s\n",
-		 "mremap HAVE_MOVE_PMD/PUD optimization time comparison for 1GB region:");
-		for (i = 0; i < ARRAY_SIZE(perf_test_cases); i++)
-			run_mremap_test_case(perf_test_cases[i], &failures,
-					     threshold_mb,
-					     rand_addr);
-	}
-
-	munmap(rand_addr, rand_size);
+	munmap(pattern_addr, pattern_size);
 
-	if (failures > 0)
-		ksft_exit_fail();
-	else
-		ksft_exit_pass();
+	ksft_finished();
 }

3/2 2026/11/02 21:06 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 18941
							output: 47
							thoughts: 324
						

Thoughts:
**Analyzing the Patch for WorthFuzzing**

Okay, let's break this down. My initial assessment hinges on whether this patch warrants fuzzing, and the instructions are pretty clear on the negative criteria. First, the patch modifies a single file: `tools/testing/selftests/mm/mremap_test.c`. That immediately raises a flag. Now, to Section 2. We are told to return `WorthFuzzing=false` if *all* modified code falls into certain categories. The key phrase here is "user-space self-tests."

Aha! `tools/testing/selftests/mm/mremap_test.c` lives right there in the `tools/testing/selftests/` directory. That's a classic user-space self-test. The instructions are very specific: these files are considered safe if they *do not* affect `vmlinux` or kernel modules, and these certainly don't. That ticks one of the negative criteria boxes.

But I'm a stickler for detail, and just to be 100% sure, I'm going to quickly verify this by double-checking the git diff. I'll probably run a simple tool check, or grep, or even a basic `git diff` check just to eliminate any hidden changes I might have overlooked. But, so far, based on the file path and the instructions, I'm leaning heavily towards a `WorthFuzzing=false` outcome here.



4/2 2026/11/02 21:06 tool grepper
0m Args:
{
  "Expression": "mremap_move_within_range",
  "PathPrefixes": [
    "tools/testing/selftests/mm/mremap_test.c"
  ]
}

Results:
{
  "Output": "tools/testing/selftests/mm/mremap_test.c=283=static void mremap_expand_merge_offset(FILE *maps_fp, unsigned long page_size)\n--\ntools/testing/selftests/mm/mremap_test.c-328- */\ntools/testing/selftests/mm/mremap_test.c:329:static void mremap_move_within_range(char *pattern_addr)\ntools/testing/selftests/mm/mremap_test.c-330-{\n--\ntools/testing/selftests/mm/mremap_test.c=1177=int main(void)\n--\ntools/testing/selftests/mm/mremap_test.c-1271-\ntools/testing/selftests/mm/mremap_test.c:1272:\tmremap_move_within_range(pattern_addr);\ntools/testing/selftests/mm/mremap_test.c-1273-\tmremap_move_1mb_from_start(pattern_addr);\n"
}

5/2 2026/11/02 21:06 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 19919
							output: 76
							thoughts: 298
						

Thoughts:
**Analyzing the Potential for Kernel Fuzzing**

Okay, let's break this down. First, I need to confirm if this commit actually touches any kernel files that would warrant fuzzing. The diff highlights only `tools/testing/selftests/mm/mremap_test.c`. Nothing else.

Now, let me reference Section 2 of my internal guidelines. Specifically, the bit about: "- User-space directories, self-tests, samples, or scripts (e.g., tools/, samples/, scripts/, usr/) that do not affect the compiled kernel image (vmlinux) or kernel modules." Bingo. This clearly falls under that category. Therefore, I'm setting `WorthFuzzing=false`.

Given `WorthFuzzing` is false, this means my `FocusSymbols` and `EnableConfigs` lists will be empty. And the rationale is straightforward and concise: this change is confined to a user-space selftest within `tools/`, it won't impact the kernel image or any kernel modules.

Finally, just a quick sanity check on the `set-results` parameters. `EnableConfigs` and `FocusSymbols` are empty, as expected, and the `Reasoning` reflects the fact that it only modifies user-space selftests and does not modify the kernel image or any kernel code. This all checks out.

Time to call `set-results`.



6/2 2026/11/02 21:06 tool set-results
0m Args:
{
  "EnableConfigs": [],
  "FocusSymbols": [],
  "Reasoning": "The patch only modifies user-space selftest code (tools/testing/selftests/mm/mremap_test.c) and does not affect the compiled kernel image or any kernel-space executable code.",
  "WorthFuzzing": false
}

Results:
{
  "EnableConfigs": null,
  "FocusSymbols": [],
  "Reasoning": "The patch only modifies user-space selftest code (tools/testing/selftests/mm/mremap_test.c) and does not affect the compiled kernel image or any kernel-space executable code.",
  "WorthFuzzing": false
}

7/1 2026/11/02 21:06 action If
0m Args:
{
  "WorthFuzzing": false
}

Results:
null

LLM Calls Summary:
Total Calls Total Tokens Avg Tokens Total Duration (Seconds) Avg Duration (Seconds)
Tool Calls Summary:
Total Calls Total Duration (Seconds) Avg Duration (Seconds)