| Seq | Timestamp | Type | Name | Duration |
|---|---|---|---|---|
| 0/0 | 2026/08/18 15:23 | flow | patch-triage |
6mArgs:null Results: {
"EnableConfigs": [
"BPF_SYSCALL",
"BPF_JIT"
],
"FocusSymbols": [
"arch_bpf_trampoline_size",
"bpf_trampoline_link_prog",
"bpf_struct_ops_prepare_trampoline"
],
"KMSANReasoning": "The patch replaces `bpf_jit_alloc_exec_rw` with `execmem_alloc` for allocating a temporary buffer used to calculate the BPF trampoline size. The buffer is only written to during the size calculation and then immediately freed. There is no risk of uninitialized memory being read, copied to userspace, or used in control flow. Any potential memory errors (like out-of-bounds writes) would be caught by KASAN. Therefore, a dedicated KMSAN fuzzing session is not required.",
"NeedsKMSAN": false,
"Reasoning": "The patch changes the memory allocation type for BPF trampolines from EXECMEM_BPF (via bpf_jit_alloc_exec_rw) to EXECMEM_MODULE_DATA (via execmem_alloc). This affects memory permissions and allocation pools for BPF trampolines, which are heavily used in tracing and networking. Fuzzing BPF trampoline updates and struct_ops preparation is recommended to ensure the new memory allocation behaves correctly.",
"WorthFuzzing": true
} |
| 1/1 | 2026/08/18 15:23 | action | read-patch-diff |
0mArgs:null Results: {
"PatchDiff": "commit ee56e85b1a8230b0ba190425320380df327d8cb7\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate: Tue Aug 18 15:23:31 2026 +0000\n\n syz-cluster: applied patch under review\n\ndiff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c\nindex 1a9fb530adc3c..2853e87797a78 100644\n--- a/arch/x86/net/bpf_jit_comp.c\n+++ b/arch/x86/net/bpf_jit_comp.c\n@@ -13,6 +13,7 @@\n #include \u003clinux/bpf_verifier.h\u003e\n #include \u003clinux/memory.h\u003e\n #include \u003clinux/sort.h\u003e\n+#include \u003clinux/execmem.h\u003e\n #include \u003casm/extable.h\u003e\n #include \u003casm/ftrace.h\u003e\n #include \u003casm/set_memory.h\u003e\n@@ -3818,15 +3819,16 @@ int arch_bpf_trampoline_size(const struct btf_func_model *m, u32 flags,\n \t *\n \t * We cannot use kvmalloc here, because we need image to be in\n \t * module memory range.\n-\t * Since it must be writable use bpf_jit_alloc_exec_rw().\n+\t * Since it must be writable use execmem_alloc(EXECMEM_MODULE_DATA)\n+\t * that returns writable memory in the module address space.\n \t */\n-\timage = bpf_jit_alloc_exec_rw(PAGE_SIZE);\n+\timage = execmem_alloc(EXECMEM_MODULE_DATA, PAGE_SIZE);\n \tif (!image)\n \t\treturn -ENOMEM;\n \n \tret = __arch_prepare_bpf_trampoline(\u0026im, image, image + PAGE_SIZE, image,\n \t\t\t\t\t m, flags, tnodes, func_addr);\n-\tbpf_jit_free_exec(image);\n+\texecmem_free(image);\n \treturn ret;\n }\n \ndiff --git a/include/linux/filter.h b/include/linux/filter.h\nindex 4a9bc6a848f2e..39decde7fc730 100644\n--- a/include/linux/filter.h\n+++ b/include/linux/filter.h\n@@ -1376,7 +1376,6 @@ bpf_jit_binary_alloc(unsigned int proglen, u8 **image_ptr,\n void bpf_jit_binary_free(struct bpf_binary_header *hdr);\n u64 bpf_jit_alloc_exec_limit(void);\n void *bpf_jit_alloc_exec(unsigned long size);\n-void *bpf_jit_alloc_exec_rw(unsigned long size);\n void bpf_jit_free_exec(void *addr);\n void bpf_jit_free(struct bpf_prog *fp);\n struct bpf_binary_header *\ndiff --git a/kernel/bpf/core.c b/kernel/bpf/core.c\nindex d55e737ed75ad..8b294dfc1ad4d 100644\n--- a/kernel/bpf/core.c\n+++ b/kernel/bpf/core.c\n@@ -1128,11 +1128,6 @@ void *bpf_jit_alloc_exec(unsigned long size)\n \treturn execmem_alloc(EXECMEM_BPF, size);\n }\n \n-void *bpf_jit_alloc_exec_rw(unsigned long size)\n-{\n-\treturn execmem_alloc_rw(EXECMEM_BPF, size);\n-}\n-\n void bpf_jit_free_exec(void *addr)\n {\n \texecmem_free(addr);\n"
} |
| 2/1 | 2026/08/18 15:23 | agent | patch-evaluator |
6mModel:best-expensive Args: null Results: {
"EnableConfigs": [
"BPF_SYSCALL",
"BPF_JIT"
],
"FocusSymbols": [
"arch_bpf_trampoline_size",
"bpf_trampoline_link_prog",
"bpf_struct_ops_prepare_trampoline"
],
"Reasoning": "The patch changes the memory allocation type for BPF trampolines from EXECMEM_BPF (via bpf_jit_alloc_exec_rw) to EXECMEM_MODULE_DATA (via execmem_alloc). This affects memory permissions and allocation pools for BPF trampolines, which are heavily used in tracing and networking. Fuzzing BPF trampoline updates and struct_ops preparation is recommended to ensure the new memory allocation behaves correctly.",
"WorthFuzzing": true
}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 ee56e85b1a8230b0ba190425320380df327d8cb7
Author: syz-cluster <triage@syzkaller.com>
Date: Tue Aug 18 15:23:31 2026 +0000
syz-cluster: applied patch under review
diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c
index 1a9fb530adc3c..2853e87797a78 100644
--- a/arch/x86/net/bpf_jit_comp.c
+++ b/arch/x86/net/bpf_jit_comp.c
@@ -13,6 +13,7 @@
#include <linux/bpf_verifier.h>
#include <linux/memory.h>
#include <linux/sort.h>
+#include <linux/execmem.h>
#include <asm/extable.h>
#include <asm/ftrace.h>
#include <asm/set_memory.h>
@@ -3818,15 +3819,16 @@ int arch_bpf_trampoline_size(const struct btf_func_model *m, u32 flags,
*
* We cannot use kvmalloc here, because we need image to be in
* module memory range.
- * Since it must be writable use bpf_jit_alloc_exec_rw().
+ * Since it must be writable use execmem_alloc(EXECMEM_MODULE_DATA)
+ * that returns writable memory in the module address space.
*/
- image = bpf_jit_alloc_exec_rw(PAGE_SIZE);
+ image = execmem_alloc(EXECMEM_MODULE_DATA, PAGE_SIZE);
if (!image)
return -ENOMEM;
ret = __arch_prepare_bpf_trampoline(&im, image, image + PAGE_SIZE, image,
m, flags, tnodes, func_addr);
- bpf_jit_free_exec(image);
+ execmem_free(image);
return ret;
}
diff --git a/include/linux/filter.h b/include/linux/filter.h
index 4a9bc6a848f2e..39decde7fc730 100644
--- a/include/linux/filter.h
+++ b/include/linux/filter.h
@@ -1376,7 +1376,6 @@ bpf_jit_binary_alloc(unsigned int proglen, u8 **image_ptr,
void bpf_jit_binary_free(struct bpf_binary_header *hdr);
u64 bpf_jit_alloc_exec_limit(void);
void *bpf_jit_alloc_exec(unsigned long size);
-void *bpf_jit_alloc_exec_rw(unsigned long size);
void bpf_jit_free_exec(void *addr);
void bpf_jit_free(struct bpf_prog *fp);
struct bpf_binary_header *
diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
index d55e737ed75ad..8b294dfc1ad4d 100644
--- a/kernel/bpf/core.c
+++ b/kernel/bpf/core.c
@@ -1128,11 +1128,6 @@ void *bpf_jit_alloc_exec(unsigned long size)
return execmem_alloc(EXECMEM_BPF, size);
}
-void *bpf_jit_alloc_exec_rw(unsigned long size)
-{
- return execmem_alloc_rw(EXECMEM_BPF, size);
-}
-
void bpf_jit_free_exec(void *addr)
{
execmem_free(addr);
|
| 3/2 | 2026/08/18 15:23 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 2690 output: 23 thoughts: 340 Thoughts: **Analyzing a BPF JIT Compiler Patch** Okay, so I'm looking at a patch that touches `arch/x86/net/bpf_jit_comp.c`, `include/linux/filter.h`, and `kernel/bpf/core.c`. Seems straightforward enough: they're removing `bpf_jit_alloc_exec_rw` and swapping it out for `execmem_alloc(EXECMEM_MODULE_DATA, PAGE_SIZE)` in `arch_bpf_trampoline_size`, and the associated `bpf_jit_free_exec(image)` is now `execmem_free(image)`. Let's dive into `arch_bpf_trampoline_size` specifically. It's part of the BPF JIT compiler for x86; essentially, it figures out the size needed for a BPF trampoline. The core of the change is just switching the memory allocation function. Before, `bpf_jit_alloc_exec_rw` was calling `execmem_alloc_rw(EXECMEM_BPF, size)`. Now, it's using `execmem_alloc(EXECMEM_MODULE_DATA, PAGE_SIZE)`. Wait a minute, is this just a refactoring, or is there a functional impact here that warrants a closer look, possibly fuzzing? The critical difference is the memory allocation type. We're moving from `EXECMEM_BPF` (handled by `execmem_alloc_rw`) to `EXECMEM_MODULE_DATA` (using just `execmem_alloc`). This could potentially alter memory permissions, or the allocation pool used, which could introduce subtle bugs or even crashes if the new memory allocation type isn't perfectly compatible with how the BPF trampolines are handled. Given the highly specific nature of BPF trampolines, it's a tight scope, but worth checking. Let's revisit `arch_bpf_trampoline_size` again, specifically looking for any assumptions being made about memory characteristics. |
| 4/2 | 2026/08/18 15:23 | tool | grepper |
0mArgs:{
"Expression": "arch_bpf_trampoline_size"
}Results: {
"Output": "arch/arm64/net/bpf_jit_comp.c=2983=bool bpf_jit_supports_fsession(void)\n--\narch/arm64/net/bpf_jit_comp.c-2987-\narch/arm64/net/bpf_jit_comp.c:2988:int arch_bpf_trampoline_size(const struct btf_func_model *m, u32 flags,\narch/arm64/net/bpf_jit_comp.c-2989-\t\t\t struct bpf_tramp_nodes *tnodes, void *func_addr)\n--\narch/loongarch/net/bpf_jit.c=2144=int arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *ro_image,\n--\narch/loongarch/net/bpf_jit.c-2181-\narch/loongarch/net/bpf_jit.c:2182:int arch_bpf_trampoline_size(const struct btf_func_model *m, u32 flags,\narch/loongarch/net/bpf_jit.c-2183-\t\t\t struct bpf_tramp_nodes *tnodes, void *func_addr)\n--\narch/powerpc/net/bpf_jit_comp.c=812=static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *rw_image,\n--\narch/powerpc/net/bpf_jit_comp.c-1191-\narch/powerpc/net/bpf_jit_comp.c:1192:int arch_bpf_trampoline_size(const struct btf_func_model *m, u32 flags,\narch/powerpc/net/bpf_jit_comp.c-1193-\t\t\t struct bpf_tramp_nodes *tnodes, void *func_addr)\n--\narch/riscv/net/bpf_jit_comp64.c=992=static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im,\n--\narch/riscv/net/bpf_jit_comp64.c-1298-\narch/riscv/net/bpf_jit_comp64.c:1299:int arch_bpf_trampoline_size(const struct btf_func_model *m, u32 flags,\narch/riscv/net/bpf_jit_comp64.c-1300-\t\t\t struct bpf_tramp_nodes *tnodes, void *func_addr)\n--\narch/s390/net/bpf_jit_comp.c=2680=static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im,\n--\narch/s390/net/bpf_jit_comp.c-2995-\narch/s390/net/bpf_jit_comp.c:2996:int arch_bpf_trampoline_size(const struct btf_func_model *m, u32 flags,\narch/s390/net/bpf_jit_comp.c-2997-\t\t\t struct bpf_tramp_nodes *tnodes, void *orig_call)\n--\narch/x86/net/bpf_jit_comp.c=3782=int arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *image, void *image_end,\n--\narch/x86/net/bpf_jit_comp.c-3810-\narch/x86/net/bpf_jit_comp.c:3811:int arch_bpf_trampoline_size(const struct btf_func_model *m, u32 flags,\narch/x86/net/bpf_jit_comp.c-3812-\t\t\t struct bpf_tramp_nodes *tnodes, void *func_addr)\n--\ninclude/linux/bpf.h=1316=int __must_check arch_protect_bpf_trampoline(void *image, unsigned int size);\ninclude/linux/bpf.h:1317:int arch_bpf_trampoline_size(const struct btf_func_model *m, u32 flags,\ninclude/linux/bpf.h-1318-\t\t\t struct bpf_tramp_nodes *tnodes, void *func_addr);\n--\nkernel/bpf/bpf_struct_ops.c=637=int bpf_struct_ops_prepare_trampoline(struct bpf_tramp_nodes *tnodes,\n--\nkernel/bpf/bpf_struct_ops.c-653-\nkernel/bpf/bpf_struct_ops.c:654:\tsize = arch_bpf_trampoline_size(model, flags, tnodes, stub_func);\nkernel/bpf/bpf_struct_ops.c-655-\tif (size \u003c= 0)\n--\nkernel/bpf/trampoline.c=710=static int bpf_trampoline_update(struct bpf_trampoline *tr, bool lock_direct_mutex,\n--\nkernel/bpf/trampoline.c-761-\nkernel/bpf/trampoline.c:762:\tsize = arch_bpf_trampoline_size(\u0026tr-\u003efunc.model, tr-\u003eflags,\nkernel/bpf/trampoline.c-763-\t\t\t\t\ttnodes, tr-\u003efunc.addr);\n--\nkernel/bpf/trampoline.c=1508=int __weak arch_protect_bpf_trampoline(void *image, unsigned int size)\n--\nkernel/bpf/trampoline.c-1513-\nkernel/bpf/trampoline.c:1514:int __weak arch_bpf_trampoline_size(const struct btf_func_model *m, u32 flags,\nkernel/bpf/trampoline.c-1515-\t\t\t\t struct bpf_tramp_nodes *tnodes, void *func_addr)\n"
} |
| 5/2 | 2026/08/18 15:23 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 5013 output: 45 thoughts: 157 Thoughts: **Analyzing a Memory Allocation Change in BPF Trampolines** Okay, so this patch is tweaking how memory gets allocated for a temporary image, specifically within `arch_bpf_trampoline_size`. It's switching from using `bpf_jit_alloc_exec_rw(PAGE_SIZE)` to `execmem_alloc(EXECMEM_MODULE_DATA, PAGE_SIZE)`. Functionally, it's just a different memory allocation method, not a change in the intended use. But, since we are dealing with a critical element during BPF trampoline updates, this warrants a closer look. The interesting part is that `arch_bpf_trampoline_size` gets called during BPF trampoline updates. This makes me wonder about its fuzzing potential. Given BPF's history as a heavily fuzzed subsystem, this is definitely something to investigate further. Time to head over to `arch/x86/net/bpf_jit_comp.c` and check out the specifics of how `arch_bpf_trampoline_size` is used there. Let's see if this allocation shift introduces any new vulnerabilities or interesting angles for exploitability. |
| 6/2 | 2026/08/18 15:23 | tool | read-file |
0mArgs:{
"File": "arch/x86/net/bpf_jit_comp.c",
"FirstLine": 3811,
"LineCount": 30
}Results: {
"Contents": "3811:\tint arch_bpf_trampoline_size(const struct btf_func_model *m, u32 flags,\n3812:\t\t\t\t struct bpf_tramp_nodes *tnodes, void *func_addr)\n3813:\t{\n3814:\t\tstruct bpf_tramp_image im;\n3815:\t\tvoid *image;\n3816:\t\tint ret;\n3817:\t\n3818:\t\t/* Allocate a temporary buffer for __arch_prepare_bpf_trampoline().\n3819:\t\t *\n3820:\t\t * We cannot use kvmalloc here, because we need image to be in\n3821:\t\t * module memory range.\n3822:\t\t * Since it must be writable use execmem_alloc(EXECMEM_MODULE_DATA)\n3823:\t\t * that returns writable memory in the module address space.\n3824:\t\t */\n3825:\t\timage = execmem_alloc(EXECMEM_MODULE_DATA, PAGE_SIZE);\n3826:\t\tif (!image)\n3827:\t\t\treturn -ENOMEM;\n3828:\t\n3829:\t\tret = __arch_prepare_bpf_trampoline(\u0026im, image, image + PAGE_SIZE, image,\n3830:\t\t\t\t\t\t m, flags, tnodes, func_addr);\n3831:\t\texecmem_free(image);\n3832:\t\treturn ret;\n3833:\t}\n3834:\t\n3835:\tstatic int emit_bpf_dispatcher(u8 **pprog, int a, int b, s64 *progs, u8 *image, u8 *buf)\n3836:\t{\n3837:\t\tu8 *jg_reloc, *prog = *pprog;\n3838:\t\tint pivot, err, jg_bytes = 1;\n3839:\t\ts64 jg_offset;\n3840:\t\n"
} |
| 7/2 | 2026/08/18 15:23 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 5972 output: 21 thoughts: 310 Thoughts: **Analyzing a BPF JIT Memory Allocation Change** Okay, so this patch is switching `bpf_jit_alloc_exec_rw` to use `execmem_alloc(EXECMEM_MODULE_DATA, PAGE_SIZE)` instead. And, it looks like `bpf_jit_alloc_exec_rw` is getting completely ripped out of `kernel/bpf/core.c`. Hmm, I recall `bpf_jit_alloc_exec_rw` was previously calling `execmem_alloc_rw(EXECMEM_BPF, size)`. So `execmem_alloc_rw` itself isn't gone, just this wrapper. The key thing here is the change in memory type, from `EXECMEM_BPF` to `EXECMEM_MODULE_DATA`. That could have some interesting implications. Different memory types mean different allocation behavior. This could potentially expose bugs if `execmem_alloc` or the BPF trampoline generation code makes assumptions about the memory properties (like whether it's executable or non-executable, or which address space it lives in) based on the type. Given that BPF trampolines are crucial for tracing (fentry/fexit) and networking (struct_ops), it's a pretty fundamental piece of the kernel. This change is absolutely worth fuzzing. I'll flag it as `WorthFuzzing=true`. Now, let me make sure I understand the full scope of potential impact. I should probably focus on `arch_bpf_trampoline_size`, `bpf_trampoline_update`, and `bpf_struct_ops_prepare_trampoline`. Let's also dig into `kernel/bpf/trampoline.c` to see if there are other related functions I should keep an eye on. |
| 8/2 | 2026/08/18 15:24 | tool | grepper |
0mArgs:{
"Expression": "bpf_trampoline_update"
}Results: {
"Output": "kernel/bpf/trampoline.c=62=struct bpf_trampoline_ops {\n--\nkernel/bpf/trampoline.c-69-#ifdef CONFIG_DYNAMIC_FTRACE_WITH_DIRECT_CALLS\nkernel/bpf/trampoline.c:70:static int bpf_trampoline_update(struct bpf_trampoline *tr, bool lock_direct_mutex,\nkernel/bpf/trampoline.c-71-\t\t\t\t const struct bpf_trampoline_ops *ops, void *data);\n--\nkernel/bpf/trampoline.c=98=static int bpf_tramp_ftrace_ops_func(struct ftrace_ops *ops, unsigned long ip,\n--\nkernel/bpf/trampoline.c-156-\t\t !(tr-\u003eflags \u0026 BPF_TRAMP_F_ORIG_STACK))\nkernel/bpf/trampoline.c:157:\t\t\tret = bpf_trampoline_update(tr, false /* lock_direct_mutex */,\nkernel/bpf/trampoline.c-158-\t\t\t\t\t\t \u0026trampoline_ops, NULL);\n--\nkernel/bpf/trampoline.c-163-\t\tif (tr-\u003eflags \u0026 BPF_TRAMP_F_ORIG_STACK)\nkernel/bpf/trampoline.c:164:\t\t\tret = bpf_trampoline_update(tr, false /* lock_direct_mutex */,\nkernel/bpf/trampoline.c-165-\t\t\t\t\t\t \u0026trampoline_ops, NULL);\n--\nkernel/bpf/trampoline.c=373=static struct bpf_trampoline *bpf_trampoline_lookup(u64 key, unsigned long ip)\n--\nkernel/bpf/trampoline.c-410-\nkernel/bpf/trampoline.c:411:static int bpf_trampoline_update_fentry(struct bpf_trampoline *tr, u32 orig_flags,\nkernel/bpf/trampoline.c-412-\t\t\t\t\tvoid *old_addr, void *new_addr)\n--\nkernel/bpf/trampoline.c=432=static int unregister_fentry(struct bpf_trampoline *tr, u32 orig_flags, void *data __maybe_unused)\n--\nkernel/bpf/trampoline.c-439-\telse\nkernel/bpf/trampoline.c:440:\t\tret = bpf_trampoline_update_fentry(tr, orig_flags, old_addr, NULL);\nkernel/bpf/trampoline.c-441-\n--\nkernel/bpf/trampoline.c=450=static int modify_fentry(struct bpf_trampoline *tr, u32 orig_flags, struct bpf_tramp_image *im,\n--\nkernel/bpf/trampoline.c-459-\t} else {\nkernel/bpf/trampoline.c:460:\t\tret = bpf_trampoline_update_fentry(tr, orig_flags, old_addr,\nkernel/bpf/trampoline.c-461-\t\t\t\t\t\t new_addr);\n--\nkernel/bpf/trampoline.c=473=static int register_fentry(struct bpf_trampoline *tr, struct bpf_tramp_image *im,\n--\nkernel/bpf/trampoline.c-490-\t} else {\nkernel/bpf/trampoline.c:491:\t\tret = bpf_trampoline_update_fentry(tr, 0, NULL, new_addr);\nkernel/bpf/trampoline.c-492-\t}\n--\nkernel/bpf/trampoline.c=703=void bpf_trampoline_set_flags(struct bpf_trampoline *tr, u32 flags)\n--\nkernel/bpf/trampoline.c-709-\nkernel/bpf/trampoline.c:710:static int bpf_trampoline_update(struct bpf_trampoline *tr, bool lock_direct_mutex,\nkernel/bpf/trampoline.c-711-\t\t\t\t const struct bpf_trampoline_ops *ops, void *data)\n--\nkernel/bpf/trampoline.c=942=static int __bpf_trampoline_link_prog(struct bpf_tramp_node *node,\n--\nkernel/bpf/trampoline.c-983-\t\treturn err;\nkernel/bpf/trampoline.c:984:\terr = bpf_trampoline_update(tr, true /* lock_direct_mutex */, ops, data);\nkernel/bpf/trampoline.c-985-\tif (err)\n--\nkernel/bpf/trampoline.c=1002=static int __bpf_trampoline_unlink_prog(struct bpf_tramp_node *node,\n--\nkernel/bpf/trampoline.c-1022-\tbpf_trampoline_remove_prog(tr, node);\nkernel/bpf/trampoline.c:1023:\treturn bpf_trampoline_update(tr, true /* lock_direct_mutex */, ops, data);\nkernel/bpf/trampoline.c-1024-}\n--\nkernel/bpf/trampoline.c=1633=static void bpf_trampoline_multi_attach_free(struct bpf_trampoline *tr)\n--\nkernel/bpf/trampoline.c-1636-\t * Only free old_image if it is no longer the active image.\nkernel/bpf/trampoline.c:1637:\t * When bpf_trampoline_update() fails before modify_fentry_multi()/\nkernel/bpf/trampoline.c-1638-\t * unregister_fentry_multi() is called, cur_image is unchanged\n"
} |
| 9/2 | 2026/08/18 15:24 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 8101 output: 22 thoughts: 149 Thoughts: **Refining the BPF Trampoline Symbol Tracking** Okay, so the core of the change seems to be around `arch_bpf_trampoline_size`. My initial instinct was to add that, and also `bpf_trampoline_update`, to `FocusSymbols`. However, a quick scan reveals that `arch_bpf_trampoline_size` is directly called from `bpf_struct_ops_prepare_trampoline` and, obviously, `bpf_trampoline_update`. Thinking this through, it makes more sense to include both `bpf_trampoline_update` and `bpf_struct_ops_prepare_trampoline` in `FocusSymbols`. This will give me a more complete picture of how the trampoline size is actually being used and updated. Now, let me make sure the relevant configurations are enabled – that's `BPF_SYSCALL`, `BPF_JIT`, and then, of course, `BPF_TRAMPOLINE`, if it's even present in this configuration. Need to confirm the full setup. |
| 10/2 | 2026/08/18 15:24 | tool | grepper |
0mError:no matches Args: {
"Expression": "config BPF_TRAMPOLINE"
}Results: {
"error": "no matches"
} |
| 11/2 | 2026/08/18 15:24 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 8516 output: 20 thoughts: 25 Thoughts: Here's my thought process, as it went: **Examining BPF Configuration Options** Okay, so I need to find the configuration options related to BPF within the kernel. My instinct tells me to start digging into the `Kconfig` files, which handle the configuration variables. The kernel's configuration options are organized hierarchically, so the `kernel/bpf/Kconfig` file seems like the most logical first place to check. It's likely that a dedicated BPF section would reside there. However, just to be thorough and not miss anything obvious, I should also quickly glance at `init/Kconfig`. It's possible, though less probable, that some top-level BPF-related options are defined there, especially if they are core to the kernel's initialization. Best to be diligent and double-check, but I expect the real meat of the BPF configurations will reside in the first location. |
| 12/2 | 2026/08/18 15:24 | tool | grepper |
0mArgs:{
"Expression": "config BPF_JIT"
}Results: {
"Output": "kernel/bpf/Kconfig=27=config BPF_SYSCALL\n--\nkernel/bpf/Kconfig-41-\nkernel/bpf/Kconfig:42:config BPF_JIT\nkernel/bpf/Kconfig-43-\tbool \"Enable BPF Just In Time compiler\"\n--\nkernel/bpf/Kconfig-57-\nkernel/bpf/Kconfig:58:config BPF_JIT_ALWAYS_ON\nkernel/bpf/Kconfig-59-\tbool \"Permanently enable BPF JIT and remove BPF interpreter\"\n--\nkernel/bpf/Kconfig-68-\nkernel/bpf/Kconfig:69:config BPF_JIT_DEFAULT_ON\nkernel/bpf/Kconfig-70-\tdef_bool ARCH_WANT_DEFAULT_BPF_JIT || BPF_JIT_ALWAYS_ON\n"
} |
| 13/2 | 2026/08/18 15:24 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 8979 output: 25 thoughts: 292 Thoughts: **My Assessment of the BPF Trampoline Memory Allocation Change** Okay, so I'm integrating this change; I need to add `BPF_SYSCALL` and `BPF_JIT` to the `EnableConfigs`. That's straightforward. The core of this patch is a fundamental shift in how we allocate memory for BPF trampolines. I need to make sure I'm following the code. Specifically, I see that we're moving from using `bpf_jit_alloc_exec_rw` (and by extension, `EXECMEM_BPF`) to `execmem_alloc` with `EXECMEM_MODULE_DATA` . This is a major functional change. We're effectively changing the permissions and allocation pool for these critical trampolines. We use them *everywhere* in tracing, networking, the whole ecosystem. My analysis indicates that this affects `execmem_alloc` and `EXECMEM_MODULE_DATA`, which are integral components of this new `execmem` API. It's a significant change to how we manage memory for BPF execution, and I need to be *absolutely* certain we don't introduce regressions. To that end, fuzzing the BPF trampoline updates and struct_ops preparation becomes critical. I need to ensure the new memory allocation behaves predictably and doesn't introduce vulnerabilities. I will have to investigate `bpf_struct_ops_prepare_trampoline` and determine whether it's safe and non-static. The critical focus for my review will be on `arch_bpf_trampoline_size`, `bpf_trampoline_update`, and `bpf_struct_ops_prepare_trampoline`. |
| 14/2 | 2026/08/18 15:25 | tool | grepper |
0mArgs:{
"Expression": "bpf_struct_ops_prepare_trampoline"
}Results: {
"Output": "include/linux/bpf.h=2222=int bpf_struct_ops_map_sys_lookup_elem(struct bpf_map *map, void *key,\ninclude/linux/bpf.h-2223-\t\t\t\t void *value);\ninclude/linux/bpf.h:2224:int bpf_struct_ops_prepare_trampoline(struct bpf_tramp_nodes *tnodes,\ninclude/linux/bpf.h-2225-\t\t\t\t struct bpf_tramp_node *node,\n--\nkernel/bpf/bpf_struct_ops.c=632=const struct bpf_link_ops bpf_struct_ops_link_lops = {\n--\nkernel/bpf/bpf_struct_ops.c-636-\nkernel/bpf/bpf_struct_ops.c:637:int bpf_struct_ops_prepare_trampoline(struct bpf_tramp_nodes *tnodes,\nkernel/bpf/bpf_struct_ops.c-638-\t\t\t\t struct bpf_tramp_node *node,\n--\nkernel/bpf/bpf_struct_ops.c=726=static long bpf_struct_ops_map_update_elem(struct bpf_map *map, void *key,\n--\nkernel/bpf/bpf_struct_ops.c-875-\t\ttrampoline_start = image_off;\nkernel/bpf/bpf_struct_ops.c:876:\t\terr = bpf_struct_ops_prepare_trampoline(tnodes, \u0026link-\u003enode,\nkernel/bpf/bpf_struct_ops.c-877-\t\t\t\t\t\t\u0026st_ops-\u003efunc_models[i],\n--\nnet/bpf/bpf_dummy_struct_ops.c=129=int bpf_struct_ops_test_run(struct bpf_prog *prog, const union bpf_attr *kattr,\n--\nnet/bpf/bpf_dummy_struct_ops.c-177-\top_idx = prog-\u003eexpected_attach_type;\nnet/bpf/bpf_dummy_struct_ops.c:178:\terr = bpf_struct_ops_prepare_trampoline(tnodes, \u0026link-\u003enode,\nnet/bpf/bpf_dummy_struct_ops.c-179-\t\t\t\t\t\t\u0026st_ops-\u003efunc_models[op_idx],\n"
} |
| 15/2 | 2026/08/18 15:25 | llm | patch-evaluator |
1mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 10256 output: 23 thoughts: 147 Thoughts: **Analyzing the Static Nature of `bpf_trampoline_update`** Okay, so I'm looking at this code and immediately noticing something that feels a bit off. `bpf_trampoline_update` is marked as `static`. I know, I *know*, it's a core function, which is often a good reason for a static scope. But the prompt is specifically suggesting we favor non-static, non-inlined API entrypoints over static helpers. Let's make sure that's relevant here. Right, so to understand the context, let's see where this thing is used. Quick grep time... Ah, here we go. It's called by `__bpf_trampoline_link_prog`, `__bpf_trampoline_unlink_prog`, and `bpf_tramp_ftrace_ops_func`. Okay, helpful to know. And digging a little deeper, I see that `__bpf_trampoline_link_prog` is itself called by `bpf_trampoline_link_prog`. That's an interesting pattern. Seems like we may need to make a decision about visibility and scope. |
| 16/2 | 2026/08/18 15:26 | tool | grepper |
0mArgs:{
"Expression": "bpf_trampoline_link_prog"
}Results: {
"Output": "include/linux/bpf.h=1506=struct bpf_tracing_multi_link;\n--\ninclude/linux/bpf.h-1508-#ifdef CONFIG_BPF_JIT\ninclude/linux/bpf.h:1509:int bpf_trampoline_link_prog(struct bpf_tramp_node *node,\ninclude/linux/bpf.h-1510-\t\t\t struct bpf_trampoline *tr,\n--\ninclude/linux/bpf.h=1603=u16 bpf_out_stack_arg_cnt(const struct bpf_verifier_env *env, const struct bpf_prog *prog);\ninclude/linux/bpf.h-1604-#else\ninclude/linux/bpf.h:1605:static inline int bpf_trampoline_link_prog(struct bpf_tramp_node *node,\ninclude/linux/bpf.h-1606-\t\t\t\t\t struct bpf_trampoline *tr,\n--\nkernel/bpf/syscall.c=3634=static int bpf_tracing_prog_attach(struct bpf_prog *prog,\n--\nkernel/bpf/syscall.c-3740-\t\t * Allow re-attach for TRACING and LSM programs. If it's\nkernel/bpf/syscall.c:3741:\t\t * currently linked, bpf_trampoline_link_prog will fail.\nkernel/bpf/syscall.c-3742-\t\t * EXT programs need to specify tgt_prog_fd, so they\n--\nkernel/bpf/syscall.c-3814-\nkernel/bpf/syscall.c:3815:\terr = bpf_trampoline_link_prog(\u0026link-\u003elink.node, tr, tgt_prog);\nkernel/bpf/syscall.c-3816-\tif (err) {\n--\nkernel/bpf/trampoline.c=923=static void bpf_trampoline_remove_prog(struct bpf_trampoline *tr,\n--\nkernel/bpf/trampoline.c-941-\nkernel/bpf/trampoline.c:942:static int __bpf_trampoline_link_prog(struct bpf_tramp_node *node,\nkernel/bpf/trampoline.c-943-\t\t\t\t struct bpf_trampoline *tr,\n--\nkernel/bpf/trampoline.c-989-\nkernel/bpf/trampoline.c:990:int bpf_trampoline_link_prog(struct bpf_tramp_node *node,\nkernel/bpf/trampoline.c-991-\t\t\t struct bpf_trampoline *tr,\n--\nkernel/bpf/trampoline.c-996-\ttrampoline_lock(tr);\nkernel/bpf/trampoline.c:997:\terr = __bpf_trampoline_link_prog(node, tr, tgt_prog, \u0026trampoline_ops, NULL);\nkernel/bpf/trampoline.c-998-\ttrampoline_unlock(tr);\n--\nkernel/bpf/trampoline.c=1123=int bpf_trampoline_link_cgroup_shim(struct bpf_prog *prog,\n--\nkernel/bpf/trampoline.c-1165-\nkernel/bpf/trampoline.c:1166:\terr = __bpf_trampoline_link_prog(\u0026shim_link-\u003elink.node, tr, NULL, \u0026trampoline_ops, NULL);\nkernel/bpf/trampoline.c-1167-\tif (err)\n--\nkernel/bpf/trampoline.c=1669=int bpf_trampoline_multi_attach(struct bpf_prog *prog, u32 *ids,\n--\nkernel/bpf/trampoline.c-1718-\t\tdata-\u003eentry = \u0026mnode-\u003eentry;\nkernel/bpf/trampoline.c:1719:\t\terr = __bpf_trampoline_link_prog(\u0026mnode-\u003enode, mnode-\u003etrampoline, NULL,\nkernel/bpf/trampoline.c-1720-\t\t\t\t\t\t \u0026trampoline_multi_ops, data);\n"
} |
| 17/2 | 2026/08/18 15:26 | llm | patch-evaluator |
1mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 11705 output: 17 thoughts: 179 Thoughts: **My BPF Trampoline Thoughts** Okay, so I'm looking at this BPF trampoline code and thinking about the right approach for this. I need to make some key decisions. First, I remember that `bpf_trampoline_link_prog` is actually non-static. Excellent! That's perfect; I can leverage that instead of trying to shoehorn `bpf_trampoline_update`. Much cleaner. But wait a minute… what about `arch_bpf_trampoline_size`? That's also non-static, right? Yep, confirmed. Okay, so my focus for this implementation needs to be centered around a specific set of symbols. I need to keep track of these, for consistency: * `arch_bpf_trampoline_size` * `bpf_trampoline_link_prog` * `bpf_struct_ops_prepare_trampoline` Now, regarding that architecture-specific size function (`arch_bpf_trampoline_size`), I need to make absolutely sure it's consistently available. Yes, that's it, this is an architecture-specific function. So I will definitely need to include that within my scope. And, before I move on, I just want to run a quick mental check on `EXECMEM_MODULE_DATA`. Any specific configurations I should be aware of? Let me think... nothing jumps out at me as a red flag, so I think I'm good to move forward. |
| 18/2 | 2026/08/18 15:28 | tool | grepper |
0mArgs:{
"Expression": "config EXECMEM"
}Results: {
"Output": "mm/Kconfig=1454=config IOMMU_MM_DATA\n--\nmm/Kconfig-1456-\nmm/Kconfig:1457:config EXECMEM\nmm/Kconfig-1458-\tbool\n"
} |
| 19/2 | 2026/08/18 15:28 | llm | patch-evaluator |
1mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 12291 output: 17 thoughts: 25 Thoughts: Here's my summary, as though I'm thinking through this myself: **Considering `EXECMEM` and its Implications** Okay, so `EXECMEM` is a boolean configuration setting, and my initial hunch is that it's likely tied into something like `BPF_JIT` or a similar just-in-time compilation mechanism. That makes sense, given the name. The presence or absence of this setting will significantly impact memory management and security considerations, specifically around executable memory regions. I need to dig deeper into the contexts where `EXECMEM` is enabled and disabled to fully grasp its impact on performance and security within this specific environment. I need to look for related code paths. |
| 20/2 | 2026/08/18 15:29 | tool | grepper |
0mArgs:{
"Expression": "select EXECMEM"
}Results: {
"Output": "arch/Kconfig=117=config KPROBES\n--\narch/Kconfig-120-\tselect KALLSYMS\narch/Kconfig:121:\tselect EXECMEM\narch/Kconfig-122-\tselect NEED_TASKS_RCU\n--\narch/x86/Kconfig=23=config X86_64\n--\narch/x86/Kconfig-37-\tselect ZONE_DMA32\narch/x86/Kconfig:38:\tselect EXECMEM if DYNAMIC_FTRACE\narch/x86/Kconfig-39-\tselect ACPI_MRRM if ACPI\n--\narch/x86/Kconfig=2651=config MITIGATION_ITS\n--\narch/x86/Kconfig-2654-\tdepends on MITIGATION_RETPOLINE \u0026\u0026 MITIGATION_RETHUNK\narch/x86/Kconfig:2655:\tselect EXECMEM\narch/x86/Kconfig-2656-\tdefault y\n--\nkernel/bpf/Kconfig=42=config BPF_JIT\n--\nkernel/bpf/Kconfig-45-\tdepends on HAVE_CBPF_JIT || HAVE_EBPF_JIT\nkernel/bpf/Kconfig:46:\tselect EXECMEM\nkernel/bpf/Kconfig-47-\thelp\n--\nkernel/module/Kconfig=2=menuconfig MODULES\n--\nkernel/module/Kconfig-4-\tmodules\nkernel/module/Kconfig:5:\tselect EXECMEM\nkernel/module/Kconfig-6-\thelp\n"
} |
| 21/2 | 2026/08/18 15:29 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 12877 output: 174 thoughts: 217 Thoughts: **My Analysis of the BPF Trampoline Memory Allocation Change** Okay, so this patch is switching up how we allocate memory for BPF trampolines. Currently, `BPF_JIT` selects `EXECMEM`. That's important. It's changing from the `EXECMEM_BPF` style (using `bpf_jit_alloc_exec_rw`) to the `EXECMEM_MODULE_DATA` style (using `execmem_alloc`). This is a critical shift, as it directly impacts both the memory permissions and the allocation pools that these trampolines rely on. Thinking about how pervasive trampolines are in tracing and networking applications, that's a big deal. To ensure this change is robust, I need to thoroughly assess it. Given the significant implications for memory management and potential impact on kernel operations, fuzzing BPF trampoline updates and the `struct_ops` preparation seems essential. That'll be how to really test the behavior. I've confirmed that enabling `BPF_SYSCALL` and `BPF_JIT` are the necessary configurations to test this change. I don't see any other flags that need to be considered. I think I'm good to go. I'll call `set-results`. |
| 22/2 | 2026/08/18 15:30 | tool | set-results |
0mArgs:{
"EnableConfigs": [
"BPF_SYSCALL",
"BPF_JIT"
],
"FocusSymbols": [
"arch_bpf_trampoline_size",
"bpf_trampoline_link_prog",
"bpf_struct_ops_prepare_trampoline"
],
"Reasoning": "The patch changes the memory allocation type for BPF trampolines from EXECMEM_BPF (via bpf_jit_alloc_exec_rw) to EXECMEM_MODULE_DATA (via execmem_alloc). This affects memory permissions and allocation pools for BPF trampolines, which are heavily used in tracing and networking. Fuzzing BPF trampoline updates and struct_ops preparation is recommended to ensure the new memory allocation behaves correctly.",
"WorthFuzzing": true
}Results: {
"EnableConfigs": [
"BPF_SYSCALL",
"BPF_JIT"
],
"FocusSymbols": [
"arch_bpf_trampoline_size",
"bpf_trampoline_link_prog",
"bpf_struct_ops_prepare_trampoline"
],
"Reasoning": "The patch changes the memory allocation type for BPF trampolines from EXECMEM_BPF (via bpf_jit_alloc_exec_rw) to EXECMEM_MODULE_DATA (via execmem_alloc). This affects memory permissions and allocation pools for BPF trampolines, which are heavily used in tracing and networking. Fuzzing BPF trampoline updates and struct_ops preparation is recommended to ensure the new memory allocation behaves correctly.",
"WorthFuzzing": true
} |
| 23/1 | 2026/08/18 15:30 | action | If |
0mArgs:{
"WorthFuzzing": true
}Results: null |
| 24/2 | 2026/08/18 15:30 | agent | kmsan-evaluator |
0mModel:best-expensive Args: null Results: {
"KMSANReasoning": "The patch replaces `bpf_jit_alloc_exec_rw` with `execmem_alloc` for allocating a temporary buffer used to calculate the BPF trampoline size. The buffer is only written to during the size calculation and then immediately freed. There is no risk of uninitialized memory being read, copied to userspace, or used in control flow. Any potential memory errors (like out-of-bounds writes) would be caught by KASAN. Therefore, a dedicated KMSAN fuzzing session is not required.",
"NeedsKMSAN": false
}Instruction: You are an expert Linux kernel security engineer specializing in kernel memory
error detectors (KASAN and KMSAN). Your job is to review the provided patch series and
determine if the code changes justify spawning a dedicated KMSAN (KernelMemorySanitizer)
fuzzing session in addition to standard KASAN fuzzing.
CRITICAL DISTINCTION BETWEEN KASAN AND KMSAN:
- Standard KASAN kernel builds (upstream-apparmor-kasan.config) already enable
a comprehensive suite of debugging tools and sanitizers, including KASAN
(out-of-bounds accesses, use-after-free, double free, invalid free), LOCKDEP
(locking bugs and deadlocks), UB-sanitizers, and memory corruption checks.
- KMSAN (KernelMemorySanitizer) detects reads of UNINITIALIZED memory (stack, heap,
or page allocations) and kernel-to-user memory info-leaks.
Rule: THERE IS NO SENSE IN RUNNING A KMSAN SESSION IF A BUG CAN BE CAUGHT BY KASAN,
LOCKDEP, OR OTHER STANDARD BUG DETECTORS.
A dedicated KMSAN fuzzing session incurs significant resource costs. You must ONLY
set NeedsKMSAN=true if the code changes introduce or expose UNINITIALIZED MEMORY risks
that are detected ONLY by KMSAN.
Look holistically at the patch series and surrounding code. Even if no direct
uninitialized field accesses or new buffer allocations are added in the diff itself,
a patch may alter control flow, bounds checking, or data length calculations in ways
that change how the rest of the code operates on existing buffers (e.g. allowing
uninitialized stack/heap memory to be read, copied to user space, or used in control
flow). Do not hesitate to use your code access tools to inspect the surrounding code,
called functions, and callers.
Set NeedsKMSAN=true ONLY IF the patch introduces or modifies:
1. Kernel structures sent to user space (via copy_to_user, put_user, netlink skb
attributes, ioctl output arguments, socket options, or BPF buffers) where fields
or structure padding might not be fully initialized/zeroed.
2. Conditional logic or branching that depends on potentially uninitialized variables
or struct fields.
3. Allocation or initialization of complex data structures where uninitialized fields
could be read later in reachable code paths.
4. Bounds checks, lengths, or logic in a way that allows surrounding code to access
uninitialized bytes of existing buffers.
Set NeedsKMSAN=false IF:
- The code changes primarily risk out-of-bounds access, array overflows, NULL pointer
dereferences, locking deadlocks, or use-after-free bugs (these are already caught
by KASAN, LOCKDEP, or standard bug detectors).
- All stack/heap structures touched or introduced by the patch are fully zeroed
or initialized (e.g. using = {0}, memset, kzalloc) before being read or copied.
- The patch does not introduce any risk of uninitialized memory usage or info-leaks.
Use your code access tools to inspect the surrounding code if necessary, then provide
detailed KMSANReasoning contrasting KASAN vs KMSAN applicability for this patch.
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 ee56e85b1a8230b0ba190425320380df327d8cb7
Author: syz-cluster <triage@syzkaller.com>
Date: Tue Aug 18 15:23:31 2026 +0000
syz-cluster: applied patch under review
diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c
index 1a9fb530adc3c..2853e87797a78 100644
--- a/arch/x86/net/bpf_jit_comp.c
+++ b/arch/x86/net/bpf_jit_comp.c
@@ -13,6 +13,7 @@
#include <linux/bpf_verifier.h>
#include <linux/memory.h>
#include <linux/sort.h>
+#include <linux/execmem.h>
#include <asm/extable.h>
#include <asm/ftrace.h>
#include <asm/set_memory.h>
@@ -3818,15 +3819,16 @@ int arch_bpf_trampoline_size(const struct btf_func_model *m, u32 flags,
*
* We cannot use kvmalloc here, because we need image to be in
* module memory range.
- * Since it must be writable use bpf_jit_alloc_exec_rw().
+ * Since it must be writable use execmem_alloc(EXECMEM_MODULE_DATA)
+ * that returns writable memory in the module address space.
*/
- image = bpf_jit_alloc_exec_rw(PAGE_SIZE);
+ image = execmem_alloc(EXECMEM_MODULE_DATA, PAGE_SIZE);
if (!image)
return -ENOMEM;
ret = __arch_prepare_bpf_trampoline(&im, image, image + PAGE_SIZE, image,
m, flags, tnodes, func_addr);
- bpf_jit_free_exec(image);
+ execmem_free(image);
return ret;
}
diff --git a/include/linux/filter.h b/include/linux/filter.h
index 4a9bc6a848f2e..39decde7fc730 100644
--- a/include/linux/filter.h
+++ b/include/linux/filter.h
@@ -1376,7 +1376,6 @@ bpf_jit_binary_alloc(unsigned int proglen, u8 **image_ptr,
void bpf_jit_binary_free(struct bpf_binary_header *hdr);
u64 bpf_jit_alloc_exec_limit(void);
void *bpf_jit_alloc_exec(unsigned long size);
-void *bpf_jit_alloc_exec_rw(unsigned long size);
void bpf_jit_free_exec(void *addr);
void bpf_jit_free(struct bpf_prog *fp);
struct bpf_binary_header *
diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
index d55e737ed75ad..8b294dfc1ad4d 100644
--- a/kernel/bpf/core.c
+++ b/kernel/bpf/core.c
@@ -1128,11 +1128,6 @@ void *bpf_jit_alloc_exec(unsigned long size)
return execmem_alloc(EXECMEM_BPF, size);
}
-void *bpf_jit_alloc_exec_rw(unsigned long size)
-{
- return execmem_alloc_rw(EXECMEM_BPF, size);
-}
-
void bpf_jit_free_exec(void *addr)
{
execmem_free(addr);
|
| 25/3 | 2026/08/18 15:30 | llm | kmsan-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 2687 output: 133 thoughts: 617 Thoughts: **KMSAN Assessment: No Uninitialized Memory Risk** Okay, so this patch is switching the memory allocator for the BPF JIT compilation process in the x86 architecture. Specifically, it's replacing `bpf_jit_alloc_exec_rw(PAGE_SIZE)` with `execmem_alloc(EXECMEM_MODULE_DATA, PAGE_SIZE)`. My initial thought was, "Hang on, does `execmem_alloc` initialize the memory it allocates?". Because if it doesn't, we might have a KMSAN problem. Looking at the code, this allocation is used for a temporary buffer called `image`. The purpose of this `image` buffer is to compute the size of the trampoline. The code snippet makes it clear: ```c image = execmem_alloc(EXECMEM_MODULE_DATA, PAGE_SIZE); if (!image) return -ENOMEM; ret = __arch_prepare_bpf_trampoline(&im, image, image + PAGE_SIZE, image, m, flags, tnodes, func_addr); execmem_free(image); ``` Okay, the function `__arch_prepare_bpf_trampoline` will *write* instructions to this `image` buffer. It's not a read-from-uninitialized-memory-and-copy situation. It's a write-calculate-size-discard situation. We are *calculating* the code size by temporarily writing it to the buffer, then freeing the buffer. Therefore, there is no risk of uninitialized memory being used. This isn't data that's being copied to userspace, or being used for control flow in a way that would be sensitive to uninitialized values. This is just a memory allocation API change, so KMSAN isn't needed here. KASAN is sufficient to catch any out-of-bounds writes. So, the conclusion is **NeedsKMSAN = false.** The reasoning is simple: the patch just refactors memory allocation of a temporary buffer. The allocated memory is only written to during the trampoline size calculation and is immediately freed. No uninitialized memory is read, copied to userspace, or used in control flow. KMSAN isn't needed. |
| 26/3 | 2026/08/18 15:30 | tool | set-results |
0mArgs:{
"KMSANReasoning": "The patch replaces `bpf_jit_alloc_exec_rw` with `execmem_alloc` for allocating a temporary buffer used to calculate the BPF trampoline size. The buffer is only written to during the size calculation and then immediately freed. There is no risk of uninitialized memory being read, copied to userspace, or used in control flow. Any potential memory errors (like out-of-bounds writes) would be caught by KASAN. Therefore, a dedicated KMSAN fuzzing session is not required.",
"NeedsKMSAN": false
}Results: {
"KMSANReasoning": "The patch replaces `bpf_jit_alloc_exec_rw` with `execmem_alloc` for allocating a temporary buffer used to calculate the BPF trampoline size. The buffer is only written to during the size calculation and then immediately freed. There is no risk of uninitialized memory being read, copied to userspace, or used in control flow. Any potential memory errors (like out-of-bounds writes) would be caught by KASAN. Therefore, a dedicated KMSAN fuzzing session is not required.",
"NeedsKMSAN": false
} |
| Total Calls | Total Tokens | Avg Tokens | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|
| Total Calls | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|