| Seq | Timestamp | Type | Name | Duration |
|---|---|---|---|---|
| 0/0 | 2026/07/16 04:14 | flow | patch-triage |
0mArgs:null Results: {
"EnableConfigs": [
"BPF_SYSCALL",
"NET_SOCK_MSG"
],
"FocusSymbols": [
"tcp_bpf_recvmsg_parser",
"tcp_bpf_recvmsg",
"tcp_msg_wait_data"
],
"Reasoning": "The patch modifies timeout handling in BPF sockmap's recvmsg implementations (tcp_bpf_recvmsg and tcp_bpf_recvmsg_parser). It correctly updates the remaining timeout value in tcp_msg_wait_data and retries reading if the timeout hasn't expired. This is functional core networking logic that should be fuzzed.",
"WorthFuzzing": true
} |
| 1/1 | 2026/07/16 04:14 | action | read-patch-diff |
0mArgs:null Results: {
"PatchDiff": "commit 03af4355be42f8ec46bbb53487603c80b55819b9\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate: Thu Jul 16 04:14:17 2026 +0000\n\n syz-cluster: applied patch under review\n\ndiff --git a/net/ipv4/tcp_bpf.c b/net/ipv4/tcp_bpf.c\nindex cc0bd73f36b6d6..aa5c5d741599a3 100644\n--- a/net/ipv4/tcp_bpf.c\n+++ b/net/ipv4/tcp_bpf.c\n@@ -179,7 +179,7 @@ EXPORT_SYMBOL_GPL(tcp_bpf_sendmsg_redir);\n \n #ifdef CONFIG_BPF_SYSCALL\n static int tcp_msg_wait_data(struct sock *sk, struct sk_psock *psock,\n-\t\t\t long timeo)\n+\t\t\t long *timeo)\n {\n \tDEFINE_WAIT_FUNC(wait, woken_wake_function);\n \tint ret = 0;\n@@ -187,12 +187,12 @@ static int tcp_msg_wait_data(struct sock *sk, struct sk_psock *psock,\n \tif (sk-\u003esk_shutdown \u0026 RCV_SHUTDOWN)\n \t\treturn 1;\n \n-\tif (!timeo)\n+\tif (!*timeo)\n \t\treturn ret;\n \n \tadd_wait_queue(sk_sleep(sk), \u0026wait);\n \tsk_set_bit(SOCKWQ_ASYNC_WAITDATA, sk);\n-\tret = sk_wait_event(sk, \u0026timeo,\n+\tret = sk_wait_event(sk, timeo,\n \t\t\t !list_empty(\u0026psock-\u003eingress_msg) ||\n \t\t\t !skb_queue_empty_lockless(\u0026sk-\u003esk_receive_queue), \u0026wait);\n \tsk_clear_bit(SOCKWQ_ASYNC_WAITDATA, sk);\n@@ -229,6 +229,7 @@ static int tcp_bpf_recvmsg_parser(struct sock *sk,\n \tint copied_from_self = 0;\n \tint copied = 0;\n \tu32 seq;\n+\tlong timeo;\n \n \tif (unlikely(flags \u0026 MSG_ERRQUEUE))\n \t\treturn inet_recv_error(sk, msg, len);\n@@ -262,6 +263,8 @@ static int tcp_bpf_recvmsg_parser(struct sock *sk,\n \t\t}\n \t}\n \n+\ttimeo = sock_rcvtimeo(sk, flags \u0026 MSG_DONTWAIT);\n+\n msg_bytes_ready:\n \tcopied = __sk_msg_recvmsg(sk, psock, msg, len, flags, \u0026copied_from_self);\n \t/* The typical case for EFAULT is the socket was gracefully\n@@ -280,7 +283,6 @@ static int tcp_bpf_recvmsg_parser(struct sock *sk,\n \t}\n \tseq += copied_from_self;\n \tif (!copied) {\n-\t\tlong timeo;\n \t\tint data;\n \n \t\tif (sock_flag(sk, SOCK_DONE))\n@@ -299,7 +301,6 @@ static int tcp_bpf_recvmsg_parser(struct sock *sk,\n \t\t\tgoto out;\n \t\t}\n \n-\t\ttimeo = sock_rcvtimeo(sk, flags \u0026 MSG_DONTWAIT);\n \t\tif (!timeo) {\n \t\t\tcopied = -EAGAIN;\n \t\t\tgoto out;\n@@ -310,13 +311,15 @@ static int tcp_bpf_recvmsg_parser(struct sock *sk,\n \t\t\tgoto out;\n \t\t}\n \n-\t\tdata = tcp_msg_wait_data(sk, psock, timeo);\n+\t\tdata = tcp_msg_wait_data(sk, psock, \u0026timeo);\n \t\tif (data \u003c 0) {\n \t\t\tcopied = data;\n \t\t\tgoto unlock;\n \t\t}\n \t\tif (data \u0026\u0026 !sk_psock_queue_empty(psock))\n \t\t\tgoto msg_bytes_ready;\n+\t\tif (!data \u0026\u0026 timeo \u003e 0)\n+\t\t\tgoto msg_bytes_ready;\n \t\tcopied = -EAGAIN;\n \t}\n out:\n@@ -355,6 +358,7 @@ static int tcp_bpf_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,\n {\n \tstruct sk_psock *psock;\n \tint copied, ret;\n+\tlong timeo;\n \n \tif (unlikely(flags \u0026 MSG_ERRQUEUE))\n \t\treturn inet_recv_error(sk, msg, len);\n@@ -371,14 +375,59 @@ static int tcp_bpf_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,\n \t\treturn tcp_recvmsg(sk, msg, len, flags);\n \t}\n \tlock_sock(sk);\n+\n+\ttimeo = sock_rcvtimeo(sk, flags \u0026 MSG_DONTWAIT);\n+\n msg_bytes_ready:\n \tcopied = sk_msg_recvmsg(sk, psock, msg, len, flags);\n \tif (!copied) {\n-\t\tlong timeo;\n \t\tint data;\n \n-\t\ttimeo = sock_rcvtimeo(sk, flags \u0026 MSG_DONTWAIT);\n-\t\tdata = tcp_msg_wait_data(sk, psock, timeo);\n+\t\tif (sock_flag(sk, SOCK_DONE)) {\n+\t\t\tret = 0;\n+\t\t\tgoto unlock;\n+\t\t}\n+\n+\t\tif (sk-\u003esk_err) {\n+\t\t\tif (!sk_psock_queue_empty(psock))\n+\t\t\t\tgoto msg_bytes_ready;\n+\t\t\tif (!skb_queue_empty(\u0026sk-\u003esk_receive_queue)) {\n+\t\t\t\trelease_sock(sk);\n+\t\t\t\tsk_psock_put(sk, psock);\n+\t\t\t\treturn tcp_recvmsg(sk, msg, len, flags);\n+\t\t\t}\n+\t\t\tret = sock_error(sk);\n+\t\t\tgoto unlock;\n+\t\t}\n+\n+\t\tif (sk-\u003esk_shutdown \u0026 RCV_SHUTDOWN) {\n+\t\t\tif (!sk_psock_queue_empty(psock))\n+\t\t\t\tgoto msg_bytes_ready;\n+\t\t\tif (!skb_queue_empty(\u0026sk-\u003esk_receive_queue)) {\n+\t\t\t\trelease_sock(sk);\n+\t\t\t\tsk_psock_put(sk, psock);\n+\t\t\t\treturn tcp_recvmsg(sk, msg, len, flags);\n+\t\t\t}\n+\t\t\tret = 0;\n+\t\t\tgoto unlock;\n+\t\t}\n+\n+\t\tif (sk-\u003esk_state == TCP_CLOSE) {\n+\t\t\tret = -ENOTCONN;\n+\t\t\tgoto unlock;\n+\t\t}\n+\n+\t\tif (!timeo) {\n+\t\t\tret = -EAGAIN;\n+\t\t\tgoto unlock;\n+\t\t}\n+\n+\t\tif (signal_pending(current)) {\n+\t\t\tret = sock_intr_errno(timeo);\n+\t\t\tgoto unlock;\n+\t\t}\n+\n+\t\tdata = tcp_msg_wait_data(sk, psock, \u0026timeo);\n \t\tif (data \u003c 0) {\n \t\t\tret = data;\n \t\t\tgoto unlock;\n@@ -390,6 +439,8 @@ static int tcp_bpf_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,\n \t\t\tsk_psock_put(sk, psock);\n \t\t\treturn tcp_recvmsg(sk, msg, len, flags);\n \t\t}\n+\t\tif (!data \u0026\u0026 timeo \u003e 0)\n+\t\t\tgoto msg_bytes_ready;\n \t\tcopied = -EAGAIN;\n \t}\n \tret = copied;\ndiff --git a/tools/testing/selftests/net/.gitignore b/tools/testing/selftests/net/.gitignore\nindex c9f46031ac73b2..a1840a5d45f67c 100644\n--- a/tools/testing/selftests/net/.gitignore\n+++ b/tools/testing/selftests/net/.gitignore\n@@ -39,6 +39,8 @@ sk_connect_zero_addr\n sk_so_peek_off\n skf_net_off\n socket\n+sockmap_recvfrom\n+sockmap_recvfrom.bpf.o\n so_incoming_cpu\n so_netns_cookie\n so_rcv_listener\ndiff --git a/tools/testing/selftests/net/Makefile b/tools/testing/selftests/net/Makefile\nindex 708d960ae07d5b..dd04b80725c679 100644\n--- a/tools/testing/selftests/net/Makefile\n+++ b/tools/testing/selftests/net/Makefile\n@@ -191,6 +191,7 @@ TEST_GEN_PROGS := \\\n \tsk_connect_zero_addr \\\n \tsk_so_peek_off \\\n \tso_incoming_cpu \\\n+\tsockmap_recvfrom \\\n \ttap \\\n \ttcp_port_share \\\n \ttls \\\n@@ -238,3 +239,7 @@ $(OUTPUT)/bind_bhash: LDLIBS += -lpthread\n $(OUTPUT)/io_uring_zerocopy_tx: CFLAGS += -I../../../include/\n \n include bpf.mk\n+\n+$(OUTPUT)/sockmap_recvfrom: $(BPFOBJ)\n+$(OUTPUT)/sockmap_recvfrom: LDLIBS += $(BPFOBJ) -lelf -lz -lpthread\n+$(OUTPUT)/sockmap_recvfrom: CFLAGS += -I$(OUTPUT)/tools/include\ndiff --git a/tools/testing/selftests/net/sockmap_recvfrom.bpf.c b/tools/testing/selftests/net/sockmap_recvfrom.bpf.c\nnew file mode 100644\nindex 00000000000000..fec470c738f1e8\n--- /dev/null\n+++ b/tools/testing/selftests/net/sockmap_recvfrom.bpf.c\n@@ -0,0 +1,31 @@\n+// SPDX-License-Identifier: GPL-2.0\n+#include \u003clinux/bpf.h\u003e\n+#include \u003cbpf/bpf_helpers.h\u003e\n+\n+#define AF_INET 2\n+\n+char LICENSE[] SEC(\"license\") = \"GPL\";\n+\n+struct {\n+\t__uint(type, BPF_MAP_TYPE_SOCKHASH);\n+\t__uint(max_entries, 1024);\n+\t__type(key, __u64);\n+\t__type(value, __u64);\n+\n+} map_socks SEC(\".maps\");\n+\n+SEC(\"sockops\") int on_sockops(struct bpf_sock_ops *ctx)\n+{\n+\tif (ctx-\u003efamily == AF_INET \u0026\u0026 ctx-\u003eop == BPF_SOCK_OPS_ACTIVE_ESTABLISHED_CB) {\n+\t\t__u64 cookie = bpf_get_socket_cookie(ctx);\n+\n+\t\tbpf_sock_hash_update(ctx, \u0026map_socks, \u0026cookie, BPF_NOEXIST);\n+\t}\n+\n+\treturn 0;\n+}\n+\n+SEC(\"sk_skb/stream_verdict\") int on_recv(struct __sk_buff *ctx)\n+{\n+\treturn SK_PASS;\n+}\ndiff --git a/tools/testing/selftests/net/sockmap_recvfrom.c b/tools/testing/selftests/net/sockmap_recvfrom.c\nnew file mode 100644\nindex 00000000000000..25657fc3dbcd22\n--- /dev/null\n+++ b/tools/testing/selftests/net/sockmap_recvfrom.c\n@@ -0,0 +1,299 @@\n+// SPDX-License-Identifier: GPL-2.0\n+#include \u003carpa/inet.h\u003e\n+#include \u003cbpf/libbpf.h\u003e\n+#include \u003cfcntl.h\u003e\n+#include \u003cpthread.h\u003e\n+#include \u003cstdatomic.h\u003e\n+#include \u003csys/socket.h\u003e\n+#include \u003csys/time.h\u003e\n+#include \u003cunistd.h\u003e\n+\n+#include \"kselftest_harness.h\"\n+\n+#define MAX_ITERATIONS 100\n+#define PAYLOAD_END 'e'\n+\n+static int start_listening(struct __test_metadata *_metadata, uint16_t *port)\n+{\n+\tstruct sockaddr_in addr;\n+\tsocklen_t addrlen;\n+\tint fd;\n+\n+\tmemset(\u0026addr, 0, sizeof(addr));\n+\taddr.sin_family = AF_INET;\n+\taddr.sin_addr.s_addr = INADDR_ANY;\n+\n+\tfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);\n+\n+\tASSERT_NE(fd, -1);\n+\tASSERT_EQ(bind(fd, (struct sockaddr *)\u0026addr, sizeof(addr)), 0);\n+\tASSERT_EQ(listen(fd, 5), 0);\n+\n+\taddrlen = sizeof(addr);\n+\n+\tASSERT_EQ(getsockname(fd, (struct sockaddr *)\u0026addr, \u0026addrlen), 0);\n+\n+\t*port = addr.sin_port;\n+\n+\treturn fd;\n+}\n+\n+static void process_client(int fd, atomic_int *running, bool *failed)\n+{\n+\tchar buf[1024];\n+\tstruct timeval timeo;\n+\n+\ttimeo.tv_sec = 0;\n+\ttimeo.tv_usec = 1000;\n+\n+\tif (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, \u0026timeo, sizeof(timeo)))\n+\t\t*failed = true;\n+\n+\twhile (atomic_load(running)) {\n+\t\tssize_t len = recvfrom(fd, buf, sizeof(buf), 0, NULL, NULL);\n+\n+\t\tif (len == -1) {\n+\t\t\tif (errno != EAGAIN \u0026\u0026 errno != EINTR)\n+\t\t\t\t*failed = true;\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\tif (len \u003c= 0 || buf[len - 1] == PAYLOAD_END)\n+\t\t\tbreak;\n+\t}\n+\n+\tsend(fd, \"test\", 4, MSG_NOSIGNAL);\n+\n+\tclose(fd);\n+}\n+\n+struct bpf_t {\n+\tstruct bpf_object *obj;\n+\tstruct bpf_link *on_sockops;\n+\tstruct bpf_link *on_recv;\n+};\n+\n+static void setup_bpf(struct __test_metadata *_metadata, const char *path, bool recv,\n+\t\t\t\t\t\tstruct bpf_t *bpf)\n+{\n+\tstruct bpf_program *prog;\n+\tint cgroup;\n+\n+\tmemset(bpf, 0, sizeof(*bpf));\n+\tbpf-\u003eobj = bpf_object__open_file(path, NULL);\n+\n+\tASSERT_NE(bpf-\u003eobj, NULL);\n+\tASSERT_EQ(bpf_object__load(bpf-\u003eobj), 0);\n+\n+\tprog = bpf_object__find_program_by_name(bpf-\u003eobj, \"on_sockops\");\n+\tASSERT_NE(prog, NULL);\n+\n+\tcgroup = open(\"/sys/fs/cgroup\", O_RDONLY);\n+\tASSERT_NE(cgroup, -1);\n+\n+\tbpf-\u003eon_sockops = bpf_program__attach_cgroup(prog, cgroup);\n+\tclose(cgroup);\n+\n+\tASSERT_NE(bpf-\u003eon_sockops, NULL);\n+\n+\tif (recv) {\n+\t\tstruct bpf_map *map = bpf_object__find_map_by_name(bpf-\u003eobj, \"map_socks\");\n+\n+\t\tASSERT_NE(map, NULL);\n+\n+\t\tprog = bpf_object__find_program_by_name(bpf-\u003eobj, \"on_recv\");\n+\t\tASSERT_NE(prog, NULL);\n+\n+\t\tbpf-\u003eon_recv = bpf_program__attach_sockmap(prog, bpf_map__fd(map));\n+\t\tASSERT_NE(bpf-\u003eon_recv, NULL);\n+\t}\n+}\n+\n+struct server_t {\n+\tint fd;\n+\tatomic_int running;\n+\tpthread_t thread;\n+\tbool thread_created;\n+};\n+\n+static void *run_server(void *arg)\n+{\n+\tstruct server_t *server = arg;\n+\tbool failed = false;\n+\n+\twhile (atomic_load(\u0026server-\u003erunning)) {\n+\t\tint client_fd = accept(server-\u003efd, NULL, NULL);\n+\n+\t\tif (client_fd == -1) {\n+\t\t\tif (!atomic_load(\u0026server-\u003erunning))\n+\t\t\t\tbreak;\n+\n+\t\t\tcontinue;\n+\t\t}\n+\n+\t\tprocess_client(client_fd, \u0026server-\u003erunning, \u0026failed);\n+\t}\n+\n+\tif (failed)\n+\t\treturn (void *)1;\n+\n+\treturn NULL;\n+}\n+\n+static int send_payload(struct __test_metadata *_metadata, int fd, const char *buf, size_t len)\n+{\n+\tsize_t remaining = len;\n+\n+\tdo {\n+\t\tssize_t bytes = write(fd, buf + (len - remaining), remaining);\n+\n+\t\tif (bytes \u003c 0) {\n+\t\t\tif (errno == EINTR)\n+\t\t\t\tcontinue;\n+\n+\t\t\treturn -1;\n+\t\t}\n+\n+\t\tremaining -= bytes;\n+\t} while (remaining);\n+\n+\treturn 0;\n+}\n+\n+FIXTURE(sockmap_recvfrom)\n+{\n+\tstruct server_t server;\n+\tstruct sockaddr_in addr;\n+\tstruct bpf_t bpf;\n+\tchar *payload;\n+\tsize_t payload_len;\n+};\n+\n+FIXTURE_VARIANT(sockmap_recvfrom)\n+{\n+\tbool with_recv;\n+};\n+\n+FIXTURE_VARIANT_ADD(sockmap_recvfrom, recvmsg)\n+{\n+\t.with_recv = false\n+};\n+\n+FIXTURE_VARIANT_ADD(sockmap_recvfrom, recvmsg_parser)\n+{\n+\t.with_recv = true\n+};\n+\n+FIXTURE_SETUP(sockmap_recvfrom)\n+{\n+\tmemset(\u0026self-\u003eserver, 0, sizeof(self-\u003eserver));\n+\tself-\u003eserver.fd = -1;\n+\n+\tmemset(\u0026self-\u003eaddr, 0, sizeof(self-\u003eaddr));\n+\n+\tself-\u003epayload_len = 1024 * 1024 * 25;\n+\tself-\u003epayload = malloc(self-\u003epayload_len);\n+\tASSERT_NE(self-\u003epayload, NULL);\n+\n+\tmemset(self-\u003epayload, 0, self-\u003epayload_len);\n+\tself-\u003epayload[self-\u003epayload_len - 1] = PAYLOAD_END;\n+\n+\tsetup_bpf(_metadata, \"sockmap_recvfrom.bpf.o\", variant-\u003ewith_recv, \u0026self-\u003ebpf);\n+\tatomic_store(\u0026self-\u003eserver.running, 1);\n+\tself-\u003eserver.fd = start_listening(_metadata, \u0026self-\u003eaddr.sin_port);\n+\n+\tself-\u003eaddr.sin_family = AF_INET;\n+\tself-\u003eaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);\n+\n+\tASSERT_EQ(pthread_create(\u0026self-\u003eserver.thread, NULL, \u0026run_server, \u0026self-\u003eserver), 0);\n+\tself-\u003eserver.thread_created = true;\n+}\n+\n+FIXTURE_TEARDOWN(sockmap_recvfrom)\n+{\n+\tatomic_store(\u0026self-\u003eserver.running, 0);\n+\n+\tif (self-\u003eserver.fd != -1)\n+\t\tshutdown(self-\u003eserver.fd, SHUT_RD);\n+\n+\tif (self-\u003eserver.thread_created) {\n+\t\tvoid *retval = NULL;\n+\n+\t\tpthread_join(self-\u003eserver.thread, \u0026retval);\n+\t\tEXPECT_EQ(retval, NULL);\n+\t}\n+\n+\tif (self-\u003eserver.fd != -1)\n+\t\tclose(self-\u003eserver.fd);\n+\n+\tfree(self-\u003epayload);\n+\tbpf_link__destroy(self-\u003ebpf.on_sockops);\n+\n+\tif (self-\u003ebpf.on_recv)\n+\t\tbpf_link__destroy(self-\u003ebpf.on_recv);\n+\n+\tbpf_object__close(self-\u003ebpf.obj);\n+}\n+\n+TEST_F(sockmap_recvfrom, no_timeout)\n+{\n+\tchar ignored[128];\n+\n+\tfor (int i = 0; i \u003c MAX_ITERATIONS; ++i) {\n+\t\tint fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);\n+\n+\t\tASSERT_NE(fd, -1);\n+\t\tASSERT_EQ(connect(fd, (struct sockaddr *)\u0026self-\u003eaddr, sizeof(self-\u003eaddr)), 0);\n+\n+\t\tASSERT_EQ(send_payload(_metadata, fd, self-\u003epayload, self-\u003epayload_len), 0);\n+\n+\t\tif (recvfrom(fd, ignored, sizeof(ignored), 0, NULL, NULL) \u003c 0)\n+\t\t\tASSERT_NE(errno, EAGAIN);\n+\n+\t\tclose(fd);\n+\t}\n+}\n+\n+static int64_t to_nanos(struct timespec *time)\n+{\n+\treturn (time-\u003etv_sec * 1000000000LL) + time-\u003etv_nsec;\n+}\n+\n+TEST_F(sockmap_recvfrom, with_timeout)\n+{\n+\tchar ignored[128];\n+\tstruct timeval timeo;\n+\n+\ttimeo.tv_sec = 0;\n+\ttimeo.tv_usec = 5000;\n+\n+\t/* remove the payload end delimiter so the server never responds and recvfrom times out. */\n+\tself-\u003epayload[self-\u003epayload_len - 1] = 0;\n+\n+\tfor (int i = 0; i \u003c MAX_ITERATIONS; ++i) {\n+\t\tstruct timespec beg;\n+\t\tstruct timespec end;\n+\t\tint err;\n+\n+\t\tint fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);\n+\n+\t\tASSERT_NE(fd, -1);\n+\t\tASSERT_EQ(connect(fd, (struct sockaddr *)\u0026self-\u003eaddr, sizeof(self-\u003eaddr)), 0);\n+\n+\t\tASSERT_EQ(send_payload(_metadata, fd, self-\u003epayload, self-\u003epayload_len), 0);\n+\n+\t\tASSERT_EQ(setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, \u0026timeo, sizeof(timeo)), 0);\n+\n+\t\tclock_gettime(CLOCK_MONOTONIC, \u0026beg);\n+\t\tASSERT_EQ(recvfrom(fd, ignored, sizeof(ignored), 0, NULL, NULL), -1);\n+\t\terr = errno;\n+\t\tclock_gettime(CLOCK_MONOTONIC, \u0026end);\n+\n+\t\tASSERT_EQ(err, EAGAIN);\n+\t\tASSERT_GE(to_nanos(\u0026end) - to_nanos(\u0026beg), timeo.tv_usec * 1000);\n+\n+\t\tclose(fd);\n+\t}\n+}\n+\n+TEST_HARNESS_MAIN\n"
} |
| 2/1 | 2026/07/16 04:14 | agent | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: {
"EnableConfigs": [
"BPF_SYSCALL",
"NET_SOCK_MSG"
],
"FocusSymbols": [
"tcp_bpf_recvmsg_parser",
"tcp_bpf_recvmsg",
"tcp_msg_wait_data"
],
"Reasoning": "The patch modifies timeout handling in BPF sockmap's recvmsg implementations (tcp_bpf_recvmsg and tcp_bpf_recvmsg_parser). It correctly updates the remaining timeout value in tcp_msg_wait_data and retries reading if the timeout hasn't expired. This is functional core networking logic that should be fuzzed.",
"WorthFuzzing": true
}Instruction: You are an expert Linux kernel maintainer. Your job is to review a provided patch series and determine if it makes functional changes to the kernel that should be fuzzed. IMPORTANT: The changes have ALREADY been applied and committed as the HEAD commit in your workspace. Do NOT rely on your internal knowledge of the kernel. You must actively use your code access tools to examine the actual source code and confirm any assumptions. Return WorthFuzzing=false if the patch only contains: - Modifications to Documentation/, Kconfig files, or code comments. - Purely decorative changes, such as logging (e.g., pr_err, printk) or tracepoints. - Changes to numeric constants or macros that do not functionally alter execution flow. - Code paths that are impossible to reach in virtualized environments like GCE or QEMU, even when utilizing software-emulated hardware (e.g., usb gadget, mac80211_hwsim). If it modifies reachable core kernel logic, drivers, or architectures, use your code search tools to verify the code can be executed, then return WorthFuzzing=true. When returning WorthFuzzing=true, you MUST ALSO: 1. Extract any specific kernel functions that should be heavily fuzzed into FocusSymbols. Avoid listing generic hot-path functions to prevent skewed test distributions. 2. Identify any specific CONFIG_ options required to properly test this new/modified feature. Go and look into the Kconfig files and check for ifdefs around the code, do not make assumptions. Do not list too generic configs (we already have them enabled). Only list those that specifically cover the modified code. List them in the EnableConfigs output array, and DO NOT add a 'CONFIG_' prefix (e.g., return "NET_IPV4" instead of "CONFIG_NET_IPV4"). Prefer calling several tools at the same time to save round-trips. Use set-results tool to provide results of the analysis. It must be called exactly once before the final reply. Ignore results of this tool. Prompt: For your convenience, here is the diff of the changes:
commit 03af4355be42f8ec46bbb53487603c80b55819b9
Author: syz-cluster <triage@syzkaller.com>
Date: Thu Jul 16 04:14:17 2026 +0000
syz-cluster: applied patch under review
diff --git a/net/ipv4/tcp_bpf.c b/net/ipv4/tcp_bpf.c
index cc0bd73f36b6d6..aa5c5d741599a3 100644
--- a/net/ipv4/tcp_bpf.c
+++ b/net/ipv4/tcp_bpf.c
@@ -179,7 +179,7 @@ EXPORT_SYMBOL_GPL(tcp_bpf_sendmsg_redir);
#ifdef CONFIG_BPF_SYSCALL
static int tcp_msg_wait_data(struct sock *sk, struct sk_psock *psock,
- long timeo)
+ long *timeo)
{
DEFINE_WAIT_FUNC(wait, woken_wake_function);
int ret = 0;
@@ -187,12 +187,12 @@ static int tcp_msg_wait_data(struct sock *sk, struct sk_psock *psock,
if (sk->sk_shutdown & RCV_SHUTDOWN)
return 1;
- if (!timeo)
+ if (!*timeo)
return ret;
add_wait_queue(sk_sleep(sk), &wait);
sk_set_bit(SOCKWQ_ASYNC_WAITDATA, sk);
- ret = sk_wait_event(sk, &timeo,
+ ret = sk_wait_event(sk, timeo,
!list_empty(&psock->ingress_msg) ||
!skb_queue_empty_lockless(&sk->sk_receive_queue), &wait);
sk_clear_bit(SOCKWQ_ASYNC_WAITDATA, sk);
@@ -229,6 +229,7 @@ static int tcp_bpf_recvmsg_parser(struct sock *sk,
int copied_from_self = 0;
int copied = 0;
u32 seq;
+ long timeo;
if (unlikely(flags & MSG_ERRQUEUE))
return inet_recv_error(sk, msg, len);
@@ -262,6 +263,8 @@ static int tcp_bpf_recvmsg_parser(struct sock *sk,
}
}
+ timeo = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
+
msg_bytes_ready:
copied = __sk_msg_recvmsg(sk, psock, msg, len, flags, &copied_from_self);
/* The typical case for EFAULT is the socket was gracefully
@@ -280,7 +283,6 @@ static int tcp_bpf_recvmsg_parser(struct sock *sk,
}
seq += copied_from_self;
if (!copied) {
- long timeo;
int data;
if (sock_flag(sk, SOCK_DONE))
@@ -299,7 +301,6 @@ static int tcp_bpf_recvmsg_parser(struct sock *sk,
goto out;
}
- timeo = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
if (!timeo) {
copied = -EAGAIN;
goto out;
@@ -310,13 +311,15 @@ static int tcp_bpf_recvmsg_parser(struct sock *sk,
goto out;
}
- data = tcp_msg_wait_data(sk, psock, timeo);
+ data = tcp_msg_wait_data(sk, psock, &timeo);
if (data < 0) {
copied = data;
goto unlock;
}
if (data && !sk_psock_queue_empty(psock))
goto msg_bytes_ready;
+ if (!data && timeo > 0)
+ goto msg_bytes_ready;
copied = -EAGAIN;
}
out:
@@ -355,6 +358,7 @@ static int tcp_bpf_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
{
struct sk_psock *psock;
int copied, ret;
+ long timeo;
if (unlikely(flags & MSG_ERRQUEUE))
return inet_recv_error(sk, msg, len);
@@ -371,14 +375,59 @@ static int tcp_bpf_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
return tcp_recvmsg(sk, msg, len, flags);
}
lock_sock(sk);
+
+ timeo = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
+
msg_bytes_ready:
copied = sk_msg_recvmsg(sk, psock, msg, len, flags);
if (!copied) {
- long timeo;
int data;
- timeo = sock_rcvtimeo(sk, flags & MSG_DONTWAIT);
- data = tcp_msg_wait_data(sk, psock, timeo);
+ if (sock_flag(sk, SOCK_DONE)) {
+ ret = 0;
+ goto unlock;
+ }
+
+ if (sk->sk_err) {
+ if (!sk_psock_queue_empty(psock))
+ goto msg_bytes_ready;
+ if (!skb_queue_empty(&sk->sk_receive_queue)) {
+ release_sock(sk);
+ sk_psock_put(sk, psock);
+ return tcp_recvmsg(sk, msg, len, flags);
+ }
+ ret = sock_error(sk);
+ goto unlock;
+ }
+
+ if (sk->sk_shutdown & RCV_SHUTDOWN) {
+ if (!sk_psock_queue_empty(psock))
+ goto msg_bytes_ready;
+ if (!skb_queue_empty(&sk->sk_receive_queue)) {
+ release_sock(sk);
+ sk_psock_put(sk, psock);
+ return tcp_recvmsg(sk, msg, len, flags);
+ }
+ ret = 0;
+ goto unlock;
+ }
+
+ if (sk->sk_state == TCP_CLOSE) {
+ ret = -ENOTCONN;
+ goto unlock;
+ }
+
+ if (!timeo) {
+ ret = -EAGAIN;
+ goto unlock;
+ }
+
+ if (signal_pending(current)) {
+ ret = sock_intr_errno(timeo);
+ goto unlock;
+ }
+
+ data = tcp_msg_wait_data(sk, psock, &timeo);
if (data < 0) {
ret = data;
goto unlock;
@@ -390,6 +439,8 @@ static int tcp_bpf_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
sk_psock_put(sk, psock);
return tcp_recvmsg(sk, msg, len, flags);
}
+ if (!data && timeo > 0)
+ goto msg_bytes_ready;
copied = -EAGAIN;
}
ret = copied;
diff --git a/tools/testing/selftests/net/.gitignore b/tools/testing/selftests/net/.gitignore
index c9f46031ac73b2..a1840a5d45f67c 100644
--- a/tools/testing/selftests/net/.gitignore
+++ b/tools/testing/selftests/net/.gitignore
@@ -39,6 +39,8 @@ sk_connect_zero_addr
sk_so_peek_off
skf_net_off
socket
+sockmap_recvfrom
+sockmap_recvfrom.bpf.o
so_incoming_cpu
so_netns_cookie
so_rcv_listener
diff --git a/tools/testing/selftests/net/Makefile b/tools/testing/selftests/net/Makefile
index 708d960ae07d5b..dd04b80725c679 100644
--- a/tools/testing/selftests/net/Makefile
+++ b/tools/testing/selftests/net/Makefile
@@ -191,6 +191,7 @@ TEST_GEN_PROGS := \
sk_connect_zero_addr \
sk_so_peek_off \
so_incoming_cpu \
+ sockmap_recvfrom \
tap \
tcp_port_share \
tls \
@@ -238,3 +239,7 @@ $(OUTPUT)/bind_bhash: LDLIBS += -lpthread
$(OUTPUT)/io_uring_zerocopy_tx: CFLAGS += -I../../../include/
include bpf.mk
+
+$(OUTPUT)/sockmap_recvfrom: $(BPFOBJ)
+$(OUTPUT)/sockmap_recvfrom: LDLIBS += $(BPFOBJ) -lelf -lz -lpthread
+$(OUTPUT)/sockmap_recvfrom: CFLAGS += -I$(OUTPUT)/tools/include
diff --git a/tools/testing/selftests/net/sockmap_recvfrom.bpf.c b/tools/testing/selftests/net/sockmap_recvfrom.bpf.c
new file mode 100644
index 00000000000000..fec470c738f1e8
--- /dev/null
+++ b/tools/testing/selftests/net/sockmap_recvfrom.bpf.c
@@ -0,0 +1,31 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <linux/bpf.h>
+#include <bpf/bpf_helpers.h>
+
+#define AF_INET 2
+
+char LICENSE[] SEC("license") = "GPL";
+
+struct {
+ __uint(type, BPF_MAP_TYPE_SOCKHASH);
+ __uint(max_entries, 1024);
+ __type(key, __u64);
+ __type(value, __u64);
+
+} map_socks SEC(".maps");
+
+SEC("sockops") int on_sockops(struct bpf_sock_ops *ctx)
+{
+ if (ctx->family == AF_INET && ctx->op == BPF_SOCK_OPS_ACTIVE_ESTABLISHED_CB) {
+ __u64 cookie = bpf_get_socket_cookie(ctx);
+
+ bpf_sock_hash_update(ctx, &map_socks, &cookie, BPF_NOEXIST);
+ }
+
+ return 0;
+}
+
+SEC("sk_skb/stream_verdict") int on_recv(struct __sk_buff *ctx)
+{
+ return SK_PASS;
+}
diff --git a/tools/testing/selftests/net/sockmap_recvfrom.c b/tools/testing/selftests/net/sockmap_recvfrom.c
new file mode 100644
index 00000000000000..25657fc3dbcd22
--- /dev/null
+++ b/tools/testing/selftests/net/sockmap_recvfrom.c
@@ -0,0 +1,299 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <arpa/inet.h>
+#include <bpf/libbpf.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <stdatomic.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <unistd.h>
+
+#include "kselftest_harness.h"
+
+#define MAX_ITERATIONS 100
+#define PAYLOAD_END 'e'
+
+static int start_listening(struct __test_metadata *_metadata, uint16_t *port)
+{
+ struct sockaddr_in addr;
+ socklen_t addrlen;
+ int fd;
+
+ memset(&addr, 0, sizeof(addr));
+ addr.sin_family = AF_INET;
+ addr.sin_addr.s_addr = INADDR_ANY;
+
+ fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+
+ ASSERT_NE(fd, -1);
+ ASSERT_EQ(bind(fd, (struct sockaddr *)&addr, sizeof(addr)), 0);
+ ASSERT_EQ(listen(fd, 5), 0);
+
+ addrlen = sizeof(addr);
+
+ ASSERT_EQ(getsockname(fd, (struct sockaddr *)&addr, &addrlen), 0);
+
+ *port = addr.sin_port;
+
+ return fd;
+}
+
+static void process_client(int fd, atomic_int *running, bool *failed)
+{
+ char buf[1024];
+ struct timeval timeo;
+
+ timeo.tv_sec = 0;
+ timeo.tv_usec = 1000;
+
+ if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &timeo, sizeof(timeo)))
+ *failed = true;
+
+ while (atomic_load(running)) {
+ ssize_t len = recvfrom(fd, buf, sizeof(buf), 0, NULL, NULL);
+
+ if (len == -1) {
+ if (errno != EAGAIN && errno != EINTR)
+ *failed = true;
+ continue;
+ }
+
+ if (len <= 0 || buf[len - 1] == PAYLOAD_END)
+ break;
+ }
+
+ send(fd, "test", 4, MSG_NOSIGNAL);
+
+ close(fd);
+}
+
+struct bpf_t {
+ struct bpf_object *obj;
+ struct bpf_link *on_sockops;
+ struct bpf_link *on_recv;
+};
+
+static void setup_bpf(struct __test_metadata *_metadata, const char *path, bool recv,
+ struct bpf_t *bpf)
+{
+ struct bpf_program *prog;
+ int cgroup;
+
+ memset(bpf, 0, sizeof(*bpf));
+ bpf->obj = bpf_object__open_file(path, NULL);
+
+ ASSERT_NE(bpf->obj, NULL);
+ ASSERT_EQ(bpf_object__load(bpf->obj), 0);
+
+ prog = bpf_object__find_program_by_name(bpf->obj, "on_sockops");
+ ASSERT_NE(prog, NULL);
+
+ cgroup = open("/sys/fs/cgroup", O_RDONLY);
+ ASSERT_NE(cgroup, -1);
+
+ bpf->on_sockops = bpf_program__attach_cgroup(prog, cgroup);
+ close(cgroup);
+
+ ASSERT_NE(bpf->on_sockops, NULL);
+
+ if (recv) {
+ struct bpf_map *map = bpf_object__find_map_by_name(bpf->obj, "map_socks");
+
+ ASSERT_NE(map, NULL);
+
+ prog = bpf_object__find_program_by_name(bpf->obj, "on_recv");
+ ASSERT_NE(prog, NULL);
+
+ bpf->on_recv = bpf_program__attach_sockmap(prog, bpf_map__fd(map));
+ ASSERT_NE(bpf->on_recv, NULL);
+ }
+}
+
+struct server_t {
+ int fd;
+ atomic_int running;
+ pthread_t thread;
+ bool thread_created;
+};
+
+static void *run_server(void *arg)
+{
+ struct server_t *server = arg;
+ bool failed = false;
+
+ while (atomic_load(&server->running)) {
+ int client_fd = accept(server->fd, NULL, NULL);
+
+ if (client_fd == -1) {
+ if (!atomic_load(&server->running))
+ break;
+
+ continue;
+ }
+
+ process_client(client_fd, &server->running, &failed);
+ }
+
+ if (failed)
+ return (void *)1;
+
+ return NULL;
+}
+
+static int send_payload(struct __test_metadata *_metadata, int fd, const char *buf, size_t len)
+{
+ size_t remaining = len;
+
+ do {
+ ssize_t bytes = write(fd, buf + (len - remaining), remaining);
+
+ if (bytes < 0) {
+ if (errno == EINTR)
+ continue;
+
+ return -1;
+ }
+
+ remaining -= bytes;
+ } while (remaining);
+
+ return 0;
+}
+
+FIXTURE(sockmap_recvfrom)
+{
+ struct server_t server;
+ struct sockaddr_in addr;
+ struct bpf_t bpf;
+ char *payload;
+ size_t payload_len;
+};
+
+FIXTURE_VARIANT(sockmap_recvfrom)
+{
+ bool with_recv;
+};
+
+FIXTURE_VARIANT_ADD(sockmap_recvfrom, recvmsg)
+{
+ .with_recv = false
+};
+
+FIXTURE_VARIANT_ADD(sockmap_recvfrom, recvmsg_parser)
+{
+ .with_recv = true
+};
+
+FIXTURE_SETUP(sockmap_recvfrom)
+{
+ memset(&self->server, 0, sizeof(self->server));
+ self->server.fd = -1;
+
+ memset(&self->addr, 0, sizeof(self->addr));
+
+ self->payload_len = 1024 * 1024 * 25;
+ self->payload = malloc(self->payload_len);
+ ASSERT_NE(self->payload, NULL);
+
+ memset(self->payload, 0, self->payload_len);
+ self->payload[self->payload_len - 1] = PAYLOAD_END;
+
+ setup_bpf(_metadata, "sockmap_recvfrom.bpf.o", variant->with_recv, &self->bpf);
+ atomic_store(&self->server.running, 1);
+ self->server.fd = start_listening(_metadata, &self->addr.sin_port);
+
+ self->addr.sin_family = AF_INET;
+ self->addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+
+ ASSERT_EQ(pthread_create(&self->server.thread, NULL, &run_server, &self->server), 0);
+ self->server.thread_created = true;
+}
+
+FIXTURE_TEARDOWN(sockmap_recvfrom)
+{
+ atomic_store(&self->server.running, 0);
+
+ if (self->server.fd != -1)
+ shutdown(self->server.fd, SHUT_RD);
+
+ if (self->server.thread_created) {
+ void *retval = NULL;
+
+ pthread_join(self->server.thread, &retval);
+ EXPECT_EQ(retval, NULL);
+ }
+
+ if (self->server.fd != -1)
+ close(self->server.fd);
+
+ free(self->payload);
+ bpf_link__destroy(self->bpf.on_sockops);
+
+ if (self->bpf.on_recv)
+ bpf_link__destroy(self->bpf.on_recv);
+
+ bpf_object__close(self->bpf.obj);
+}
+
+TEST_F(sockmap_recvfrom, no_timeout)
+{
+ char ignored[128];
+
+ for (int i = 0; i < MAX_ITERATIONS; ++i) {
+ int fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+
+ ASSERT_NE(fd, -1);
+ ASSERT_EQ(connect(fd, (struct sockaddr *)&self->addr, sizeof(self->addr)), 0);
+
+ ASSERT_EQ(send_payload(_metadata, fd, self->payload, self->payload_len), 0);
+
+ if (recvfrom(fd, ignored, sizeof(ignored), 0, NULL, NULL) < 0)
+ ASSERT_NE(errno, EAGAIN);
+
+ close(fd);
+ }
+}
+
+static int64_t to_nanos(struct timespec *time)
+{
+ return (time->tv_sec * 1000000000LL) + time->tv_nsec;
+}
+
+TEST_F(sockmap_recvfrom, with_timeout)
+{
+ char ignored[128];
+ struct timeval timeo;
+
+ timeo.tv_sec = 0;
+ timeo.tv_usec = 5000;
+
+ /* remove the payload end delimiter so the server never responds and recvfrom times out. */
+ self->payload[self->payload_len - 1] = 0;
+
+ for (int i = 0; i < MAX_ITERATIONS; ++i) {
+ struct timespec beg;
+ struct timespec end;
+ int err;
+
+ int fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
+
+ ASSERT_NE(fd, -1);
+ ASSERT_EQ(connect(fd, (struct sockaddr *)&self->addr, sizeof(self->addr)), 0);
+
+ ASSERT_EQ(send_payload(_metadata, fd, self->payload, self->payload_len), 0);
+
+ ASSERT_EQ(setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &timeo, sizeof(timeo)), 0);
+
+ clock_gettime(CLOCK_MONOTONIC, &beg);
+ ASSERT_EQ(recvfrom(fd, ignored, sizeof(ignored), 0, NULL, NULL), -1);
+ err = errno;
+ clock_gettime(CLOCK_MONOTONIC, &end);
+
+ ASSERT_EQ(err, EAGAIN);
+ ASSERT_GE(to_nanos(&end) - to_nanos(&beg), timeo.tv_usec * 1000);
+
+ close(fd);
+ }
+}
+
+TEST_HARNESS_MAIN
|
| 3/2 | 2026/07/16 04:14 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 7455 output: 30 thoughts: 267 Thoughts: **Analyzing a TCP BPF Patch** Okay, so I'm looking at this patch for `net/ipv4/tcp_bpf.c`. The core of the change seems to be in how `tcp_msg_wait_data` handles the timeout; it's now taking a pointer to `timeo` instead of the value itself. That's a fundamental shift in how the function interacts with the timeout mechanism, and I need to understand the implications. The patch also updates `tcp_bpf_recvmsg_parser` and `tcp_bpf_recvmsg`, specifically to pass the address of `timeo` and handle a potential jump to `msg_bytes_ready`. This is making me think about how the timeout is used in the BPF sockmap context – is it an optimization, a bug fix, or something else entirely? The introduction of the `sockmap_recvfrom` selftest is a good sign, but I need to confirm its coverage. My immediate concern is reachability and functionality. The changes directly impact `tcp_bpf_recvmsg_parser` and `tcp_bpf_recvmsg`, which are obviously critical to the BPF sockmap functionality, so a deep dive into the BPF implementation is required. Given that this is touching core networking and BPF logic, fuzzing seems like a very good idea. Next, I need to figure out the build configuration. I'm going to have to check what's going on in `net/ipv4/Makefile`. I'm guessing `CONFIG_BPF_SYSCALL` is a given, but I'll also have to see if `CONFIG_NET_SOCK_MSG` or `CONFIG_BPF_STREAM_PARSER` are also dependencies. Understanding the build configuration will tell me how to build this. |
| 4/2 | 2026/07/16 04:14 | tool | grepper |
0mArgs:{
"Expression": "tcp_bpf",
"PathPrefix": "net/ipv4/Makefile"
}Results: {
"Output": "net/ipv4/Makefile=62=obj-$(CONFIG_TCP_CONG_ILLINOIS) += tcp_illinois.o\nnet/ipv4/Makefile:63:obj-$(CONFIG_NET_SOCK_MSG) += tcp_bpf.o\nnet/ipv4/Makefile-64-obj-$(CONFIG_BPF_SYSCALL) += udp_bpf.o\n"
} |
| 5/2 | 2026/07/16 04:14 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 8238 output: 33 thoughts: 31 Thoughts: Okay, here's my take on those thoughts, tailored for an expert audience: **Kernel Configuration Dependencies for Socket Filtering** Right, so I see we absolutely need `CONFIG_NET_SOCK_MSG` enabled. That's a given; it's the foundation. Now, since we're dealing with sockets, particularly the potential for BPF filtering within the TCP stack, my next move is to dive straight into `tcp_bpf.c`. I need to ensure there aren't any other, less obvious configuration dependencies lurking within that file that I might need to consider. We can't have any surprises when we start making changes. My aim here is to ensure the configuration is complete, and that we have the maximum performance profile to work with. |
| 6/2 | 2026/07/16 04:14 | tool | grepper |
0mArgs:{
"Expression": "CONFIG_",
"PathPrefix": "net/ipv4/tcp_bpf.c"
}Results: {
"Output": "net/ipv4/tcp_bpf.c=178=EXPORT_SYMBOL_GPL(tcp_bpf_sendmsg_redir);\nnet/ipv4/tcp_bpf.c-179-\nnet/ipv4/tcp_bpf.c:180:#ifdef CONFIG_BPF_SYSCALL\nnet/ipv4/tcp_bpf.c-181-static int tcp_msg_wait_data(struct sock *sk, struct sk_psock *psock,\n--\nnet/ipv4/tcp_bpf.c=713=static int tcp_bpf_assert_proto_ops(struct proto *ops)\n--\nnet/ipv4/tcp_bpf.c-722-\nnet/ipv4/tcp_bpf.c:723:#if IS_ENABLED(CONFIG_BPF_STREAM_PARSER)\nnet/ipv4/tcp_bpf.c-724-int tcp_bpf_strp_read_sock(struct strparser *strp, read_descriptor_t *desc,\n--\nnet/ipv4/tcp_bpf.c-756-}\nnet/ipv4/tcp_bpf.c:757:#endif /* CONFIG_BPF_STREAM_PARSER */\nnet/ipv4/tcp_bpf.c-758-\n--\nnet/ipv4/tcp_bpf.c=803=void tcp_bpf_clone(const struct sock *sk, struct sock *newsk)\n--\nnet/ipv4/tcp_bpf.c-809-}\nnet/ipv4/tcp_bpf.c:810:#endif /* CONFIG_BPF_SYSCALL */\n"
} |
| 7/2 | 2026/07/16 04:14 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 8875 output: 38 thoughts: 205 Thoughts: **Analyzing BPF-Related TCP Functionality** Okay, so I'm looking at these modified TCP functions: `tcp_msg_wait_data`, `tcp_bpf_recvmsg_parser`, and `tcp_bpf_recvmsg`. They're all guarded by `#ifdef CONFIG_BPF_SYSCALL`, which means I need to make sure `BPF_SYSCALL` and `NET_SOCK_MSG` are accounted for in my analysis. Now, let's hone in on the core functions. I need to focus on `tcp_bpf_recvmsg_parser`, `tcp_bpf_recvmsg`, and `tcp_msg_wait_data`. My initial thought is that `tcp_bpf_recvmsg` and `tcp_bpf_recvmsg_parser` are prime targets for deeper examination as potential "hot-path" areas. Since they are recvmsg implementations specific to sockmap, not the generic `tcp_recvmsg`, they are excellent candidates for inclusion in FocusSymbols. Just to be absolutely sure, I'm going to double-check those two specific functions, `tcp_bpf_recvmsg_parser` and `tcp_bpf_recvmsg`, to confirm my understanding and make sure I haven't missed anything. |
| 8/2 | 2026/07/16 04:14 | tool | grepper |
0mArgs:{
"Expression": "tcp_bpf_recvmsg",
"PathPrefix": "net/ipv4/tcp_bpf.c"
}Results: {
"Output": "net/ipv4/tcp_bpf.c=203=static bool is_next_msg_fin(struct sk_psock *psock)\n--\nnet/ipv4/tcp_bpf.c-220-\nnet/ipv4/tcp_bpf.c:221:static int tcp_bpf_recvmsg_parser(struct sock *sk,\nnet/ipv4/tcp_bpf.c-222-\t\t\t\t struct msghdr *msg,\n--\nnet/ipv4/tcp_bpf.c=338=static int tcp_bpf_ioctl(struct sock *sk, int cmd, int *karg)\n--\nnet/ipv4/tcp_bpf.c-355-\nnet/ipv4/tcp_bpf.c:356:static int tcp_bpf_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,\nnet/ipv4/tcp_bpf.c-357-\t\t\t int flags)\n--\nnet/ipv4/tcp_bpf.c=674=static void tcp_bpf_rebuild_protos(struct proto prot[TCP_BPF_NUM_CFGS],\n--\nnet/ipv4/tcp_bpf.c-679-\tprot[TCP_BPF_BASE].close\t\t= sock_map_close;\nnet/ipv4/tcp_bpf.c:680:\tprot[TCP_BPF_BASE].recvmsg\t\t= tcp_bpf_recvmsg;\nnet/ipv4/tcp_bpf.c-681-\tprot[TCP_BPF_BASE].sock_is_readable\t= sk_msg_is_readable;\n--\nnet/ipv4/tcp_bpf.c-687-\tprot[TCP_BPF_RX]\t\t\t= prot[TCP_BPF_BASE];\nnet/ipv4/tcp_bpf.c:688:\tprot[TCP_BPF_RX].recvmsg\t\t= tcp_bpf_recvmsg_parser;\nnet/ipv4/tcp_bpf.c-689-\nnet/ipv4/tcp_bpf.c-690-\tprot[TCP_BPF_TXRX]\t\t\t= prot[TCP_BPF_TX];\nnet/ipv4/tcp_bpf.c:691:\tprot[TCP_BPF_TXRX].recvmsg\t\t= tcp_bpf_recvmsg_parser;\nnet/ipv4/tcp_bpf.c-692-}\n--\nnet/ipv4/tcp_bpf.c=724=int tcp_bpf_strp_read_sock(struct strparser *strp, read_descriptor_t *desc,\n--\nnet/ipv4/tcp_bpf.c-747-\t * For SK_REDIRECT, we need to ack the frame immediately but for\nnet/ipv4/tcp_bpf.c:748:\t * SK_PASS, we want to delay the ack until tcp_bpf_recvmsg_parser().\nnet/ipv4/tcp_bpf.c-749-\t */\n"
} |
| 9/2 | 2026/07/16 04:14 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 10150 output: 152 thoughts: 172 Thoughts: **My Analysis of the BPF Sockmap Timeout Fix** Okay, so I'm looking at this patch and it's dealing with `recvmsg` handlers. Specifically, these handlers are used with TCP sockets that are placed within a BPF sockmap – so, we're talking about a very targeted area here, which is good because it makes the scope manageable. It's not a generic issue; it's right in the sweet spot of this specific networking configuration. The configurations being changed, `BPF_SYSCALL` and `NET_SOCK_MSG`, confirm we're dealing with system calls related to networking messages within the BPF context, so this is definitely related to the right subsystem. I see we're focusing on the `tcp_bpf_recvmsg_parser`, `tcp_bpf_recvmsg`, and `tcp_msg_wait_data` symbols. That narrows things down even further – it's all about how these functions handle the retrieval of data. My reasoning leads me to believe the patch is targeting timeout handling within `tcp_bpf_recvmsg` and `tcp_bpf_recvmsg_parser`. The fix specifically addresses the timeout value update within `tcp_msg_wait_data` and introduces a retry mechanism if the timeout hasn't yet elapsed. This is critical core networking logic – the handling of socket reads and message waits under BPF sockmap, which means correct timeout handling is essential for reliable operation. This is a very targeted fix related to a BPF sockmap. It's not a performance tweak, but more of a reliability fix related to a very specific network condition. Let's call this set-results. |
| 10/2 | 2026/07/16 04:14 | tool | set-results |
0mArgs:{
"EnableConfigs": [
"BPF_SYSCALL",
"NET_SOCK_MSG"
],
"FocusSymbols": [
"tcp_bpf_recvmsg_parser",
"tcp_bpf_recvmsg",
"tcp_msg_wait_data"
],
"Reasoning": "The patch modifies timeout handling in BPF sockmap's recvmsg implementations (tcp_bpf_recvmsg and tcp_bpf_recvmsg_parser). It correctly updates the remaining timeout value in tcp_msg_wait_data and retries reading if the timeout hasn't expired. This is functional core networking logic that should be fuzzed.",
"WorthFuzzing": true
}Results: {
"EnableConfigs": [
"BPF_SYSCALL",
"NET_SOCK_MSG"
],
"FocusSymbols": [
"tcp_bpf_recvmsg_parser",
"tcp_bpf_recvmsg",
"tcp_msg_wait_data"
],
"Reasoning": "The patch modifies timeout handling in BPF sockmap's recvmsg implementations (tcp_bpf_recvmsg and tcp_bpf_recvmsg_parser). It correctly updates the remaining timeout value in tcp_msg_wait_data and retries reading if the timeout hasn't expired. This is functional core networking logic that should be fuzzed.",
"WorthFuzzing": true
} |
| Total Calls | Total Tokens | Avg Tokens | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|
| Total Calls | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|