| Seq | Timestamp | Type | Name | Duration |
|---|---|---|---|---|
| 0/0 | 2026/09/04 19:04 | flow | patch-triage |
1mArgs:null Results: {
"EnableConfigs": [
"BPF_SYSCALL",
"DEBUG_INFO_BTF",
"INET"
],
"FocusSymbols": [
"bpf_sock_destroy",
"tcp_abort"
],
"KMSANReasoning": "The patch modifies `bpf_sock_destroy` in `net/core/filter.c` to only check `sk-\u003esk_protocol` when `sk_fullsock(sk)` is true, allowing non-full sockets (such as TCP TIME_WAIT sockets) with a valid `sk_prot-\u003ediag_destroy` callback to be destroyed via the BPF kfunc.\n\nThis change does not introduce or expose any uninitialized memory risks. It does not allocate memory buffers, copy data to user space, or introduce branching on uninitialized data. In fact, checking `sk_fullsock()` avoids reading fields beyond `sock_common` for miniature sockets. Any potential risks related to socket destruction lifecycle or locking are covered by KASAN and LOCKDEP. Therefore, dedicated KMSAN fuzzing is not required.",
"NeedsKMSAN": false,
"Reasoning": "The patch modifies bpf_sock_destroy() in net/core/filter.c to allow protocol abort handlers (e.g., tcp_abort) to destroy non-full sockets (such as TCP TIME_WAIT and SYN_RECV sockets) by qualifying the protocol check with sk_fullsock(). This enables new execution paths reachable through BPF socket iterator programs in standard virtualized environments.",
"WorthFuzzing": true
} |
| 1/1 | 2026/09/04 19:04 | action | read-patch-diff |
0mArgs:null Results: {
"PatchDiff": "commit e4e455baa671300d259799e8eaf43e01a9fd872f\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate: Fri Sep 4 19:04:23 2026 +0000\n\n syz-cluster: applied patch under review\n\ndiff --git a/net/core/filter.c b/net/core/filter.c\nindex 61940e7535523..1bbb72138ac64 100644\n--- a/net/core/filter.c\n+++ b/net/core/filter.c\n@@ -12912,8 +12912,8 @@ __bpf_kfunc_start_defs();\n * @sock: Pointer to socket to be destroyed\n *\n * Return:\n- * On error, may return EPROTONOSUPPORT, EINVAL.\n- * EPROTONOSUPPORT if protocol specific destroy handler is not supported.\n+ * On error, may return EOPNOTSUPP, EINVAL.\n+ * EOPNOTSUPP if protocol specific destroy handler is not supported.\n * 0 otherwise\n */\n __bpf_kfunc int bpf_sock_destroy(struct sock_common *sock)\n@@ -12925,8 +12925,12 @@ __bpf_kfunc int bpf_sock_destroy(struct sock_common *sock)\n \t * Supporting protocols will need to acquire sock lock in the BPF context\n \t * prior to invoking this kfunc.\n \t */\n-\tif (!sk-\u003esk_prot-\u003ediag_destroy || (sk-\u003esk_protocol != IPPROTO_TCP \u0026\u0026\n-\t\t\t\t\t sk-\u003esk_protocol != IPPROTO_UDP))\n+\tif (!sk-\u003esk_prot-\u003ediag_destroy)\n+\t\treturn -EOPNOTSUPP;\n+\n+\tif (sk_fullsock(sk) \u0026\u0026\n+\t sk-\u003esk_protocol != IPPROTO_TCP \u0026\u0026\n+\t sk-\u003esk_protocol != IPPROTO_UDP)\n \t\treturn -EOPNOTSUPP;\n \n \treturn sk-\u003esk_prot-\u003ediag_destroy(sk, ECONNABORTED);\ndiff --git a/tools/testing/selftests/bpf/prog_tests/sock_destroy.c b/tools/testing/selftests/bpf/prog_tests/sock_destroy.c\nindex 9c11938fe597d..6ccc7cda410bf 100644\n--- a/tools/testing/selftests/bpf/prog_tests/sock_destroy.c\n+++ b/tools/testing/selftests/bpf/prog_tests/sock_destroy.c\n@@ -110,6 +110,65 @@ static void test_tcp_server(struct sock_destroy_prog *skel)\n \t\tclose(serv);\n }\n \n+static void test_tcp_timewait(struct sock_destroy_prog *skel)\n+{\n+\tint serv = -1, clien = -1, accept_serv = -1, n;\n+\tstruct timeval tv = {};\n+\tchar buf[1];\n+\n+\tserv = start_server(AF_INET6, SOCK_STREAM, NULL, 0, 0);\n+\tif (!ASSERT_GE(serv, 0, \"start_server\"))\n+\t\tgoto cleanup;\n+\n+\tclien = connect_to_fd(serv, 0);\n+\tif (!ASSERT_GE(clien, 0, \"connect_to_fd\"))\n+\t\tgoto cleanup;\n+\n+\taccept_serv = accept(serv, NULL, NULL);\n+\tif (!ASSERT_GE(accept_serv, 0, \"serv accept\"))\n+\t\tgoto cleanup;\n+\n+\t/* Active close from the client, then close the server side. Once\n+\t * recv() sees EOF the server FIN has been processed and the client\n+\t * sock is in TIME_WAIT. Block without timeout so a loaded CI box\n+\t * can't race us.\n+\t */\n+\tif (!ASSERT_OK(setsockopt(clien, SOL_SOCKET, SO_RCVTIMEO, \u0026tv,\n+\t\t\t\t sizeof(tv)), \"clear rcvtimeo\"))\n+\t\tgoto cleanup;\n+\tif (!ASSERT_OK(shutdown(clien, SHUT_WR), \"client shutdown\"))\n+\t\tgoto cleanup;\n+\n+\tclose(accept_serv);\n+\taccept_serv = -1;\n+\n+\t/* block until return EOF */\n+\tn = recv(clien, buf, sizeof(buf), 0);\n+\tif (!ASSERT_EQ(n, 0, \"client recv EOF\"))\n+\t\tgoto cleanup;\n+\n+\t/* Run iterator program that destroys the timewait client sock. */\n+\tskel-\u003ebss-\u003etw_found = 0;\n+\tstart_iter_sockets(skel-\u003eprogs.iter_tcp6_timewait);\n+\tif (!ASSERT_EQ(skel-\u003ebss-\u003etw_found, 1, \"timewait sock found\"))\n+\t\tgoto cleanup;\n+\n+\tASSERT_OK(skel-\u003ebss-\u003etw_destroy_err, \"destroy timewait sock\");\n+\n+\t/* The destroyed timewait sock must be gone. */\n+\tskel-\u003ebss-\u003etw_found = 0;\n+\tstart_iter_sockets(skel-\u003eprogs.iter_tcp6_timewait);\n+\tASSERT_EQ(skel-\u003ebss-\u003etw_found, 0, \"timewait sock destroyed\");\n+\n+cleanup:\n+\tif (clien != -1)\n+\t\tclose(clien);\n+\tif (accept_serv != -1)\n+\t\tclose(accept_serv);\n+\tif (serv != -1)\n+\t\tclose(serv);\n+}\n+\n static void test_udp_client(struct sock_destroy_prog *skel)\n {\n \tint serv = -1, clien = -1, n = 0;\n@@ -204,11 +263,12 @@ void test_sock_destroy(void)\n \t\ttest_tcp_client(skel);\n \tif (test__start_subtest(\"tcp_server\"))\n \t\ttest_tcp_server(skel);\n+\tif (test__start_subtest(\"tcp_timewait\"))\n+\t\ttest_tcp_timewait(skel);\n \tif (test__start_subtest(\"udp_client\"))\n \t\ttest_udp_client(skel);\n \tif (test__start_subtest(\"udp_server\"))\n \t\ttest_udp_server(skel);\n-\n \tRUN_TESTS(sock_destroy_prog_fail);\n \n cleanup:\ndiff --git a/tools/testing/selftests/bpf/progs/sock_destroy_prog.c b/tools/testing/selftests/bpf/progs/sock_destroy_prog.c\nindex 9e0bf7a54cec9..0a8887543218a 100644\n--- a/tools/testing/selftests/bpf/progs/sock_destroy_prog.c\n+++ b/tools/testing/selftests/bpf/progs/sock_destroy_prog.c\n@@ -7,6 +7,8 @@\n #include \"bpf_tracing_net.h\"\n \n __be16 serv_port = 0;\n+int tw_found = 0;\n+int tw_destroy_err = 0;\n \n int bpf_sock_destroy(struct sock_common *sk) __ksym;\n \n@@ -100,6 +102,34 @@ int iter_tcp6_server(struct bpf_iter__tcp *ctx)\n \treturn 0;\n }\n \n+SEC(\"iter/tcp\")\n+int iter_tcp6_timewait(struct bpf_iter__tcp *ctx)\n+{\n+\tstruct sock_common *sk_common = ctx-\u003esk_common;\n+\t__u64 *val;\n+\tint key = 0;\n+\n+\tif (!sk_common)\n+\t\treturn 0;\n+\n+\tif (sk_common-\u003eskc_family != AF_INET6)\n+\t\treturn 0;\n+\n+\tif (!bpf_skc_to_tcp_timewait_sock(sk_common))\n+\t\treturn 0;\n+\n+\tval = bpf_map_lookup_elem(\u0026tcp_conn_sockets, \u0026key);\n+\tif (!val)\n+\t\treturn 0;\n+\t/* The timewait sock inherits the cookie of the closed client sock. */\n+\tif (bpf_get_socket_cookie(sk_common) != *val)\n+\t\treturn 0;\n+\n+\ttw_found++;\n+\ttw_destroy_err = bpf_sock_destroy(sk_common);\n+\n+\treturn 0;\n+}\n \n SEC(\"iter/udp\")\n int iter_udp6_client(struct bpf_iter__udp *ctx)\n"
} |
| 2/1 | 2026/09/04 19:04 | agent | patch-evaluator |
1mModel:core Args: null Results: {
"EnableConfigs": [
"BPF_SYSCALL",
"DEBUG_INFO_BTF",
"INET"
],
"FocusSymbols": [
"bpf_sock_destroy",
"tcp_abort"
],
"Reasoning": "The patch modifies bpf_sock_destroy() in net/core/filter.c to allow protocol abort handlers (e.g., tcp_abort) to destroy non-full sockets (such as TCP TIME_WAIT and SYN_RECV sockets) by qualifying the protocol check with sk_fullsock(). This enables new execution paths reachable through BPF socket iterator programs in standard virtualized environments.",
"WorthFuzzing": true
}Instruction: You are an expert Linux kernel maintainer and security engineer.
Your job is to review a provided patch series and evaluate whether it warrants fuzzing with syzkaller.
IMPORTANT: The changes have ALREADY been applied and committed as the HEAD commit in
your workspace. Do NOT rely on internal assumptions. You must actively use your code access
tools to inspect the actual source code, callers, and surrounding context.
================================================================================
1. CORE TRIAGE PHILOSOPHY
================================================================================
The goal of patch fuzzing is to discover crashes, regressions, exposed latent bugs,
and newly triggered assertions introduced by the patch series.
- REACHABILITY IS THE PRIMARY GATE:
Fuzzing can only discover bugs in code that can actually execute in standard virtualized
environments (GCE or QEMU, utilizing software-emulated devices like USB gadgets, netdev, tun/tap).
If the modified code is structurally unreachable (see Section 2), it MUST NOT be fuzzed,
regardless of whether it adds assertions or complex logic.
- DO NOT BLINDLY TRUST "NO FUNCTIONAL CHANGE" (NFCI) OR "REFACTORING" CLAIMS:
Patch authors routinely label changes as "cleanups", "refactorings", or state
"No functional change intended". Do NOT take these claims at face value.
Code refactorings that rearrange logic, introduce helper functions, or alter state management
in core subsystems frequently introduce subtle semantic shifts or uncover latent kernel bugs.
If reachable executable code is modified or refactored, it MUST be fuzzed.
- NEW OR MODIFIED ASSERTIONS IN REACHABLE CODE MUST BE FUZZED:
When a patch introduces or modifies runtime checks or assertions (e.g., WARN_ON*, VM_WARN_ON*,
BUG_ON*, lockdep_assert*) in reachable code paths, it enforces new or stricter invariants.
Even if the author believes the invariant always holds, fuzzing is essential to verify whether
an unusual sequence of operations can violate it.
================================================================================
2. WHEN TO RETURN WorthFuzzing=false (NEGATIVE CRITERIA)
================================================================================
Return WorthFuzzing=false ONLY IF all modified code falls strictly into one or more of these categories:
- Non-kernel and non-executable changes:
* Modifications to Documentation/, comments, or spelling fixes.
* User-space directories, self-tests, samples, or scripts (e.g., tools/, samples/, scripts/, usr/)
that do not affect the compiled kernel image (vmlinux) or kernel modules.
* Purely decorative logging (e.g., message strings in pr_err, printk, dev_info) or tracepoints
that do not alter control flow or data structures.
* Build system or Kconfig changes that do not alter compiled C logic.
- Structurally unreachable hardware:
* Vendor-specific PCIe switches, SmartNICs, or GPU drivers (e.g., mlxsw, pds_core, qed,
ionic, amdgpu) requiring physical ASIC/PCIe cards not emulated in standard QEMU.
- Unreachable execution paths:
* Driver teardown callbacks (.remove, .shutdown, pci_unregister_driver) executed only during
physical PCI hot-unplug or manual sysfs driver unbinding.
* Code paths exclusive to architectures other than the target architecture.
================================================================================
3. WHEN TO RETURN WorthFuzzing=true (POSITIVE CRITERIA)
================================================================================
Return WorthFuzzing=true whenever the patch touches reachable executable code, including:
- Core Subsystems:
* Any logic modifications in memory management (mm/), synchronization/locking (kernel/locking/),
BPF, scheduler, core networking, VFS, or syscall handling.
- Refactorings and Code Cleanups:
* Any restructuring of reachable data structures, helper abstractions, or algorithm flows.
- Runtime Assertions and Defensive Checks:
* Any introduction or alteration of assertions (WARN_ON*, VM_WARN_ON*, BUG_ON*, etc.) in reachable paths.
- Reachable Drivers and Protocols:
* Drivers accessible via virtual buses (virtio, USB gadget, loopback, netlink, binder, sockets, etc.).
================================================================================
4. EXTRACTING FocusSymbols (PREVENTING DILUTION)
================================================================================
When WorthFuzzing=true, you must extract specific kernel functions into FocusSymbols to guide the fuzzer:
- AVOID UBIQUITOUS LIFECYCLE HOT-PATHS:
Do NOT list generic, ubiquitous functions called by almost every program in the corpus
(including, but not limited to: general memory allocators and deallocators, page fault
and trap handlers, or core synchronization primitives; this is not an exhaustive list).
Listing ubiquitous functions causes the fuzzer to classify thousands of unrelated tests as "focused",
which severely dilutes fuzzing effort away from the actual changes.
- TARGET SPECIFIC FEATURE LOGIC AND ENTRYPOINTS:
List functions that specifically implement the logic being added or altered, or direct API entrypoints
for the subsystem feature under review.
- HANDLING STATIC INLINE FUNCTIONS IN HEADERS (.h):
Compiler-inlined static functions (such as static inlines in mm/*.h or include/linux/*.h) lack
distinct symbol addresses in vmlinux and cannot be targeted directly by symbol coverage filters.
If the changes are primarily in static inline helpers, identify non-static, feature-specific caller
functions in .c files that exercise them (avoiding ubiquitous lifecycle wrappers).
================================================================================
5. IDENTIFYING EnableConfigs
================================================================================
Identify any specific CONFIG_ options required to properly compile and reach the modified code:
- Inspect Kconfig files and #ifdef guards; do not make assumptions.
- Check "depends on" lines in Kconfig to include any non-standard parent subsystem configs needed.
- Strip any 'CONFIG_' prefix (e.g., return "NET_IPV4" instead of "CONFIG_NET_IPV4").
Prefer calling several tools at the same time to save round-trips.
Use set-results tool to provide results of the analysis.
It must be called exactly once before the final reply.
Ignore results of this tool.
Prompt: Target architecture: amd64
For your convenience, here is the diff of the changes:
commit e4e455baa671300d259799e8eaf43e01a9fd872f
Author: syz-cluster <triage@syzkaller.com>
Date: Fri Sep 4 19:04:23 2026 +0000
syz-cluster: applied patch under review
diff --git a/net/core/filter.c b/net/core/filter.c
index 61940e7535523..1bbb72138ac64 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -12912,8 +12912,8 @@ __bpf_kfunc_start_defs();
* @sock: Pointer to socket to be destroyed
*
* Return:
- * On error, may return EPROTONOSUPPORT, EINVAL.
- * EPROTONOSUPPORT if protocol specific destroy handler is not supported.
+ * On error, may return EOPNOTSUPP, EINVAL.
+ * EOPNOTSUPP if protocol specific destroy handler is not supported.
* 0 otherwise
*/
__bpf_kfunc int bpf_sock_destroy(struct sock_common *sock)
@@ -12925,8 +12925,12 @@ __bpf_kfunc int bpf_sock_destroy(struct sock_common *sock)
* Supporting protocols will need to acquire sock lock in the BPF context
* prior to invoking this kfunc.
*/
- if (!sk->sk_prot->diag_destroy || (sk->sk_protocol != IPPROTO_TCP &&
- sk->sk_protocol != IPPROTO_UDP))
+ if (!sk->sk_prot->diag_destroy)
+ return -EOPNOTSUPP;
+
+ if (sk_fullsock(sk) &&
+ sk->sk_protocol != IPPROTO_TCP &&
+ sk->sk_protocol != IPPROTO_UDP)
return -EOPNOTSUPP;
return sk->sk_prot->diag_destroy(sk, ECONNABORTED);
diff --git a/tools/testing/selftests/bpf/prog_tests/sock_destroy.c b/tools/testing/selftests/bpf/prog_tests/sock_destroy.c
index 9c11938fe597d..6ccc7cda410bf 100644
--- a/tools/testing/selftests/bpf/prog_tests/sock_destroy.c
+++ b/tools/testing/selftests/bpf/prog_tests/sock_destroy.c
@@ -110,6 +110,65 @@ static void test_tcp_server(struct sock_destroy_prog *skel)
close(serv);
}
+static void test_tcp_timewait(struct sock_destroy_prog *skel)
+{
+ int serv = -1, clien = -1, accept_serv = -1, n;
+ struct timeval tv = {};
+ char buf[1];
+
+ serv = start_server(AF_INET6, SOCK_STREAM, NULL, 0, 0);
+ if (!ASSERT_GE(serv, 0, "start_server"))
+ goto cleanup;
+
+ clien = connect_to_fd(serv, 0);
+ if (!ASSERT_GE(clien, 0, "connect_to_fd"))
+ goto cleanup;
+
+ accept_serv = accept(serv, NULL, NULL);
+ if (!ASSERT_GE(accept_serv, 0, "serv accept"))
+ goto cleanup;
+
+ /* Active close from the client, then close the server side. Once
+ * recv() sees EOF the server FIN has been processed and the client
+ * sock is in TIME_WAIT. Block without timeout so a loaded CI box
+ * can't race us.
+ */
+ if (!ASSERT_OK(setsockopt(clien, SOL_SOCKET, SO_RCVTIMEO, &tv,
+ sizeof(tv)), "clear rcvtimeo"))
+ goto cleanup;
+ if (!ASSERT_OK(shutdown(clien, SHUT_WR), "client shutdown"))
+ goto cleanup;
+
+ close(accept_serv);
+ accept_serv = -1;
+
+ /* block until return EOF */
+ n = recv(clien, buf, sizeof(buf), 0);
+ if (!ASSERT_EQ(n, 0, "client recv EOF"))
+ goto cleanup;
+
+ /* Run iterator program that destroys the timewait client sock. */
+ skel->bss->tw_found = 0;
+ start_iter_sockets(skel->progs.iter_tcp6_timewait);
+ if (!ASSERT_EQ(skel->bss->tw_found, 1, "timewait sock found"))
+ goto cleanup;
+
+ ASSERT_OK(skel->bss->tw_destroy_err, "destroy timewait sock");
+
+ /* The destroyed timewait sock must be gone. */
+ skel->bss->tw_found = 0;
+ start_iter_sockets(skel->progs.iter_tcp6_timewait);
+ ASSERT_EQ(skel->bss->tw_found, 0, "timewait sock destroyed");
+
+cleanup:
+ if (clien != -1)
+ close(clien);
+ if (accept_serv != -1)
+ close(accept_serv);
+ if (serv != -1)
+ close(serv);
+}
+
static void test_udp_client(struct sock_destroy_prog *skel)
{
int serv = -1, clien = -1, n = 0;
@@ -204,11 +263,12 @@ void test_sock_destroy(void)
test_tcp_client(skel);
if (test__start_subtest("tcp_server"))
test_tcp_server(skel);
+ if (test__start_subtest("tcp_timewait"))
+ test_tcp_timewait(skel);
if (test__start_subtest("udp_client"))
test_udp_client(skel);
if (test__start_subtest("udp_server"))
test_udp_server(skel);
-
RUN_TESTS(sock_destroy_prog_fail);
cleanup:
diff --git a/tools/testing/selftests/bpf/progs/sock_destroy_prog.c b/tools/testing/selftests/bpf/progs/sock_destroy_prog.c
index 9e0bf7a54cec9..0a8887543218a 100644
--- a/tools/testing/selftests/bpf/progs/sock_destroy_prog.c
+++ b/tools/testing/selftests/bpf/progs/sock_destroy_prog.c
@@ -7,6 +7,8 @@
#include "bpf_tracing_net.h"
__be16 serv_port = 0;
+int tw_found = 0;
+int tw_destroy_err = 0;
int bpf_sock_destroy(struct sock_common *sk) __ksym;
@@ -100,6 +102,34 @@ int iter_tcp6_server(struct bpf_iter__tcp *ctx)
return 0;
}
+SEC("iter/tcp")
+int iter_tcp6_timewait(struct bpf_iter__tcp *ctx)
+{
+ struct sock_common *sk_common = ctx->sk_common;
+ __u64 *val;
+ int key = 0;
+
+ if (!sk_common)
+ return 0;
+
+ if (sk_common->skc_family != AF_INET6)
+ return 0;
+
+ if (!bpf_skc_to_tcp_timewait_sock(sk_common))
+ return 0;
+
+ val = bpf_map_lookup_elem(&tcp_conn_sockets, &key);
+ if (!val)
+ return 0;
+ /* The timewait sock inherits the cookie of the closed client sock. */
+ if (bpf_get_socket_cookie(sk_common) != *val)
+ return 0;
+
+ tw_found++;
+ tw_destroy_err = bpf_sock_destroy(sk_common);
+
+ return 0;
+}
SEC("iter/udp")
int iter_udp6_client(struct bpf_iter__udp *ctx)
|
| 3/2 | 2026/09/04 19:04 | llm | patch-evaluator |
0mModel:gemini-3.7-flash Args: null Results: null Tokens: input: 4766 output: 37 thoughts: 314 Thoughts: **Analyzing the BPF Patch: A Deep Dive** Okay, let's break this down. First, I need to understand the intent of this patch within `net/core/filter.c`. I'll start by reading the patch itself, then I'll leverage my knowledge of BPF and socket internals to assess its impact. The change in `bpf_sock_destroy` is immediately apparent. The code is being modified to restrict its use, particularly for sockets beyond TCP and UDP. Previously, there was a check that allowed the function to proceed if `diag_destroy` was not implemented. Now, a return of `-EOPNOTSUPP` occurs if `diag_destroy` isn't implemented and the socket is not TCP or UDP. Furthermore, there's an added check using `sk_fullsock`, which indicates this function might be more limited to full sockets other than TCP/UDP. The comment highlighting "locking semantics" and concurrent execution is a key red flag, of course. My initial hunch is that this is related to ensuring data integrity and preventing race conditions during socket teardown within BPF contexts. Supporting protocols must now acquire the sock lock to ensure safety. To gain a more complete understanding, I'll need to see how `bpf_sock_destroy` is *used* within this file and potentially in other parts of the network stack. I'll need to look around this function to see where it is called and how its return values are handled. I'll use `read-file` or `grepper` to explore the surrounding code and understand the bigger picture. Are there any existing BPF programs that rely on this functionality? How are they affected by this change? What's the impact on the existing implementations that depend on this kfunc? I need to track down those uses. My goal is to determine if this change is sound, whether it introduces any regressions, and if it's properly documented. A thorough review will require looking at the locking strategy and the implications of this new restriction. |
| 4/2 | 2026/09/04 19:04 | tool | read-file |
0mArgs:{
"File": "net/core/filter.c",
"FirstLine": 12905,
"LineCount": 40
}Results: {
"Contents": "12905:\t * The function expects a non-NULL pointer to a socket, and invokes the\n12906:\t * protocol specific socket destroy handlers.\n12907:\t *\n12908:\t * The helper can only be called from BPF contexts that have acquired the socket\n12909:\t * locks.\n12910:\t *\n12911:\t * Parameters:\n12912:\t * @sock: Pointer to socket to be destroyed\n12913:\t *\n12914:\t * Return:\n12915:\t * On error, may return EOPNOTSUPP, EINVAL.\n12916:\t * EOPNOTSUPP if protocol specific destroy handler is not supported.\n12917:\t * 0 otherwise\n12918:\t */\n12919:\t__bpf_kfunc int bpf_sock_destroy(struct sock_common *sock)\n12920:\t{\n12921:\t\tstruct sock *sk = (struct sock *)sock;\n12922:\t\n12923:\t\t/* The locking semantics that allow for synchronous execution of the\n12924:\t\t * destroy handlers are only supported for TCP and UDP.\n12925:\t\t * Supporting protocols will need to acquire sock lock in the BPF context\n12926:\t\t * prior to invoking this kfunc.\n12927:\t\t */\n12928:\t\tif (!sk-\u003esk_prot-\u003ediag_destroy)\n12929:\t\t\treturn -EOPNOTSUPP;\n12930:\t\n12931:\t\tif (sk_fullsock(sk) \u0026\u0026\n12932:\t\t sk-\u003esk_protocol != IPPROTO_TCP \u0026\u0026\n12933:\t\t sk-\u003esk_protocol != IPPROTO_UDP)\n12934:\t\t\treturn -EOPNOTSUPP;\n12935:\t\n12936:\t\treturn sk-\u003esk_prot-\u003ediag_destroy(sk, ECONNABORTED);\n12937:\t}\n12938:\t\n12939:\t__bpf_kfunc_end_defs();\n12940:\t\n12941:\tBTF_KFUNCS_START(bpf_sk_iter_kfunc_ids)\n12942:\tBTF_ID_FLAGS(func, bpf_sock_destroy)\n12943:\tBTF_KFUNCS_END(bpf_sk_iter_kfunc_ids)\n12944:\t\n"
} |
| 5/2 | 2026/09/04 19:04 | llm | patch-evaluator |
0mModel:gemini-3.7-flash Args: null Results: null Tokens: input: 6199 output: 18 thoughts: 257 Thoughts: **Analyzing the Evolution of `bpf_sock_destroy`** Okay, let's break this down. My initial understanding is that `bpf_sock_destroy` is a BPF kfunc, part of the standard BPF toolkit used to clean up socket resources, especially those accessed through socket and BPF iterators. I recall that, previously, its usage was rather restricted, requiring that the socket's protocol be either TCP or UDP. The code snippet is talking about a change here. The core of the change seems to center around sockets that aren't fully formed—let's call them "non-fullsock" sockets—specifically, timewait sockets, request sockets and the like. Now, the `sk_protocol` field, the one used to validate if we are dealing with TCP or UDP, doesn't always exist at the same offset in the `sock_common` structure for these "partial" socket types. Furthermore, calling `sk_fullsock(sk)` returns false for these socket types. This is where the issue came in. The fix I'm looking at utilizes `sk_fullsock(sk)`. Before this change, the kfunc would have failed in those situations. But by using `sk_fullsock(sk)` as a check, the code now *conditionally* applies the protocol check. This allows the kfunc to correctly destroy these timewait sockets, even when the `sk_protocol` field isn't reliably available in the same memory location, or at all. I can see how this can be useful in functions like `tcp_twsk_diag_destroy`, `tcp_diag_destroy`, and `inet_twsk_deschedule_put`. The new code handles these types of sockets by destroying them now that `sk_fullsock(sk)` is being used to validate first. Next, I need to look at how `diag_destroy` is implemented in other parts of the kernel, to see if there is any broader impact or if this is the start of a trend. |
| 6/2 | 2026/09/04 19:04 | tool | grepper |
0mArgs:{
"Expression": "\\.diag_destroy"
}Results: {
"Output": "net/ipv4/raw.c=948=struct proto raw_prot = {\n--\nnet/ipv4/raw.c-972-#endif\nnet/ipv4/raw.c:973:\t.diag_destroy\t = raw_abort,\nnet/ipv4/raw.c-974-};\n--\nnet/ipv4/tcp_ipv4.c=3347=struct proto tcp_prot = {\n--\nnet/ipv4/tcp_ipv4.c-3395-\t.no_autobind\t\t= true,\nnet/ipv4/tcp_ipv4.c:3396:\t.diag_destroy\t\t= tcp_abort,\nnet/ipv4/tcp_ipv4.c-3397-};\n--\nnet/ipv4/udp.c=3143=struct proto udp_prot = {\n--\nnet/ipv4/udp.c-3173-\t.obj_size\t\t= sizeof(struct udp_sock),\nnet/ipv4/udp.c:3174:\t.diag_destroy\t\t= udp_abort,\nnet/ipv4/udp.c-3175-};\n--\nnet/ipv6/raw.c=1207=struct proto rawv6_prot = {\n--\nnet/ipv6/raw.c-1231-#endif\nnet/ipv6/raw.c:1232:\t.diag_destroy\t = raw_abort,\nnet/ipv6/raw.c-1233-};\n--\nnet/ipv6/tcp_ipv6.c=2276=struct proto tcpv6_prot = {\n--\nnet/ipv6/tcp_ipv6.c-2325-\t.no_autobind\t\t= true,\nnet/ipv6/tcp_ipv6.c:2326:\t.diag_destroy\t\t= tcp_abort,\nnet/ipv6/tcp_ipv6.c-2327-};\n--\nnet/ipv6/udp.c=1908=struct proto udpv6_prot = {\n--\nnet/ipv6/udp.c-1940-\t.ipv6_pinfo_offset = offsetof(struct udp6_sock, inet6),\nnet/ipv6/udp.c:1941:\t.diag_destroy\t\t= udp_abort,\nnet/ipv6/udp.c-1942-};\n--\nnet/mptcp/subflow.c=2146=void __init mptcp_subflow_init(void)\n--\nnet/mptcp/subflow.c-2166-\ttcp_prot_override.release_cb = tcp_release_cb_override;\nnet/mptcp/subflow.c:2167:\ttcp_prot_override.diag_destroy = tcp_abort_override;\nnet/mptcp/subflow.c-2168-#ifdef CONFIG_BPF_SYSCALL\n--\nnet/mptcp/subflow.c=2180=void __init mptcp_subflow_v6_init(void)\n--\nnet/mptcp/subflow.c-2213-\ttcpv6_prot_override.release_cb = tcp_release_cb_override;\nnet/mptcp/subflow.c:2214:\ttcpv6_prot_override.diag_destroy = tcp_abort_override;\nnet/mptcp/subflow.c-2215-#ifdef CONFIG_BPF_SYSCALL\n"
} |
| 7/2 | 2026/09/04 19:04 | llm | patch-evaluator |
0mModel:gemini-3.7-flash Args: null Results: null Tokens: input: 7769 output: 18 thoughts: 336 Thoughts: **My Fuzzing Assessment** Okay, let's break this down. `bpf_sock_destroy` is a BPF kfunc, that is important as it is a core networking and BPF function that's reachable through standard syscalls like `bpf()` and iterator file descriptors. QEMU and GCE are standard targets for this type of work, so that's good. The key here is that the change modifies `bpf_sock_destroy`'s behavior, specifically allowing it to destroy *non-full* sockets, like TIME_WAIT sockets, for example, which is triggered through something like `tcp_abort`. That's interesting; it's changing the execution paths for sockets in TIME_WAIT or request states. Is this worth fuzzing? Let's see... Section 3 of my guidelines are: core subsystems, refactorings, and reachable code. This hits on "core networking," "BPF," and is definitely "reachable code" so the answer is clearly TRUE. This is a very good target. Now, let's look at the FocusSymbols: `bpf_sock_destroy` itself, in `net/core/filter.c`, is the function being modified. And related functions? `tcp_abort` is the obvious one, or is it just the `bpf_sock_destroy`? I need to look into what `tcp_abort` actually does with TIME_WAIT sockets. Need to dive into that specific function. |
| 8/2 | 2026/09/04 19:04 | tool | grepper |
0mArgs:{
"Expression": "int tcp_abort"
}Results: {
"Output": "include/net/tcp.h=1704=void tcp_done(struct sock *sk);\ninclude/net/tcp.h:1705:int tcp_abort(struct sock *sk, int err);\ninclude/net/tcp.h-1706-\n--\nnet/ipv4/tcp.c=5089=void tcp_done(struct sock *sk)\n--\nnet/ipv4/tcp.c-5114-\nnet/ipv4/tcp.c:5115:int tcp_abort(struct sock *sk, int err)\nnet/ipv4/tcp.c-5116-{\n--\nnet/mptcp/subflow.c=2096=static void tcp_release_cb_override(struct sock *ssk)\n--\nnet/mptcp/subflow.c-2111-\nnet/mptcp/subflow.c:2112:static int tcp_abort_override(struct sock *ssk, int err)\nnet/mptcp/subflow.c-2113-{\n"
} |
| 9/2 | 2026/09/04 19:04 | llm | patch-evaluator |
0mModel:gemini-3.7-flash Args: null Results: null Tokens: input: 8706 output: 37 thoughts: 21 Thoughts: Here's my attempt at summarizing the thought process, tailored for an expert audience: **Diving into the `tcp_abort` Implementation** Alright, let's get down to brass tacks. I need a refresher on the `tcp_abort` function's behavior. Time to go spelunking in the kernel. Specifically, I'm heading over to `net/ipv4/tcp.c`. My focus right now is pinpointing the exact implementation details of `tcp_abort`. I want to quickly refresh on how it handles the abrupt termination of a TCP connection from the kernel's perspective. I'm looking for the nitty-gritty: error handling, resource cleanup, how it interfaces with the TCP state machine. |
| 10/2 | 2026/09/04 19:04 | tool | read-file |
0mArgs:{
"File": "net/ipv4/tcp.c",
"FirstLine": 5115,
"LineCount": 35
}Results: {
"Contents": "5115:\tint tcp_abort(struct sock *sk, int err)\n5116:\t{\n5117:\t\tint state = inet_sk_state_load(sk);\n5118:\t\n5119:\t\tif (state == TCP_NEW_SYN_RECV) {\n5120:\t\t\tstruct request_sock *req = inet_reqsk(sk);\n5121:\t\n5122:\t\t\tlocal_bh_disable();\n5123:\t\t\tinet_csk_reqsk_queue_drop(req-\u003ersk_listener, req);\n5124:\t\t\tlocal_bh_enable();\n5125:\t\t\treturn 0;\n5126:\t\t}\n5127:\t\tif (state == TCP_TIME_WAIT) {\n5128:\t\t\tstruct inet_timewait_sock *tw = inet_twsk(sk);\n5129:\t\n5130:\t\t\trefcount_inc(\u0026tw-\u003etw_refcnt);\n5131:\t\t\tlocal_bh_disable();\n5132:\t\t\tinet_twsk_deschedule_put(tw);\n5133:\t\t\tlocal_bh_enable();\n5134:\t\t\treturn 0;\n5135:\t\t}\n5136:\t\n5137:\t\t/* BPF context ensures sock locking. */\n5138:\t\tif (!has_current_bpf_ctx())\n5139:\t\t\t/* Don't race with userspace socket closes such as tcp_close. */\n5140:\t\t\tlock_sock(sk);\n5141:\t\n5142:\t\t/* Avoid closing the same socket twice. */\n5143:\t\tif (sk-\u003esk_state == TCP_CLOSE) {\n5144:\t\t\tif (!has_current_bpf_ctx())\n5145:\t\t\t\trelease_sock(sk);\n5146:\t\t\treturn -ENOENT;\n5147:\t\t}\n5148:\t\n5149:\t\tif (sk-\u003esk_state == TCP_LISTEN) {\n"
} |
| 11/2 | 2026/09/04 19:04 | llm | patch-evaluator |
0mModel:gemini-3.7-flash Args: null Results: null Tokens: input: 9441 output: 35 thoughts: 298 Thoughts: **Analyzing the Patch for `bpf_sock_destroy`** Okay, let's break this down. I see we're dealing with a fix related to `bpf_sock_destroy` and its interaction with sockets in different states. I need to understand why this patch is necessary and what it's enabling. First, I'm looking at how `tcp_abort` is currently handled. I see the conditional check `if (state == TCP_TIME_WAIT)`. That's good, it confirms that `tcp_abort` is *already* written to deal with `TCP_TIME_WAIT` sockets. Same for `TCP_NEW_SYN_RECV`, it’s being handled. This implies there's no inherent problem in *tcp_abort* itself. The issue must be in *how* these functions are called, or perhaps, *when*. The text says `bpf_sock_destroy()` was the blocker. The key here is the `sk->sk_protocol` check *before* the `sk_fullsock(sk)` check within `bpf_sock_destroy()`. Right, that's the culprit. That conditional logic was preventing `bpf_sock_destroy` from being called on sockets in states like `TCP_TIME_WAIT`, which are not *full* sockets. The fix is now allowing `bpf_sock_destroy` to operate on *non-full* sockets. Makes sense, that allows the cleanup of these socket structures. Now, to fully grasp the implications, I need to understand where `bpf_sock_destroy` is defined and how it's compiled. Let's find out about the Kconfig requirements, I'll go to `net/core/filter.c` and search around line 12900 or use a direct search for the function's definition. This will reveal the build configuration dependencies and confirm that `bpf_sock_destroy` is properly enabled for the relevant BPF iterator usage. |
| 12/2 | 2026/09/04 19:05 | tool | grepper |
0mArgs:{
"Expression": "bpf_sk_iter_kfunc_ids",
"PathPrefix": "net/core/"
}Results: {
"Output": "net/core/filter.c=12939=__bpf_kfunc_end_defs();\nnet/core/filter.c-12940-\nnet/core/filter.c:12941:BTF_KFUNCS_START(bpf_sk_iter_kfunc_ids)\nnet/core/filter.c-12942-BTF_ID_FLAGS(func, bpf_sock_destroy)\nnet/core/filter.c:12943:BTF_KFUNCS_END(bpf_sk_iter_kfunc_ids)\nnet/core/filter.c-12944-\nnet/core/filter.c=12945=static int tracing_iter_filter(const struct bpf_prog *prog, u32 kfunc_id)\nnet/core/filter.c-12946-{\nnet/core/filter.c:12947:\tif (btf_id_set8_contains(\u0026bpf_sk_iter_kfunc_ids, kfunc_id) \u0026\u0026\nnet/core/filter.c-12948-\t prog-\u003eexpected_attach_type != BPF_TRACE_ITER)\n--\nnet/core/filter.c=12953=static const struct btf_kfunc_id_set bpf_sk_iter_kfunc_set = {\nnet/core/filter.c-12954-\t.owner = THIS_MODULE,\nnet/core/filter.c:12955:\t.set = \u0026bpf_sk_iter_kfunc_ids,\nnet/core/filter.c-12956-\t.filter = tracing_iter_filter,\n"
} |
| 13/2 | 2026/09/04 19:05 | llm | patch-evaluator |
0mModel:gemini-3.7-flash Args: null Results: null Tokens: input: 10626 output: 37 thoughts: 37 Thoughts: **Investigating the Registration of `bpf_sk_iter_kfunc_set` in `net/core/filter.c`** Okay, time to dig into this. I need to understand where `bpf_sk_iter_kfunc_set` is actually registered within the kernel, specifically within `net/core/filter.c`. Given the nature of BPF functions, my first instinct is to check for any conditional compilation – those `#ifdef` blocks – that might govern its inclusion based on kernel configuration. I'm assuming that its availability is tied to some specific feature or module that needs to be enabled. I want to identify those conditions because it gives me context on its purpose, usage requirements, and the surrounding environment the function expects to work within. Understanding this will inform any further analysis, debugging, or modifications I might need to perform on related BPF code. Time to fire up the editor and start tracing those dependencies. |
| 14/2 | 2026/09/04 19:05 | tool | read-file |
0mArgs:{
"File": "net/core/filter.c",
"FirstLine": 12940,
"LineCount": 40
}Results: {
"Contents": "12940:\t\n12941:\tBTF_KFUNCS_START(bpf_sk_iter_kfunc_ids)\n12942:\tBTF_ID_FLAGS(func, bpf_sock_destroy)\n12943:\tBTF_KFUNCS_END(bpf_sk_iter_kfunc_ids)\n12944:\t\n12945:\tstatic int tracing_iter_filter(const struct bpf_prog *prog, u32 kfunc_id)\n12946:\t{\n12947:\t\tif (btf_id_set8_contains(\u0026bpf_sk_iter_kfunc_ids, kfunc_id) \u0026\u0026\n12948:\t\t prog-\u003eexpected_attach_type != BPF_TRACE_ITER)\n12949:\t\t\treturn -EACCES;\n12950:\t\treturn 0;\n12951:\t}\n12952:\t\n12953:\tstatic const struct btf_kfunc_id_set bpf_sk_iter_kfunc_set = {\n12954:\t\t.owner = THIS_MODULE,\n12955:\t\t.set = \u0026bpf_sk_iter_kfunc_ids,\n12956:\t\t.filter = tracing_iter_filter,\n12957:\t};\n12958:\t\n12959:\tstatic int init_subsystem(void)\n12960:\t{\n12961:\t\treturn register_btf_kfunc_id_set(BPF_PROG_TYPE_TRACING, \u0026bpf_sk_iter_kfunc_set);\n12962:\t}\n12963:\tlate_initcall(init_subsystem);\n"
} |
| 15/2 | 2026/09/04 19:05 | llm | patch-evaluator |
0mModel:gemini-3.7-flash Args: null Results: null Tokens: input: 11359 output: 37 thoughts: 50 Thoughts: **Investigating Potential Conditional Compilation in `net/core/filter.c`** Okay, so I need to quickly determine if there are any conditional compilation directives, specifically `#ifdef` preprocessor statements, surrounding the `init_subsystem` or `bpf_sock_destroy` functions within the `net/core/filter.c` file. Given my familiarity with the kernel codebase, this seems like a sensible place to start looking for potential build-time variations in how the BPF subsystem might be initialized or torn down. Knowing this, and having looked at the general architecture of the network filter, I have a good idea where to start looking, and around line 12900 seems like a reasonable point to begin my scan. I want to see how these functions, or their behavior, are potentially controlled by build configurations or specific kernel versions. This is a common pattern in the kernel, and understanding these conditional blocks is crucial for debugging or porting BPF-related code. Let's dig in. |
| 16/2 | 2026/09/04 19:05 | tool | read-file |
0mArgs:{
"File": "net/core/filter.c",
"FirstLine": 12890,
"LineCount": 30
}Results: {
"Contents": "12890:\t\tret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_SCHED_CLS, \u0026bpf_kfunc_set_skb_meta);\n12891:\t\tret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_SCHED_ACT, \u0026bpf_kfunc_set_skb_meta);\n12892:\t\tret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_XDP, \u0026bpf_kfunc_set_xdp);\n12893:\t\tret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_CGROUP_SOCK_ADDR,\n12894:\t\t\t\t\t\t \u0026bpf_kfunc_set_sock_addr);\n12895:\t\tret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_SCHED_CLS, \u0026bpf_kfunc_set_tcp_reqsk);\n12896:\t\tret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_CGROUP_SKB, \u0026bpf_kfunc_set_icmp_send);\n12897:\t\treturn ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_SOCK_OPS, \u0026bpf_kfunc_set_sock_ops);\n12898:\t}\n12899:\tlate_initcall(bpf_kfunc_init);\n12900:\t\n12901:\t__bpf_kfunc_start_defs();\n12902:\t\n12903:\t/* bpf_sock_destroy: Destroy the given socket with ECONNABORTED error code.\n12904:\t *\n12905:\t * The function expects a non-NULL pointer to a socket, and invokes the\n12906:\t * protocol specific socket destroy handlers.\n12907:\t *\n12908:\t * The helper can only be called from BPF contexts that have acquired the socket\n12909:\t * locks.\n12910:\t *\n12911:\t * Parameters:\n12912:\t * @sock: Pointer to socket to be destroyed\n12913:\t *\n12914:\t * Return:\n12915:\t * On error, may return EOPNOTSUPP, EINVAL.\n12916:\t * EOPNOTSUPP if protocol specific destroy handler is not supported.\n12917:\t * 0 otherwise\n12918:\t */\n12919:\t__bpf_kfunc int bpf_sock_destroy(struct sock_common *sock)\n"
} |
| 17/2 | 2026/09/04 19:05 | llm | patch-evaluator |
0mModel:gemini-3.7-flash Args: null Results: null Tokens: input: 12370 output: 27 thoughts: 17 Thoughts: Here's my summary, as though I'm thinking it: **Digging into the Network Core Makefile** Okay, so I need to find out how `filter.c` gets built within the network core. The obvious place to start is `net/core/Makefile`. That's where all the fundamental build rules and dependencies for this section of the kernel reside. Let's see what we can unearth in there. Time to crack open that Makefile and hunt down the relevant section... gotta find those build directives. |
| 18/2 | 2026/09/04 19:05 | tool | grepper |
0mArgs:{
"Expression": "filter\\.o",
"PathPrefix": "net/core/"
}Results: {
"Output": "net/core/Makefile=12=obj-y\t\t += dev.o dev_api.o dev_addr_lists.o dst.o netevent.o \\\nnet/core/Makefile:13:\t\t\tneighbour.o rtnetlink.o utils.o link_watch.o filter.o \\\nnet/core/Makefile-14-\t\t\tsock_diag.o dev_ioctl.o tso.o sock_reuseport.o \\\n--\nnet/core/pktgen.c-87- *\nnet/core/pktgen.c:88: * Remove if fix from added Harald Welte \u003claforge@netfilter.org\u003e 040419\nnet/core/pktgen.c-89- * ia64 compilation fix from Aron Griffis \u003caron@hp.com\u003e 040604\n"
} |
| 19/2 | 2026/09/04 19:05 | llm | patch-evaluator |
0mModel:gemini-3.7-flash Args: null Results: null Tokens: input: 12731 output: 35 thoughts: 29 Thoughts: Okay, here's my summary, taking the form of my thought process as an expert in my field: **Checking for Conditional Compilation of BPF_SYSCALL in `net/core/filter.c`** Alright, let's dive in. I need to quickly ascertain the presence of any conditional compilation directives related to `BPF_SYSCALL` within the `net/core/filter.c` file. This suggests that the functionality or definition of `BPF_SYSCALL` might be dependent on some configuration setting, kernel version, or other compile-time flag. I'll need to look for `#ifdef`, `#ifndef`, `#if`, or potentially even `#define` usage surrounding this macro. The purpose of this could be a compatibility measure for older kernels, a feature flag, or something else entirely, so it is necessary to determine exactly what this means. This is often the first step in understanding how a particular feature is enabled or disabled and how it fits into the broader kernel landscape. The presence of conditionals here would immediately raise some questions in my mind about the potential implications for portability, configuration options, or the stability of BPF-related code. Let's start the search. |
| 20/2 | 2026/09/04 19:05 | tool | grepper |
0mArgs:{
"Expression": "CONFIG_BPF_SYSCALL",
"PathPrefix": "net/core/filter.c"
}Results: {
"Output": "net/core/filter.c=4534=EXPORT_SYMBOL_GPL(xdp_do_flush);\nnet/core/filter.c-4535-\nnet/core/filter.c:4536:#if defined(CONFIG_DEBUG_NET) \u0026\u0026 defined(CONFIG_BPF_SYSCALL)\nnet/core/filter.c-4537-void xdp_do_check_flushed(struct napi_struct *napi)\n"
} |
| 21/2 | 2026/09/04 19:05 | llm | patch-evaluator |
0mModel:gemini-3.7-flash Args: null Results: null Tokens: input: 13168 output: 25 thoughts: 30 Thoughts: Here's my summary, as though I'm thinking through this process: **Diving into `register_btf_kfunc_id_set` and BPF_SYSCALL** Okay, so I need to understand the implications of `register_btf_kfunc_id_set`. My first instinct is always to check the definition and any guarding conditions. I know this function is related to BPF, and given the context, I suspect the use of `BPF_SYSCALL` is important here. I need to quickly determine *where* this function is defined and what conditional logic is wrapped around its use. Are we using a `#ifdef` or something similar? Is it an inline function? My goal is to determine what conditions must be met for this function to be even considered at compile time. This is critical for understanding its potential impact and dependencies. Let's get to the code. I need to see if this is enabled by a specific kernel config option, maybe a feature flag... Knowing those details will help me immensely in evaluating the overall design. |
| 22/2 | 2026/09/04 19:05 | tool | grepper |
0mArgs:{
"Expression": "register_btf_kfunc_id_set"
}Results: {
"Output": "Documentation/bpf/kfuncs.rst=494=type. An example is shown below::\n--\nDocumentation/bpf/kfuncs.rst-507- {\nDocumentation/bpf/kfuncs.rst:508: return register_btf_kfunc_id_set(BPF_PROG_TYPE_TRACING, \u0026bpf_task_kfunc_set);\nDocumentation/bpf/kfuncs.rst-509- }\n--\ndrivers/base/power/wakeup.c=1227=static void __init wakeup_sources_bpf_init(void)\ndrivers/base/power/wakeup.c-1228-{\ndrivers/base/power/wakeup.c:1229:\tif (register_btf_kfunc_id_set(BPF_PROG_TYPE_SYSCALL, \u0026wakeup_source_kfunc_set))\ndrivers/base/power/wakeup.c-1230-\t\tpm_pr_dbg(\"Wakeup: failed to register BTF kfuncs\\n\");\n--\ndrivers/hid/bpf/hid_bpf_dispatch.c=658=static int __init hid_bpf_init(void)\n--\ndrivers/hid/bpf/hid_bpf_dispatch.c-667-\ndrivers/hid/bpf/hid_bpf_dispatch.c:668:\terr = register_btf_kfunc_id_set(BPF_PROG_TYPE_STRUCT_OPS, \u0026hid_bpf_kfunc_set);\ndrivers/hid/bpf/hid_bpf_dispatch.c-669-\tif (err) {\n--\ndrivers/hid/bpf/hid_bpf_dispatch.c-673-\ndrivers/hid/bpf/hid_bpf_dispatch.c:674:\terr = register_btf_kfunc_id_set(BPF_PROG_TYPE_SYSCALL, \u0026hid_bpf_syscall_kfunc_set);\ndrivers/hid/bpf/hid_bpf_dispatch.c-675-\tif (err) {\n--\nfs/binfmt_misc_bpf.c=321=static int bm_bpf_init(struct btf *btf)\nfs/binfmt_misc_bpf.c-322-{\nfs/binfmt_misc_bpf.c:323:\treturn register_btf_kfunc_id_set(BPF_PROG_TYPE_STRUCT_OPS,\nfs/binfmt_misc_bpf.c-324-\t\t\t\t\t \u0026bm_bpf_kfunc_set);\n--\nfs/bpf_fs_kfuncs.c=492=static int __init bpf_fs_kfuncs_init(void)\n--\nfs/bpf_fs_kfuncs.c-495-\nfs/bpf_fs_kfuncs.c:496:\tret = register_btf_kfunc_id_set(BPF_PROG_TYPE_LSM, \u0026bpf_fs_kfunc_set);\nfs/bpf_fs_kfuncs.c-497-\tif (ret || !IS_ENABLED(CONFIG_BINFMT_MISC_BPF))\nfs/bpf_fs_kfuncs.c-498-\t\treturn ret;\nfs/bpf_fs_kfuncs.c:499:\treturn register_btf_kfunc_id_set(BPF_PROG_TYPE_STRUCT_OPS,\nfs/bpf_fs_kfuncs.c-500-\t\t\t\t\t \u0026bpf_fs_kfunc_set);\n--\nfs/verity/measure.c=186=void __init fsverity_init_bpf(void)\nfs/verity/measure.c-187-{\nfs/verity/measure.c:188:\tregister_btf_kfunc_id_set(BPF_PROG_TYPE_LSM, \u0026bpf_fsverity_set);\nfs/verity/measure.c-189-}\n--\ninclude/linux/btf.h=587=u32 *btf_kfunc_is_modify_return(const struct btf *btf, u32 kfunc_btf_id,\ninclude/linux/btf.h-588-\t\t\t\tconst struct bpf_prog *prog);\ninclude/linux/btf.h:589:int register_btf_kfunc_id_set(enum bpf_prog_type prog_type,\ninclude/linux/btf.h-590-\t\t\t const struct btf_kfunc_id_set *s);\n--\ninclude/linux/btf.h=647=static inline u32 *btf_kfunc_id_set_contains(const struct btf *btf,\n--\ninclude/linux/btf.h-653-}\ninclude/linux/btf.h:654:static inline int register_btf_kfunc_id_set(enum bpf_prog_type prog_type,\ninclude/linux/btf.h-655-\t\t\t\t\t const struct btf_kfunc_id_set *s)\n--\nio_uring/bpf-ops.c=120=static int bpf_io_init(struct btf *btf)\n--\nio_uring/bpf-ops.c-129-\nio_uring/bpf-ops.c:130:\tret = register_btf_kfunc_id_set(BPF_PROG_TYPE_STRUCT_OPS,\nio_uring/bpf-ops.c-131-\t\t\t\t\t\u0026bpf_io_uring_kfunc_set);\n--\nkernel/bpf/arena.c=1131=static int __init kfunc_init(void)\nkernel/bpf/arena.c-1132-{\nkernel/bpf/arena.c:1133:\treturn register_btf_kfunc_id_set(BPF_PROG_TYPE_UNSPEC, \u0026common_kfunc_set);\nkernel/bpf/arena.c-1134-}\n--\nkernel/bpf/btf.c=8902=static int btf_populate_kfunc_set(struct btf *btf, enum btf_kfunc_hook hook,\n--\nkernel/bpf/btf.c-8948-\tset = tab-\u003esets[hook];\nkernel/bpf/btf.c:8949:\t/* Warn when register_btf_kfunc_id_set is called twice for the same hook\nkernel/bpf/btf.c-8950-\t * for module sets.\n--\nkernel/bpf/btf.c=9173=u32 *btf_kfunc_is_modify_return(const struct btf *btf, u32 kfunc_btf_id,\n--\nkernel/bpf/btf.c-9181-\nkernel/bpf/btf.c:9182:static int __register_btf_kfunc_id_set(enum btf_kfunc_hook hook,\nkernel/bpf/btf.c-9183-\t\t\t\t const struct btf_kfunc_id_set *kset)\n--\nkernel/bpf/btf.c-9208-/* This function must be invoked only from initcalls/module init functions */\nkernel/bpf/btf.c:9209:int register_btf_kfunc_id_set(enum bpf_prog_type prog_type,\nkernel/bpf/btf.c-9210-\t\t\t const struct btf_kfunc_id_set *kset)\n--\nkernel/bpf/btf.c-9222-\thook = bpf_prog_type_to_kfunc_hook(prog_type);\nkernel/bpf/btf.c:9223:\treturn __register_btf_kfunc_id_set(hook, kset);\nkernel/bpf/btf.c-9224-}\nkernel/bpf/btf.c:9225:EXPORT_SYMBOL_GPL(register_btf_kfunc_id_set);\nkernel/bpf/btf.c-9226-\n--\nkernel/bpf/btf.c=9228=int register_btf_fmodret_id_set(const struct btf_kfunc_id_set *kset)\nkernel/bpf/btf.c-9229-{\nkernel/bpf/btf.c:9230:\treturn __register_btf_kfunc_id_set(BTF_KFUNC_HOOK_FMODRET, kset);\nkernel/bpf/btf.c-9231-}\n--\nkernel/bpf/cpumask.c=515=static int __init cpumask_kfunc_init(void)\n--\nkernel/bpf/cpumask.c-525-\tret = bpf_mem_alloc_init(\u0026bpf_cpumask_ma, sizeof(struct bpf_cpumask), false);\nkernel/bpf/cpumask.c:526:\tret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_TRACING, \u0026cpumask_kfunc_set);\nkernel/bpf/cpumask.c:527:\tret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_STRUCT_OPS, \u0026cpumask_kfunc_set);\nkernel/bpf/cpumask.c:528:\tret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_SYSCALL, \u0026cpumask_kfunc_set);\nkernel/bpf/cpumask.c-529-\treturn ret ?: register_btf_id_dtor_kfuncs(cpumask_dtors,\n--\nkernel/bpf/crypto.c=379=static int __init crypto_kfunc_init(void)\n--\nkernel/bpf/crypto.c-388-\nkernel/bpf/crypto.c:389:\tret = register_btf_kfunc_id_set(BPF_PROG_TYPE_SCHED_CLS, \u0026crypt_kfunc_set);\nkernel/bpf/crypto.c:390:\tret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_SCHED_ACT, \u0026crypt_kfunc_set);\nkernel/bpf/crypto.c:391:\tret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_XDP, \u0026crypt_kfunc_set);\nkernel/bpf/crypto.c:392:\tret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_SYSCALL,\nkernel/bpf/crypto.c-393-\t\t\t\t\t \u0026crypt_init_kfunc_set);\n--\nkernel/bpf/helpers.c=4982=static int __init kfunc_init(void)\n--\nkernel/bpf/helpers.c-4997-\nkernel/bpf/helpers.c:4998:\tret = register_btf_kfunc_id_set(BPF_PROG_TYPE_TRACING, \u0026generic_kfunc_set);\nkernel/bpf/helpers.c:4999:\tret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_SCHED_CLS, \u0026generic_kfunc_set);\nkernel/bpf/helpers.c:5000:\tret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_XDP, \u0026generic_kfunc_set);\nkernel/bpf/helpers.c:5001:\tret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_STRUCT_OPS, \u0026generic_kfunc_set);\nkernel/bpf/helpers.c:5002:\tret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_SYSCALL, \u0026generic_kfunc_set);\nkernel/bpf/helpers.c:5003:\tret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_CGROUP_SKB, \u0026generic_kfunc_set);\nkernel/bpf/helpers.c-5004-\tret = ret ?: register_btf_id_dtor_kfuncs(generic_dtors,\n--\nkernel/bpf/helpers.c-5006-\t\t\t\t\t\t THIS_MODULE);\nkernel/bpf/helpers.c:5007:\treturn ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_UNSPEC, \u0026common_kfunc_set);\nkernel/bpf/helpers.c-5008-}\n--\nkernel/bpf/map_iter.c=230=static int init_subsystem(void)\nkernel/bpf/map_iter.c-231-{\nkernel/bpf/map_iter.c:232:\treturn register_btf_kfunc_id_set(BPF_PROG_TYPE_UNSPEC, \u0026bpf_map_iter_kfunc_set);\nkernel/bpf/map_iter.c-233-}\n--\nkernel/bpf/rqspinlock.c=759=static __init int rqspinlock_register_kfuncs(void)\nkernel/bpf/rqspinlock.c-760-{\nkernel/bpf/rqspinlock.c:761:\treturn register_btf_kfunc_id_set(BPF_PROG_TYPE_UNSPEC, \u0026rqspinlock_kfunc_set);\nkernel/bpf/rqspinlock.c-762-}\n--\nkernel/cgroup/rstat.c=766=static int __init bpf_rstat_kfunc_init(void)\nkernel/cgroup/rstat.c-767-{\nkernel/cgroup/rstat.c:768:\treturn register_btf_kfunc_id_set(BPF_PROG_TYPE_TRACING,\nkernel/cgroup/rstat.c-769-\t\t\t\t\t \u0026bpf_rstat_kfunc_set);\n--\nkernel/sched/ext/cid.c=1160=int scx_cid_kfunc_init(void)\nkernel/sched/ext/cid.c-1161-{\nkernel/sched/ext/cid.c:1162:\treturn register_btf_kfunc_id_set(BPF_PROG_TYPE_STRUCT_OPS, \u0026scx_kfunc_set_init_cids) ?:\nkernel/sched/ext/cid.c:1163:\t\tregister_btf_kfunc_id_set(BPF_PROG_TYPE_STRUCT_OPS, \u0026scx_kfunc_set_cid) ?:\nkernel/sched/ext/cid.c:1164:\t\tregister_btf_kfunc_id_set(BPF_PROG_TYPE_TRACING, \u0026scx_kfunc_set_cid) ?:\nkernel/sched/ext/cid.c:1165:\t\tregister_btf_kfunc_id_set(BPF_PROG_TYPE_SYSCALL, \u0026scx_kfunc_set_cid);\nkernel/sched/ext/cid.c-1166-}\n--\nkernel/sched/ext/ext.c=10898=static int __init scx_init(void)\n--\nkernel/sched/ext/ext.c-10976-\t * kfunc registration can't be done from init_sched_ext_class() as\nkernel/sched/ext/ext.c:10977:\t * register_btf_kfunc_id_set() needs most of the system to be up.\nkernel/sched/ext/ext.c-10978-\t *\n--\nkernel/sched/ext/ext.c-10986-\t */\nkernel/sched/ext/ext.c:10987:\tif ((ret = register_btf_kfunc_id_set(BPF_PROG_TYPE_STRUCT_OPS,\nkernel/sched/ext/ext.c-10988-\t\t\t\t\t \u0026scx_kfunc_set_enqueue_dispatch)) ||\nkernel/sched/ext/ext.c:10989:\t (ret = register_btf_kfunc_id_set(BPF_PROG_TYPE_STRUCT_OPS,\nkernel/sched/ext/ext.c-10990-\t\t\t\t\t \u0026scx_kfunc_set_dispatch)) ||\nkernel/sched/ext/ext.c:10991:\t (ret = register_btf_kfunc_id_set(BPF_PROG_TYPE_STRUCT_OPS,\nkernel/sched/ext/ext.c-10992-\t\t\t\t\t \u0026scx_kfunc_set_cpu_release)) ||\nkernel/sched/ext/ext.c:10993:\t (ret = register_btf_kfunc_id_set(BPF_PROG_TYPE_STRUCT_OPS,\nkernel/sched/ext/ext.c-10994-\t\t\t\t\t \u0026scx_kfunc_set_unlocked)) ||\nkernel/sched/ext/ext.c:10995:\t (ret = register_btf_kfunc_id_set(BPF_PROG_TYPE_SYSCALL,\nkernel/sched/ext/ext.c-10996-\t\t\t\t\t \u0026scx_kfunc_set_unlocked)) ||\nkernel/sched/ext/ext.c:10997:\t (ret = register_btf_kfunc_id_set(BPF_PROG_TYPE_STRUCT_OPS,\nkernel/sched/ext/ext.c-10998-\t\t\t\t\t \u0026scx_kfunc_set_any)) ||\nkernel/sched/ext/ext.c:10999:\t (ret = register_btf_kfunc_id_set(BPF_PROG_TYPE_TRACING,\nkernel/sched/ext/ext.c-11000-\t\t\t\t\t \u0026scx_kfunc_set_any)) ||\nkernel/sched/ext/ext.c:11001:\t (ret = register_btf_kfunc_id_set(BPF_PROG_TYPE_SYSCALL,\nkernel/sched/ext/ext.c-11002-\t\t\t\t\t \u0026scx_kfunc_set_any))) {\n--\nkernel/sched/ext/idle.c=1554=int scx_idle_init(void)\nkernel/sched/ext/idle.c-1555-{\nkernel/sched/ext/idle.c:1556:\treturn register_btf_kfunc_id_set(BPF_PROG_TYPE_STRUCT_OPS, \u0026scx_kfunc_set_idle) ?:\nkernel/sched/ext/idle.c:1557:\t register_btf_kfunc_id_set(BPF_PROG_TYPE_TRACING, \u0026scx_kfunc_set_idle) ?:\nkernel/sched/ext/idle.c:1558:\t register_btf_kfunc_id_set(BPF_PROG_TYPE_SYSCALL, \u0026scx_kfunc_set_idle) ?:\nkernel/sched/ext/idle.c:1559:\t register_btf_kfunc_id_set(BPF_PROG_TYPE_STRUCT_OPS, \u0026scx_kfunc_set_select_cpu) ?:\nkernel/sched/ext/idle.c:1560:\t register_btf_kfunc_id_set(BPF_PROG_TYPE_SYSCALL, \u0026scx_kfunc_set_select_cpu);\nkernel/sched/ext/idle.c-1561-}\n--\nkernel/trace/bpf_trace.c=3459=static int __init bpf_trace_kfuncs_init(void)\n--\nkernel/trace/bpf_trace.c-3462-\nkernel/trace/bpf_trace.c:3463:\terr = err ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_KPROBE, \u0026bpf_session_kfunc_set);\nkernel/trace/bpf_trace.c:3464:\terr = err ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_TRACING, \u0026bpf_session_kfunc_set);\nkernel/trace/bpf_trace.c-3465-\n--\nmm/bpf_memcontrol.c=182=static int __init bpf_memcontrol_init(void)\n--\nmm/bpf_memcontrol.c-185-\nmm/bpf_memcontrol.c:186:\terr = register_btf_kfunc_id_set(BPF_PROG_TYPE_UNSPEC,\nmm/bpf_memcontrol.c-187-\t\t\t\t\t\u0026bpf_memcontrol_kfunc_set);\n--\nnet/bpf/test_run.c=1888=static int __init bpf_prog_test_run_init(void)\n--\nnet/bpf/test_run.c-1902-\tret = register_btf_fmodret_id_set(\u0026bpf_test_modify_return_set);\nnet/bpf/test_run.c:1903:\tret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_SCHED_CLS, \u0026bpf_prog_test_kfunc_set);\nnet/bpf/test_run.c:1904:\tret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_TRACING, \u0026bpf_prog_test_kfunc_set);\nnet/bpf/test_run.c:1905:\tret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_SYSCALL, \u0026bpf_prog_test_kfunc_set);\nnet/bpf/test_run.c-1906-\treturn ret ?: register_btf_id_dtor_kfuncs(bpf_prog_test_dtor_kfunc,\n--\nnet/core/bpf_ksock.c=307=static int __init bpf_ksock_kfunc_init(void)\n--\nnet/core/bpf_ksock.c-316-\nnet/core/bpf_ksock.c:317:\tret = register_btf_kfunc_id_set(BPF_PROG_TYPE_SYSCALL,\nnet/core/bpf_ksock.c-318-\t\t\t\t\t\u0026ksock_init_kfunc_set);\nnet/core/bpf_ksock.c:319:\tret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_SYSCALL,\nnet/core/bpf_ksock.c-320-\t\t\t\t\t \u0026ksock_kfunc_set);\nnet/core/bpf_ksock.c:321:\tret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_LSM,\nnet/core/bpf_ksock.c-322-\t\t\t\t\t \u0026ksock_kfunc_set);\n--\nnet/core/filter.c=12875=static int __init bpf_kfunc_init(void)\n--\nnet/core/filter.c-12878-\nnet/core/filter.c:12879:\tret = register_btf_kfunc_id_set(BPF_PROG_TYPE_SCHED_CLS, \u0026bpf_kfunc_set_skb);\nnet/core/filter.c:12880:\tret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_SCHED_ACT, \u0026bpf_kfunc_set_skb);\nnet/core/filter.c:12881:\tret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_SK_SKB, \u0026bpf_kfunc_set_skb);\nnet/core/filter.c:12882:\tret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_SOCKET_FILTER, \u0026bpf_kfunc_set_skb);\nnet/core/filter.c:12883:\tret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_CGROUP_SKB, \u0026bpf_kfunc_set_skb);\nnet/core/filter.c:12884:\tret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_LWT_OUT, \u0026bpf_kfunc_set_skb);\nnet/core/filter.c:12885:\tret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_LWT_IN, \u0026bpf_kfunc_set_skb);\nnet/core/filter.c:12886:\tret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_LWT_XMIT, \u0026bpf_kfunc_set_skb);\nnet/core/filter.c:12887:\tret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_LWT_SEG6LOCAL, \u0026bpf_kfunc_set_skb);\nnet/core/filter.c:12888:\tret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_NETFILTER, \u0026bpf_kfunc_set_skb);\nnet/core/filter.c:12889:\tret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_TRACING, \u0026bpf_kfunc_set_skb);\nnet/core/filter.c:12890:\tret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_SCHED_CLS, \u0026bpf_kfunc_set_skb_meta);\nnet/core/filter.c:12891:\tret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_SCHED_ACT, \u0026bpf_kfunc_set_skb_meta);\nnet/core/filter.c:12892:\tret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_XDP, \u0026bpf_kfunc_set_xdp);\nnet/core/filter.c:12893:\tret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_CGROUP_SOCK_ADDR,\nnet/core/filter.c-12894-\t\t\t\t\t \u0026bpf_kfunc_set_sock_addr);\nnet/core/filter.c:12895:\tret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_SCHED_CLS, \u0026bpf_kfunc_set_tcp_reqsk);\nnet/core/filter.c:12896:\tret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_CGROUP_SKB, \u0026bpf_kfunc_set_icmp_send);\nnet/core/filter.c:12897:\treturn ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_SOCK_OPS, \u0026bpf_kfunc_set_sock_ops);\nnet/core/filter.c-12898-}\n--\nnet/core/filter.c=12959=static int init_subsystem(void)\nnet/core/filter.c-12960-{\nnet/core/filter.c:12961:\treturn register_btf_kfunc_id_set(BPF_PROG_TYPE_TRACING, \u0026bpf_sk_iter_kfunc_set);\nnet/core/filter.c-12962-}\n--\nnet/core/xdp.c=993=static int __init xdp_metadata_init(void)\nnet/core/xdp.c-994-{\nnet/core/xdp.c:995:\treturn register_btf_kfunc_id_set(BPF_PROG_TYPE_XDP, \u0026xdp_metadata_kfunc_set);\nnet/core/xdp.c-996-}\n--\nnet/ipv4/bpf_tcp_ca.c=345=static int __init bpf_tcp_ca_kfunc_init(void)\n--\nnet/ipv4/bpf_tcp_ca.c-348-\nnet/ipv4/bpf_tcp_ca.c:349:\tret = register_btf_kfunc_id_set(BPF_PROG_TYPE_STRUCT_OPS, \u0026bpf_tcp_ca_kfunc_set);\nnet/ipv4/bpf_tcp_ca.c-350-\tret = ret ?: register_bpf_struct_ops(\u0026bpf_tcp_congestion_ops, tcp_congestion_ops);\n--\nnet/ipv4/fou_bpf.c=113=int register_fou_bpf(void)\nnet/ipv4/fou_bpf.c-114-{\nnet/ipv4/fou_bpf.c:115:\treturn register_btf_kfunc_id_set(BPF_PROG_TYPE_SCHED_CLS,\nnet/ipv4/fou_bpf.c-116-\t\t\t\t\t \u0026fou_bpf_kfunc_set);\n--\nnet/ipv4/tcp_bbr.c=1175=static int __init bbr_register(void)\n--\nnet/ipv4/tcp_bbr.c-1180-\nnet/ipv4/tcp_bbr.c:1181:\tret = register_btf_kfunc_id_set(BPF_PROG_TYPE_STRUCT_OPS, \u0026tcp_bbr_kfunc_set);\nnet/ipv4/tcp_bbr.c-1182-\tif (ret \u003c 0)\n--\nnet/ipv4/tcp_cubic.c=501=static int __init cubictcp_register(void)\n--\nnet/ipv4/tcp_cubic.c-534-\nnet/ipv4/tcp_cubic.c:535:\tret = register_btf_kfunc_id_set(BPF_PROG_TYPE_STRUCT_OPS, \u0026tcp_cubic_kfunc_set);\nnet/ipv4/tcp_cubic.c-536-\tif (ret \u003c 0)\n--\nnet/ipv4/tcp_dctcp.c=294=static int __init dctcp_register(void)\n--\nnet/ipv4/tcp_dctcp.c-299-\nnet/ipv4/tcp_dctcp.c:300:\tret = register_btf_kfunc_id_set(BPF_PROG_TYPE_STRUCT_OPS, \u0026tcp_dctcp_kfunc_set);\nnet/ipv4/tcp_dctcp.c-301-\tif (ret \u003c 0)\n--\nnet/netfilter/nf_conntrack_bpf.c=540=int register_nf_conntrack_bpf(void)\n--\nnet/netfilter/nf_conntrack_bpf.c-543-\nnet/netfilter/nf_conntrack_bpf.c:544:\tret = register_btf_kfunc_id_set(BPF_PROG_TYPE_XDP, \u0026nf_conntrack_kfunc_set);\nnet/netfilter/nf_conntrack_bpf.c:545:\tret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_SCHED_CLS, \u0026nf_conntrack_kfunc_set);\nnet/netfilter/nf_conntrack_bpf.c-546-\tif (!ret) {\n--\nnet/netfilter/nf_flow_table_bpf.c=116=int nf_flow_register_bpf(void)\nnet/netfilter/nf_flow_table_bpf.c-117-{\nnet/netfilter/nf_flow_table_bpf.c:118:\treturn register_btf_kfunc_id_set(BPF_PROG_TYPE_XDP,\nnet/netfilter/nf_flow_table_bpf.c-119-\t\t\t\t\t \u0026nf_flow_kfunc_set);\n--\nnet/netfilter/nf_nat_bpf.c=66=int register_nf_nat_bpf(void)\n--\nnet/netfilter/nf_nat_bpf.c-69-\nnet/netfilter/nf_nat_bpf.c:70:\tret = register_btf_kfunc_id_set(BPF_PROG_TYPE_XDP,\nnet/netfilter/nf_nat_bpf.c-71-\t\t\t\t\t\u0026nf_bpf_nat_kfunc_set);\n--\nnet/netfilter/nf_nat_bpf.c-74-\nnet/netfilter/nf_nat_bpf.c:75:\treturn register_btf_kfunc_id_set(BPF_PROG_TYPE_SCHED_CLS,\nnet/netfilter/nf_nat_bpf.c-76-\t\t\t\t\t \u0026nf_bpf_nat_kfunc_set);\n--\nnet/sched/bpf_qdisc.c=460=static int __init bpf_qdisc_kfunc_init(void)\n--\nnet/sched/bpf_qdisc.c-469-\nnet/sched/bpf_qdisc.c:470:\tret = register_btf_kfunc_id_set(BPF_PROG_TYPE_STRUCT_OPS, \u0026bpf_qdisc_kfunc_set);\nnet/sched/bpf_qdisc.c-471-\tret = ret ?: register_btf_id_dtor_kfuncs(skb_kfunc_dtors,\n--\nnet/xfrm/xfrm_interface_bpf.c=106=int __init register_xfrm_interface_bpf(void)\nnet/xfrm/xfrm_interface_bpf.c-107-{\nnet/xfrm/xfrm_interface_bpf.c:108:\treturn register_btf_kfunc_id_set(BPF_PROG_TYPE_SCHED_CLS,\nnet/xfrm/xfrm_interface_bpf.c-109-\t\t\t\t\t \u0026xfrm_interface_kfunc_set);\n--\nnet/xfrm/xfrm_state_bpf.c=130=int __init register_xfrm_state_bpf(void)\nnet/xfrm/xfrm_state_bpf.c-131-{\nnet/xfrm/xfrm_state_bpf.c:132:\treturn register_btf_kfunc_id_set(BPF_PROG_TYPE_XDP,\nnet/xfrm/xfrm_state_bpf.c-133-\t\t\t\t\t \u0026xfrm_state_xdp_kfunc_set);\n--\ntools/testing/selftests/bpf/test_kmods/bpf_test_modorder_x.c=25=static int __init bpf_test_modorder_x_init(void)\ntools/testing/selftests/bpf/test_kmods/bpf_test_modorder_x.c-26-{\ntools/testing/selftests/bpf/test_kmods/bpf_test_modorder_x.c:27:\treturn register_btf_kfunc_id_set(BPF_PROG_TYPE_SCHED_CLS,\ntools/testing/selftests/bpf/test_kmods/bpf_test_modorder_x.c-28-\t\t\t\t\t \u0026bpf_test_modorder_x_set);\n--\ntools/testing/selftests/bpf/test_kmods/bpf_test_modorder_y.c=25=static int __init bpf_test_modorder_y_init(void)\ntools/testing/selftests/bpf/test_kmods/bpf_test_modorder_y.c-26-{\ntools/testing/selftests/bpf/test_kmods/bpf_test_modorder_y.c:27:\treturn register_btf_kfunc_id_set(BPF_PROG_TYPE_SCHED_CLS,\ntools/testing/selftests/bpf/test_kmods/bpf_test_modorder_y.c-28-\t\t\t\t\t \u0026bpf_test_modorder_y_set);\n--\ntools/testing/selftests/bpf/test_kmods/bpf_testmod.c=2130=static int bpf_testmod_init(void)\n--\ntools/testing/selftests/bpf/test_kmods/bpf_testmod.c-2140-\ntools/testing/selftests/bpf/test_kmods/bpf_testmod.c:2141:\tret = register_btf_kfunc_id_set(BPF_PROG_TYPE_UNSPEC, \u0026bpf_testmod_common_kfunc_set);\ntools/testing/selftests/bpf/test_kmods/bpf_testmod.c:2142:\tret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_SCHED_CLS, \u0026bpf_testmod_kfunc_set);\ntools/testing/selftests/bpf/test_kmods/bpf_testmod.c:2143:\tret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_TRACING, \u0026bpf_testmod_kfunc_set);\ntools/testing/selftests/bpf/test_kmods/bpf_testmod.c:2144:\tret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_SYSCALL, \u0026bpf_testmod_kfunc_set);\ntools/testing/selftests/bpf/test_kmods/bpf_testmod.c:2145:\tret = ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_STRUCT_OPS, \u0026bpf_testmod_kfunc_set);\ntools/testing/selftests/bpf/test_kmods/bpf_testmod.c-2146-\tret = ret ?: register_btf_fmodret_id_set(\u0026bpf_testmod_trampoline_count_fmodret_set);\n"
} |
| 23/2 | 2026/09/04 19:05 | llm | patch-evaluator |
0mModel:gemini-3.7-flash Args: null Results: null Tokens: input: 23099 output: 29 thoughts: 92 Thoughts: **Checking BPF Configuration Dependencies** Okay, let's get down to brass tacks. I need to quickly verify a few critical configurations for BPF kfunc functionality. Specifically, I'm thinking about the essentials: `BPF_SYSCALL` and `DEBUG_INFO_BTF`. My experience tells me that BPF kfuncs rely on both of these being enabled. Of course, `CONFIG_NET` and `CONFIG_INET` are also fundamental for networking-related BPF applications. To be thorough, I'm going to double-check the dependencies in the kernel configuration files. The logical places to find this information are in `init/Kconfig` or `kernel/bpf/Kconfig`. It's always good to be certain about these core settings before diving deeper. |
| 24/2 | 2026/09/04 19:05 | tool | grepper |
0mError:no matches Args: {
"Expression": "config BPF_SYSCALL",
"PathPrefix": "init/"
}Results: {
"error": "no matches"
} |
| 25/2 | 2026/09/04 19:05 | llm | patch-evaluator |
0mModel:gemini-3.7-flash Args: null Results: null Tokens: input: 23401 output: 32 thoughts: 13 Thoughts: Here's a summary of my thought process, as requested: **Navigating the Kernel's BPF Configuration** Okay, time to dive in. My immediate thought is to start with the configuration file for the Berkeley Packet Filter (BPF) subsystem. I need to get a handle on the available options and dependencies before I go deeper. That means I need to look at `kernel/bpf/Kconfig`. This Kconfig file will be the central point to understand how BPF is integrated into the kernel's build system and what features can be enabled or disabled. This is where the core BPF controls are defined, and where I can start untangling the relationships between different BPF features. This is the logical first step for me to understand how BPF fits into the kernel configuration. Let's see what's in there. |
| 26/2 | 2026/09/04 19:05 | tool | grepper |
0mArgs:{
"Expression": "config BPF_SYSCALL",
"PathPrefix": "kernel/bpf/"
}Results: {
"Output": "kernel/bpf/Kconfig=25=menu \"BPF subsystem\"\nkernel/bpf/Kconfig-26-\nkernel/bpf/Kconfig:27:config BPF_SYSCALL\nkernel/bpf/Kconfig-28-\tbool \"Enable bpf() system call\"\n"
} |
| 27/2 | 2026/09/04 19:05 | llm | patch-evaluator |
0mModel:gemini-3.7-flash Args: null Results: null Tokens: input: 23704 output: 34 thoughts: 22 Thoughts: Here's my take on those thoughts: **Checking the BPF_SYSCALL Configuration** Alright, let's dive right in and see what's happening with `BPF_SYSCALL`. I need to get a clear picture of its configuration options, so my first move is to navigate to `kernel/bpf/Kconfig`. Understanding how this is set up is crucial to figuring out its impact. I'm looking for the details of the configuration options, dependencies, and any other relevant context. This will give me the information I need to confirm if it is as I expect. It's a quick but essential step to assess its presence or absence and its general behavior. |
| 28/2 | 2026/09/04 19:05 | tool | read-file |
0mArgs:{
"File": "kernel/bpf/Kconfig",
"FirstLine": 25,
"LineCount": 35
}Results: {
"Contents": " 25:\tmenu \"BPF subsystem\"\n 26:\t\n 27:\tconfig BPF_SYSCALL\n 28:\t\tbool \"Enable bpf() system call\"\n 29:\t\tselect BPF\n 30:\t\tselect IRQ_WORK\n 31:\t\tselect NEED_TASKS_RCU\n 32:\t\tselect TASKS_TRACE_RCU\n 33:\t\tselect BINARY_PRINTF\n 34:\t\tselect NET_SOCK_MSG if NET\n 35:\t\tselect NET_XGRESS if NET\n 36:\t\tselect PAGE_POOL if NET\n 37:\t\tdefault n\n 38:\t\thelp\n 39:\t\t Enable the bpf() system call that allows to manipulate BPF programs\n 40:\t\t and maps via file descriptors.\n 41:\t\n 42:\tconfig BPF_JIT\n 43:\t\tbool \"Enable BPF Just In Time compiler\"\n 44:\t\tdepends on BPF\n 45:\t\tdepends on HAVE_CBPF_JIT || HAVE_EBPF_JIT\n 46:\t\tselect EXECMEM\n 47:\t\thelp\n 48:\t\t BPF programs are normally handled by a BPF interpreter. This option\n 49:\t\t allows the kernel to generate native code when a program is loaded\n 50:\t\t into the kernel. This will significantly speed-up processing of BPF\n 51:\t\t programs.\n 52:\t\n 53:\t\t Note, an admin should enable this feature changing:\n 54:\t\t /proc/sys/net/core/bpf_jit_enable\n 55:\t\t /proc/sys/net/core/bpf_jit_harden (optional)\n 56:\t\t /proc/sys/net/core/bpf_jit_kallsyms (optional)\n 57:\t\n 58:\tconfig BPF_JIT_ALWAYS_ON\n 59:\t\tbool \"Permanently enable BPF JIT and remove BPF interpreter\"\n"
} |
| 29/2 | 2026/09/04 19:05 | llm | patch-evaluator |
0mModel:gemini-3.7-flash Args: null Results: null Tokens: input: 24410 output: 21 thoughts: 21 Thoughts: Here's my take on those thoughts, tailored for an expert audience: **Debugging BTF Information: A Kconfig Deep Dive** Okay, so I need to get a handle on the BTF debugging situation. First thing's first: I need to refresh my memory on where the relevant Kconfig options are defined. The place to start is always `lib/Kconfig.debug`. That's where I'll find the gatekeepers for debug-related configurations, including anything related to BTF. I'm mentally parsing where the actual configuration lines are and how they relate to the build. This is a common starting point for figuring out what configurations I have available. Time to open that file and get to it. |
| 30/2 | 2026/09/04 19:05 | tool | grepper |
0mArgs:{
"Expression": "config DEBUG_INFO_BTF"
}Results: {
"Output": "lib/Kconfig.debug=378=config DEBUG_INFO_SPLIT\n--\nlib/Kconfig.debug-397-\nlib/Kconfig.debug:398:config DEBUG_INFO_BTF\nlib/Kconfig.debug-399-\tbool \"Generate BTF type information\"\n--\nlib/Kconfig.debug=419=config PAHOLE_HAS_LANG_EXCLUDE\n--\nlib/Kconfig.debug-427-\nlib/Kconfig.debug:428:config DEBUG_INFO_BTF_MODULES\nlib/Kconfig.debug-429-\tbool \"Generate BTF type information for kernel modules\"\n"
} |
| 31/2 | 2026/09/04 19:05 | llm | patch-evaluator |
0mModel:gemini-3.7-flash Args: null Results: null Tokens: input: 24772 output: 34 thoughts: 22 Thoughts: Here's my summary, as though I'm thinking through this process: **Diving into the Debug Configuration** Okay, so I need to get a handle on some debug settings in this build. Let's see...I'm going to jump into `lib/Kconfig.debug`. Specifically, I want to zero in on lines 398 through 420. This section is probably going to lay out some conditional logic or define some macros related to debugging features. Given the file name, it's very likely this area is dedicated to parameters or configurations for core or foundational debugging parameters. I'll need to assess the interdependencies of these values and their impact on build size and performance. It's time to dig in and see what nuances or potential tweaks are hidden in this section. |
| 32/2 | 2026/09/04 19:05 | tool | read-file |
0mArgs:{
"File": "lib/Kconfig.debug",
"FirstLine": 398,
"LineCount": 25
}Results: {
"Contents": " 398:\tconfig DEBUG_INFO_BTF\n 399:\t\tbool \"Generate BTF type information\"\n 400:\t\tdepends on !DEBUG_INFO_SPLIT \u0026\u0026 !DEBUG_INFO_REDUCED\n 401:\t\tdepends on !GCC_PLUGIN_RANDSTRUCT || COMPILE_TEST\n 402:\t\tdepends on BPF_SYSCALL\n 403:\t\tdepends on PAHOLE_VERSION \u003e= 122\n 404:\t\t# pahole uses elfutils, which does not have support for Hexagon relocations\n 405:\t\tdepends on !HEXAGON\n 406:\t\thelp\n 407:\t\t Generate deduplicated BTF type information from DWARF debug info.\n 408:\t\t Turning this on requires pahole v1.22 or later, which will convert\n 409:\t\t DWARF type info into equivalent deduplicated BTF type info.\n 410:\t\n 411:\tconfig PAHOLE_HAS_BTF_TAG\n 412:\t\tdef_bool PAHOLE_VERSION \u003e= 123\n 413:\t\tdepends on CC_IS_CLANG\n 414:\t\thelp\n 415:\t\t Decide whether pahole emits btf_tag attributes (btf_type_tag and\n 416:\t\t btf_decl_tag) or not. Currently only clang compiler implements\n 417:\t\t these attributes, so make the config depend on CC_IS_CLANG.\n 418:\t\n 419:\tconfig PAHOLE_HAS_LANG_EXCLUDE\n 420:\t\tdef_bool PAHOLE_VERSION \u003e= 124\n 421:\t\thelp\n 422:\t\t Support for the --lang_exclude flag which makes pahole exclude\n"
} |
| 33/2 | 2026/09/04 19:05 | llm | patch-evaluator |
0mModel:gemini-3.7-flash Args: null Results: null Tokens: input: 25444 output: 147 thoughts: 455 Thoughts: **My Analysis of the Kernel Patch and Fuzzing Strategy** Okay, let's break this down. First, I need to confirm the configurations. We're dealing with `bpf_sock_destroy`, which is used to destroy sockets (TCP, UDP, the usual suspects). The standard `CONFIG_INET` is, of course, a given. It also looks like `BPF_SYSCALL` and `DEBUG_INFO_BTF` are essential as well. Now, let's get focused. My main target is `bpf_sock_destroy`. The modification is in the kernel image. It looks like `tcp_abort` is closely related, as it handles TIME_WAIT socket destruction. Let's see... `tracing_iter_filter` is in the same file but it wasn't modified. `bpf_sock_destroy` is definitely the prime focus. We should keep an eye on `tcp_abort` since it's directly invoked. I need to confirm if `bpf_sock_destroy` and `tcp_abort` are globally accessible. Okay, `bpf_sock_destroy` is a global kfunc symbol in `net/core/filter.c`. And `tcp_abort` is also non-static, found in `net/ipv4/tcp.c`. Good. Just to be safe, I'm verifying those required configs again: `BPF_SYSCALL`, `DEBUG_INFO_BTF`, and `INET`. The rationale is sound. This patch modifies `bpf_sock_destroy` to handle the destruction of non-full sockets, specifically those in `TCP_TIME_WAIT` and `TCP_NEW_SYN_RECV` states. It's doing this by checking `sk_fullsock(sk)` first. This is crucial because it lets BPF iterators call `bpf_sock_destroy` on sockets in `TIME_WAIT`, which in turn triggers protocol-specific abort routines like `tcp_abort`. The code path is reachable in virtualized environments due to BPF iterators, so fuzzing is certainly warranted. Alright, I'm ready to prepare the `set-results` tool call. |
| 34/2 | 2026/09/04 19:05 | tool | set-results |
0mArgs:{
"EnableConfigs": [
"BPF_SYSCALL",
"DEBUG_INFO_BTF",
"INET"
],
"FocusSymbols": [
"bpf_sock_destroy",
"tcp_abort"
],
"Reasoning": "The patch modifies bpf_sock_destroy() in net/core/filter.c to allow protocol abort handlers (e.g., tcp_abort) to destroy non-full sockets (such as TCP TIME_WAIT and SYN_RECV sockets) by qualifying the protocol check with sk_fullsock(). This enables new execution paths reachable through BPF socket iterator programs in standard virtualized environments.",
"WorthFuzzing": true
}Results: {
"EnableConfigs": [
"BPF_SYSCALL",
"DEBUG_INFO_BTF",
"INET"
],
"FocusSymbols": [
"bpf_sock_destroy",
"tcp_abort"
],
"Reasoning": "The patch modifies bpf_sock_destroy() in net/core/filter.c to allow protocol abort handlers (e.g., tcp_abort) to destroy non-full sockets (such as TCP TIME_WAIT and SYN_RECV sockets) by qualifying the protocol check with sk_fullsock(). This enables new execution paths reachable through BPF socket iterator programs in standard virtualized environments.",
"WorthFuzzing": true
} |
| 35/1 | 2026/09/04 19:05 | action | If |
0mArgs:{
"WorthFuzzing": true
}Results: null |
| 36/2 | 2026/09/04 19:05 | agent | kmsan-evaluator |
0mModel:core Args: null Results: {
"KMSANReasoning": "The patch modifies `bpf_sock_destroy` in `net/core/filter.c` to only check `sk-\u003esk_protocol` when `sk_fullsock(sk)` is true, allowing non-full sockets (such as TCP TIME_WAIT sockets) with a valid `sk_prot-\u003ediag_destroy` callback to be destroyed via the BPF kfunc.\n\nThis change does not introduce or expose any uninitialized memory risks. It does not allocate memory buffers, copy data to user space, or introduce branching on uninitialized data. In fact, checking `sk_fullsock()` avoids reading fields beyond `sock_common` for miniature sockets. Any potential risks related to socket destruction lifecycle or locking are covered by KASAN and LOCKDEP. Therefore, dedicated KMSAN fuzzing 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: Target architecture: amd64
For your convenience, here is the diff of the changes:
commit e4e455baa671300d259799e8eaf43e01a9fd872f
Author: syz-cluster <triage@syzkaller.com>
Date: Fri Sep 4 19:04:23 2026 +0000
syz-cluster: applied patch under review
diff --git a/net/core/filter.c b/net/core/filter.c
index 61940e7535523..1bbb72138ac64 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -12912,8 +12912,8 @@ __bpf_kfunc_start_defs();
* @sock: Pointer to socket to be destroyed
*
* Return:
- * On error, may return EPROTONOSUPPORT, EINVAL.
- * EPROTONOSUPPORT if protocol specific destroy handler is not supported.
+ * On error, may return EOPNOTSUPP, EINVAL.
+ * EOPNOTSUPP if protocol specific destroy handler is not supported.
* 0 otherwise
*/
__bpf_kfunc int bpf_sock_destroy(struct sock_common *sock)
@@ -12925,8 +12925,12 @@ __bpf_kfunc int bpf_sock_destroy(struct sock_common *sock)
* Supporting protocols will need to acquire sock lock in the BPF context
* prior to invoking this kfunc.
*/
- if (!sk->sk_prot->diag_destroy || (sk->sk_protocol != IPPROTO_TCP &&
- sk->sk_protocol != IPPROTO_UDP))
+ if (!sk->sk_prot->diag_destroy)
+ return -EOPNOTSUPP;
+
+ if (sk_fullsock(sk) &&
+ sk->sk_protocol != IPPROTO_TCP &&
+ sk->sk_protocol != IPPROTO_UDP)
return -EOPNOTSUPP;
return sk->sk_prot->diag_destroy(sk, ECONNABORTED);
diff --git a/tools/testing/selftests/bpf/prog_tests/sock_destroy.c b/tools/testing/selftests/bpf/prog_tests/sock_destroy.c
index 9c11938fe597d..6ccc7cda410bf 100644
--- a/tools/testing/selftests/bpf/prog_tests/sock_destroy.c
+++ b/tools/testing/selftests/bpf/prog_tests/sock_destroy.c
@@ -110,6 +110,65 @@ static void test_tcp_server(struct sock_destroy_prog *skel)
close(serv);
}
+static void test_tcp_timewait(struct sock_destroy_prog *skel)
+{
+ int serv = -1, clien = -1, accept_serv = -1, n;
+ struct timeval tv = {};
+ char buf[1];
+
+ serv = start_server(AF_INET6, SOCK_STREAM, NULL, 0, 0);
+ if (!ASSERT_GE(serv, 0, "start_server"))
+ goto cleanup;
+
+ clien = connect_to_fd(serv, 0);
+ if (!ASSERT_GE(clien, 0, "connect_to_fd"))
+ goto cleanup;
+
+ accept_serv = accept(serv, NULL, NULL);
+ if (!ASSERT_GE(accept_serv, 0, "serv accept"))
+ goto cleanup;
+
+ /* Active close from the client, then close the server side. Once
+ * recv() sees EOF the server FIN has been processed and the client
+ * sock is in TIME_WAIT. Block without timeout so a loaded CI box
+ * can't race us.
+ */
+ if (!ASSERT_OK(setsockopt(clien, SOL_SOCKET, SO_RCVTIMEO, &tv,
+ sizeof(tv)), "clear rcvtimeo"))
+ goto cleanup;
+ if (!ASSERT_OK(shutdown(clien, SHUT_WR), "client shutdown"))
+ goto cleanup;
+
+ close(accept_serv);
+ accept_serv = -1;
+
+ /* block until return EOF */
+ n = recv(clien, buf, sizeof(buf), 0);
+ if (!ASSERT_EQ(n, 0, "client recv EOF"))
+ goto cleanup;
+
+ /* Run iterator program that destroys the timewait client sock. */
+ skel->bss->tw_found = 0;
+ start_iter_sockets(skel->progs.iter_tcp6_timewait);
+ if (!ASSERT_EQ(skel->bss->tw_found, 1, "timewait sock found"))
+ goto cleanup;
+
+ ASSERT_OK(skel->bss->tw_destroy_err, "destroy timewait sock");
+
+ /* The destroyed timewait sock must be gone. */
+ skel->bss->tw_found = 0;
+ start_iter_sockets(skel->progs.iter_tcp6_timewait);
+ ASSERT_EQ(skel->bss->tw_found, 0, "timewait sock destroyed");
+
+cleanup:
+ if (clien != -1)
+ close(clien);
+ if (accept_serv != -1)
+ close(accept_serv);
+ if (serv != -1)
+ close(serv);
+}
+
static void test_udp_client(struct sock_destroy_prog *skel)
{
int serv = -1, clien = -1, n = 0;
@@ -204,11 +263,12 @@ void test_sock_destroy(void)
test_tcp_client(skel);
if (test__start_subtest("tcp_server"))
test_tcp_server(skel);
+ if (test__start_subtest("tcp_timewait"))
+ test_tcp_timewait(skel);
if (test__start_subtest("udp_client"))
test_udp_client(skel);
if (test__start_subtest("udp_server"))
test_udp_server(skel);
-
RUN_TESTS(sock_destroy_prog_fail);
cleanup:
diff --git a/tools/testing/selftests/bpf/progs/sock_destroy_prog.c b/tools/testing/selftests/bpf/progs/sock_destroy_prog.c
index 9e0bf7a54cec9..0a8887543218a 100644
--- a/tools/testing/selftests/bpf/progs/sock_destroy_prog.c
+++ b/tools/testing/selftests/bpf/progs/sock_destroy_prog.c
@@ -7,6 +7,8 @@
#include "bpf_tracing_net.h"
__be16 serv_port = 0;
+int tw_found = 0;
+int tw_destroy_err = 0;
int bpf_sock_destroy(struct sock_common *sk) __ksym;
@@ -100,6 +102,34 @@ int iter_tcp6_server(struct bpf_iter__tcp *ctx)
return 0;
}
+SEC("iter/tcp")
+int iter_tcp6_timewait(struct bpf_iter__tcp *ctx)
+{
+ struct sock_common *sk_common = ctx->sk_common;
+ __u64 *val;
+ int key = 0;
+
+ if (!sk_common)
+ return 0;
+
+ if (sk_common->skc_family != AF_INET6)
+ return 0;
+
+ if (!bpf_skc_to_tcp_timewait_sock(sk_common))
+ return 0;
+
+ val = bpf_map_lookup_elem(&tcp_conn_sockets, &key);
+ if (!val)
+ return 0;
+ /* The timewait sock inherits the cookie of the closed client sock. */
+ if (bpf_get_socket_cookie(sk_common) != *val)
+ return 0;
+
+ tw_found++;
+ tw_destroy_err = bpf_sock_destroy(sk_common);
+
+ return 0;
+}
SEC("iter/udp")
int iter_udp6_client(struct bpf_iter__udp *ctx)
|
| 37/3 | 2026/09/04 19:05 | llm | kmsan-evaluator |
0mModel:gemini-3.7-flash Args: null Results: null Tokens: input: 3978 output: 25 thoughts: 357 Thoughts: **KMSAN Fuzzing Evaluation** Okay, let's break this down. My initial instinct is to determine if this patch necessitates KMSAN fuzzing in addition to our standard KASAN fuzzing. I need to understand the implications of these changes in `net/core/filter.c`. Right, so the patch modifies `bpf_sock_destroy`. It looks like it's removing a check for `sk->sk_protocol` within an early return. The original logic prevented the execution of `diag_destroy` if the socket wasn't TCP or UDP. The new logic is allowing `diag_destroy` to be executed when the socket isn't "fullsock". Now I need to understand the interaction between `bpf_sock_destroy` and `diag_destroy` for sockets that are not "fullsock," specifically timewait sockets or request sockets, which I *know* can exist. To proceed efficiently, I'll leverage `grepper` (or if that's not available, `read-file`) to trace the calls to `bpf_sock_destroy` and the implementation of `tcp_twsk_diag_destroy`, `inet_twsk_diag_destroy`, and any other relevant `diag_destroy` functions to see how this change affects the handling of those socket types. My primary concern is memory safety: are we now potentially freeing memory or accessing freed memory in a way that wasn't previously possible? That's what I'll be looking for in the call paths. If there's a good chance of memory issues, KMSAN fuzzing is definitely warranted. |
| 38/3 | 2026/09/04 19:06 | tool | grepper |
0mArgs:{
"Expression": "diag_destroy",
"PathPrefix": "net/"
}Results: {
"Output": "net/core/filter.c=12919=__bpf_kfunc int bpf_sock_destroy(struct sock_common *sock)\n--\nnet/core/filter.c-12927-\t */\nnet/core/filter.c:12928:\tif (!sk-\u003esk_prot-\u003ediag_destroy)\nnet/core/filter.c-12929-\t\treturn -EOPNOTSUPP;\n--\nnet/core/filter.c-12935-\nnet/core/filter.c:12936:\treturn sk-\u003esk_prot-\u003ediag_destroy(sk, ECONNABORTED);\nnet/core/filter.c-12937-}\n--\nnet/core/sock_diag.c=143=static void sock_diag_broadcast_destroy_work(struct work_struct *work)\n--\nnet/core/sock_diag.c-149-\tstruct sk_buff *skb;\nnet/core/sock_diag.c:150:\tconst enum sknetlink_groups group = sock_diag_destroy_group(sk);\nnet/core/sock_diag.c-151-\tint err = -1;\n--\nnet/core/sock_diag.c=295=static int sock_diag_bind(struct net *net, int group)\n--\nnet/core/sock_diag.c-311-\nnet/core/sock_diag.c:312:int sock_diag_destroy(struct sock *sk, int err)\nnet/core/sock_diag.c-313-{\n--\nnet/core/sock_diag.c-316-\nnet/core/sock_diag.c:317:\tif (!sk-\u003esk_prot-\u003ediag_destroy)\nnet/core/sock_diag.c-318-\t\treturn -EOPNOTSUPP;\nnet/core/sock_diag.c-319-\nnet/core/sock_diag.c:320:\treturn sk-\u003esk_prot-\u003ediag_destroy(sk, err);\nnet/core/sock_diag.c-321-}\nnet/core/sock_diag.c:322:EXPORT_SYMBOL_GPL(sock_diag_destroy);\nnet/core/sock_diag.c-323-\n--\nnet/ipv4/raw.c=948=struct proto raw_prot = {\n--\nnet/ipv4/raw.c-972-#endif\nnet/ipv4/raw.c:973:\t.diag_destroy\t = raw_abort,\nnet/ipv4/raw.c-974-};\n--\nnet/ipv4/raw_diag.c=187=static void raw_diag_get_info(struct sock *sk, struct inet_diag_msg *r,\n--\nnet/ipv4/raw_diag.c-194-#ifdef CONFIG_INET_DIAG_DESTROY\nnet/ipv4/raw_diag.c:195:static int raw_diag_destroy(struct sk_buff *in_skb,\nnet/ipv4/raw_diag.c-196-\t\t\t const struct inet_diag_req_v2 *r)\n--\nnet/ipv4/raw_diag.c-204-\t\treturn PTR_ERR(sk);\nnet/ipv4/raw_diag.c:205:\terr = sock_diag_destroy(sk, ECONNABORTED);\nnet/ipv4/raw_diag.c-206-\tsock_put(sk);\n--\nnet/ipv4/raw_diag.c=211=static const struct inet_diag_handler raw_diag_handler = {\n--\nnet/ipv4/raw_diag.c-218-#ifdef CONFIG_INET_DIAG_DESTROY\nnet/ipv4/raw_diag.c:219:\t.destroy\t\t= raw_diag_destroy,\nnet/ipv4/raw_diag.c-220-#endif\n--\nnet/ipv4/tcp_diag.c=604=static int tcp_diag_dump_one(struct netlink_callback *cb,\n--\nnet/ipv4/tcp_diag.c-641-#ifdef CONFIG_INET_DIAG_DESTROY\nnet/ipv4/tcp_diag.c:642:static int tcp_diag_destroy(struct sk_buff *in_skb,\nnet/ipv4/tcp_diag.c-643-\t\t\t const struct inet_diag_req_v2 *req)\n--\nnet/ipv4/tcp_diag.c-652-\nnet/ipv4/tcp_diag.c:653:\terr = sock_diag_destroy(sk, ECONNABORTED);\nnet/ipv4/tcp_diag.c-654-\n--\nnet/ipv4/tcp_diag.c=661=static const struct inet_diag_handler tcp_diag_handler = {\n--\nnet/ipv4/tcp_diag.c-669-#ifdef CONFIG_INET_DIAG_DESTROY\nnet/ipv4/tcp_diag.c:670:\t.destroy\t\t= tcp_diag_destroy,\nnet/ipv4/tcp_diag.c-671-#endif\n--\nnet/ipv4/tcp_ipv4.c=3347=struct proto tcp_prot = {\n--\nnet/ipv4/tcp_ipv4.c-3395-\t.no_autobind\t\t= true,\nnet/ipv4/tcp_ipv4.c:3396:\t.diag_destroy\t\t= tcp_abort,\nnet/ipv4/tcp_ipv4.c-3397-};\n--\nnet/ipv4/udp.c=3143=struct proto udp_prot = {\n--\nnet/ipv4/udp.c-3173-\t.obj_size\t\t= sizeof(struct udp_sock),\nnet/ipv4/udp.c:3174:\t.diag_destroy\t\t= udp_abort,\nnet/ipv4/udp.c-3175-};\n--\nnet/ipv4/udp_diag.c=144=static void udp_diag_get_info(struct sock *sk, struct inet_diag_msg *r,\n--\nnet/ipv4/udp_diag.c-151-#ifdef CONFIG_INET_DIAG_DESTROY\nnet/ipv4/udp_diag.c:152:static int udp_diag_destroy(struct sk_buff *in_skb,\nnet/ipv4/udp_diag.c-153-\t\t\t const struct inet_diag_req_v2 *req)\n--\nnet/ipv4/udp_diag.c-200-\nnet/ipv4/udp_diag.c:201:\terr = sock_diag_destroy(sk, ECONNABORTED);\nnet/ipv4/udp_diag.c-202-\n--\nnet/ipv4/udp_diag.c=209=static const struct inet_diag_handler udp_diag_handler = {\n--\nnet/ipv4/udp_diag.c-216-#ifdef CONFIG_INET_DIAG_DESTROY\nnet/ipv4/udp_diag.c:217:\t.destroy\t = udp_diag_destroy,\nnet/ipv4/udp_diag.c-218-#endif\n--\nnet/ipv6/raw.c=1207=struct proto rawv6_prot = {\n--\nnet/ipv6/raw.c-1231-#endif\nnet/ipv6/raw.c:1232:\t.diag_destroy\t = raw_abort,\nnet/ipv6/raw.c-1233-};\n--\nnet/ipv6/tcp_ipv6.c=2276=struct proto tcpv6_prot = {\n--\nnet/ipv6/tcp_ipv6.c-2325-\t.no_autobind\t\t= true,\nnet/ipv6/tcp_ipv6.c:2326:\t.diag_destroy\t\t= tcp_abort,\nnet/ipv6/tcp_ipv6.c-2327-};\n--\nnet/ipv6/udp.c=1908=struct proto udpv6_prot = {\n--\nnet/ipv6/udp.c-1940-\t.ipv6_pinfo_offset = offsetof(struct udp6_sock, inet6),\nnet/ipv6/udp.c:1941:\t.diag_destroy\t\t= udp_abort,\nnet/ipv6/udp.c-1942-};\n--\nnet/mptcp/subflow.c=2146=void __init mptcp_subflow_init(void)\n--\nnet/mptcp/subflow.c-2166-\ttcp_prot_override.release_cb = tcp_release_cb_override;\nnet/mptcp/subflow.c:2167:\ttcp_prot_override.diag_destroy = tcp_abort_override;\nnet/mptcp/subflow.c-2168-#ifdef CONFIG_BPF_SYSCALL\n--\nnet/mptcp/subflow.c=2180=void __init mptcp_subflow_v6_init(void)\n--\nnet/mptcp/subflow.c-2213-\ttcpv6_prot_override.release_cb = tcp_release_cb_override;\nnet/mptcp/subflow.c:2214:\ttcpv6_prot_override.diag_destroy = tcp_abort_override;\nnet/mptcp/subflow.c-2215-#ifdef CONFIG_BPF_SYSCALL\n"
} |
| 39/3 | 2026/09/04 19:06 | llm | kmsan-evaluator |
0mModel:gemini-3.7-flash Args: null Results: null Tokens: input: 7050 output: 27 thoughts: 39 Thoughts: Okay, let's dive into this. Here's my take on it: **Considering TCP Socket Abort & Timewait Socket Handling** Alright, I'm thinking about the nitty-gritty details of TCP socket management. Specifically, I'm trying to decide the best way to approach a particular problem that I'm working through. My mind immediately goes to the distinction between `tcp_twsk_diag_destroy` and `tcp_abort`. The interplay between these two is central to understanding how timewait sockets are ultimately handled and cleaned up. This feels like it might hold the key to understanding a bug or performance issue I am facing. First, I think I'll focus on `tcp_abort`. That seems like the most likely place to start. Let's see what's what. |
| 40/3 | 2026/09/04 19:06 | tool | grepper |
0mArgs:{
"Expression": "int tcp_abort\\(",
"PathPrefix": "net/"
}Results: {
"Output": "net/ipv4/tcp.c=5089=void tcp_done(struct sock *sk)\n--\nnet/ipv4/tcp.c-5114-\nnet/ipv4/tcp.c:5115:int tcp_abort(struct sock *sk, int err)\nnet/ipv4/tcp.c-5116-{\n"
} |
| 41/3 | 2026/09/04 19:06 | llm | kmsan-evaluator |
0mModel:gemini-3.7-flash Args: null Results: null Tokens: input: 7385 output: 37 thoughts: 22 Thoughts: Here's my attempt at summarizing the thought process, tailored for an expert audience: **Diving into the TCP Core** Okay, time to get my hands dirty. I need to refresh my memory on how TCP's managing congestion control, particularly around how it handles retransmissions. Let's start by zeroing in on the `net/ipv4/tcp.c` file, specifically around line 5115. That should be a good starting point to understand the interactions. I'm guessing that area probably deals with the core logic. Might as well use that to guide the next few minutes. |
| 42/3 | 2026/09/04 19:06 | tool | read-file |
0mArgs:{
"File": "net/ipv4/tcp.c",
"FirstLine": 5115,
"LineCount": 40
}Results: {
"Contents": "5115:\tint tcp_abort(struct sock *sk, int err)\n5116:\t{\n5117:\t\tint state = inet_sk_state_load(sk);\n5118:\t\n5119:\t\tif (state == TCP_NEW_SYN_RECV) {\n5120:\t\t\tstruct request_sock *req = inet_reqsk(sk);\n5121:\t\n5122:\t\t\tlocal_bh_disable();\n5123:\t\t\tinet_csk_reqsk_queue_drop(req-\u003ersk_listener, req);\n5124:\t\t\tlocal_bh_enable();\n5125:\t\t\treturn 0;\n5126:\t\t}\n5127:\t\tif (state == TCP_TIME_WAIT) {\n5128:\t\t\tstruct inet_timewait_sock *tw = inet_twsk(sk);\n5129:\t\n5130:\t\t\trefcount_inc(\u0026tw-\u003etw_refcnt);\n5131:\t\t\tlocal_bh_disable();\n5132:\t\t\tinet_twsk_deschedule_put(tw);\n5133:\t\t\tlocal_bh_enable();\n5134:\t\t\treturn 0;\n5135:\t\t}\n5136:\t\n5137:\t\t/* BPF context ensures sock locking. */\n5138:\t\tif (!has_current_bpf_ctx())\n5139:\t\t\t/* Don't race with userspace socket closes such as tcp_close. */\n5140:\t\t\tlock_sock(sk);\n5141:\t\n5142:\t\t/* Avoid closing the same socket twice. */\n5143:\t\tif (sk-\u003esk_state == TCP_CLOSE) {\n5144:\t\t\tif (!has_current_bpf_ctx())\n5145:\t\t\t\trelease_sock(sk);\n5146:\t\t\treturn -ENOENT;\n5147:\t\t}\n5148:\t\n5149:\t\tif (sk-\u003esk_state == TCP_LISTEN) {\n5150:\t\t\ttcp_set_state(sk, TCP_CLOSE);\n5151:\t\t\tinet_csk_listen_stop(sk);\n5152:\t\t}\n5153:\t\n5154:\t\t/* Don't race with BH socket closes such as inet_csk_listen_stop. */\n"
} |
| 43/3 | 2026/09/04 19:06 | llm | kmsan-evaluator |
0mModel:gemini-3.7-flash Args: null Results: null Tokens: input: 8175 output: 195 thoughts: 1425 Thoughts: **Analysis of `bpf_sock_destroy` Patch** Okay, let's break this down. The core issue is `bpf_sock_destroy`, which takes a `sock_common` pointer. Previously, it was reading `sk->sk_protocol` directly. The problem is that not all sockets, specifically time-wait or request sockets (`!sk_fullsock(sk)`), actually have `sk->sk_protocol` defined within the `sock_common` structure. It's only within the full `struct sock`. The check `sk->sk_fullsock(sk)` is used to determine if it is a full socket. In other words, accessing `sk->sk_protocol` on time-wait sockets was leading to out-of-bounds reads, or potentially accessing uninitialized memory. Moreover, it was blocking time-wait sockets from being destroyed because of the protocol check. The patch fixes this. It now checks if the socket is a full socket *before* accessing `sk->sk_protocol`. If it's *not* a full socket (like a time-wait socket), it skips the protocol check entirely and proceeds directly to calling `sk->sk_prot->diag_destroy`. This is correct. The protocol-specific `diag_destroy` function (`tcp_abort` in the case of TCP) already handles the time-wait or new-syn-recv states properly. This resolves the previous issue. Now, we need to ensure this change doesn't introduce *new* problems. Let's consider possible issues: * **Uninitialized memory:** Does the patch allocate any new buffers or introduce new uninitialized fields? No, the patch actually *prevents* an out-of-bounds read. * **Data copies to user space:** Does this patch copy any potentially uninitialized data to userspace? No. * **Uninitialized branching or memory reads:** Does it introduce any branching based on uninitialized memory? No. In fact, it's safer. * **Memory corruption, locking, or lifetime issues:** Any risks? The main concerns would be use-after-free or race conditions, but these would be caught by KASAN or lockdep, respectively. This leads us to the crucial question: Does this code change warrant KMSAN (Kernel Memory Sanitizer)? KMSAN is resource-intensive. We only need it if the change exposes *uninitialized memory* risks that are *not* caught by KASAN, lockdep, or other standard bug detectors. Reviewing the four KMSAN criteria: 1. **Kernel structures to user space:** No. 2. **Conditional logic based on uninitialized data:** No. The patch fixed a potential read of uninitialized data. 3. **Complex data structures with uninitialized fields:** No. 4. **Bounds checks exposing uninitialized data:** No. Therefore, `NeedsKMSAN=false`. The code change does *not* introduce any new risks of uninitialized memory usage or information leaks. A final double-check of the touched files ( `net/core/filter.c`, `tools/testing/selftests/...`) confirms this analysis. The changes are straightforward and do not introduce new uninitialized memory hazards. Time to `set-results`. |
| 44/3 | 2026/09/04 19:06 | tool | set-results |
0mArgs:{
"KMSANReasoning": "The patch modifies `bpf_sock_destroy` in `net/core/filter.c` to only check `sk-\u003esk_protocol` when `sk_fullsock(sk)` is true, allowing non-full sockets (such as TCP TIME_WAIT sockets) with a valid `sk_prot-\u003ediag_destroy` callback to be destroyed via the BPF kfunc.\n\nThis change does not introduce or expose any uninitialized memory risks. It does not allocate memory buffers, copy data to user space, or introduce branching on uninitialized data. In fact, checking `sk_fullsock()` avoids reading fields beyond `sock_common` for miniature sockets. Any potential risks related to socket destruction lifecycle or locking are covered by KASAN and LOCKDEP. Therefore, dedicated KMSAN fuzzing is not required.",
"NeedsKMSAN": false
}Results: {
"KMSANReasoning": "The patch modifies `bpf_sock_destroy` in `net/core/filter.c` to only check `sk-\u003esk_protocol` when `sk_fullsock(sk)` is true, allowing non-full sockets (such as TCP TIME_WAIT sockets) with a valid `sk_prot-\u003ediag_destroy` callback to be destroyed via the BPF kfunc.\n\nThis change does not introduce or expose any uninitialized memory risks. It does not allocate memory buffers, copy data to user space, or introduce branching on uninitialized data. In fact, checking `sk_fullsock()` avoids reading fields beyond `sock_common` for miniature sockets. Any potential risks related to socket destruction lifecycle or locking are covered by KASAN and LOCKDEP. Therefore, dedicated KMSAN fuzzing 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) |
|---|