| Seq | Timestamp | Type | Name | Duration |
|---|---|---|---|---|
| 0/0 | 2026/07/20 23:36 | flow | patch-triage |
0mArgs:null Results: {
"EnableConfigs": [
"BPF_SYSCALL"
],
"FocusSymbols": [
"adjust_ptr_min_max_vals"
],
"Reasoning": "The patch modifies the BPF verifier to preserve the frame number when performing pointer arithmetic on stack pointers. This is a functional change in the core BPF verifier logic that handles pointer bounds and types, which is reachable via the bpf() syscall.",
"WorthFuzzing": true
} |
| 1/1 | 2026/07/20 23:36 | action | read-patch-diff |
0mArgs:null Results: {
"PatchDiff": "commit a21e7f49947b892fcb75fa3d62d3cc8a435dd923\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate: Mon Jul 20 23:36:50 2026 +0000\n\n syz-cluster: applied patch under review\n\ndiff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c\nindex 52be0a118cce07..58017141d52b7b 100644\n--- a/kernel/bpf/verifier.c\n+++ b/kernel/bpf/verifier.c\n@@ -13796,11 +13796,14 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env,\n \t\treturn -EACCES;\n \t}\n \n-\t/* In case of 'scalar += pointer', dst_reg inherits pointer type and id.\n-\t * The id may be overwritten later if we create a new variable offset.\n+\t/* In case of 'scalar += pointer', dst_reg inherits pointer type, id,\n+\t * and for stack pointers also the frame number. The id may be overwritten\n+\t * later if we create a new variable offset.\n \t */\n \tdst_reg-\u003etype = ptr_reg-\u003etype;\n \tdst_reg-\u003eid = ptr_reg-\u003eid;\n+\tif (base_type(ptr_reg-\u003etype) == PTR_TO_STACK)\n+\t\tdst_reg-\u003eframeno = ptr_reg-\u003eframeno;\n \n \tif (!check_reg_sane_offset_scalar(env, off_reg, ptr_reg-\u003etype) ||\n \t !check_reg_sane_offset_ptr(env, ptr_reg, ptr_reg-\u003etype))\ndiff --git a/tools/testing/selftests/bpf/prog_tests/verifier.c b/tools/testing/selftests/bpf/prog_tests/verifier.c\nindex be97f6887f0e7f..0483ae340726c9 100644\n--- a/tools/testing/selftests/bpf/prog_tests/verifier.c\n+++ b/tools/testing/selftests/bpf/prog_tests/verifier.c\n@@ -11,7 +11,6 @@\n #include \"verifier_arena_globals2.skel.h\"\n #include \"verifier_array_access.skel.h\"\n #include \"verifier_async_cb_context.skel.h\"\n-#include \"verifier_basic_stack.skel.h\"\n #include \"verifier_bitfield_write.skel.h\"\n #include \"verifier_bounds.skel.h\"\n #include \"verifier_bounds_deduction.skel.h\"\n@@ -165,7 +164,6 @@ void test_verifier_arena(void) { RUN(verifier_arena); }\n void test_verifier_arena_large(void) { RUN(verifier_arena_large); }\n void test_verifier_arena_globals1(void) { RUN(verifier_arena_globals1); }\n void test_verifier_arena_globals2(void) { RUN(verifier_arena_globals2); }\n-void test_verifier_basic_stack(void) { RUN(verifier_basic_stack); }\n void test_verifier_bitfield_write(void) { RUN(verifier_bitfield_write); }\n void test_verifier_bounds(void) { RUN(verifier_bounds); }\n void test_verifier_bounds_deduction(void) { RUN(verifier_bounds_deduction); }\ndiff --git a/tools/testing/selftests/bpf/prog_tests/verifier_basic_stack.c b/tools/testing/selftests/bpf/prog_tests/verifier_basic_stack.c\nnew file mode 100644\nindex 00000000000000..279f389729b8ef\n--- /dev/null\n+++ b/tools/testing/selftests/bpf/prog_tests/verifier_basic_stack.c\n@@ -0,0 +1,28 @@\n+// SPDX-License-Identifier: GPL-2.0-only\n+\n+#include \u003ctest_progs.h\u003e\n+\n+#include \"cap_helpers.h\"\n+#include \"verifier_basic_stack.skel.h\"\n+\n+void test_verifier_basic_stack(void)\n+{\n+\tstruct test_loader tester = {};\n+\t__u64 old_caps;\n+\tint err;\n+\n+\t/* test_verifier tests are executed w/o CAP_SYS_ADMIN, do the same here */\n+\terr = cap_disable_effective(1ULL \u003c\u003c CAP_SYS_ADMIN, \u0026old_caps);\n+\tif (err) {\n+\t\tPRINT_FAIL(\"failed to drop CAP_SYS_ADMIN: %i, %s\\n\", err, strerror(-err));\n+\t\treturn;\n+\t}\n+\n+\ttest_loader__run_subtests(\u0026tester, \"verifier_basic_stack\",\n+\t\t\t\t verifier_basic_stack__elf_bytes);\n+\ttest_loader_fini(\u0026tester);\n+\n+\terr = cap_enable_effective(old_caps, NULL);\n+\tif (err)\n+\t\tPRINT_FAIL(\"failed to restore CAP_SYS_ADMIN: %i, %s\\n\", err, strerror(-err));\n+}\ndiff --git a/tools/testing/selftests/bpf/progs/verifier_basic_stack.c b/tools/testing/selftests/bpf/progs/verifier_basic_stack.c\nindex fb62e09f21146d..634183fc86883f 100644\n--- a/tools/testing/selftests/bpf/progs/verifier_basic_stack.c\n+++ b/tools/testing/selftests/bpf/progs/verifier_basic_stack.c\n@@ -97,4 +97,45 @@ __naked void misaligned_read_from_stack(void)\n \"\t::: __clobber_all);\n }\n \n+SEC(\"socket\")\n+__description(\"stack pointer arithmetic preserves frame number\")\n+__failure __msg(\"R7 invalid mem access 'scalar'\")\n+__naked void stack_ptr_arith_preserves_frameno(void)\n+{\n+\tasm volatile (\"\t\t\t\t\t\\\n+\tr3 = 0;\t\t\t\t\t\t\\\n+\t*(u64 *)(r10 - 8) = r3;\t\t\t\\\n+\tr1 = %[map_hash_8b] ll;\t\t\t\\\n+\tr2 = r10;\t\t\t\t\t\\\n+\tr2 += -8;\t\t\t\t\t\\\n+\tcall %[bpf_map_lookup_elem];\t\t\t\\\n+\tif r0 != 0 goto +2;\t\t\t\t\\\n+\tr0 = 0;\t\t\t\t\t\t\\\n+\texit;\t\t\t\t\t\t\\\n+\tr1 = r0;\t\t\t\t\t\\\n+\tr2 = 0;\t\t\t\t\t\t\\\n+\tr3 = 0;\t\t\t\t\t\t\\\n+\tcall stack_ptr_arith_preserves_frameno_subprog;\t\\\n+\tr0 = 0;\t\t\t\t\t\t\\\n+\texit;\t\t\t\t\t\t\\\n+\"\t:\n+\t: __imm(bpf_map_lookup_elem),\n+\t __imm_addr(map_hash_8b)\n+\t: __clobber_all);\n+}\n+\n+static __used __naked void stack_ptr_arith_preserves_frameno_subprog(void)\n+{\n+\tasm volatile (\"\t\t\t\t\t\\\n+\t*(u64 *)(r10 - 8) = r1;\t\t\t\\\n+\tr6 = -8;\t\t\t\t\t\\\n+\tr6 += r10;\t\t\t\t\t\\\n+\t*(u64 *)(r6 + 0) = r2;\t\t\t\\\n+\tr7 = *(u64 *)(r10 - 8);\t\t\t\\\n+\t*(u64 *)(r7 + 0) = r3;\t\t\t\\\n+\tr0 = 0;\t\t\t\t\t\t\\\n+\texit;\t\t\t\t\t\t\\\n+\"\t::: __clobber_all);\n+}\n+\n char _license[] SEC(\"license\") = \"GPL\";\n"
} |
| 2/1 | 2026/07/20 23:36 | agent | patch-evaluator |
0mModel:best-expensive Args: null Results: {
"EnableConfigs": [
"BPF_SYSCALL"
],
"FocusSymbols": [
"adjust_ptr_min_max_vals"
],
"Reasoning": "The patch modifies the BPF verifier to preserve the frame number when performing pointer arithmetic on stack pointers. This is a functional change in the core BPF verifier logic that handles pointer bounds and types, which is reachable via the bpf() syscall.",
"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). 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. 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. Do not list too generic configs (we already have them enabled). Only list those that specifically cover the modified code. 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 a21e7f49947b892fcb75fa3d62d3cc8a435dd923
Author: syz-cluster <triage@syzkaller.com>
Date: Mon Jul 20 23:36:50 2026 +0000
syz-cluster: applied patch under review
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 52be0a118cce07..58017141d52b7b 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -13796,11 +13796,14 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env,
return -EACCES;
}
- /* In case of 'scalar += pointer', dst_reg inherits pointer type and id.
- * The id may be overwritten later if we create a new variable offset.
+ /* In case of 'scalar += pointer', dst_reg inherits pointer type, id,
+ * and for stack pointers also the frame number. The id may be overwritten
+ * later if we create a new variable offset.
*/
dst_reg->type = ptr_reg->type;
dst_reg->id = ptr_reg->id;
+ if (base_type(ptr_reg->type) == PTR_TO_STACK)
+ dst_reg->frameno = ptr_reg->frameno;
if (!check_reg_sane_offset_scalar(env, off_reg, ptr_reg->type) ||
!check_reg_sane_offset_ptr(env, ptr_reg, ptr_reg->type))
diff --git a/tools/testing/selftests/bpf/prog_tests/verifier.c b/tools/testing/selftests/bpf/prog_tests/verifier.c
index be97f6887f0e7f..0483ae340726c9 100644
--- a/tools/testing/selftests/bpf/prog_tests/verifier.c
+++ b/tools/testing/selftests/bpf/prog_tests/verifier.c
@@ -11,7 +11,6 @@
#include "verifier_arena_globals2.skel.h"
#include "verifier_array_access.skel.h"
#include "verifier_async_cb_context.skel.h"
-#include "verifier_basic_stack.skel.h"
#include "verifier_bitfield_write.skel.h"
#include "verifier_bounds.skel.h"
#include "verifier_bounds_deduction.skel.h"
@@ -165,7 +164,6 @@ void test_verifier_arena(void) { RUN(verifier_arena); }
void test_verifier_arena_large(void) { RUN(verifier_arena_large); }
void test_verifier_arena_globals1(void) { RUN(verifier_arena_globals1); }
void test_verifier_arena_globals2(void) { RUN(verifier_arena_globals2); }
-void test_verifier_basic_stack(void) { RUN(verifier_basic_stack); }
void test_verifier_bitfield_write(void) { RUN(verifier_bitfield_write); }
void test_verifier_bounds(void) { RUN(verifier_bounds); }
void test_verifier_bounds_deduction(void) { RUN(verifier_bounds_deduction); }
diff --git a/tools/testing/selftests/bpf/prog_tests/verifier_basic_stack.c b/tools/testing/selftests/bpf/prog_tests/verifier_basic_stack.c
new file mode 100644
index 00000000000000..279f389729b8ef
--- /dev/null
+++ b/tools/testing/selftests/bpf/prog_tests/verifier_basic_stack.c
@@ -0,0 +1,28 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <test_progs.h>
+
+#include "cap_helpers.h"
+#include "verifier_basic_stack.skel.h"
+
+void test_verifier_basic_stack(void)
+{
+ struct test_loader tester = {};
+ __u64 old_caps;
+ int err;
+
+ /* test_verifier tests are executed w/o CAP_SYS_ADMIN, do the same here */
+ err = cap_disable_effective(1ULL << CAP_SYS_ADMIN, &old_caps);
+ if (err) {
+ PRINT_FAIL("failed to drop CAP_SYS_ADMIN: %i, %s\n", err, strerror(-err));
+ return;
+ }
+
+ test_loader__run_subtests(&tester, "verifier_basic_stack",
+ verifier_basic_stack__elf_bytes);
+ test_loader_fini(&tester);
+
+ err = cap_enable_effective(old_caps, NULL);
+ if (err)
+ PRINT_FAIL("failed to restore CAP_SYS_ADMIN: %i, %s\n", err, strerror(-err));
+}
diff --git a/tools/testing/selftests/bpf/progs/verifier_basic_stack.c b/tools/testing/selftests/bpf/progs/verifier_basic_stack.c
index fb62e09f21146d..634183fc86883f 100644
--- a/tools/testing/selftests/bpf/progs/verifier_basic_stack.c
+++ b/tools/testing/selftests/bpf/progs/verifier_basic_stack.c
@@ -97,4 +97,45 @@ __naked void misaligned_read_from_stack(void)
" ::: __clobber_all);
}
+SEC("socket")
+__description("stack pointer arithmetic preserves frame number")
+__failure __msg("R7 invalid mem access 'scalar'")
+__naked void stack_ptr_arith_preserves_frameno(void)
+{
+ asm volatile (" \
+ r3 = 0; \
+ *(u64 *)(r10 - 8) = r3; \
+ r1 = %[map_hash_8b] ll; \
+ r2 = r10; \
+ r2 += -8; \
+ call %[bpf_map_lookup_elem]; \
+ if r0 != 0 goto +2; \
+ r0 = 0; \
+ exit; \
+ r1 = r0; \
+ r2 = 0; \
+ r3 = 0; \
+ call stack_ptr_arith_preserves_frameno_subprog; \
+ r0 = 0; \
+ exit; \
+" :
+ : __imm(bpf_map_lookup_elem),
+ __imm_addr(map_hash_8b)
+ : __clobber_all);
+}
+
+static __used __naked void stack_ptr_arith_preserves_frameno_subprog(void)
+{
+ asm volatile (" \
+ *(u64 *)(r10 - 8) = r1; \
+ r6 = -8; \
+ r6 += r10; \
+ *(u64 *)(r6 + 0) = r2; \
+ r7 = *(u64 *)(r10 - 8); \
+ *(u64 *)(r7 + 0) = r3; \
+ r0 = 0; \
+ exit; \
+" ::: __clobber_all);
+}
+
char _license[] SEC("license") = "GPL";
|
| 3/2 | 2026/07/20 23:36 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 3609 output: 37 thoughts: 252 Thoughts: **BPF Verifier Patch Analysis** Okay, so I'm looking at this patch that modifies `kernel/bpf/verifier.c`. Specifically, the change is within the `adjust_ptr_min_max_vals` function. The code's logic handles the case of `scalar += pointer` operations. My understanding is that previously, when you did something like that, the destination register (`dst_reg`) was inheriting the pointer's type and ID, which is correct. The ID might get overwritten later, and that's fine. However, it wasn't preserving the frame number associated with stack pointers. This change adds a check to ensure that if the pointer (`ptr_reg`) is a stack pointer (i.e., `base_type(ptr_reg->type) == PTR_TO_STACK`), the destination register *also* gets the correct `frameno`. So, it's a subtle but important fix to how the BPF verifier handles stack pointer arithmetic. This is definitely a functional change in the BPF verifier, addressing a specific bug. Therefore, because it's a modification of critical kernel code that affects memory safety and program execution, I should flag this as worth fuzzing. |
| 4/2 | 2026/07/20 23:36 | tool | grepper |
0mArgs:{
"Expression": "adjust_ptr_min_max_vals",
"PathPrefix": "kernel/bpf/verifier.c"
}Results: {
"Output": "kernel/bpf/verifier.c=4003=static int check_stack_read(struct bpf_verifier_env *env,\n--\nkernel/bpf/verifier.c-4027-\t * check_stack_access_for_ptr_arithmetic() called by\nkernel/bpf/verifier.c:4028:\t * adjust_ptr_min_max_vals() prevents users from creating stack pointers\nkernel/bpf/verifier.c-4029-\t * with variable offsets, therefore no check is required here. Further,\n--\nkernel/bpf/verifier.c=13680=static int sanitize_check_bounds(struct bpf_verifier_env *env,\n--\nkernel/bpf/verifier.c-13716- */\nkernel/bpf/verifier.c:13717:static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env,\nkernel/bpf/verifier.c-13718-\t\t\t\t struct bpf_insn *insn,\n--\nkernel/bpf/verifier.c=14804=static int adjust_reg_min_max_vals(struct bpf_verifier_env *env,\n--\nkernel/bpf/verifier.c-14866-\t\t\t\t\treturn err;\nkernel/bpf/verifier.c:14867:\t\t\t\treturn adjust_ptr_min_max_vals(env, insn,\nkernel/bpf/verifier.c-14868-\t\t\t\t\t\t\t src_reg, dst_reg);\n--\nkernel/bpf/verifier.c-14874-\t\t\t\treturn err;\nkernel/bpf/verifier.c:14875:\t\t\treturn adjust_ptr_min_max_vals(env, insn,\nkernel/bpf/verifier.c-14876-\t\t\t\t\t\t dst_reg, src_reg);\n--\nkernel/bpf/verifier.c-14890-\t\tif (ptr_reg) /* pointer += K */\nkernel/bpf/verifier.c:14891:\t\t\treturn adjust_ptr_min_max_vals(env, insn,\nkernel/bpf/verifier.c-14892-\t\t\t\t\t\t ptr_reg, src_reg);\n"
} |
| 5/2 | 2026/07/20 23:36 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 4710 output: 29 thoughts: 84 Thoughts: **Investigating the Configuration Requirements for `adjust_ptr_min_max_vals`** Okay, so `adjust_ptr_min_max_vals` is called by `adjust_reg_min_max_vals`. My immediate thought is, what are the relevant configurations that are going to impact this? Given my background, I'm pretty sure BPF is usually toggled on by `CONFIG_BPF` and `CONFIG_BPF_SYSCALL`. I'll want to verify that and get the dependencies straight. To do this, I'm going to quickly check in `kernel/bpf/Makefile` or `kernel/bpf/Kconfig`. That should give me a solid view of the configuration landscape here. |
| 6/2 | 2026/07/20 23:37 | tool | grepper |
0mArgs:{
"Expression": "verifier.o",
"PathPrefix": "kernel/bpf/Makefile"
}Results: {
"Output": "kernel/bpf/Makefile=7=CFLAGS_core.o += -Wno-override-init $(cflags-nogcse-yy)\nkernel/bpf/Makefile-8-\nkernel/bpf/Makefile:9:obj-$(CONFIG_BPF_SYSCALL) += syscall.o verifier.o inode.o helpers.o tnum.o cnum.o log.o token.o liveness.o const_fold.o\nkernel/bpf/Makefile-10-obj-$(CONFIG_BPF_SYSCALL) += bpf_iter.o map_iter.o task_iter.o prog_iter.o link_iter.o\n"
} |
| 7/2 | 2026/07/20 23:37 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 5142 output: 101 thoughts: 277 Thoughts: **My Assessment of the Patch's Fuzzing Potential** Okay, so I've zeroed in on the `BPF_SYSCALL` configuration option. That's my starting point. The crucial function within the patch, the one that really seems to grab my attention, is `adjust_ptr_min_max_vals`. Let me just quickly confirm that there aren't any other functions that warrant similar attention. Nope, `adjust_ptr_min_max_vals` remains the key. Now, the important question: is this function a "hot path"? Not in the usual sense of real-time packet processing or scheduler code, no. But this is the BPF verifier, and `adjust_ptr_min_max_vals` is *part* of the verifier. It's executed when a BPF program is loaded, which makes it a critical part of the attack surface, and a perfect target for fuzzing via `bpf()` syscalls, as Syzkaller does. This is where the vulnerability hunting is. Alright, I'll quickly verify that `adjust_ptr_min_max_vals` is declared static. Yes, it is. All the better. Let's summarize this. **WorthFuzzing: True** **FocusSymbols: ["adjust_ptr_min_max_vals"]** **EnableConfigs: ["BPF_SYSCALL"]** **Reasoning: "This patch fundamentally alters the BPF verifier's behavior by preserving the frame number during pointer arithmetic on stack pointers. This change directly impacts the core logic of the verifier, particularly how it handles pointer bounds and types. The BPF verifier logic is accessible through the `bpf()` syscall and is therefore suitable for fuzzing."** |
| 8/2 | 2026/07/20 23:37 | tool | set-results |
0mArgs:{
"EnableConfigs": [
"BPF_SYSCALL"
],
"FocusSymbols": [
"adjust_ptr_min_max_vals"
],
"Reasoning": "The patch modifies the BPF verifier to preserve the frame number when performing pointer arithmetic on stack pointers. This is a functional change in the core BPF verifier logic that handles pointer bounds and types, which is reachable via the bpf() syscall.",
"WorthFuzzing": true
}Results: {
"EnableConfigs": [
"BPF_SYSCALL"
],
"FocusSymbols": [
"adjust_ptr_min_max_vals"
],
"Reasoning": "The patch modifies the BPF verifier to preserve the frame number when performing pointer arithmetic on stack pointers. This is a functional change in the core BPF verifier logic that handles pointer bounds and types, which is reachable via the bpf() syscall.",
"WorthFuzzing": true
} |
| Total Calls | Total Tokens | Avg Tokens | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|
| Total Calls | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|