AI Trajectory


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

Results:
{
  "EnableConfigs": [
    "BPF_SYSCALL",
    "BPF_STREAM_PARSER"
  ],
  "FocusSymbols": [
    "sk_psock_init_strp",
    "sk_psock_start_strp",
    "sk_psock_start_verdict",
    "sk_msg_recvmsg"
  ],
  "Reasoning": "The patch modifies `sk_psock_skb_ingress_self` and `sk_psock_skb_ingress` to handle `sk_forward_alloc` deficit when assigning receive ownership to a direct strparser SK_PASS clone. This is a functional change in the sockmap/skmsg BPF infrastructure. The code is reachable via BPF sockmap with a stream parser and verdict program attached.",
  "WorthFuzzing": true
}

1/1 2026/08/02 11:17 action read-patch-diff
0m Args:
null

Results:
{
  "PatchDiff": "commit efac91bb3393edeff902be24e65caa62f673ebc3\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate:   Sun Aug 2 11:17:27 2026 +0000\n\n    syz-cluster: applied patch under review\n\ndiff --git a/net/core/skmsg.c b/net/core/skmsg.c\nindex 2521b643fa05d..ce5ad81602828 100644\n--- a/net/core/skmsg.c\n+++ b/net/core/skmsg.c\n@@ -586,7 +586,8 @@ static int sk_psock_skb_ingress_enqueue(struct sk_buff *skb,\n }\n \n static int sk_psock_skb_ingress_self(struct sk_psock *psock, struct sk_buff *skb,\n-\t\t\t\t     u32 off, u32 len, bool take_ref);\n+\t\t\t\t     u32 off, u32 len, bool take_ref,\n+\t\t\t\t     bool settle_fwd_alloc);\n \n static int sk_psock_skb_ingress(struct sk_psock *psock, struct sk_buff *skb,\n \t\t\t\tu32 off, u32 len)\n@@ -595,12 +596,9 @@ static int sk_psock_skb_ingress(struct sk_psock *psock, struct sk_buff *skb,\n \tstruct sk_msg *msg;\n \tint err;\n \n-\t/* If we are receiving on the same sock skb-\u003esk is already assigned,\n-\t * skip memory accounting and owner transition seeing it already set\n-\t * correctly.\n-\t */\n \tif (unlikely(skb-\u003esk == sk))\n-\t\treturn sk_psock_skb_ingress_self(psock, skb, off, len, true);\n+\t\treturn sk_psock_skb_ingress_self(psock, skb, off, len, true,\n+\t\t\t\t\t\t skb_bpf_strparser(skb));\n \tmsg = sk_psock_create_ingress_msg(sk, skb);\n \tif (!msg)\n \t\treturn -EAGAIN;\n@@ -618,12 +616,14 @@ static int sk_psock_skb_ingress(struct sk_psock *psock, struct sk_buff *skb,\n \treturn err;\n }\n \n-/* Puts an skb on the ingress queue of the socket already assigned to the\n- * skb. In this case we do not need to check memory limits or skb_set_owner_r\n- * because the skb is already accounted for here.\n+/* Puts an skb on the ingress queue for psock-\u003esk.\n+ *\n+ * Before assigning receive ownership to a direct strparser SK_PASS clone,\n+ * settle any existing sk_forward_alloc deficit from earlier clone charges.\n  */\n static int sk_psock_skb_ingress_self(struct sk_psock *psock, struct sk_buff *skb,\n-\t\t\t\t     u32 off, u32 len, bool take_ref)\n+\t\t\t\t     u32 off, u32 len, bool take_ref,\n+\t\t\t\t     bool settle_fwd_alloc)\n {\n \tstruct sk_msg *msg = alloc_sk_msg(GFP_ATOMIC);\n \tstruct sock *sk = psock-\u003esk;\n@@ -631,6 +631,13 @@ static int sk_psock_skb_ingress_self(struct sk_psock *psock, struct sk_buff *skb\n \n \tif (unlikely(!msg))\n \t\treturn -EAGAIN;\n+\n+\tif (settle_fwd_alloc \u0026\u0026\n+\t    !sk_rmem_schedule(sk, skb, 0)) {\n+\t\tkfree(msg);\n+\t\treturn -EAGAIN;\n+\t}\n+\n \tskb_set_owner_r(skb, sk);\n \n \t/* This is used in tcp_bpf_recvmsg_parser() to determine whether the\n@@ -1017,6 +1024,8 @@ static int sk_psock_verdict_apply(struct sk_psock *psock, struct sk_buff *skb,\n \t\t * retrying later from workqueue.\n \t\t */\n \t\tif (skb_queue_empty(\u0026psock-\u003eingress_skb)) {\n+\t\t\tbool settle_fwd_alloc = false;\n+\n \t\t\tlen = skb-\u003elen;\n \t\t\toff = 0;\n \t\t\tif (skb_bpf_strparser(skb)) {\n@@ -1024,8 +1033,10 @@ static int sk_psock_verdict_apply(struct sk_psock *psock, struct sk_buff *skb,\n \n \t\t\t\toff = stm-\u003eoffset;\n \t\t\t\tlen = stm-\u003efull_len;\n+\t\t\t\tsettle_fwd_alloc = true;\n \t\t\t}\n-\t\t\terr = sk_psock_skb_ingress_self(psock, skb, off, len, false);\n+\t\t\terr = sk_psock_skb_ingress_self(psock, skb, off, len,\n+\t\t\t\t\t\t\tfalse, settle_fwd_alloc);\n \t\t}\n \t\tif (err \u003c 0) {\n \t\t\tspin_lock_bh(\u0026psock-\u003eingress_lock);\ndiff --git a/tools/testing/selftests/bpf/prog_tests/sockmap_strp.c b/tools/testing/selftests/bpf/prog_tests/sockmap_strp.c\nindex 1d7231728eafd..c7ad21d0bbf49 100644\n--- a/tools/testing/selftests/bpf/prog_tests/sockmap_strp.c\n+++ b/tools/testing/selftests/bpf/prog_tests/sockmap_strp.c\n@@ -1,5 +1,9 @@\n // SPDX-License-Identifier: GPL-2.0\n #include \u003cerror.h\u003e\n+#include \u003clinux/inet_diag.h\u003e\n+#include \u003clinux/netlink.h\u003e\n+#include \u003clinux/rtnetlink.h\u003e\n+#include \u003clinux/sock_diag.h\u003e\n #include \u003cnetinet/tcp.h\u003e\n #include \u003ctest_progs.h\u003e\n #include \"sockmap_helpers.h\"\n@@ -460,6 +464,171 @@ static void test_sockmap_strp_parser_reject(void)\n \ttest_sockmap_strp__destroy(strp);\n }\n \n+/* Read sk_forward_alloc through inet_diag meminfo. */\n+static int sockmap_strp_get_fwd_alloc(int sock, int *fwd_alloc)\n+{\n+\tstruct sockaddr_storage local = {}, peer = {};\n+\tstruct sockaddr_in *local_in, *peer_in;\n+\tsocklen_t addr_len = sizeof(local);\n+\tchar buf[1024];\n+\tstruct {\n+\t\tstruct nlmsghdr nlh;\n+\t\tstruct inet_diag_req_v2 req;\n+\t} req = {\n+\t\t.nlh = {\n+\t\t\t.nlmsg_len = sizeof(req),\n+\t\t\t.nlmsg_type = SOCK_DIAG_BY_FAMILY,\n+\t\t\t.nlmsg_flags = NLM_F_REQUEST,\n+\t\t\t.nlmsg_seq = 1,\n+\t\t},\n+\t\t.req = {\n+\t\t\t.sdiag_family = AF_INET,\n+\t\t\t.sdiag_protocol = IPPROTO_TCP,\n+\t\t\t.idiag_ext = 1 \u003c\u003c (INET_DIAG_MEMINFO - 1),\n+\t\t\t.idiag_states = ~0U,\n+\t\t\t.id.idiag_cookie = {\n+\t\t\t\tINET_DIAG_NOCOOKIE,\n+\t\t\t\tINET_DIAG_NOCOOKIE,\n+\t\t\t},\n+\t\t},\n+\t};\n+\tint diag_fd, ret, err = -ENOENT;\n+\n+\tif (getsockname(sock, (struct sockaddr *)\u0026local, \u0026addr_len))\n+\t\treturn -errno;\n+\taddr_len = sizeof(peer);\n+\tif (getpeername(sock, (struct sockaddr *)\u0026peer, \u0026addr_len))\n+\t\treturn -errno;\n+\n+\tlocal_in = (struct sockaddr_in *)\u0026local;\n+\tpeer_in = (struct sockaddr_in *)\u0026peer;\n+\treq.req.id.idiag_sport = local_in-\u003esin_port;\n+\treq.req.id.idiag_dport = peer_in-\u003esin_port;\n+\treq.req.id.idiag_src[0] = local_in-\u003esin_addr.s_addr;\n+\treq.req.id.idiag_dst[0] = peer_in-\u003esin_addr.s_addr;\n+\n+\tdiag_fd = socket(AF_NETLINK, SOCK_RAW | SOCK_CLOEXEC,\n+\t\t\t NETLINK_SOCK_DIAG);\n+\tif (diag_fd \u003c 0)\n+\t\treturn -errno;\n+\n+\tret = send(diag_fd, \u0026req, sizeof(req), 0);\n+\tif (ret \u003c 0) {\n+\t\terr = -errno;\n+\t\tgoto out;\n+\t}\n+\tif (ret != sizeof(req)) {\n+\t\terr = -EIO;\n+\t\tgoto out;\n+\t}\n+\n+\tret = recv(diag_fd, buf, sizeof(buf), 0);\n+\tif (ret \u003c 0) {\n+\t\terr = -errno;\n+\t\tgoto out;\n+\t}\n+\n+\tfor (struct nlmsghdr *nlh = (struct nlmsghdr *)buf;\n+\t     NLMSG_OK(nlh, ret); nlh = NLMSG_NEXT(nlh, ret)) {\n+\t\tstruct inet_diag_msg *msg = NLMSG_DATA(nlh);\n+\t\tstruct rtattr *attr;\n+\t\tint len;\n+\n+\t\tif (nlh-\u003enlmsg_type == NLMSG_ERROR) {\n+\t\t\terr = -EINVAL;\n+\t\t\tgoto out;\n+\t\t}\n+\t\tif (nlh-\u003enlmsg_type == NLMSG_DONE)\n+\t\t\tbreak;\n+\n+\t\tlen = nlh-\u003enlmsg_len - NLMSG_LENGTH(sizeof(*msg));\n+\t\tfor (attr = (struct rtattr *)(msg + 1); RTA_OK(attr, len);\n+\t\t     attr = RTA_NEXT(attr, len)) {\n+\t\t\tstruct inet_diag_meminfo *minfo;\n+\n+\t\t\tif (attr-\u003erta_type != INET_DIAG_MEMINFO)\n+\t\t\t\tcontinue;\n+\t\t\tminfo = RTA_DATA(attr);\n+\t\t\t*fwd_alloc = (__s32)minfo-\u003eidiag_fmem;\n+\t\t\terr = 0;\n+\t\t\tgoto out;\n+\t\t}\n+\t}\n+\n+out:\n+\tclose(diag_fd);\n+\treturn err;\n+}\n+\n+/* Test strparser SK_PASS delivery to the same socket. */\n+static void test_sockmap_strp_self_pass_fwd_alloc(void)\n+{\n+\tstruct test_sockmap_strp *strp = NULL;\n+\tchar snd[4 * 1024];\n+\tint c = -1, p = -1;\n+\tint fwd_alloc;\n+\tint sndbuf = sizeof(snd);\n+\tint zero = 0;\n+\tchar rcv;\n+\tint sent, recvd;\n+\tint map;\n+\tint err;\n+\n+\tmemset(snd, 0xa5, sizeof(snd));\n+\n+\tstrp = test_sockmap_strp__open_and_load();\n+\tif (!ASSERT_OK_PTR(strp, \"test_sockmap_strp__open_and_load\"))\n+\t\treturn;\n+\n+\tmap = bpf_map__fd(strp-\u003emaps.sock_map);\n+\terr = xbpf_prog_attach(bpf_program__fd(strp-\u003eprogs.prog_skb_parser_one),\n+\t\t\t       map, BPF_SK_SKB_STREAM_PARSER, 0);\n+\tif (err)\n+\t\tgoto out_destroy;\n+\n+\terr = xbpf_prog_attach(bpf_program__fd(strp-\u003eprogs.prog_skb_verdict_pass),\n+\t\t\t       map, BPF_SK_SKB_STREAM_VERDICT, 0);\n+\tif (err)\n+\t\tgoto out_destroy;\n+\n+\terr = create_pair(AF_INET, SOCK_STREAM, \u0026c, \u0026p);\n+\tif (!ASSERT_OK(err, \"create_pair\"))\n+\t\tgoto out_destroy;\n+\n+\terr = xsetsockopt(c, SOL_SOCKET, SO_SNDBUF, \u0026sndbuf, sizeof(sndbuf));\n+\tif (err)\n+\t\tgoto out_destroy;\n+\n+\terr = xsetsockopt(p, SOL_SOCKET, SO_RCVBUF, \u0026sndbuf, sizeof(sndbuf));\n+\tif (err)\n+\t\tgoto out_destroy;\n+\n+\terr = xbpf_map_update_elem(map, \u0026zero, \u0026p, BPF_NOEXIST);\n+\tif (err)\n+\t\tgoto out_destroy;\n+\n+\tsent = send(c, snd, sizeof(snd), MSG_DONTWAIT);\n+\tif (!ASSERT_EQ(sent, sizeof(snd), \"send\"))\n+\t\tgoto out_destroy;\n+\n+\trecvd = recv_timeout(p, \u0026rcv, sizeof(rcv), MSG_DONTWAIT,\n+\t\t\t     IO_TIMEOUT_SEC);\n+\tif (!ASSERT_EQ(recvd, sizeof(rcv), \"recv_timeout\") ||\n+\t    !ASSERT_EQ(rcv, snd[0], \"data mismatch\"))\n+\t\tgoto out_destroy;\n+\n+\terr = sockmap_strp_get_fwd_alloc(p, \u0026fwd_alloc);\n+\tif (!ASSERT_OK(err, \"sockmap_strp_get_fwd_alloc\") ||\n+\t    !ASSERT_GE(fwd_alloc, 0, \"sk_forward_alloc\"))\n+\t\tgoto out_destroy;\n+out_destroy:\n+\ttest_sockmap_strp__destroy(strp);\n+\tif (c \u003e= 0)\n+\t\tclose(c);\n+\tif (p \u003e= 0)\n+\t\tclose(p);\n+}\n+\n void test_sockmap_strp(void)\n {\n \tif (test__start_subtest(\"sockmap strp tcp pass\"))\n@@ -482,4 +651,6 @@ void test_sockmap_strp(void)\n \t\ttest_sockmap_strp_dispatch_pkt(AF_INET, SOCK_STREAM);\n \tif (test__start_subtest(\"sockmap strp parser reject pkt mod\"))\n \t\ttest_sockmap_strp_parser_reject();\n+\tif (test__start_subtest(\"sockmap strp self pass fwd alloc\"))\n+\t\ttest_sockmap_strp_self_pass_fwd_alloc();\n }\ndiff --git a/tools/testing/selftests/bpf/progs/test_sockmap_strp.c b/tools/testing/selftests/bpf/progs/test_sockmap_strp.c\nindex fe88fa6d40bc5..682e53d40751c 100644\n--- a/tools/testing/selftests/bpf/progs/test_sockmap_strp.c\n+++ b/tools/testing/selftests/bpf/progs/test_sockmap_strp.c\n@@ -50,6 +50,12 @@ int prog_skb_parser_partial(struct __sk_buff *skb)\n \treturn 10;\n }\n \n+SEC(\"sk_skb/stream_parser\")\n+int prog_skb_parser_one(struct __sk_buff *skb)\n+{\n+\treturn 1;\n+}\n+\n SEC(\"sk_skb/stream_parser\")\n int prog_skb_parser_resize(struct __sk_buff *skb)\n {\n"
}

2/1 2026/08/02 11:17 agent patch-evaluator
1m Model:
best-expensive

Args:
null

Results:
{
  "EnableConfigs": [
    "BPF_SYSCALL",
    "BPF_STREAM_PARSER"
  ],
  "FocusSymbols": [
    "sk_psock_init_strp",
    "sk_psock_start_strp",
    "sk_psock_start_verdict",
    "sk_msg_recvmsg"
  ],
  "Reasoning": "The patch modifies `sk_psock_skb_ingress_self` and `sk_psock_skb_ingress` to handle `sk_forward_alloc` deficit when assigning receive ownership to a direct strparser SK_PASS clone. This is a functional change in the sockmap/skmsg BPF infrastructure. The code is reachable via BPF sockmap with a stream parser and verdict program attached.",
  "WorthFuzzing": true
}

Instruction:
You are an expert Linux kernel maintainer.
Your job is to review a provided patch series and determine
if it makes functional changes to the kernel that should be fuzzed.

IMPORTANT: The changes have ALREADY been applied and committed as the HEAD commit in
your workspace. Do NOT rely on your internal knowledge of the kernel. You must actively
use your code access tools to examine the actual source code and confirm any assumptions.

Return WorthFuzzing=false if the patch only contains:
- Modifications to Documentation/, Kconfig files, or code comments.
- Purely decorative changes, such as logging (e.g., pr_err, printk) or tracepoints.
- Changes to numeric constants or macros that do not functionally alter execution flow.
- Code paths that are impossible to reach in virtualized environments like GCE or QEMU,
  even when utilizing software-emulated hardware (e.g., usb gadget, mac80211_hwsim).
- Code in vendor-specific PCIe switch, SmartNIC, or GPU drivers (e.g., mlxsw, pds_core, qed,
  ionic, amdgpu) that require physical PCIe hardware cards not emulated in standard QEMU.
- Driver .remove, .shutdown, or pci_unregister_driver teardown callbacks (e.g., igb_remove)
  that are executed only during PCI hot-unplug or sysfs driver unbind operations.

If it modifies reachable core kernel logic, drivers, or architectures, use your code search
tools to verify the code can be executed, then return WorthFuzzing=true.

When returning WorthFuzzing=true, you MUST ALSO:
1. Extract any specific kernel functions that should be heavily fuzzed into FocusSymbols.
   Avoid listing generic hot-path functions to prevent skewed test distributions.
   Prefer non-static, non-inlined API entrypoint functions over internal static helper functions
   (which are inlined by the compiler and do not have distinct symbol addresses).
2. Identify any specific CONFIG_ options required to properly test this new/modified feature.
   Go and look into the Kconfig files and check for ifdefs around the code, do not make assumptions.
   Also check "depends on" lines in Kconfig to include any non-standard parent subsystem configs
   needed for Kbuild to compile the code statically into vmlinux. List them in the EnableConfigs
   output array, and DO NOT add a 'CONFIG_' prefix (e.g., return "NET_IPV4" instead of "CONFIG_NET_IPV4").
Prefer calling several tools at the same time to save round-trips.


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

Prompt:
For your convenience, here is the diff of the changes:
commit efac91bb3393edeff902be24e65caa62f673ebc3
Author: syz-cluster <triage@syzkaller.com>
Date:   Sun Aug 2 11:17:27 2026 +0000

    syz-cluster: applied patch under review

diff --git a/net/core/skmsg.c b/net/core/skmsg.c
index 2521b643fa05d..ce5ad81602828 100644
--- a/net/core/skmsg.c
+++ b/net/core/skmsg.c
@@ -586,7 +586,8 @@ static int sk_psock_skb_ingress_enqueue(struct sk_buff *skb,
 }
 
 static int sk_psock_skb_ingress_self(struct sk_psock *psock, struct sk_buff *skb,
-				     u32 off, u32 len, bool take_ref);
+				     u32 off, u32 len, bool take_ref,
+				     bool settle_fwd_alloc);
 
 static int sk_psock_skb_ingress(struct sk_psock *psock, struct sk_buff *skb,
 				u32 off, u32 len)
@@ -595,12 +596,9 @@ static int sk_psock_skb_ingress(struct sk_psock *psock, struct sk_buff *skb,
 	struct sk_msg *msg;
 	int err;
 
-	/* If we are receiving on the same sock skb->sk is already assigned,
-	 * skip memory accounting and owner transition seeing it already set
-	 * correctly.
-	 */
 	if (unlikely(skb->sk == sk))
-		return sk_psock_skb_ingress_self(psock, skb, off, len, true);
+		return sk_psock_skb_ingress_self(psock, skb, off, len, true,
+						 skb_bpf_strparser(skb));
 	msg = sk_psock_create_ingress_msg(sk, skb);
 	if (!msg)
 		return -EAGAIN;
@@ -618,12 +616,14 @@ static int sk_psock_skb_ingress(struct sk_psock *psock, struct sk_buff *skb,
 	return err;
 }
 
-/* Puts an skb on the ingress queue of the socket already assigned to the
- * skb. In this case we do not need to check memory limits or skb_set_owner_r
- * because the skb is already accounted for here.
+/* Puts an skb on the ingress queue for psock->sk.
+ *
+ * Before assigning receive ownership to a direct strparser SK_PASS clone,
+ * settle any existing sk_forward_alloc deficit from earlier clone charges.
  */
 static int sk_psock_skb_ingress_self(struct sk_psock *psock, struct sk_buff *skb,
-				     u32 off, u32 len, bool take_ref)
+				     u32 off, u32 len, bool take_ref,
+				     bool settle_fwd_alloc)
 {
 	struct sk_msg *msg = alloc_sk_msg(GFP_ATOMIC);
 	struct sock *sk = psock->sk;
@@ -631,6 +631,13 @@ static int sk_psock_skb_ingress_self(struct sk_psock *psock, struct sk_buff *skb
 
 	if (unlikely(!msg))
 		return -EAGAIN;
+
+	if (settle_fwd_alloc &&
+	    !sk_rmem_schedule(sk, skb, 0)) {
+		kfree(msg);
+		return -EAGAIN;
+	}
+
 	skb_set_owner_r(skb, sk);
 
 	/* This is used in tcp_bpf_recvmsg_parser() to determine whether the
@@ -1017,6 +1024,8 @@ static int sk_psock_verdict_apply(struct sk_psock *psock, struct sk_buff *skb,
 		 * retrying later from workqueue.
 		 */
 		if (skb_queue_empty(&psock->ingress_skb)) {
+			bool settle_fwd_alloc = false;
+
 			len = skb->len;
 			off = 0;
 			if (skb_bpf_strparser(skb)) {
@@ -1024,8 +1033,10 @@ static int sk_psock_verdict_apply(struct sk_psock *psock, struct sk_buff *skb,
 
 				off = stm->offset;
 				len = stm->full_len;
+				settle_fwd_alloc = true;
 			}
-			err = sk_psock_skb_ingress_self(psock, skb, off, len, false);
+			err = sk_psock_skb_ingress_self(psock, skb, off, len,
+							false, settle_fwd_alloc);
 		}
 		if (err < 0) {
 			spin_lock_bh(&psock->ingress_lock);
diff --git a/tools/testing/selftests/bpf/prog_tests/sockmap_strp.c b/tools/testing/selftests/bpf/prog_tests/sockmap_strp.c
index 1d7231728eafd..c7ad21d0bbf49 100644
--- a/tools/testing/selftests/bpf/prog_tests/sockmap_strp.c
+++ b/tools/testing/selftests/bpf/prog_tests/sockmap_strp.c
@@ -1,5 +1,9 @@
 // SPDX-License-Identifier: GPL-2.0
 #include <error.h>
+#include <linux/inet_diag.h>
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+#include <linux/sock_diag.h>
 #include <netinet/tcp.h>
 #include <test_progs.h>
 #include "sockmap_helpers.h"
@@ -460,6 +464,171 @@ static void test_sockmap_strp_parser_reject(void)
 	test_sockmap_strp__destroy(strp);
 }
 
+/* Read sk_forward_alloc through inet_diag meminfo. */
+static int sockmap_strp_get_fwd_alloc(int sock, int *fwd_alloc)
+{
+	struct sockaddr_storage local = {}, peer = {};
+	struct sockaddr_in *local_in, *peer_in;
+	socklen_t addr_len = sizeof(local);
+	char buf[1024];
+	struct {
+		struct nlmsghdr nlh;
+		struct inet_diag_req_v2 req;
+	} req = {
+		.nlh = {
+			.nlmsg_len = sizeof(req),
+			.nlmsg_type = SOCK_DIAG_BY_FAMILY,
+			.nlmsg_flags = NLM_F_REQUEST,
+			.nlmsg_seq = 1,
+		},
+		.req = {
+			.sdiag_family = AF_INET,
+			.sdiag_protocol = IPPROTO_TCP,
+			.idiag_ext = 1 << (INET_DIAG_MEMINFO - 1),
+			.idiag_states = ~0U,
+			.id.idiag_cookie = {
+				INET_DIAG_NOCOOKIE,
+				INET_DIAG_NOCOOKIE,
+			},
+		},
+	};
+	int diag_fd, ret, err = -ENOENT;
+
+	if (getsockname(sock, (struct sockaddr *)&local, &addr_len))
+		return -errno;
+	addr_len = sizeof(peer);
+	if (getpeername(sock, (struct sockaddr *)&peer, &addr_len))
+		return -errno;
+
+	local_in = (struct sockaddr_in *)&local;
+	peer_in = (struct sockaddr_in *)&peer;
+	req.req.id.idiag_sport = local_in->sin_port;
+	req.req.id.idiag_dport = peer_in->sin_port;
+	req.req.id.idiag_src[0] = local_in->sin_addr.s_addr;
+	req.req.id.idiag_dst[0] = peer_in->sin_addr.s_addr;
+
+	diag_fd = socket(AF_NETLINK, SOCK_RAW | SOCK_CLOEXEC,
+			 NETLINK_SOCK_DIAG);
+	if (diag_fd < 0)
+		return -errno;
+
+	ret = send(diag_fd, &req, sizeof(req), 0);
+	if (ret < 0) {
+		err = -errno;
+		goto out;
+	}
+	if (ret != sizeof(req)) {
+		err = -EIO;
+		goto out;
+	}
+
+	ret = recv(diag_fd, buf, sizeof(buf), 0);
+	if (ret < 0) {
+		err = -errno;
+		goto out;
+	}
+
+	for (struct nlmsghdr *nlh = (struct nlmsghdr *)buf;
+	     NLMSG_OK(nlh, ret); nlh = NLMSG_NEXT(nlh, ret)) {
+		struct inet_diag_msg *msg = NLMSG_DATA(nlh);
+		struct rtattr *attr;
+		int len;
+
+		if (nlh->nlmsg_type == NLMSG_ERROR) {
+			err = -EINVAL;
+			goto out;
+		}
+		if (nlh->nlmsg_type == NLMSG_DONE)
+			break;
+
+		len = nlh->nlmsg_len - NLMSG_LENGTH(sizeof(*msg));
+		for (attr = (struct rtattr *)(msg + 1); RTA_OK(attr, len);
+		     attr = RTA_NEXT(attr, len)) {
+			struct inet_diag_meminfo *minfo;
+
+			if (attr->rta_type != INET_DIAG_MEMINFO)
+				continue;
+			minfo = RTA_DATA(attr);
+			*fwd_alloc = (__s32)minfo->idiag_fmem;
+			err = 0;
+			goto out;
+		}
+	}
+
+out:
+	close(diag_fd);
+	return err;
+}
+
+/* Test strparser SK_PASS delivery to the same socket. */
+static void test_sockmap_strp_self_pass_fwd_alloc(void)
+{
+	struct test_sockmap_strp *strp = NULL;
+	char snd[4 * 1024];
+	int c = -1, p = -1;
+	int fwd_alloc;
+	int sndbuf = sizeof(snd);
+	int zero = 0;
+	char rcv;
+	int sent, recvd;
+	int map;
+	int err;
+
+	memset(snd, 0xa5, sizeof(snd));
+
+	strp = test_sockmap_strp__open_and_load();
+	if (!ASSERT_OK_PTR(strp, "test_sockmap_strp__open_and_load"))
+		return;
+
+	map = bpf_map__fd(strp->maps.sock_map);
+	err = xbpf_prog_attach(bpf_program__fd(strp->progs.prog_skb_parser_one),
+			       map, BPF_SK_SKB_STREAM_PARSER, 0);
+	if (err)
+		goto out_destroy;
+
+	err = xbpf_prog_attach(bpf_program__fd(strp->progs.prog_skb_verdict_pass),
+			       map, BPF_SK_SKB_STREAM_VERDICT, 0);
+	if (err)
+		goto out_destroy;
+
+	err = create_pair(AF_INET, SOCK_STREAM, &c, &p);
+	if (!ASSERT_OK(err, "create_pair"))
+		goto out_destroy;
+
+	err = xsetsockopt(c, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(sndbuf));
+	if (err)
+		goto out_destroy;
+
+	err = xsetsockopt(p, SOL_SOCKET, SO_RCVBUF, &sndbuf, sizeof(sndbuf));
+	if (err)
+		goto out_destroy;
+
+	err = xbpf_map_update_elem(map, &zero, &p, BPF_NOEXIST);
+	if (err)
+		goto out_destroy;
+
+	sent = send(c, snd, sizeof(snd), MSG_DONTWAIT);
+	if (!ASSERT_EQ(sent, sizeof(snd), "send"))
+		goto out_destroy;
+
+	recvd = recv_timeout(p, &rcv, sizeof(rcv), MSG_DONTWAIT,
+			     IO_TIMEOUT_SEC);
+	if (!ASSERT_EQ(recvd, sizeof(rcv), "recv_timeout") ||
+	    !ASSERT_EQ(rcv, snd[0], "data mismatch"))
+		goto out_destroy;
+
+	err = sockmap_strp_get_fwd_alloc(p, &fwd_alloc);
+	if (!ASSERT_OK(err, "sockmap_strp_get_fwd_alloc") ||
+	    !ASSERT_GE(fwd_alloc, 0, "sk_forward_alloc"))
+		goto out_destroy;
+out_destroy:
+	test_sockmap_strp__destroy(strp);
+	if (c >= 0)
+		close(c);
+	if (p >= 0)
+		close(p);
+}
+
 void test_sockmap_strp(void)
 {
 	if (test__start_subtest("sockmap strp tcp pass"))
@@ -482,4 +651,6 @@ void test_sockmap_strp(void)
 		test_sockmap_strp_dispatch_pkt(AF_INET, SOCK_STREAM);
 	if (test__start_subtest("sockmap strp parser reject pkt mod"))
 		test_sockmap_strp_parser_reject();
+	if (test__start_subtest("sockmap strp self pass fwd alloc"))
+		test_sockmap_strp_self_pass_fwd_alloc();
 }
diff --git a/tools/testing/selftests/bpf/progs/test_sockmap_strp.c b/tools/testing/selftests/bpf/progs/test_sockmap_strp.c
index fe88fa6d40bc5..682e53d40751c 100644
--- a/tools/testing/selftests/bpf/progs/test_sockmap_strp.c
+++ b/tools/testing/selftests/bpf/progs/test_sockmap_strp.c
@@ -50,6 +50,12 @@ int prog_skb_parser_partial(struct __sk_buff *skb)
 	return 10;
 }
 
+SEC("sk_skb/stream_parser")
+int prog_skb_parser_one(struct __sk_buff *skb)
+{
+	return 1;
+}
+
 SEC("sk_skb/stream_parser")
 int prog_skb_parser_resize(struct __sk_buff *skb)
 {

3/2 2026/08/02 11:17 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 5763
							output: 37
							thoughts: 340
						

Thoughts:
**Analyzing the `net/core/skmsg.c` Patch**

Okay, so I'm looking at this patch. It looks like it's a specific fix involving `net/core/skmsg.c` and a new test in `tools/testing/selftests/bpf/prog_tests/sockmap_strp.c`. The core of the change seems to be around handling the `sk_forward_alloc` deficit when dealing with direct strparser SK_PASS clones during receive ownership assignment. Specifically, they've added a `settle_fwd_alloc` boolean parameter to `sk_psock_skb_ingress_self` and are calling `sk_rmem_schedule(sk, skb, 0)` if it's set to true.

My first thought is always about reachability and functionality. Since we're dealing with `sk_psock_skb_ingress` and `sk_psock_verdict_apply`, which are critical components of the sockmap/skmsg BPF infrastructure, I'm pretty confident that these functions *are* reachable and functional. They're fundamental to the whole process.

Now, my next step is to figure out the right places to focus fuzzing efforts. `sk_psock_skb_ingress` and `sk_psock_verdict_apply` are the obvious candidates. `sk_psock_skb_ingress_self` is static, which limits its exposure, so the former two are likely the more critical targets.

To solidify my understanding, I'll need to locate those two functions, `sk_psock_skb_ingress` and `sk_psock_verdict_apply`, within `net/core/skmsg.c`.



4/2 2026/08/02 11:17 tool grepper
0m Args:
{
  "Expression": "sk_psock_skb_ingress",
  "PathPrefix": "net/core/skmsg.c"
}

Results:
{
  "Output": "net/core/skmsg.c=533=static struct sk_msg *sk_psock_create_ingress_msg(struct sock *sk,\n--\nnet/core/skmsg.c-544-\nnet/core/skmsg.c:545:static int sk_psock_skb_ingress_enqueue(struct sk_buff *skb,\nnet/core/skmsg.c-546-\t\t\t\t\tu32 off, u32 len,\n--\nnet/core/skmsg.c-587-\nnet/core/skmsg.c:588:static int sk_psock_skb_ingress_self(struct sk_psock *psock, struct sk_buff *skb,\nnet/core/skmsg.c-589-\t\t\t\t     u32 off, u32 len, bool take_ref,\n--\nnet/core/skmsg.c-591-\nnet/core/skmsg.c:592:static int sk_psock_skb_ingress(struct sk_psock *psock, struct sk_buff *skb,\nnet/core/skmsg.c-593-\t\t\t\tu32 off, u32 len)\n--\nnet/core/skmsg.c-599-\tif (unlikely(skb-\u003esk == sk))\nnet/core/skmsg.c:600:\t\treturn sk_psock_skb_ingress_self(psock, skb, off, len, true,\nnet/core/skmsg.c-601-\t\t\t\t\t\t skb_bpf_strparser(skb));\n--\nnet/core/skmsg.c-612-\tskb_set_owner_r(skb, sk);\nnet/core/skmsg.c:613:\terr = sk_psock_skb_ingress_enqueue(skb, off, len, psock, sk, msg, true);\nnet/core/skmsg.c-614-\tif (err \u003c 0)\n--\nnet/core/skmsg.c-623- */\nnet/core/skmsg.c:624:static int sk_psock_skb_ingress_self(struct sk_psock *psock, struct sk_buff *skb,\nnet/core/skmsg.c-625-\t\t\t\t     u32 off, u32 len, bool take_ref,\n--\nnet/core/skmsg.c-647-\tmsg-\u003esk = sk;\nnet/core/skmsg.c:648:\terr = sk_psock_skb_ingress_enqueue(skb, off, len, psock, sk, msg, take_ref);\nnet/core/skmsg.c-649-\tif (err \u003c 0)\n--\nnet/core/skmsg.c=654=static int sk_psock_handle_skb(struct sk_psock *psock, struct sk_buff *skb,\n--\nnet/core/skmsg.c-662-\nnet/core/skmsg.c:663:\treturn sk_psock_skb_ingress(psock, skb, off, len);\nnet/core/skmsg.c-664-}\n--\nnet/core/skmsg.c=1003=static int sk_psock_verdict_apply(struct sk_psock *psock, struct sk_buff *skb,\n--\nnet/core/skmsg.c-1022-\t\t * queue work otherwise we may get OOO data. Otherwise,\nnet/core/skmsg.c:1023:\t\t * if sk_psock_skb_ingress errors will be handled by\nnet/core/skmsg.c-1024-\t\t * retrying later from workqueue.\n--\nnet/core/skmsg.c-1037-\t\t\t}\nnet/core/skmsg.c:1038:\t\t\terr = sk_psock_skb_ingress_self(psock, skb, off, len,\nnet/core/skmsg.c-1039-\t\t\t\t\t\t\tfalse, settle_fwd_alloc);\n"
}

5/2 2026/08/02 11:17 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 7527
							output: 37
							thoughts: 47
						

Thoughts:
Okay, here's my take on those thoughts, framed as a first-person expert summary:

**Analyzing Packet Socket Verdict Application**

Alright, so I'm looking at this code and the first thing that jumps out is that `sk_psock_skb_ingress` and `sk_psock_verdict_apply` are both declared as `static`. That's a good initial clue – it tells me these functions have *internal linkage* within their compilation unit. They're not meant to be called directly from outside that specific module or file.

Given that, my next thought is: *Who* is calling `sk_psock_verdict_apply`? Since it's static, the call has to originate within the same source file, so I need to find its callers to really understand how this packet socket verdicting process works and what the constraints are. The fact that it is a *verdict application* means that it is applying some decision about the packet, so I need to understand what those decisions are and what the decision-making process depends on. This seems like a core part of whatever system this code is implementing, and I need to figure out how this *ingress* function interacts with the verdict application to understand the whole picture. Let's see what the call sites reveal...



6/2 2026/08/02 11:17 tool grepper
0m Args:
{
  "Expression": "sk_psock_verdict_apply",
  "PathPrefix": "net/core/skmsg.c"
}

Results:
{
  "Output": "net/core/skmsg.c=965=static int sk_psock_skb_redirect(struct sk_psock *from, struct sk_buff *skb)\n--\nnet/core/skmsg.c-1002-\nnet/core/skmsg.c:1003:static int sk_psock_verdict_apply(struct sk_psock *psock, struct sk_buff *skb,\nnet/core/skmsg.c-1004-\t\t\t\t  int verdict)\n--\nnet/core/skmsg.c=1086=static void sk_psock_strp_read(struct strparser *strp, struct sk_buff *skb)\n--\nnet/core/skmsg.c-1109-\t}\nnet/core/skmsg.c:1110:\tsk_psock_verdict_apply(psock, skb, ret);\nnet/core/skmsg.c-1111-out:\n--\nnet/core/skmsg.c=1209=static int sk_psock_verdict_recv(struct sock *sk, struct sk_buff *skb)\n--\nnet/core/skmsg.c-1232-\t}\nnet/core/skmsg.c:1233:\tret = sk_psock_verdict_apply(psock, skb, ret);\nnet/core/skmsg.c-1234-\tif (ret \u003c 0)\n"
}

7/2 2026/08/02 11:17 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 8254
							output: 37
							thoughts: 45
						

Thoughts:
Okay, here's my interpretation of those thoughts, presented as my own mental process, given my expertise:

**Examining the Interplay of psock Function Calls**

Alright, so `sk_psock_strp_read` and `sk_psock_verdict_recv` both, it seems, end up calling `sk_psock_verdict_apply`. This is the crucial point for me. I'm immediately thinking about how that affects the overall flow and functionality of packet socket (psock) operations. The question then becomes how is it used, I need to understand that relationship.

The immediate thing I'm focused on is whether `sk_psock_verdict_apply` is declared as static. This has real implications for scoping, visibility, and potentially, optimization. A static function would be scoped only within the compilation unit, meaning it's not directly accessible from other modules, but rather acts as a private helper. Knowing if it's static gives me an important piece of the puzzle in terms of how the code is structured and designed.



8/2 2026/08/02 11:17 tool grepper
0m Args:
{
  "Expression": "sk_psock_strp_read",
  "PathPrefix": "net/core/skmsg.c"
}

Results:
{
  "Output": "net/core/skmsg.c=1068=static void sk_psock_write_space(struct sock *sk)\n--\nnet/core/skmsg.c-1085-#if IS_ENABLED(CONFIG_BPF_STREAM_PARSER)\nnet/core/skmsg.c:1086:static void sk_psock_strp_read(struct strparser *strp, struct sk_buff *skb)\nnet/core/skmsg.c-1087-{\n--\nnet/core/skmsg.c-1114-\nnet/core/skmsg.c:1115:static int sk_psock_strp_read_done(struct strparser *strp, int err)\nnet/core/skmsg.c-1116-{\n--\nnet/core/skmsg.c=1154=int sk_psock_init_strp(struct sock *sk, struct sk_psock *psock)\n--\nnet/core/skmsg.c-1158-\tstatic const struct strp_callbacks cb = {\nnet/core/skmsg.c:1159:\t\t.rcv_msg\t= sk_psock_strp_read,\nnet/core/skmsg.c:1160:\t\t.read_sock_done\t= sk_psock_strp_read_done,\nnet/core/skmsg.c-1161-\t\t.parse_msg\t= sk_psock_strp_parse,\n"
}

9/2 2026/08/02 11:17 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 8936
							output: 37
							thoughts: 32
						

Thoughts:
Okay, here's my take on those thoughts, framed as an expert's internal monologue:

**Investigating `sk_psock_init_strp` and `sk_psock_verdict_recv`**

Right, so `sk_psock_init_strp` isn't declared static. That immediately piques my interest. It implies this function might be exposed and called from outside its primary compilation unit. Makes me wonder where and why. Is it part of a public API? Is it used in some kind of helper module? I'll need to trace its callers.

Now, let's look at `sk_psock_verdict_recv`. That suggests we're dealing with packet sockets, and potentially some kind of filtering or verdict mechanism on the received packets. The name is pretty clear, but the context matters. Is this related to some kind of packet filter like BPF? Or perhaps a user-space application controlling the behaviour of raw sockets? It needs further investigation to understand its integration and functionality, so I'll need to dive into that one next.



10/2 2026/08/02 11:17 tool grepper
0m Args:
{
  "Expression": "sk_psock_verdict_recv",
  "PathPrefix": "net/core/skmsg.c"
}

Results:
{
  "Output": "net/core/skmsg.c=1204=static void sk_psock_done_strp(struct sk_psock *psock)\n--\nnet/core/skmsg.c-1208-\nnet/core/skmsg.c:1209:static int sk_psock_verdict_recv(struct sock *sk, struct sk_buff *skb)\nnet/core/skmsg.c-1210-{\n--\nnet/core/skmsg.c=1241=static void sk_psock_verdict_data_ready(struct sock *sk)\n--\nnet/core/skmsg.c-1257-\nnet/core/skmsg.c:1258:\tcopied = ops-\u003eread_skb(sk, sk_psock_verdict_recv);\nnet/core/skmsg.c-1259-\tif (copied \u003e= 0) {\n"
}

11/2 2026/08/02 11:17 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 9470
							output: 39
							thoughts: 36
						

Thoughts:
Okay, here's my take on those thoughts, framed as an expert's internal monologue:

**Investigating `sk_psock_verdict_data_ready`**

Right, `sk_psock_verdict_data_ready` is flagged as `static`. That immediately piques my interest. Static functions, within a kernel context like this, usually mean it's an internal function, probably for a very specific module or subsystem. It's likely not meant to be called directly from outside its compilation unit.

So, let's trace this function and understand its purpose within the broader picture. My next move is clear: I need to quickly identify all the call sites of `sk_psock_verdict_data_ready`. Understanding where it's called from is crucial to grasping its function and the context it operates within. This will help me quickly understand its function.



12/2 2026/08/02 11:17 tool grepper
0m Args:
{
  "Expression": "sk_psock_verdict_data_ready",
  "PathPrefix": "net/core/skmsg.c"
}

Results:
{
  "Output": "net/core/skmsg.c=1209=static int sk_psock_verdict_recv(struct sock *sk, struct sk_buff *skb)\n--\nnet/core/skmsg.c-1240-\nnet/core/skmsg.c:1241:static void sk_psock_verdict_data_ready(struct sock *sk)\nnet/core/skmsg.c-1242-{\n--\nnet/core/skmsg.c=1268=void sk_psock_start_verdict(struct sock *sk, struct sk_psock *psock)\n--\nnet/core/skmsg.c-1273-\tpsock-\u003esaved_data_ready = sk-\u003esk_data_ready;\nnet/core/skmsg.c:1274:\tWRITE_ONCE(sk-\u003esk_data_ready, sk_psock_verdict_data_ready);\nnet/core/skmsg.c-1275-\tWRITE_ONCE(sk-\u003esk_write_space, sk_psock_write_space);\n"
}

13/2 2026/08/02 11:17 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 10007
							output: 51
							thoughts: 144
						

Thoughts:
**Analyzing the Packet Socket Data Path**

Okay, so I'm diving into this packet socket code, and the first thing that jumps out is that `sk_psock_start_verdict` isn't declared static. That's my initial point of focus. It looks like `sk_psock_init_strp` and `sk_psock_start_verdict` are the key functions to understand how the socket starts. But, hang on... these appear to be initialization functions, not the actual data path. I need to figure out where the data actually flows.

Alright, the data processing functions are probably `sk_psock_strp_read` and `sk_psock_verdict_recv`. Oh, but they're *static*. That’s a potential roadblock. So, my goal now is to find out if there are any *non*-static functions involved in this data path. I need to trace the data flow.

Let's check `sk_psock_skb_ingress` as a possible path. Hmm, static. Okay, that's not it. I need to widen the search. I need to make sure I am not missing anything that might be involved. I'll need to look at other non-static functions in `net/core/skmsg.c`.



14/2 2026/08/02 11:17 tool grepper
0m Args:
{
  "Expression": "^[a-zA-Z0-9_]+ [a-zA-Z0-9_]+\\(",
  "PathPrefix": "net/core/skmsg.c"
}

Results:
{
  "Output": "net/core/skmsg.c=12=static bool sk_msg_try_coalesce_ok(struct sk_msg *msg, int elem_first_coalesce)\n--\nnet/core/skmsg.c-25-\nnet/core/skmsg.c:26:int sk_msg_alloc(struct sock *sk, struct sk_msg *msg, int len,\nnet/core/skmsg.c-27-\t\t int elem_first_coalesce)\n--\nnet/core/skmsg.c=85=EXPORT_SYMBOL_GPL(sk_msg_alloc);\nnet/core/skmsg.c-86-\nnet/core/skmsg.c:87:int sk_msg_clone(struct sock *sk, struct sk_msg *dst, struct sk_msg *src,\nnet/core/skmsg.c-88-\t\t u32 off, u32 len)\n--\nnet/core/skmsg.c=136=EXPORT_SYMBOL_GPL(sk_msg_clone);\nnet/core/skmsg.c-137-\nnet/core/skmsg.c:138:void sk_msg_return_zero(struct sock *sk, struct sk_msg *msg, int bytes)\nnet/core/skmsg.c-139-{\n--\nnet/core/skmsg.c=160=EXPORT_SYMBOL_GPL(sk_msg_return_zero);\nnet/core/skmsg.c-161-\nnet/core/skmsg.c:162:void sk_msg_return(struct sock *sk, struct sk_msg *msg, int bytes)\nnet/core/skmsg.c-163-{\n--\nnet/core/skmsg.c=194=static int __sk_msg_free(struct sock *sk, struct sk_msg *msg, u32 i,\n--\nnet/core/skmsg.c-211-\nnet/core/skmsg.c:212:int sk_msg_free_nocharge(struct sock *sk, struct sk_msg *msg)\nnet/core/skmsg.c-213-{\n--\nnet/core/skmsg.c=216=EXPORT_SYMBOL_GPL(sk_msg_free_nocharge);\nnet/core/skmsg.c-217-\nnet/core/skmsg.c:218:int sk_msg_free(struct sock *sk, struct sk_msg *msg)\nnet/core/skmsg.c-219-{\n--\nnet/core/skmsg.c=224=static void __sk_msg_free_partial(struct sock *sk, struct sk_msg *msg,\n--\nnet/core/skmsg.c-251-\nnet/core/skmsg.c:252:void sk_msg_free_partial(struct sock *sk, struct sk_msg *msg, u32 bytes)\nnet/core/skmsg.c-253-{\n--\nnet/core/skmsg.c=256=EXPORT_SYMBOL_GPL(sk_msg_free_partial);\nnet/core/skmsg.c-257-\nnet/core/skmsg.c:258:void sk_msg_free_partial_nocharge(struct sock *sk, struct sk_msg *msg,\nnet/core/skmsg.c-259-\t\t\t\t  u32 bytes)\n--\nnet/core/skmsg.c-263-\nnet/core/skmsg.c:264:void sk_msg_trim(struct sock *sk, struct sk_msg *msg, int len)\nnet/core/skmsg.c-265-{\n--\nnet/core/skmsg.c=310=EXPORT_SYMBOL_GPL(sk_msg_trim);\nnet/core/skmsg.c-311-\nnet/core/skmsg.c:312:int sk_msg_zerocopy_from_iter(struct sock *sk, struct iov_iter *from,\nnet/core/skmsg.c-313-\t\t\t      struct sk_msg *msg, u32 bytes)\n--\nnet/core/skmsg.c=367=EXPORT_SYMBOL_GPL(sk_msg_zerocopy_from_iter);\nnet/core/skmsg.c-368-\nnet/core/skmsg.c:369:int sk_msg_memcopy_from_iter(struct sock *sk, struct iov_iter *from,\nnet/core/skmsg.c-370-\t\t\t     struct sk_msg *msg, u32 bytes)\n--\nnet/core/skmsg.c=411=EXPORT_SYMBOL_GPL(sk_msg_memcopy_from_iter);\nnet/core/skmsg.c-412-\nnet/core/skmsg.c:413:int __sk_msg_recvmsg(struct sock *sk, struct sk_psock *psock, struct msghdr *msg,\nnet/core/skmsg.c-414-\t\t     int len, int flags, int *copied_from_self)\n--\nnet/core/skmsg.c-500-/* Receive sk_msg from psock-\u003eingress_msg to @msg. */\nnet/core/skmsg.c:501:int sk_msg_recvmsg(struct sock *sk, struct sk_psock *psock, struct msghdr *msg,\nnet/core/skmsg.c-502-\t\t   int len, int flags)\n--\nnet/core/skmsg.c=506=EXPORT_SYMBOL_GPL(sk_msg_recvmsg);\nnet/core/skmsg.c-507-\nnet/core/skmsg.c:508:bool sk_msg_is_readable(struct sock *sk)\nnet/core/skmsg.c-509-{\n--\nnet/core/skmsg.c=851=static void sk_psock_link_destroy(struct sk_psock *psock)\n--\nnet/core/skmsg.c-860-\nnet/core/skmsg.c:861:void sk_psock_stop(struct sk_psock *psock)\nnet/core/skmsg.c-862-{\n--\nnet/core/skmsg.c=871=static void sk_psock_destroy(struct work_struct *work)\n--\nnet/core/skmsg.c-895-\nnet/core/skmsg.c:896:void sk_psock_drop(struct sock *sk, struct sk_psock *psock)\nnet/core/skmsg.c-897-{\n--\nnet/core/skmsg.c=914=static int sk_psock_map_verd(int verdict, bool redir)\n--\nnet/core/skmsg.c-926-\nnet/core/skmsg.c:927:int sk_psock_msg_verdict(struct sock *sk, struct sk_psock *psock,\nnet/core/skmsg.c-928-\t\t\t struct sk_msg *msg)\n--\nnet/core/skmsg.c=1138=static void sk_psock_strp_data_ready(struct sock *sk)\n--\nnet/core/skmsg.c-1153-\nnet/core/skmsg.c:1154:int sk_psock_init_strp(struct sock *sk, struct sk_psock *psock)\nnet/core/skmsg.c-1155-{\n--\nnet/core/skmsg.c-1174-\nnet/core/skmsg.c:1175:void sk_psock_start_strp(struct sock *sk, struct sk_psock *psock)\nnet/core/skmsg.c-1176-{\n--\nnet/core/skmsg.c-1184-\nnet/core/skmsg.c:1185:void sk_psock_stop_strp(struct sock *sk, struct sk_psock *psock)\nnet/core/skmsg.c-1186-{\n--\nnet/core/skmsg.c=1241=static void sk_psock_verdict_data_ready(struct sock *sk)\n--\nnet/core/skmsg.c-1267-\nnet/core/skmsg.c:1268:void sk_psock_start_verdict(struct sock *sk, struct sk_psock *psock)\nnet/core/skmsg.c-1269-{\n--\nnet/core/skmsg.c-1277-\nnet/core/skmsg.c:1278:void sk_psock_stop_verdict(struct sock *sk, struct sk_psock *psock)\nnet/core/skmsg.c-1279-{\n"
}

15/2 2026/08/02 11:17 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 12656
							output: 27
							thoughts: 329
						

Thoughts:
**Analyzing the psock Flow**

Okay, so I'm trying to trace the execution path for these packet socket functions. I've got a few strong contenders right off the bat: `sk_psock_init_strp`, `sk_psock_start_strp`, and `sk_psock_start_verdict`. Those look like promising starting points. But I need to make sure I haven't missed anything.

The core of the issue seems to revolve around `sk_psock_skb_ingress_self` and `sk_psock_skb_ingress`. These are the functions I need to understand. They are called by `sk_psock_handle_skb` and `sk_psock_verdict_apply`. Now, `sk_psock_verdict_apply` is triggered from `sk_psock_strp_read` and `sk_psock_verdict_recv`.  `sk_psock_strp_read` is registered as `.rcv_msg` within `sk_psock_init_strp`, which makes perfect sense. Furthermore, `sk_psock_verdict_recv` is called by `sk_psock_verdict_data_ready`, which is registered as `.sk_data_ready` in `sk_psock_start_verdict`.

Alright, I think I'm getting a clearer picture.  `sk_psock_init_strp` and `sk_psock_start_verdict` seem to be the primary entry points for setting up the entire processing flow. They're where the chain likely begins.

Now, what about `sk_psock_msg_verdict`? I need to check if this is relevant to the `sk_buff` path. Ah, it seems like it's specific to `sk_msg` so it probably won't be as important for what I'm looking at.

Time to switch gears and check the configuration options. I'll need to confirm what's enabled. Also, the code for the related `sk_msg` operations should be in `net/core/skmsg.c`. Let's take a look at the `Makefile` in `net/core/` to see how those are built.



16/2 2026/08/02 11:18 tool grepper
0m Args:
{
  "Expression": "skmsg",
  "PathPrefix": "net/core/Makefile"
}

Results:
{
  "Output": "net/core/Makefile=43=obj-$(CONFIG_FAILOVER) += failover.o\nnet/core/Makefile:44:obj-$(CONFIG_NET_SOCK_MSG) += skmsg.o\nnet/core/Makefile-45-obj-$(CONFIG_BPF_SYSCALL) += sock_map.o\n"
}

17/2 2026/08/02 11:18 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 13595
							output: 37
							thoughts: 87
						

Thoughts:
Okay, here's my breakdown of what I'm looking at:

**Investigating Network Socket Messaging Dependencies**

Right, so I'm seeing a dependency on `CONFIG_NET_SOCK_MSG`. That much is straightforward. Now, it looks like `CONFIG_BPF_STREAM_PARSER` *might* also be a requirement, because that `sk_psock_strp_read` function is conditionally compiled, wrapped in an `#if IS_ENABLED(CONFIG_BPF_STREAM_PARSER)` block. I need to confirm whether that's actually the case. Best bet is to jump into `net/core/skmsg.c` and take a closer look at the surrounding code to see how `CONFIG_BPF_STREAM_PARSER` is used and if it's truly essential in this scenario.



18/2 2026/08/02 11:18 tool grepper
0m Args:
{
  "Expression": "CONFIG_BPF_STREAM_PARSER",
  "PathPrefix": "net/core/skmsg.c"
}

Results:
{
  "Output": "net/core/skmsg.c=545=static int sk_psock_skb_ingress_enqueue(struct sk_buff *skb,\n--\nnet/core/skmsg.c-573-\nnet/core/skmsg.c:574:#if IS_ENABLED(CONFIG_BPF_STREAM_PARSER)\nnet/core/skmsg.c-575-\tpsock-\u003eingress_bytes += len;\n--\nnet/core/skmsg.c=1068=static void sk_psock_write_space(struct sock *sk)\n--\nnet/core/skmsg.c-1084-\nnet/core/skmsg.c:1085:#if IS_ENABLED(CONFIG_BPF_STREAM_PARSER)\nnet/core/skmsg.c-1086-static void sk_psock_strp_read(struct strparser *strp, struct sk_buff *skb)\n--\nnet/core/skmsg.c=1204=static void sk_psock_done_strp(struct sk_psock *psock)\n--\nnet/core/skmsg.c-1206-}\nnet/core/skmsg.c:1207:#endif /* CONFIG_BPF_STREAM_PARSER */\nnet/core/skmsg.c-1208-\n"
}

19/2 2026/08/02 11:18 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 14232
							output: 30
							thoughts: 82
						

Thoughts:
Okay, here's my take on those thoughts, framed as my own mental processing:

**Kernel Configuration Dependencies for BPF Stream Parser**

Right, so I'm digging into this BPF stream parser stuff. It's clear that `CONFIG_BPF_STREAM_PARSER` is a must-have for the strparser path, no question about that. Now, a question pops into my head: what's the deal with `CONFIG_BPF_SYSCALL`? It *usually* goes hand-in-hand with BPF functionality in general, right? I need to clarify if it's strictly *required* here or just generally recommended. Let's see...I should check the kernel's Kconfig files to see how `NET_SOCK_MSG` and `BPF_STREAM_PARSER` are tied together. Either `net/core/Kconfig` or just the main `net/Kconfig` file should have the answers I need. That's the logical place to start digging for the dependencies.



20/2 2026/08/02 11:18 tool grepper
0m Args:
{
  "Expression": "config NET_SOCK_MSG",
  "PathPrefix": "net/Kconfig"
}

Results:
{
  "Output": "net/Kconfig=475=config NET_SELFTESTS\n--\nnet/Kconfig-478-\nnet/Kconfig:479:config NET_SOCK_MSG\nnet/Kconfig-480-\tbool\n"
}

21/2 2026/08/02 11:18 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 14632
							output: 26
							thoughts: 21
						

Thoughts:
Here's my summary, as though I'm thinking through this myself:

**Hidden Bool Investigation: NET\_SOCK\_MSG**

Okay, so there's this `NET_SOCK_MSG` variable, and it's a hidden boolean. Meaning it's being used internally, probably not directly exposed for configuration or user input. My gut says this wasn't declared on a whim. The fact that it's hidden implies it's being set or unset based on *some* condition, *some* other part of the system is deciding when this flag is active. I need to figure out what that triggering mechanism is. What are the logical pathways that lead to this bool being modified? It's the key to understanding how this net socket message handling actually works, and that's where I need to focus my efforts.



22/2 2026/08/02 11:18 tool grepper
0m Args:
{
  "Expression": "select NET_SOCK_MSG",
  "PathPrefix": ""
}

Results:
{
  "Output": "kernel/bpf/Kconfig=27=config BPF_SYSCALL\n--\nkernel/bpf/Kconfig-33-\tselect BINARY_PRINTF\nkernel/bpf/Kconfig:34:\tselect NET_SOCK_MSG if NET\nkernel/bpf/Kconfig-35-\tselect NET_XGRESS if NET\n--\nnet/Kconfig=361=config BPF_STREAM_PARSER\n--\nnet/Kconfig-366-\tselect STREAM_PARSER\nnet/Kconfig:367:\tselect NET_SOCK_MSG\nnet/Kconfig-368-\thelp\n--\nnet/ipv4/Kconfig=382=config INET_ESPINTCP\n--\nnet/ipv4/Kconfig-385-\tselect STREAM_PARSER\nnet/ipv4/Kconfig:386:\tselect NET_SOCK_MSG\nnet/ipv4/Kconfig-387-\tselect XFRM_ESPINTCP\n--\nnet/ipv6/Kconfig=90=config INET6_ESPINTCP\n--\nnet/ipv6/Kconfig-93-\tselect STREAM_PARSER\nnet/ipv6/Kconfig:94:\tselect NET_SOCK_MSG\nnet/ipv6/Kconfig-95-\tselect XFRM_ESPINTCP\n--\nnet/tls/Kconfig=5=config TLS\n--\nnet/tls/Kconfig-10-\tselect CRYPTO_GCM\nnet/tls/Kconfig:11:\tselect NET_SOCK_MSG\nnet/tls/Kconfig-12-\tdefault n\n"
}

23/2 2026/08/02 11:18 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 15246
							output: 32
							thoughts: 49
						

Thoughts:
Okay, here's my interpretation of these thoughts, summarized in the first person, assuming the audience is another expert:

**Investigating the NET_SOCK_MSG Pathway**

Alright, so the initial thought process seems straightforward: I see that `BPF_SYSCALL` is triggering `NET_SOCK_MSG`, and also, strangely, that `BPF_STREAM_PARSER` is selecting `NET_SOCK_MSG` too. That’s worth digging into. Given the overlap, my immediate focus is on understanding the interaction and potential implications of this shared behavior. Specifically, I need to check `BPF_STREAM_PARSER` because it is less conventional and likely the source of the overlap. I need to understand why both seem to be pointing toward the same net socket message handling. There could be some interesting architecture choices here.



24/2 2026/08/02 11:18 tool grepper
0m Args:
{
  "Expression": "config BPF_STREAM_PARSER",
  "PathPrefix": "net/Kconfig"
}

Results:
{
  "Output": "net/Kconfig=354=config BQL\n--\nnet/Kconfig-360-\nnet/Kconfig:361:config BPF_STREAM_PARSER\nnet/Kconfig-362-\tbool \"enable BPF STREAM_PARSER\"\n"
}

25/2 2026/08/02 11:18 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 15579
							output: 34
							thoughts: 50
						

Thoughts:
Okay, here's my take on those thoughts, framed as my own mental processing:

**Enabling BPF Stream Parsing and Syscall Integration**

Alright, so it's looking like `BPF_STREAM_PARSER` is exposed as a boolean setting. That's a good starting point. My initial thought is that we definitely need to enable both `BPF_STREAM_PARSER` and `BPF_SYSCALL` functionality. The combined power here is significant for what I'm aiming to achieve.

Now, before I proceed further, I want to take a closer look at the `BPF_SYSCALL` mechanism. I need to refresh my understanding of its current state and any recent changes. I need to assess what the implications are of this coupling, and what impact it will have on performance.



26/2 2026/08/02 11:18 tool grepper
0m Args:
{
  "Expression": "config BPF_SYSCALL",
  "PathPrefix": "kernel/bpf/Kconfig"
}

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/08/02 11:18 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 15920
							output: 34
							thoughts: 354
						

Thoughts:
**My Assessment of the BPF Stream Parser Modification**

Okay, so I've been looking at this BPF stream parser patch, and it looks like it addresses a `sk_forward_alloc` deficit in the context of direct strparser SK_PASS clones. From the code, I see that the primary focus, config-wise, involves enabling `BPF_SYSCALL` and `BPF_STREAM_PARSER`.

Functionally, I'm pretty confident in the fix. Now, let's nail down a good fuzzing strategy.

My initial thoughts on worthfuzzing are positive. We should be able to get some good testing out of this.

Regarding focus symbols, I initially had a list: `sk_psock_init_strp`, `sk_psock_start_strp`, `sk_psock_start_verdict`, and potentially `sk_psock_skb_ingress` (though that's static, so it's likely not going to be feasible). Wait, `sk_psock_verdict_apply` is also static. So, I need to adjust this list and keep things practical.

We should be able to use `sk_psock_init_strp`, `sk_psock_start_strp`, and `sk_psock_start_verdict`.

Thinking about the connection of `BPF_SK_SKB_STREAM_PARSER` and `sk_psock_init_strp` (that looks promising since it's an attach call). Also, `sk_psock_start_verdict` is called by BPF_SK_SKB_STREAM_VERDICT.

These are good entry points to the code.

Checking again, `sk_psock_init_strp` and `sk_psock_start_verdict` are indeed the best entry points to the modified code path. These seem like the right symbols to prioritize.

Also, `sk_msg_recvmsg` is likely relevant since it reads those queued messages.



28/2 2026/08/02 11:18 tool grepper
0m Args:
{
  "Expression": "sk_msg_recvmsg",
  "PathPrefix": "net/core/skmsg.c"
}

Results:
{
  "Output": "net/core/skmsg.c=411=EXPORT_SYMBOL_GPL(sk_msg_memcopy_from_iter);\nnet/core/skmsg.c-412-\nnet/core/skmsg.c:413:int __sk_msg_recvmsg(struct sock *sk, struct sk_psock *psock, struct msghdr *msg,\nnet/core/skmsg.c-414-\t\t     int len, int flags, int *copied_from_self)\n--\nnet/core/skmsg.c-500-/* Receive sk_msg from psock-\u003eingress_msg to @msg. */\nnet/core/skmsg.c:501:int sk_msg_recvmsg(struct sock *sk, struct sk_psock *psock, struct msghdr *msg,\nnet/core/skmsg.c-502-\t\t   int len, int flags)\nnet/core/skmsg.c-503-{\nnet/core/skmsg.c:504:\treturn __sk_msg_recvmsg(sk, psock, msg, len, flags, NULL);\nnet/core/skmsg.c-505-}\nnet/core/skmsg.c:506:EXPORT_SYMBOL_GPL(sk_msg_recvmsg);\nnet/core/skmsg.c-507-\n"
}

29/2 2026/08/02 11:18 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 17085
							output: 37
							thoughts: 367
						

Thoughts:
**Analyzing Potential Entry Points for Network Socket Functionality**

Okay, so `sk_msg_recvmsg` is definitely exported, that's our starting point. I need to figure out what else in `net/core/skmsg.c` is relevant, specifically non-static functions, as those are the ones we can use. I quickly rule out `sk_psock_msg_verdict` because that seems to be related to the *send* path (`sk_msg`), not the receive path (`sk_buff`) which is what I'm more interested in here.

The patch I'm looking at focuses on `sk_psock_skb_ingress_self`, but that's called indirectly. Let me trace the calls: it's called from `sk_psock_skb_ingress` and `sk_psock_verdict_apply`. `sk_psock_skb_ingress` is further called by `sk_psock_handle_skb`, which itself is invoked by `sk_psock_backlog` which is, of course, a workqueue. Then `sk_psock_verdict_apply` gets called from `sk_psock_strp_read` and `sk_psock_verdict_recv`.

So, that tells me the main entry points are essentially: `sk_psock_strp_read` (which is static, and registered through `sk_psock_init_strp`), `sk_psock_verdict_recv` (also static, registered through `sk_psock_start_verdict`), and finally, the workqueue `sk_psock_backlog`.

Given the constraint on non-static functions, it seems that `sk_psock_init_strp` and `sk_psock_start_verdict` are the key entry points and the best options for our use-case, as they register the static functions. Adding `sk_msg_recvmsg` makes sense too, since it actually consumes the messages. Let me go back and give those two functions a closer look.



30/2 2026/08/02 11:18 tool grepper
0m Args:
{
  "Expression": "sk_psock_init_strp",
  "PathPrefix": "net/core/skmsg.c"
}

Results:
{
  "Output": "net/core/skmsg.c=1138=static void sk_psock_strp_data_ready(struct sock *sk)\n--\nnet/core/skmsg.c-1153-\nnet/core/skmsg.c:1154:int sk_psock_init_strp(struct sock *sk, struct sk_psock *psock)\nnet/core/skmsg.c-1155-{\n"
}

31/2 2026/08/02 11:18 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 18059
							output: 38
							thoughts: 19
						

Thoughts:
Okay, let's dive into this code.

**Investigating the Call Sites of `sk_psock_init_strp`**

Right, so I need to understand how this `sk_psock_init_strp` function is being used. First things first, I need to pinpoint every single location where it's being called within this project. Knowing the call graph will give me the context and the critical pieces of information that I'll need to know. That's the logical starting point. Understanding *why* it is being called will come after that. Then I can start to form an idea of why this function exists and what role it plays within the bigger picture. Time to get searching!



32/2 2026/08/02 11:18 tool grepper
0m Args:
{
  "Expression": "sk_psock_init_strp",
  "PathPrefix": "net/core/sock_map.c"
}

Results:
{
  "Output": "net/core/sock_map.c=217=static int sock_map_link(struct bpf_map *map, struct sock *sk)\n--\nnet/core/sock_map.c-306-\t\tif (sk_is_tcp(sk))\nnet/core/sock_map.c:307:\t\t\tret = sk_psock_init_strp(sk, psock);\nnet/core/sock_map.c-308-\t\telse\n"
}

33/2 2026/08/02 11:18 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 18392
							output: 34
							thoughts: 82
						

Thoughts:
Okay, let's break this down.

**Investigating the Socket Map Linking Process**

Right, so I'm tracing this execution path, and it looks like `sock_map_link` is the critical function here, being called by `sock_map_update_elem`. Now, I need to understand what's happening within `sock_map_link` because I'm seeing this call to `sk_psock_init_strp` conditional on there being a parser program associated with the map. That suggests a potentially important interaction with program loading or some sort of pre-processing. The fact that `sk_psock_init_strp` is called, likely means we need to evaluate the implications of the parser program at map link time. Let's head straight into `net/core/sock_map.c` and take a closer look at the `sock_map_link` function. I need to understand the logic flow and precisely what conditions trigger that `sk_psock_init_strp` call. It's time to dive into the code.



34/2 2026/08/02 11:18 tool grepper
0m Args:
{
  "Expression": "sock_map_link",
  "PathPrefix": "net/core/sock_map.c"
}

Results:
{
  "Output": "net/core/sock_map.c=197=static struct sk_psock *sock_map_psock_get_checked(struct sock *sk)\n--\nnet/core/sock_map.c-216-\nnet/core/sock_map.c:217:static int sock_map_link(struct bpf_map *map, struct sock *sk)\nnet/core/sock_map.c-218-{\n--\nnet/core/sock_map.c=470=static int sock_map_update_common(struct bpf_map *map, u32 idx,\n--\nnet/core/sock_map.c-488-\nnet/core/sock_map.c:489:\tret = sock_map_link(map, sk);\nnet/core/sock_map.c-490-\tif (ret \u003c 0)\n--\nnet/core/sock_map.c=993=static int sock_hash_update_common(struct bpf_map *map, void *key,\n--\nnet/core/sock_map.c-1011-\nnet/core/sock_map.c:1012:\tret = sock_map_link(map, sk);\nnet/core/sock_map.c-1013-\tif (ret \u003c 0)\n--\nnet/core/sock_map.c=1737=struct sockmap_link {\n--\nnet/core/sock_map.c-1741-\nnet/core/sock_map.c:1742:static void sock_map_link_release(struct bpf_link *link)\nnet/core/sock_map.c-1743-{\n--\nnet/core/sock_map.c-1758-\nnet/core/sock_map.c:1759:static int sock_map_link_detach(struct bpf_link *link)\nnet/core/sock_map.c-1760-{\nnet/core/sock_map.c:1761:\tsock_map_link_release(link);\nnet/core/sock_map.c-1762-\treturn 0;\n--\nnet/core/sock_map.c-1764-\nnet/core/sock_map.c:1765:static void sock_map_link_dealloc(struct bpf_link *link)\nnet/core/sock_map.c-1766-{\n--\nnet/core/sock_map.c-1773- */\nnet/core/sock_map.c:1774:static int sock_map_link_update_prog(struct bpf_link *link,\nnet/core/sock_map.c-1775-\t\t\t\t     struct bpf_prog *prog,\n--\nnet/core/sock_map.c-1833-\nnet/core/sock_map.c:1834:static u32 sock_map_link_get_map_id(const struct sockmap_link *sockmap_link)\nnet/core/sock_map.c-1835-{\n--\nnet/core/sock_map.c-1844-\nnet/core/sock_map.c:1845:static int sock_map_link_fill_info(const struct bpf_link *link,\nnet/core/sock_map.c-1846-\t\t\t\t   struct bpf_link_info *info)\n--\nnet/core/sock_map.c-1848-\tconst struct sockmap_link *sockmap_link = container_of(link, struct sockmap_link, link);\nnet/core/sock_map.c:1849:\tu32 map_id = sock_map_link_get_map_id(sockmap_link);\nnet/core/sock_map.c-1850-\n--\nnet/core/sock_map.c-1855-\nnet/core/sock_map.c:1856:static void sock_map_link_show_fdinfo(const struct bpf_link *link,\nnet/core/sock_map.c-1857-\t\t\t\t      struct seq_file *seq)\n--\nnet/core/sock_map.c-1859-\tconst struct sockmap_link *sockmap_link = container_of(link, struct sockmap_link, link);\nnet/core/sock_map.c:1860:\tu32 map_id = sock_map_link_get_map_id(sockmap_link);\nnet/core/sock_map.c-1861-\n--\nnet/core/sock_map.c-1865-\nnet/core/sock_map.c:1866:static const struct bpf_link_ops sock_map_link_ops = {\nnet/core/sock_map.c:1867:\t.release = sock_map_link_release,\nnet/core/sock_map.c:1868:\t.dealloc = sock_map_link_dealloc,\nnet/core/sock_map.c:1869:\t.detach = sock_map_link_detach,\nnet/core/sock_map.c:1870:\t.update_prog = sock_map_link_update_prog,\nnet/core/sock_map.c:1871:\t.fill_link_info = sock_map_link_fill_info,\nnet/core/sock_map.c:1872:\t.show_fdinfo = sock_map_link_show_fdinfo,\nnet/core/sock_map.c-1873-};\nnet/core/sock_map.c-1874-\nnet/core/sock_map.c:1875:int sock_map_link_create(const union bpf_attr *attr, struct bpf_prog *prog)\nnet/core/sock_map.c-1876-{\n--\nnet/core/sock_map.c-1900-\tattach_type = attr-\u003elink_create.attach_type;\nnet/core/sock_map.c:1901:\tbpf_link_init(\u0026sockmap_link-\u003elink, BPF_LINK_TYPE_SOCKMAP, \u0026sock_map_link_ops, prog,\nnet/core/sock_map.c-1902-\t\t      attach_type);\n"
}

35/2 2026/08/02 11:18 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 20314
							output: 51
							thoughts: 171
						

Thoughts:
**Focusing Fuzzing Efforts**

Okay, so I'm zeroing in on the best entry points for fuzzing this BPF code. It looks like `sock_map_update_elem` and `sock_hash_update_elem` are the top-level calls. However, they are fundamentally map operations. The real meat of the fuzzing should concentrate on the interaction between the BPF map updates and the socket operations themselves.

Specifically, I should be looking closely at `sk_psock_init_strp` and `sk_psock_start_verdict`. Those look like promising targets. Also, `sk_msg_recvmsg` is definitely worth some attention.

Just to be sure, let me double-check `sk_psock_skb_ingress`. Nope, that's static. Same with `sk_psock_handle_skb` and `sk_psock_backlog`. Those won't work as direct entry points.

Alright, I need to expand my search. Let's head over to `net/core/skmsg.c`. That file should contain some useful non-static functions related to the SKMSG implementation.



36/2 2026/08/02 11:18 tool grepper
0m Args:
{
  "Expression": "^[a-zA-Z0-9_]+ [a-zA-Z0-9_]+\\(",
  "PathPrefix": "net/core/skmsg.c"
}

Results:
{
  "Output": "net/core/skmsg.c=12=static bool sk_msg_try_coalesce_ok(struct sk_msg *msg, int elem_first_coalesce)\n--\nnet/core/skmsg.c-25-\nnet/core/skmsg.c:26:int sk_msg_alloc(struct sock *sk, struct sk_msg *msg, int len,\nnet/core/skmsg.c-27-\t\t int elem_first_coalesce)\n--\nnet/core/skmsg.c=85=EXPORT_SYMBOL_GPL(sk_msg_alloc);\nnet/core/skmsg.c-86-\nnet/core/skmsg.c:87:int sk_msg_clone(struct sock *sk, struct sk_msg *dst, struct sk_msg *src,\nnet/core/skmsg.c-88-\t\t u32 off, u32 len)\n--\nnet/core/skmsg.c=136=EXPORT_SYMBOL_GPL(sk_msg_clone);\nnet/core/skmsg.c-137-\nnet/core/skmsg.c:138:void sk_msg_return_zero(struct sock *sk, struct sk_msg *msg, int bytes)\nnet/core/skmsg.c-139-{\n--\nnet/core/skmsg.c=160=EXPORT_SYMBOL_GPL(sk_msg_return_zero);\nnet/core/skmsg.c-161-\nnet/core/skmsg.c:162:void sk_msg_return(struct sock *sk, struct sk_msg *msg, int bytes)\nnet/core/skmsg.c-163-{\n--\nnet/core/skmsg.c=194=static int __sk_msg_free(struct sock *sk, struct sk_msg *msg, u32 i,\n--\nnet/core/skmsg.c-211-\nnet/core/skmsg.c:212:int sk_msg_free_nocharge(struct sock *sk, struct sk_msg *msg)\nnet/core/skmsg.c-213-{\n--\nnet/core/skmsg.c=216=EXPORT_SYMBOL_GPL(sk_msg_free_nocharge);\nnet/core/skmsg.c-217-\nnet/core/skmsg.c:218:int sk_msg_free(struct sock *sk, struct sk_msg *msg)\nnet/core/skmsg.c-219-{\n--\nnet/core/skmsg.c=224=static void __sk_msg_free_partial(struct sock *sk, struct sk_msg *msg,\n--\nnet/core/skmsg.c-251-\nnet/core/skmsg.c:252:void sk_msg_free_partial(struct sock *sk, struct sk_msg *msg, u32 bytes)\nnet/core/skmsg.c-253-{\n--\nnet/core/skmsg.c=256=EXPORT_SYMBOL_GPL(sk_msg_free_partial);\nnet/core/skmsg.c-257-\nnet/core/skmsg.c:258:void sk_msg_free_partial_nocharge(struct sock *sk, struct sk_msg *msg,\nnet/core/skmsg.c-259-\t\t\t\t  u32 bytes)\n--\nnet/core/skmsg.c-263-\nnet/core/skmsg.c:264:void sk_msg_trim(struct sock *sk, struct sk_msg *msg, int len)\nnet/core/skmsg.c-265-{\n--\nnet/core/skmsg.c=310=EXPORT_SYMBOL_GPL(sk_msg_trim);\nnet/core/skmsg.c-311-\nnet/core/skmsg.c:312:int sk_msg_zerocopy_from_iter(struct sock *sk, struct iov_iter *from,\nnet/core/skmsg.c-313-\t\t\t      struct sk_msg *msg, u32 bytes)\n--\nnet/core/skmsg.c=367=EXPORT_SYMBOL_GPL(sk_msg_zerocopy_from_iter);\nnet/core/skmsg.c-368-\nnet/core/skmsg.c:369:int sk_msg_memcopy_from_iter(struct sock *sk, struct iov_iter *from,\nnet/core/skmsg.c-370-\t\t\t     struct sk_msg *msg, u32 bytes)\n--\nnet/core/skmsg.c=411=EXPORT_SYMBOL_GPL(sk_msg_memcopy_from_iter);\nnet/core/skmsg.c-412-\nnet/core/skmsg.c:413:int __sk_msg_recvmsg(struct sock *sk, struct sk_psock *psock, struct msghdr *msg,\nnet/core/skmsg.c-414-\t\t     int len, int flags, int *copied_from_self)\n--\nnet/core/skmsg.c-500-/* Receive sk_msg from psock-\u003eingress_msg to @msg. */\nnet/core/skmsg.c:501:int sk_msg_recvmsg(struct sock *sk, struct sk_psock *psock, struct msghdr *msg,\nnet/core/skmsg.c-502-\t\t   int len, int flags)\n--\nnet/core/skmsg.c=506=EXPORT_SYMBOL_GPL(sk_msg_recvmsg);\nnet/core/skmsg.c-507-\nnet/core/skmsg.c:508:bool sk_msg_is_readable(struct sock *sk)\nnet/core/skmsg.c-509-{\n--\nnet/core/skmsg.c=851=static void sk_psock_link_destroy(struct sk_psock *psock)\n--\nnet/core/skmsg.c-860-\nnet/core/skmsg.c:861:void sk_psock_stop(struct sk_psock *psock)\nnet/core/skmsg.c-862-{\n--\nnet/core/skmsg.c=871=static void sk_psock_destroy(struct work_struct *work)\n--\nnet/core/skmsg.c-895-\nnet/core/skmsg.c:896:void sk_psock_drop(struct sock *sk, struct sk_psock *psock)\nnet/core/skmsg.c-897-{\n--\nnet/core/skmsg.c=914=static int sk_psock_map_verd(int verdict, bool redir)\n--\nnet/core/skmsg.c-926-\nnet/core/skmsg.c:927:int sk_psock_msg_verdict(struct sock *sk, struct sk_psock *psock,\nnet/core/skmsg.c-928-\t\t\t struct sk_msg *msg)\n--\nnet/core/skmsg.c=1138=static void sk_psock_strp_data_ready(struct sock *sk)\n--\nnet/core/skmsg.c-1153-\nnet/core/skmsg.c:1154:int sk_psock_init_strp(struct sock *sk, struct sk_psock *psock)\nnet/core/skmsg.c-1155-{\n--\nnet/core/skmsg.c-1174-\nnet/core/skmsg.c:1175:void sk_psock_start_strp(struct sock *sk, struct sk_psock *psock)\nnet/core/skmsg.c-1176-{\n--\nnet/core/skmsg.c-1184-\nnet/core/skmsg.c:1185:void sk_psock_stop_strp(struct sock *sk, struct sk_psock *psock)\nnet/core/skmsg.c-1186-{\n--\nnet/core/skmsg.c=1241=static void sk_psock_verdict_data_ready(struct sock *sk)\n--\nnet/core/skmsg.c-1267-\nnet/core/skmsg.c:1268:void sk_psock_start_verdict(struct sock *sk, struct sk_psock *psock)\nnet/core/skmsg.c-1269-{\n--\nnet/core/skmsg.c-1277-\nnet/core/skmsg.c:1278:void sk_psock_stop_verdict(struct sock *sk, struct sk_psock *psock)\nnet/core/skmsg.c-1279-{\n"
}

37/2 2026/08/02 11:18 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 22960
							output: 38
							thoughts: 76
						

Thoughts:
Okay, here's my take on those functions.

**Initial Assessment of Socket Functions**

Alright, let's see. My initial instinct is that `sk_psock_init_strp`, `sk_psock_start_strp`, `sk_psock_start_verdict`, and `sk_msg_recvmsg` look promising. These seem like they're in the right ballpark for what I'm trying to achieve. They align with the general flow I was expecting.

Now, a slight pause for thought. Wasn't it `sk_psock_start_strp` that was also called from `sock_map_link`? I should probably double check that. It would be good to understand the full call graph to avoid any unexpected interactions. Let's dig a little deeper.



38/2 2026/08/02 11:18 tool grepper
0m Args:
{
  "Expression": "sk_psock_start_strp",
  "PathPrefix": "net/core/sock_map.c"
}

Results:
{
  "Output": "net/core/sock_map.c=217=static int sock_map_link(struct bpf_map *map, struct sock *sk)\n--\nnet/core/sock_map.c-314-\t\t}\nnet/core/sock_map.c:315:\t\tsk_psock_start_strp(sk, psock);\nnet/core/sock_map.c-316-\t} else if (!stream_parser \u0026\u0026 stream_verdict \u0026\u0026 !psock-\u003esaved_data_ready) {\n"
}

39/2 2026/08/02 11:18 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 23387
							output: 179
							thoughts: 390
						

Thoughts:
**My Analysis of the Socket Processing Path**

Okay, so I've traced the execution flow related to this patch. I see that `sk_psock_start_strp` is indeed called from `sock_map_link`, as I suspected. That means the key setup functions I need to focus on are `sk_psock_init_strp`, `sk_psock_start_strp`, and `sk_psock_start_verdict`. The actual data path is triggered by the socket's receive mechanism, which then goes through either `strparser` or `sk_data_ready`. Since we can't zero in directly on the static data path functions, I think the most effective approach is to focus on those setup functions I mentioned, plus `sk_msg_recvmsg`. Adding in `sock_map_update_elem` and `sock_hash_update_elem` is tempting, but they're map operations and might introduce unnecessary noise. I'll stick to the core setup functions and `sk_msg_recvmsg` to keep it concise and focused.

Now, let me just double-check the relevant configuration options. Right, we have `BPF_SYSCALL`, `BPF_STREAM_PARSER`, and `NET_SOCK_MSG`, which is selected by both of the first two. So, `BPF_SYSCALL` and `BPF_STREAM_PARSER` are sufficient to trigger the relevant code paths.

The reasoning here is that the patch alters `sk_psock_skb_ingress_self` and `sk_psock_skb_ingress` to handle situations where `sk_forward_alloc` is insufficient during receive ownership assignment when a direct `strparser` SK_PASS clone is involved. This is a functional change within the sockmap/skmsg BPF infrastructure. So the code being changed is reached when a BPF sockmap with a stream parser and verdict program are attached.



40/2 2026/08/02 11:18 tool set-results
0m Args:
{
  "EnableConfigs": [
    "BPF_SYSCALL",
    "BPF_STREAM_PARSER"
  ],
  "FocusSymbols": [
    "sk_psock_init_strp",
    "sk_psock_start_strp",
    "sk_psock_start_verdict",
    "sk_msg_recvmsg"
  ],
  "Reasoning": "The patch modifies `sk_psock_skb_ingress_self` and `sk_psock_skb_ingress` to handle `sk_forward_alloc` deficit when assigning receive ownership to a direct strparser SK_PASS clone. This is a functional change in the sockmap/skmsg BPF infrastructure. The code is reachable via BPF sockmap with a stream parser and verdict program attached.",
  "WorthFuzzing": true
}

Results:
{
  "EnableConfigs": [
    "BPF_SYSCALL",
    "BPF_STREAM_PARSER"
  ],
  "FocusSymbols": [
    "sk_psock_init_strp",
    "sk_psock_start_strp",
    "sk_psock_start_verdict",
    "sk_msg_recvmsg"
  ],
  "Reasoning": "The patch modifies `sk_psock_skb_ingress_self` and `sk_psock_skb_ingress` to handle `sk_forward_alloc` deficit when assigning receive ownership to a direct strparser SK_PASS clone. This is a functional change in the sockmap/skmsg BPF infrastructure. The code is reachable via BPF sockmap with a stream parser and verdict program attached.",
  "WorthFuzzing": true
}

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