| Seq | Timestamp | Type | Name | Duration |
|---|---|---|---|---|
| 0/0 | 2026/07/31 22:17 | flow | patch-triage |
0mArgs:null Results: {
"EnableConfigs": null,
"FocusSymbols": [],
"Reasoning": "The patch introduces `set_direct_map_ro_noflush` and uses it exclusively in `thp_shrinker_init`, which is an `__init` function executed only once during kernel boot. There are no runtime-reachable code paths that a fuzzer can trigger or focus on.",
"WorthFuzzing": false
} |
| 1/1 | 2026/07/31 22:17 | action | read-patch-diff |
0mArgs:null Results: {
"PatchDiff": "commit 3b602dfd5cecdbb08ebe9e86009f1e41a32d81c7\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate: Fri Jul 31 22:17:23 2026 +0000\n\n syz-cluster: applied patch under review\n\ndiff --git a/arch/arm64/include/asm/set_memory.h b/arch/arm64/include/asm/set_memory.h\nindex 90f61b17275e1..7083260303c3c 100644\n--- a/arch/arm64/include/asm/set_memory.h\n+++ b/arch/arm64/include/asm/set_memory.h\n@@ -14,6 +14,8 @@ int set_memory_valid(unsigned long addr, int numpages, int enable);\n int set_direct_map_invalid_noflush(struct page *page);\n int set_direct_map_default_noflush(struct page *page);\n int set_direct_map_valid_noflush(struct page *page, unsigned nr, bool valid);\n+int set_direct_map_ro_noflush(const void *addr, unsigned long nr_pages);\n+#define set_direct_map_ro_noflush set_direct_map_ro_noflush\n bool kernel_page_present(struct page *page);\n \n int set_memory_encrypted(unsigned long addr, int numpages);\ndiff --git a/arch/arm64/mm/pageattr.c b/arch/arm64/mm/pageattr.c\nindex ce035e1b4eaf6..c51236b616519 100644\n--- a/arch/arm64/mm/pageattr.c\n+++ b/arch/arm64/mm/pageattr.c\n@@ -365,6 +365,16 @@ int set_direct_map_valid_noflush(struct page *page, unsigned nr, bool valid)\n \treturn set_memory_valid(addr, nr, valid);\n }\n \n+int set_direct_map_ro_noflush(const void *addr, unsigned long nr_pages)\n+{\n+\tif (!can_set_direct_map())\n+\t\treturn 0;\n+\n+\treturn update_range_prot((unsigned long)addr, PAGE_SIZE * nr_pages,\n+\t\t\t\t __pgprot(PTE_RDONLY),\n+\t\t\t\t __pgprot(PTE_WRITE));\n+}\n+\n #ifdef CONFIG_DEBUG_PAGEALLOC\n /*\n * This is - apart from the return value - doing the same\ndiff --git a/arch/x86/include/asm/set_memory.h b/arch/x86/include/asm/set_memory.h\nindex 4362c26aa992d..bd3817e06052c 100644\n--- a/arch/x86/include/asm/set_memory.h\n+++ b/arch/x86/include/asm/set_memory.h\n@@ -89,6 +89,8 @@ int set_pages_rw(struct page *page, int numpages);\n int set_direct_map_invalid_noflush(struct page *page);\n int set_direct_map_default_noflush(struct page *page);\n int set_direct_map_valid_noflush(struct page *page, unsigned nr, bool valid);\n+int set_direct_map_ro_noflush(const void *addr, unsigned long nr_pages);\n+#define set_direct_map_ro_noflush set_direct_map_ro_noflush\n bool kernel_page_present(struct page *page);\n \n extern int kernel_set_to_readonly;\ndiff --git a/arch/x86/mm/pat/set_memory.c b/arch/x86/mm/pat/set_memory.c\nindex d023a40a1e034..5987f4c84f6fe 100644\n--- a/arch/x86/mm/pat/set_memory.c\n+++ b/arch/x86/mm/pat/set_memory.c\n@@ -2662,6 +2662,21 @@ int set_direct_map_valid_noflush(struct page *page, unsigned nr, bool valid)\n \treturn __set_pages_np(page, nr);\n }\n \n+int set_direct_map_ro_noflush(const void *addr, unsigned long nr_pages)\n+{\n+\tunsigned long tempaddr = (unsigned long)addr;\n+\tstruct cpa_data cpa = {\n+\t\t.vaddr = \u0026tempaddr,\n+\t\t.pgd = NULL,\n+\t\t.numpages = nr_pages,\n+\t\t.mask_set = __pgprot(0),\n+\t\t.mask_clr = __pgprot(_PAGE_RW | _PAGE_DIRTY),\n+\t\t.flags = CPA_NO_CHECK_ALIAS,\n+\t};\n+\n+\treturn __change_page_attr_set_clr(\u0026cpa, 1);\n+}\n+\n #ifdef CONFIG_DEBUG_PAGEALLOC\n void __kernel_map_pages(struct page *page, int numpages, int enable)\n {\ndiff --git a/include/linux/set_memory.h b/include/linux/set_memory.h\nindex 3030d9245f5ac..e83ced6a38277 100644\n--- a/include/linux/set_memory.h\n+++ b/include/linux/set_memory.h\n@@ -40,6 +40,24 @@ static inline int set_direct_map_valid_noflush(struct page *page,\n \treturn 0;\n }\n \n+/**\n+ * set_direct_map_ro_noflush - make a direct-map range read-only\n+ * @addr: start address in the direct map\n+ * @nr_pages: number of pages starting at @addr\n+ *\n+ * Make the direct-map range starting at @addr read-only without invalidating\n+ * TLBs. Callers must either ensure that no stale writable translations can\n+ * be used, or treat the permission change as a best-effort hardening step.\n+ *\n+ * Return: 0 on success or when direct-map permission changes are unsupported,\n+ * or a negative errno on failure.\n+ */\n+static inline int set_direct_map_ro_noflush(const void *addr,\n+\t\t\t\t\t unsigned long nr_pages)\n+{\n+\treturn 0;\n+}\n+\n static inline bool kernel_page_present(struct page *page)\n {\n \treturn true;\n@@ -56,6 +74,17 @@ static inline bool can_set_direct_map(void)\n }\n #define can_set_direct_map can_set_direct_map\n #endif\n+\n+#ifndef set_direct_map_ro_noflush\n+/* See the comment above the generic fallback for the _noflush contract. */\n+static inline int set_direct_map_ro_noflush(const void *addr,\n+\t\t\t\t\t unsigned long nr_pages)\n+{\n+\treturn 0;\n+}\n+\n+#define set_direct_map_ro_noflush set_direct_map_ro_noflush\n+#endif\n #endif /* CONFIG_ARCH_HAS_SET_DIRECT_MAP */\n \n #ifdef CONFIG_X86_64\ndiff --git a/mm/huge_memory.c b/mm/huge_memory.c\nindex 970e077019b75..2dfc7a4218c3d 100644\n--- a/mm/huge_memory.c\n+++ b/mm/huge_memory.c\n@@ -40,8 +40,10 @@\n #include \u003clinux/pgalloc.h\u003e\n #include \u003clinux/pgalloc_tag.h\u003e\n #include \u003clinux/pagewalk.h\u003e\n+#include \u003clinux/set_memory.h\u003e\n \n #include \u003casm/tlb.h\u003e\n+#include \u003casm/tlbflush.h\u003e\n #include \"internal.h\"\n #include \"swap.h\"\n \n@@ -932,6 +934,8 @@ static int __init thp_shrinker_init(void)\n \tshrinker_register(deferred_split_shrinker);\n \n \tif (IS_ENABLED(CONFIG_PERSISTENT_HUGE_ZERO_FOLIO)) {\n+\t\tunsigned long addr;\n+\n \t\t/*\n \t\t * Bump the reference of the huge_zero_folio and do not\n \t\t * initialize the shrinker.\n@@ -940,8 +944,22 @@ static int __init thp_shrinker_init(void)\n \t\t * that get_huge_zero_folio() will most likely not fail as\n \t\t * thp_shrinker_init() is invoked early on during boot.\n \t\t */\n-\t\tif (!get_huge_zero_folio())\n+\t\tif (!get_huge_zero_folio()) {\n \t\t\tpr_warn(\"Allocating persistent huge zero folio failed\\n\");\n+\t\t\treturn 0;\n+\t\t}\n+\n+\t\t/* Highmem folios have no permanent direct-map mapping to protect. */\n+\t\tif (folio_test_highmem(huge_zero_folio))\n+\t\t\treturn 0;\n+\n+\t\taddr = (unsigned long)folio_address(huge_zero_folio);\n+\t\t/*\n+\t\t * The folio was zeroed through the writable direct map. Flush\n+\t\t * after the page-table update to invalidate stale translations.\n+\t\t */\n+\t\tset_direct_map_ro_noflush((void *)addr, HPAGE_PMD_NR);\n+\t\tflush_tlb_kernel_range(addr, addr + HPAGE_PMD_SIZE);\n \t\treturn 0;\n \t}\n \n"
} |
| 2/1 | 2026/07/31 22:17 | agent | patch-evaluator |
0mModel:best-expensive Args: null Results: {
"EnableConfigs": null,
"FocusSymbols": [],
"Reasoning": "The patch introduces `set_direct_map_ro_noflush` and uses it exclusively in `thp_shrinker_init`, which is an `__init` function executed only once during kernel boot. There are no runtime-reachable code paths that a fuzzer can trigger or focus on.",
"WorthFuzzing": false
}Instruction: You are an expert Linux kernel maintainer. Your job is to review a provided patch series and determine if it makes functional changes to the kernel that should be fuzzed. IMPORTANT: The changes have ALREADY been applied and committed as the HEAD commit in your workspace. Do NOT rely on your internal knowledge of the kernel. You must actively use your code access tools to examine the actual source code and confirm any assumptions. Return WorthFuzzing=false if the patch only contains: - Modifications to Documentation/, Kconfig files, or code comments. - Purely decorative changes, such as logging (e.g., pr_err, printk) or tracepoints. - Changes to numeric constants or macros that do not functionally alter execution flow. - Code paths that are impossible to reach in virtualized environments like GCE or QEMU, even when utilizing software-emulated hardware (e.g., usb gadget, mac80211_hwsim). - Code in vendor-specific PCIe switch, SmartNIC, or GPU drivers (e.g., mlxsw, pds_core, qed, ionic, amdgpu) that require physical PCIe hardware cards not emulated in standard QEMU. - Driver .remove, .shutdown, or pci_unregister_driver teardown callbacks (e.g., igb_remove) that are executed only during PCI hot-unplug or sysfs driver unbind operations. If it modifies reachable core kernel logic, drivers, or architectures, use your code search tools to verify the code can be executed, then return WorthFuzzing=true. When returning WorthFuzzing=true, you MUST ALSO: 1. Extract any specific kernel functions that should be heavily fuzzed into FocusSymbols. Avoid listing generic hot-path functions to prevent skewed test distributions. Prefer non-static, non-inlined API entrypoint functions over internal static helper functions (which are inlined by the compiler and do not have distinct symbol addresses). 2. Identify any specific CONFIG_ options required to properly test this new/modified feature. Go and look into the Kconfig files and check for ifdefs around the code, do not make assumptions. Also check "depends on" lines in Kconfig to include any non-standard parent subsystem configs needed for Kbuild to compile the code statically into vmlinux. List them in the EnableConfigs output array, and DO NOT add a '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: For your convenience, here is the diff of the changes:
commit 3b602dfd5cecdbb08ebe9e86009f1e41a32d81c7
Author: syz-cluster <triage@syzkaller.com>
Date: Fri Jul 31 22:17:23 2026 +0000
syz-cluster: applied patch under review
diff --git a/arch/arm64/include/asm/set_memory.h b/arch/arm64/include/asm/set_memory.h
index 90f61b17275e1..7083260303c3c 100644
--- a/arch/arm64/include/asm/set_memory.h
+++ b/arch/arm64/include/asm/set_memory.h
@@ -14,6 +14,8 @@ int set_memory_valid(unsigned long addr, int numpages, int enable);
int set_direct_map_invalid_noflush(struct page *page);
int set_direct_map_default_noflush(struct page *page);
int set_direct_map_valid_noflush(struct page *page, unsigned nr, bool valid);
+int set_direct_map_ro_noflush(const void *addr, unsigned long nr_pages);
+#define set_direct_map_ro_noflush set_direct_map_ro_noflush
bool kernel_page_present(struct page *page);
int set_memory_encrypted(unsigned long addr, int numpages);
diff --git a/arch/arm64/mm/pageattr.c b/arch/arm64/mm/pageattr.c
index ce035e1b4eaf6..c51236b616519 100644
--- a/arch/arm64/mm/pageattr.c
+++ b/arch/arm64/mm/pageattr.c
@@ -365,6 +365,16 @@ int set_direct_map_valid_noflush(struct page *page, unsigned nr, bool valid)
return set_memory_valid(addr, nr, valid);
}
+int set_direct_map_ro_noflush(const void *addr, unsigned long nr_pages)
+{
+ if (!can_set_direct_map())
+ return 0;
+
+ return update_range_prot((unsigned long)addr, PAGE_SIZE * nr_pages,
+ __pgprot(PTE_RDONLY),
+ __pgprot(PTE_WRITE));
+}
+
#ifdef CONFIG_DEBUG_PAGEALLOC
/*
* This is - apart from the return value - doing the same
diff --git a/arch/x86/include/asm/set_memory.h b/arch/x86/include/asm/set_memory.h
index 4362c26aa992d..bd3817e06052c 100644
--- a/arch/x86/include/asm/set_memory.h
+++ b/arch/x86/include/asm/set_memory.h
@@ -89,6 +89,8 @@ int set_pages_rw(struct page *page, int numpages);
int set_direct_map_invalid_noflush(struct page *page);
int set_direct_map_default_noflush(struct page *page);
int set_direct_map_valid_noflush(struct page *page, unsigned nr, bool valid);
+int set_direct_map_ro_noflush(const void *addr, unsigned long nr_pages);
+#define set_direct_map_ro_noflush set_direct_map_ro_noflush
bool kernel_page_present(struct page *page);
extern int kernel_set_to_readonly;
diff --git a/arch/x86/mm/pat/set_memory.c b/arch/x86/mm/pat/set_memory.c
index d023a40a1e034..5987f4c84f6fe 100644
--- a/arch/x86/mm/pat/set_memory.c
+++ b/arch/x86/mm/pat/set_memory.c
@@ -2662,6 +2662,21 @@ int set_direct_map_valid_noflush(struct page *page, unsigned nr, bool valid)
return __set_pages_np(page, nr);
}
+int set_direct_map_ro_noflush(const void *addr, unsigned long nr_pages)
+{
+ unsigned long tempaddr = (unsigned long)addr;
+ struct cpa_data cpa = {
+ .vaddr = &tempaddr,
+ .pgd = NULL,
+ .numpages = nr_pages,
+ .mask_set = __pgprot(0),
+ .mask_clr = __pgprot(_PAGE_RW | _PAGE_DIRTY),
+ .flags = CPA_NO_CHECK_ALIAS,
+ };
+
+ return __change_page_attr_set_clr(&cpa, 1);
+}
+
#ifdef CONFIG_DEBUG_PAGEALLOC
void __kernel_map_pages(struct page *page, int numpages, int enable)
{
diff --git a/include/linux/set_memory.h b/include/linux/set_memory.h
index 3030d9245f5ac..e83ced6a38277 100644
--- a/include/linux/set_memory.h
+++ b/include/linux/set_memory.h
@@ -40,6 +40,24 @@ static inline int set_direct_map_valid_noflush(struct page *page,
return 0;
}
+/**
+ * set_direct_map_ro_noflush - make a direct-map range read-only
+ * @addr: start address in the direct map
+ * @nr_pages: number of pages starting at @addr
+ *
+ * Make the direct-map range starting at @addr read-only without invalidating
+ * TLBs. Callers must either ensure that no stale writable translations can
+ * be used, or treat the permission change as a best-effort hardening step.
+ *
+ * Return: 0 on success or when direct-map permission changes are unsupported,
+ * or a negative errno on failure.
+ */
+static inline int set_direct_map_ro_noflush(const void *addr,
+ unsigned long nr_pages)
+{
+ return 0;
+}
+
static inline bool kernel_page_present(struct page *page)
{
return true;
@@ -56,6 +74,17 @@ static inline bool can_set_direct_map(void)
}
#define can_set_direct_map can_set_direct_map
#endif
+
+#ifndef set_direct_map_ro_noflush
+/* See the comment above the generic fallback for the _noflush contract. */
+static inline int set_direct_map_ro_noflush(const void *addr,
+ unsigned long nr_pages)
+{
+ return 0;
+}
+
+#define set_direct_map_ro_noflush set_direct_map_ro_noflush
+#endif
#endif /* CONFIG_ARCH_HAS_SET_DIRECT_MAP */
#ifdef CONFIG_X86_64
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index 970e077019b75..2dfc7a4218c3d 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -40,8 +40,10 @@
#include <linux/pgalloc.h>
#include <linux/pgalloc_tag.h>
#include <linux/pagewalk.h>
+#include <linux/set_memory.h>
#include <asm/tlb.h>
+#include <asm/tlbflush.h>
#include "internal.h"
#include "swap.h"
@@ -932,6 +934,8 @@ static int __init thp_shrinker_init(void)
shrinker_register(deferred_split_shrinker);
if (IS_ENABLED(CONFIG_PERSISTENT_HUGE_ZERO_FOLIO)) {
+ unsigned long addr;
+
/*
* Bump the reference of the huge_zero_folio and do not
* initialize the shrinker.
@@ -940,8 +944,22 @@ static int __init thp_shrinker_init(void)
* that get_huge_zero_folio() will most likely not fail as
* thp_shrinker_init() is invoked early on during boot.
*/
- if (!get_huge_zero_folio())
+ if (!get_huge_zero_folio()) {
pr_warn("Allocating persistent huge zero folio failed\n");
+ return 0;
+ }
+
+ /* Highmem folios have no permanent direct-map mapping to protect. */
+ if (folio_test_highmem(huge_zero_folio))
+ return 0;
+
+ addr = (unsigned long)folio_address(huge_zero_folio);
+ /*
+ * The folio was zeroed through the writable direct map. Flush
+ * after the page-table update to invalidate stale translations.
+ */
+ set_direct_map_ro_noflush((void *)addr, HPAGE_PMD_NR);
+ flush_tlb_kernel_range(addr, addr + HPAGE_PMD_SIZE);
return 0;
}
|
| 3/2 | 2026/07/31 22:17 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 4167 output: 26 thoughts: 349 Thoughts: **Analyzing a Boot-Time Memory Protection Patch** Okay, so I'm looking at this patch and it's introducing `set_direct_map_ro_noflush`, which is being used in `thp_shrinker_init`. The functional change here seems to be memory protection – making the persistent huge zero folio read-only in the direct map. This happens during boot, which is interesting because `thp_shrinker_init` is an `__init` function. My initial thought is, "is fuzzing even applicable here?". Fuzzing generally targets runtime behaviors, syscalls, things that are constantly interacting with the system. This, on the other hand, is a one-time thing that runs during boot. So, I have to consider whether this is a fruitful area for fuzzing. Let me quickly confirm – is `thp_shrinker_init` *only* used here? I need to be sure. Alright, yes, within *this* patch, it looks like it's only used in `thp_shrinker_init`. But I better double-check the diff again to be absolutely certain. Okay, I'm now looking at the broader context. This `thp_shrinker_init` call is indeed early in the boot process. The new function, `set_direct_map_ro_noflush`, has been added to `arch/arm64/mm/pageattr.c`, `arch/x86/mm/pat/set_memory.c`, and it's used within `mm/huge_memory.c`. Specifically, the usage in `mm/huge_memory.c` is within an `if (IS_ENABLED(CONFIG_PERSISTENT_HUGE_ZERO_FOLIO))` block. So, the next logical step is to understand what `CONFIG_PERSISTENT_HUGE_ZERO_FOLIO` actually *is*. I need to find its definition. I'll use my grepper tool to get the definition. |
| 4/2 | 2026/07/31 22:17 | tool | grepper |
0mArgs:{
"Expression": "config PERSISTENT_HUGE_ZERO_FOLIO"
}Results: {
"Output": "mm/Kconfig=771=config ARCH_WANTS_THP_SWAP\n--\nmm/Kconfig-773-\nmm/Kconfig:774:config PERSISTENT_HUGE_ZERO_FOLIO\nmm/Kconfig-775-\tbool \"Allocate a PMD sized folio for zeroing\"\n"
} |
| 5/2 | 2026/07/31 22:17 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 5061 output: 32 thoughts: 17 Thoughts: Here's a summary of my thought process, as requested: **Navigating the Kconfig Labyrinth** Okay, so I'm diving back into this configuration space. I need to get a better handle on how this specific feature is implemented, so I'm thinking I'll start with the main `mm/Kconfig` file. Specifically, I'm going to jump to around line 774. That's usually a good place to start when I'm looking for the definitions related to a kernel memory management related feature, as that section is usually a good starting place for related topics. I'm hoping to find the dependencies, the build options, and how everything is hooked together. Let's see what gems lie within. |
| 6/2 | 2026/07/31 22:17 | tool | read-file |
0mArgs:{
"File": "mm/Kconfig",
"FirstLine": 770,
"LineCount": 20
}Results: {
"Contents": " 770:\t\n 771:\tconfig ARCH_WANTS_THP_SWAP\n 772:\t\tdef_bool n\n 773:\t\n 774:\tconfig PERSISTENT_HUGE_ZERO_FOLIO\n 775:\t\tbool \"Allocate a PMD sized folio for zeroing\"\n 776:\t\tdepends on TRANSPARENT_HUGEPAGE\n 777:\t\thelp\n 778:\t\t Enable this option to reduce the runtime refcounting overhead\n 779:\t\t of the huge zero folio and expand the places in the kernel\n 780:\t\t that can use huge zero folios. For instance, block I/O benefits\n 781:\t\t from access to large folios for zeroing memory.\n 782:\t\n 783:\t\t With this option enabled, the huge zero folio is allocated\n 784:\t\t once and never freed. One full huge page's worth of memory shall\n 785:\t\t be used.\n 786:\t\n 787:\t\t Say Y if your system has lots of memory. Say N if you are\n 788:\t\t memory constrained.\n 789:\t\n"
} |
| 7/2 | 2026/07/31 22:17 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 5574 output: 24 thoughts: 402 Thoughts: **Fuzzing This Patch: Worth the Effort?** Alright, let's break this down. We're looking at `CONFIG_PERSISTENT_HUGE_ZERO_FOLIO`, and this patch makes the huge zero folio read-only in the direct map. This is clearly a security hardening measure, aimed at preventing accidental writes and thus, potential vulnerabilities. My initial thought is, does this introduce any new code paths that are repeatedly reachable, which would make it fuzzable? The patch adds `set_direct_map_ro_noflush`, and the way it's used looks like it's only called once during boot. If that's the case, fuzzing seems less impactful, since it's just a permission change that occurs before the fuzzer even has a chance to run. It's essentially initializing something. However... if this read-only setting catches any accidental writes, that *is* a hardening feature that the fuzzer could potentially expose by triggering those writes. If the fuzzer can trigger writes to this folio, and the kernel would panic as a result, that *is* a bug the fuzzer could expose. The problem is, this patch *is* just the initialization itself. The question is, does the boot-time nature of this code make it worth fuzzing? I recall the check for "WorthFuzzing". It lists scenarios where we *shouldn't* fuzz, things like "Code paths that are impossible to reach in virtualized environments", "Purely decorative changes", "Documentation modifications", "Changes to numeric constants", or ".remove" code. But it doesn't *explicitly* exclude "boot-time only initialization." Then, I remember, the key here is `set_direct_map_ro_noflush`. This is a new API. But *is* it used anywhere else? It's called *only* in `thp_shrinker_init`. Now the key is, is `thp_shrinker_init` only called during boot? Let's check. |
| 8/2 | 2026/07/31 22:17 | tool | grepper |
0mArgs:{
"Expression": "set_direct_map_ro_noflush"
}Results: {
"Output": "arch/arm64/include/asm/set_memory.h=16=int set_direct_map_valid_noflush(struct page *page, unsigned nr, bool valid);\narch/arm64/include/asm/set_memory.h:17:int set_direct_map_ro_noflush(const void *addr, unsigned long nr_pages);\narch/arm64/include/asm/set_memory.h:18:#define set_direct_map_ro_noflush set_direct_map_ro_noflush\narch/arm64/include/asm/set_memory.h-19-bool kernel_page_present(struct page *page);\n--\narch/arm64/mm/pageattr.c=358=int set_direct_map_valid_noflush(struct page *page, unsigned nr, bool valid)\n--\narch/arm64/mm/pageattr.c-367-\narch/arm64/mm/pageattr.c:368:int set_direct_map_ro_noflush(const void *addr, unsigned long nr_pages)\narch/arm64/mm/pageattr.c-369-{\n--\narch/x86/include/asm/set_memory.h=91=int set_direct_map_valid_noflush(struct page *page, unsigned nr, bool valid);\narch/x86/include/asm/set_memory.h:92:int set_direct_map_ro_noflush(const void *addr, unsigned long nr_pages);\narch/x86/include/asm/set_memory.h:93:#define set_direct_map_ro_noflush set_direct_map_ro_noflush\narch/x86/include/asm/set_memory.h-94-bool kernel_page_present(struct page *page);\n--\narch/x86/mm/pat/set_memory.c=2657=int set_direct_map_valid_noflush(struct page *page, unsigned nr, bool valid)\n--\narch/x86/mm/pat/set_memory.c-2664-\narch/x86/mm/pat/set_memory.c:2665:int set_direct_map_ro_noflush(const void *addr, unsigned long nr_pages)\narch/x86/mm/pat/set_memory.c-2666-{\n--\ninclude/linux/set_memory.h=37=static inline int set_direct_map_valid_noflush(struct page *page,\n--\ninclude/linux/set_memory.h-43-/**\ninclude/linux/set_memory.h:44: * set_direct_map_ro_noflush - make a direct-map range read-only\ninclude/linux/set_memory.h-45- * @addr: start address in the direct map\n--\ninclude/linux/set_memory.h-54- */\ninclude/linux/set_memory.h:55:static inline int set_direct_map_ro_noflush(const void *addr,\ninclude/linux/set_memory.h-56-\t\t\t\t\t unsigned long nr_pages)\n--\ninclude/linux/set_memory.h=71=static inline bool can_set_direct_map(void)\n--\ninclude/linux/set_memory.h-77-\ninclude/linux/set_memory.h:78:#ifndef set_direct_map_ro_noflush\ninclude/linux/set_memory.h-79-/* See the comment above the generic fallback for the _noflush contract. */\ninclude/linux/set_memory.h:80:static inline int set_direct_map_ro_noflush(const void *addr,\ninclude/linux/set_memory.h-81-\t\t\t\t\t unsigned long nr_pages)\n--\ninclude/linux/set_memory.h-85-\ninclude/linux/set_memory.h:86:#define set_direct_map_ro_noflush set_direct_map_ro_noflush\ninclude/linux/set_memory.h-87-#endif\n--\nmm/huge_memory.c=923=static int __init thp_shrinker_init(void)\n--\nmm/huge_memory.c-960-\t\t */\nmm/huge_memory.c:961:\t\tset_direct_map_ro_noflush((void *)addr, HPAGE_PMD_NR);\nmm/huge_memory.c-962-\t\tflush_tlb_kernel_range(addr, addr + HPAGE_PMD_SIZE);\n"
} |
| 9/2 | 2026/07/31 22:17 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 7552 output: 35 thoughts: 310 Thoughts: **Analyzing the Fuzzing Potential of This Code** Okay, so this change seems to be limited to `thp_shrinker_init`. Since it's an initialization function (`__init`), it's only called once during boot, right? The question is, can this be effectively fuzzed? My initial thought is no. Fuzzing generally focuses on functions that are reachable at runtime, triggered by syscalls or other inputs. If a function is only called during boot, a fuzzer can't target it. However, the patch *does* introduce `set_direct_map_ro_noflush`, which is new code located in both `arch/arm64/mm/pageattr.c` and `arch/x86/mm/pat/set_memory.c`. Now *that* sounds like potential fuzzing targets. But wait... are those called from anywhere *other* than `thp_shrinker_init`? No, it looks like they are only called from within `thp_shrinker_init` as well. So, in essence, there are no runtime-accessible functions here that a fuzzer could directly trigger. If I were to indicate "WorthFuzzing=false", the reason would be that the code is *only* executed once during the boot process and not by the fuzzer. Let me just quickly double-check that there aren't any other sneaky changes here. Okay, nope, it's just `set_direct_map_ro_noflush` and its use in `thp_shrinker_init`. Hmmm, is there *any* way to re-trigger `thp_shrinker_init`? Nope, it looks like it's a `module_init` or a `subsys_initcall` or similar. It’s definitely not something that I can reasonably expect to happen after the initial boot sequence. Let's move on and take a look at `mm/huge_memory.c` just to be sure. |
| 10/2 | 2026/07/31 22:17 | tool | read-file |
0mArgs:{
"File": "mm/huge_memory.c",
"FirstLine": 920,
"LineCount": 50
}Results: {
"Contents": " 920:\t}\n 921:\t#endif /* CONFIG_SYSFS */\n 922:\t\n 923:\tstatic int __init thp_shrinker_init(void)\n 924:\t{\n 925:\t\tdeferred_split_shrinker = shrinker_alloc(SHRINKER_NUMA_AWARE |\n 926:\t\t\t\t\t\t\t SHRINKER_MEMCG_AWARE |\n 927:\t\t\t\t\t\t\t SHRINKER_NONSLAB,\n 928:\t\t\t\t\t\t\t \"thp-deferred_split\");\n 929:\t\tif (!deferred_split_shrinker)\n 930:\t\t\treturn -ENOMEM;\n 931:\t\n 932:\t\tdeferred_split_shrinker-\u003ecount_objects = deferred_split_count;\n 933:\t\tdeferred_split_shrinker-\u003escan_objects = deferred_split_scan;\n 934:\t\tshrinker_register(deferred_split_shrinker);\n 935:\t\n 936:\t\tif (IS_ENABLED(CONFIG_PERSISTENT_HUGE_ZERO_FOLIO)) {\n 937:\t\t\tunsigned long addr;\n 938:\t\n 939:\t\t\t/*\n 940:\t\t\t * Bump the reference of the huge_zero_folio and do not\n 941:\t\t\t * initialize the shrinker.\n 942:\t\t\t *\n 943:\t\t\t * huge_zero_folio will always be NULL on failure. We assume\n 944:\t\t\t * that get_huge_zero_folio() will most likely not fail as\n 945:\t\t\t * thp_shrinker_init() is invoked early on during boot.\n 946:\t\t\t */\n 947:\t\t\tif (!get_huge_zero_folio()) {\n 948:\t\t\t\tpr_warn(\"Allocating persistent huge zero folio failed\\n\");\n 949:\t\t\t\treturn 0;\n 950:\t\t\t}\n 951:\t\n 952:\t\t\t/* Highmem folios have no permanent direct-map mapping to protect. */\n 953:\t\t\tif (folio_test_highmem(huge_zero_folio))\n 954:\t\t\t\treturn 0;\n 955:\t\n 956:\t\t\taddr = (unsigned long)folio_address(huge_zero_folio);\n 957:\t\t\t/*\n 958:\t\t\t * The folio was zeroed through the writable direct map. Flush\n 959:\t\t\t * after the page-table update to invalidate stale translations.\n 960:\t\t\t */\n 961:\t\t\tset_direct_map_ro_noflush((void *)addr, HPAGE_PMD_NR);\n 962:\t\t\tflush_tlb_kernel_range(addr, addr + HPAGE_PMD_SIZE);\n 963:\t\t\treturn 0;\n 964:\t\t}\n 965:\t\n 966:\t\thuge_zero_folio_shrinker = shrinker_alloc(0, \"thp-zero\");\n 967:\t\tif (!huge_zero_folio_shrinker) {\n 968:\t\t\tshrinker_free(deferred_split_shrinker);\n 969:\t\t\treturn -ENOMEM;\n"
} |
| 11/2 | 2026/07/31 22:17 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 9131 output: 94 thoughts: 618 Thoughts: **My Assessment of the Patch's Fuzzing Potential** Okay, so I've got this patch involving `thp_shrinker_init`. Right away, I see it's an `__init` function, which means it's executed during the boot process. The added function, `set_direct_map_ro_noflush`, is only called from within `thp_shrinker_init`. My initial thought is that since this code runs only at boot, a fuzzer won't be able to reach it directly or meaningfully focus on it. I need to confirm if there is any other way to trigger `set_direct_map_ro_noflush`. I considered if there was another trigger path. Nope. So, I need to decide if this patch is actually worth fuzzing. I was leaning towards `WorthFuzzing: false`, as it's boot-time code. The prompt does list specific scenarios where I should return `WorthFuzzing: false`. The prompt doesn't explicitly mention boot-time code. But if I said `WorthFuzzing: true`, I'd need to provide `FocusSymbols`. What would those be? `set_direct_map_ro_noflush`? It's only called during boot; the fuzzer can't target it. `thp_shrinker_init`? Same problem: `__init` functions aren't typically fuzzed. This strengthens my inclination for `WorthFuzzing: false`. Let me just double-check, though, just to be absolutely sure. I'll grep the codebase for `set_direct_map_ro_noflush`. Okay, it's *only* used within `thp_shrinker_init`. So, it's definitely boot-time only. Therefore, my decision is **`WorthFuzzing: false`**. The reason I'm giving is: The patch introduces `set_direct_map_ro_noflush` and uses it exclusively within the `thp_shrinker_init` function, which is an `__init` function and is executed only once during kernel boot. There are no runtime-reachable code paths that a fuzzer could trigger or meaningfully focus on. |
| 12/2 | 2026/07/31 22:17 | tool | set-results |
0mArgs:{
"EnableConfigs": [],
"FocusSymbols": [],
"Reasoning": "The patch introduces `set_direct_map_ro_noflush` and uses it exclusively in `thp_shrinker_init`, which is an `__init` function executed only once during kernel boot. There are no runtime-reachable code paths that a fuzzer can trigger or focus on.",
"WorthFuzzing": false
}Results: {
"EnableConfigs": null,
"FocusSymbols": [],
"Reasoning": "The patch introduces `set_direct_map_ro_noflush` and uses it exclusively in `thp_shrinker_init`, which is an `__init` function executed only once during kernel boot. There are no runtime-reachable code paths that a fuzzer can trigger or focus on.",
"WorthFuzzing": false
} |
| Total Calls | Total Tokens | Avg Tokens | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|
| Total Calls | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|