AI Trajectory


Trajectory: (Expand/Collapse All)
Seq Timestamp Type Name Duration
0/0 2026/07/01 18:01 flow patch-triage
0m Args:
null

Results:
{
  "EnableConfigs": [
    "PACKET"
  ],
  "FocusSymbols": [
    "packet_set_ring"
  ],
  "Reasoning": "The patch fixes a bug where a fanout hook could be re-added to a dead device in packet_set_ring by checking if the device is dead (ifindex != -1) before calling register_prot_hook. This is a functional change in the core AF_PACKET logic.",
  "WorthFuzzing": true
}

1/1 2026/07/01 18:01 action read-patch-diff
0m Args:
null

Results:
{
  "PatchDiff": "commit 51d13e3c7a932b4c8144fffaa7247270432be983\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate:   Wed Jul 1 18:01:29 2026 +0000\n\n    syz-cluster: applied patch under review\n\ndiff --git a/net/packet/af_packet.c b/net/packet/af_packet.c\nindex 8e6f3a734ba0bd..e75d2932475ac0 100644\n--- a/net/packet/af_packet.c\n+++ b/net/packet/af_packet.c\n@@ -4561,7 +4561,11 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u,\n \n \tspin_lock(\u0026po-\u003ebind_lock);\n \tWRITE_ONCE(po-\u003enum, num);\n-\tif (was_running)\n+\t/*\n+\t * NETDEV_UNREGISTER may have invalidated the binding while bind_lock\n+\t * was dropped above.  Do not re-add a fanout hook to a dead device.\n+\t */\n+\tif (was_running \u0026\u0026 READ_ONCE(po-\u003eifindex) != -1)\n \t\tregister_prot_hook(sk);\n \n \tspin_unlock(\u0026po-\u003ebind_lock);\n"
}

2/1 2026/07/01 18:01 agent patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
{
  "EnableConfigs": [
    "PACKET"
  ],
  "FocusSymbols": [
    "packet_set_ring"
  ],
  "Reasoning": "The patch fixes a bug where a fanout hook could be re-added to a dead device in packet_set_ring by checking if the device is dead (ifindex != -1) before calling register_prot_hook. This is a functional change in the core AF_PACKET logic.",
  "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 51d13e3c7a932b4c8144fffaa7247270432be983
Author: syz-cluster <triage@syzkaller.com>
Date:   Wed Jul 1 18:01:29 2026 +0000

    syz-cluster: applied patch under review

diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 8e6f3a734ba0bd..e75d2932475ac0 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -4561,7 +4561,11 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u,
 
 	spin_lock(&po->bind_lock);
 	WRITE_ONCE(po->num, num);
-	if (was_running)
+	/*
+	 * NETDEV_UNREGISTER may have invalidated the binding while bind_lock
+	 * was dropped above.  Do not re-add a fanout hook to a dead device.
+	 */
+	if (was_running && READ_ONCE(po->ifindex) != -1)
 		register_prot_hook(sk);
 
 	spin_unlock(&po->bind_lock);

3/2 2026/07/01 18:01 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 1890
							output: 34
							thoughts: 225
						

Thoughts:
**Analyzing a Packet Ring Fix**

Okay, so I'm looking at this patch for `net/packet/af_packet.c`, specifically the `packet_set_ring` function. The change here is pretty clear: it's adding a check before re-registering a fanout hook.  My initial impression is that this is a solid, functional bug fix. Essentially, it appears we're preventing a fanout hook from being added to a network device that's already gone; a "dead device", as the comment puts it. The key is that `NETDEV_UNREGISTER` might have invalidated the binding while the `bind_lock` was dropped, and this conditional `READ_ONCE(po->ifindex) != -1` is the new guard.  Essentially, it's making sure the device is still valid before trying to register the hook. This is good practice.

Just to be absolutely certain, I'm going to quickly grep the code to double-check my understanding of how `packet_set_ring` is used and ensure there are no unintended side effects. Time to fire up grepper and get a broader view of the function's context.



4/2 2026/07/01 18:01 tool grepper
0m Args:
{
  "Expression": "packet_set_ring",
  "PathPrefix": "net/packet/af_packet.c"
}

Results:
{
  "Output": "net/packet/af_packet.c-36- *         Ulises Alonso        :       Frame number limit removal and\nnet/packet/af_packet.c:37: *                                      packet_set_ring memory leak.\nnet/packet/af_packet.c-38- *\t\tEric Biederman\t:\tAllow for \u003e 8 byte hardware addresses.\n--\nnet/packet/af_packet.c=167=union tpacket_uhdr {\n--\nnet/packet/af_packet.c-173-\nnet/packet/af_packet.c:174:static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u,\nnet/packet/af_packet.c-175-\t\tint closing, int tx_ring);\n--\nnet/packet/af_packet.c=3122=static int packet_release(struct socket *sock)\n--\nnet/packet/af_packet.c-3157-\t\tmemset(\u0026req_u, 0, sizeof(req_u));\nnet/packet/af_packet.c:3158:\t\tpacket_set_ring(sk, \u0026req_u, 1, 0);\nnet/packet/af_packet.c-3159-\t}\n--\nnet/packet/af_packet.c-3162-\t\tmemset(\u0026req_u, 0, sizeof(req_u));\nnet/packet/af_packet.c:3163:\t\tpacket_set_ring(sk, \u0026req_u, 1, 1);\nnet/packet/af_packet.c-3164-\t}\n--\nnet/packet/af_packet.c=3787=packet_setsockopt(struct socket *sock, int level, int optname, sockptr_t optval,\n--\nnet/packet/af_packet.c-3844-\t\tif (!ret)\nnet/packet/af_packet.c:3845:\t\t\tret = packet_set_ring(sk, \u0026req_u, 0,\nnet/packet/af_packet.c-3846-\t\t\t\t\t      optname == PACKET_TX_RING);\n--\nnet/packet/af_packet.c=4391=static struct pgv *alloc_pg_vec(struct tpacket_req *req, int order)\n--\nnet/packet/af_packet.c-4415-\nnet/packet/af_packet.c:4416:static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u,\nnet/packet/af_packet.c-4417-\t\tint closing, int tx_ring)\n"
}

5/2 2026/07/01 18:01 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 3058
							output: 29
							thoughts: 90
						

Thoughts:
Okay, here's my summary, presented as a simulation of my thought process:

**Reviewing a Potential Fuzzing Target**

Alright, the initial assessment is promising. The core change, the one I want to investigate further, is within `packet_set_ring`. The fact that it's already considered functional and primed for fuzzing is a good sign. That suggests someone has already identified this as a potential source of interesting behavior.

Now, I need to understand the call path. `packet_set_ring` is called from `packet_setsockopt`. More specifically, it's invoked when `PACKET_TX_RING` or `PACKET_RX_RING` socket options are used. This confirms that socket options are likely the interface we will be fuzzing on. The overall subsystem configuration is clearly dependent on the `CONFIG_PACKET` kernel option for AF_PACKET.

My next step is to examine the configuration options more closely. I should verify the build flags, dependencies, and any other relevant Kconfig directives. Let's dig into `net/packet/Kconfig` to confirm these assumptions and explore whether there are any other potentially relevant options.



6/2 2026/07/01 18:01 tool grepper
0m Args:
{
  "Expression": "config PACKET",
  "PathPrefix": "net/packet/Kconfig"
}

Results:
{
  "Output": "net/packet/Kconfig-5-\nnet/packet/Kconfig:6:config PACKET\nnet/packet/Kconfig-7-\ttristate \"Packet socket\"\n--\nnet/packet/Kconfig-18-\nnet/packet/Kconfig:19:config PACKET_DIAG\nnet/packet/Kconfig-20-\ttristate \"Packet: sockets monitoring interface\"\n"
}

7/2 2026/07/01 18:01 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 3530
							output: 31
							thoughts: 126
						

Thoughts:
**Analyzing the Kernel Packet Configuration**

Okay, so the main configuration here, it looks like, is `CONFIG_PACKET`. Got it. The key function we're focusing on is `packet_set_ring`.

Right, let's just make sure we haven't missed any other potentially relevant configurations. Although `PACKET` is typically enabled by default, it's always a good practice to explicitly include it to be sure.

Ah, the patch is centered around `packet_set_ring` and also `register_prot_hook(sk)`. The comment... "Do not re-add a fanout hook to a dead device." That suggests there's a related fanout mechanism. That's interesting, let's see if there is a specific config for that... I'll check `net/packet/af_packet.c` to see how the `fanout` functionality is handled.



8/2 2026/07/01 18:01 tool grepper
0m Args:
{
  "Expression": "fanout",
  "PathPrefix": "net/packet/af_packet.c"
}

Results:
{
  "Output": "net/packet/af_packet.c=216=struct packet_skb_cb {\n--\nnet/packet/af_packet.c-242-\nnet/packet/af_packet.c:243:static void __fanout_unlink(struct sock *sk, struct packet_sock *po);\nnet/packet/af_packet.c:244:static void __fanout_link(struct sock *sk, struct packet_sock *po);\nnet/packet/af_packet.c-245-\n--\nnet/packet/af_packet.c=336=static void __register_prot_hook(struct sock *sk)\n--\nnet/packet/af_packet.c-340-\tif (!packet_sock_flag(po, PACKET_SOCK_RUNNING)) {\nnet/packet/af_packet.c:341:\t\tif (po-\u003efanout)\nnet/packet/af_packet.c:342:\t\t\t__fanout_link(sk, po);\nnet/packet/af_packet.c-343-\t\telse\n--\nnet/packet/af_packet.c=363=static void __unregister_prot_hook(struct sock *sk, bool sync)\n--\nnet/packet/af_packet.c-370-\nnet/packet/af_packet.c:371:\tif (po-\u003efanout)\nnet/packet/af_packet.c:372:\t\t__fanout_unlink(sk, po);\nnet/packet/af_packet.c-373-\telse\n--\nnet/packet/af_packet.c=1325=static void packet_sock_destruct(struct sock *sk)\n--\nnet/packet/af_packet.c-1337-\nnet/packet/af_packet.c:1338:static bool fanout_flow_is_huge(struct packet_sock *po, struct sk_buff *skb)\nnet/packet/af_packet.c-1339-{\n--\nnet/packet/af_packet.c-1357-\nnet/packet/af_packet.c:1358:static unsigned int fanout_demux_hash(struct packet_fanout *f,\nnet/packet/af_packet.c-1359-\t\t\t\t      struct sk_buff *skb,\n--\nnet/packet/af_packet.c-1364-\nnet/packet/af_packet.c:1365:static unsigned int fanout_demux_lb(struct packet_fanout *f,\nnet/packet/af_packet.c-1366-\t\t\t\t    struct sk_buff *skb,\n--\nnet/packet/af_packet.c-1373-\nnet/packet/af_packet.c:1374:static unsigned int fanout_demux_cpu(struct packet_fanout *f,\nnet/packet/af_packet.c-1375-\t\t\t\t     struct sk_buff *skb,\n--\nnet/packet/af_packet.c-1380-\nnet/packet/af_packet.c:1381:static unsigned int fanout_demux_rnd(struct packet_fanout *f,\nnet/packet/af_packet.c-1382-\t\t\t\t     struct sk_buff *skb,\n--\nnet/packet/af_packet.c-1387-\nnet/packet/af_packet.c:1388:static unsigned int fanout_demux_rollover(struct packet_fanout *f,\nnet/packet/af_packet.c-1389-\t\t\t\t\t  struct sk_buff *skb,\n--\nnet/packet/af_packet.c-1400-\t\tif (room == ROOM_NORMAL ||\nnet/packet/af_packet.c:1401:\t\t    (room == ROOM_LOW \u0026\u0026 !fanout_flow_is_huge(po, skb)))\nnet/packet/af_packet.c-1402-\t\t\treturn idx;\n--\nnet/packet/af_packet.c-1427-\nnet/packet/af_packet.c:1428:static unsigned int fanout_demux_qm(struct packet_fanout *f,\nnet/packet/af_packet.c-1429-\t\t\t\t    struct sk_buff *skb,\n--\nnet/packet/af_packet.c-1434-\nnet/packet/af_packet.c:1435:static unsigned int fanout_demux_bpf(struct packet_fanout *f,\nnet/packet/af_packet.c-1436-\t\t\t\t     struct sk_buff *skb,\n--\nnet/packet/af_packet.c-1450-\nnet/packet/af_packet.c:1451:static bool fanout_has_flag(struct packet_fanout *f, u16 flag)\nnet/packet/af_packet.c-1452-{\n--\nnet/packet/af_packet.c-1455-\nnet/packet/af_packet.c:1456:static int packet_rcv_fanout(struct sk_buff *skb, struct net_device *dev,\nnet/packet/af_packet.c-1457-\t\t\t     struct packet_type *pt, struct net_device *orig_dev)\nnet/packet/af_packet.c-1458-{\nnet/packet/af_packet.c:1459:\tstruct packet_fanout *f = pt-\u003eaf_packet_priv;\nnet/packet/af_packet.c-1460-\tunsigned int num = READ_ONCE(f-\u003enum_members);\n--\nnet/packet/af_packet.c-1469-\nnet/packet/af_packet.c:1470:\tif (fanout_has_flag(f, PACKET_FANOUT_FLAG_DEFRAG)) {\nnet/packet/af_packet.c-1471-\t\tskb = ip_check_defrag(net, skb, IP_DEFRAG_AF_PACKET);\n--\nnet/packet/af_packet.c-1477-\tdefault:\nnet/packet/af_packet.c:1478:\t\tidx = fanout_demux_hash(f, skb, num);\nnet/packet/af_packet.c-1479-\t\tbreak;\nnet/packet/af_packet.c-1480-\tcase PACKET_FANOUT_LB:\nnet/packet/af_packet.c:1481:\t\tidx = fanout_demux_lb(f, skb, num);\nnet/packet/af_packet.c-1482-\t\tbreak;\nnet/packet/af_packet.c-1483-\tcase PACKET_FANOUT_CPU:\nnet/packet/af_packet.c:1484:\t\tidx = fanout_demux_cpu(f, skb, num);\nnet/packet/af_packet.c-1485-\t\tbreak;\nnet/packet/af_packet.c-1486-\tcase PACKET_FANOUT_RND:\nnet/packet/af_packet.c:1487:\t\tidx = fanout_demux_rnd(f, skb, num);\nnet/packet/af_packet.c-1488-\t\tbreak;\nnet/packet/af_packet.c-1489-\tcase PACKET_FANOUT_QM:\nnet/packet/af_packet.c:1490:\t\tidx = fanout_demux_qm(f, skb, num);\nnet/packet/af_packet.c-1491-\t\tbreak;\nnet/packet/af_packet.c-1492-\tcase PACKET_FANOUT_ROLLOVER:\nnet/packet/af_packet.c:1493:\t\tidx = fanout_demux_rollover(f, skb, 0, false, num);\nnet/packet/af_packet.c-1494-\t\tbreak;\n--\nnet/packet/af_packet.c-1496-\tcase PACKET_FANOUT_EBPF:\nnet/packet/af_packet.c:1497:\t\tidx = fanout_demux_bpf(f, skb, num);\nnet/packet/af_packet.c-1498-\t\tbreak;\n--\nnet/packet/af_packet.c-1500-\nnet/packet/af_packet.c:1501:\tif (fanout_has_flag(f, PACKET_FANOUT_FLAG_ROLLOVER))\nnet/packet/af_packet.c:1502:\t\tidx = fanout_demux_rollover(f, skb, idx, true, num);\nnet/packet/af_packet.c-1503-\n--\nnet/packet/af_packet.c-1507-\nnet/packet/af_packet.c:1508:DEFINE_MUTEX(fanout_mutex);\nnet/packet/af_packet.c:1509:EXPORT_SYMBOL_GPL(fanout_mutex);\nnet/packet/af_packet.c:1510:static LIST_HEAD(fanout_list);\nnet/packet/af_packet.c:1511:static u16 fanout_next_id;\nnet/packet/af_packet.c-1512-\nnet/packet/af_packet.c:1513:static void __fanout_link(struct sock *sk, struct packet_sock *po)\nnet/packet/af_packet.c-1514-{\nnet/packet/af_packet.c:1515:\tstruct packet_fanout *f = po-\u003efanout;\nnet/packet/af_packet.c-1516-\n--\nnet/packet/af_packet.c-1525-\nnet/packet/af_packet.c:1526:static void __fanout_unlink(struct sock *sk, struct packet_sock *po)\nnet/packet/af_packet.c-1527-{\nnet/packet/af_packet.c:1528:\tstruct packet_fanout *f = po-\u003efanout;\nnet/packet/af_packet.c-1529-\tint i;\n--\nnet/packet/af_packet.c-1546-\nnet/packet/af_packet.c:1547:static bool match_fanout_group(struct packet_type *ptype, struct sock *sk)\nnet/packet/af_packet.c-1548-{\n--\nnet/packet/af_packet.c-1551-\nnet/packet/af_packet.c:1552:\treturn ptype-\u003eaf_packet_priv == pkt_sk(sk)-\u003efanout;\nnet/packet/af_packet.c-1553-}\nnet/packet/af_packet.c-1554-\nnet/packet/af_packet.c:1555:static void fanout_init_data(struct packet_fanout *f)\nnet/packet/af_packet.c-1556-{\n--\nnet/packet/af_packet.c-1567-\nnet/packet/af_packet.c:1568:static void __fanout_set_data_bpf(struct packet_fanout *f, struct bpf_prog *new)\nnet/packet/af_packet.c-1569-{\n--\nnet/packet/af_packet.c-1582-\nnet/packet/af_packet.c:1583:static int fanout_set_data_cbpf(struct packet_sock *po, sockptr_t data,\nnet/packet/af_packet.c-1584-\t\t\t\tunsigned int len)\n--\nnet/packet/af_packet.c-1600-\nnet/packet/af_packet.c:1601:\t__fanout_set_data_bpf(po-\u003efanout, new);\nnet/packet/af_packet.c-1602-\treturn 0;\n--\nnet/packet/af_packet.c-1604-\nnet/packet/af_packet.c:1605:static int fanout_set_data_ebpf(struct packet_sock *po, sockptr_t data,\nnet/packet/af_packet.c-1606-\t\t\t\tunsigned int len)\n--\nnet/packet/af_packet.c-1621-\nnet/packet/af_packet.c:1622:\t__fanout_set_data_bpf(po-\u003efanout, new);\nnet/packet/af_packet.c-1623-\treturn 0;\n--\nnet/packet/af_packet.c-1625-\nnet/packet/af_packet.c:1626:static int fanout_set_data(struct packet_sock *po, sockptr_t data,\nnet/packet/af_packet.c-1627-\t\t\t   unsigned int len)\nnet/packet/af_packet.c-1628-{\nnet/packet/af_packet.c:1629:\tswitch (po-\u003efanout-\u003etype) {\nnet/packet/af_packet.c-1630-\tcase PACKET_FANOUT_CBPF:\nnet/packet/af_packet.c:1631:\t\treturn fanout_set_data_cbpf(po, data, len);\nnet/packet/af_packet.c-1632-\tcase PACKET_FANOUT_EBPF:\nnet/packet/af_packet.c:1633:\t\treturn fanout_set_data_ebpf(po, data, len);\nnet/packet/af_packet.c-1634-\tdefault:\n--\nnet/packet/af_packet.c-1638-\nnet/packet/af_packet.c:1639:static void fanout_release_data(struct packet_fanout *f)\nnet/packet/af_packet.c-1640-{\n--\nnet/packet/af_packet.c-1643-\tcase PACKET_FANOUT_EBPF:\nnet/packet/af_packet.c:1644:\t\t__fanout_set_data_bpf(f, NULL);\nnet/packet/af_packet.c-1645-\t}\n--\nnet/packet/af_packet.c-1647-\nnet/packet/af_packet.c:1648:static bool __fanout_id_is_free(struct sock *sk, u16 candidate_id)\nnet/packet/af_packet.c-1649-{\nnet/packet/af_packet.c:1650:\tstruct packet_fanout *f;\nnet/packet/af_packet.c-1651-\nnet/packet/af_packet.c:1652:\tlist_for_each_entry(f, \u0026fanout_list, list) {\nnet/packet/af_packet.c-1653-\t\tif (f-\u003eid == candidate_id \u0026\u0026\n--\nnet/packet/af_packet.c-1660-\nnet/packet/af_packet.c:1661:static bool fanout_find_new_id(struct sock *sk, u16 *new_id)\nnet/packet/af_packet.c-1662-{\nnet/packet/af_packet.c:1663:\tu16 id = fanout_next_id;\nnet/packet/af_packet.c-1664-\nnet/packet/af_packet.c-1665-\tdo {\nnet/packet/af_packet.c:1666:\t\tif (__fanout_id_is_free(sk, id)) {\nnet/packet/af_packet.c-1667-\t\t\t*new_id = id;\nnet/packet/af_packet.c:1668:\t\t\tfanout_next_id = id + 1;\nnet/packet/af_packet.c-1669-\t\t\treturn true;\n--\nnet/packet/af_packet.c-1672-\t\tid++;\nnet/packet/af_packet.c:1673:\t} while (id != fanout_next_id);\nnet/packet/af_packet.c-1674-\n--\nnet/packet/af_packet.c-1677-\nnet/packet/af_packet.c:1678:static int fanout_add(struct sock *sk, struct fanout_args *args)\nnet/packet/af_packet.c-1679-{\n--\nnet/packet/af_packet.c-1682-\tu16 type_flags = args-\u003etype_flags;\nnet/packet/af_packet.c:1683:\tstruct packet_fanout *f, *match;\nnet/packet/af_packet.c-1684-\tu8 type = type_flags \u0026 0xff;\n--\nnet/packet/af_packet.c-1705-\nnet/packet/af_packet.c:1706:\tmutex_lock(\u0026fanout_mutex);\nnet/packet/af_packet.c-1707-\nnet/packet/af_packet.c-1708-\terr = -EALREADY;\nnet/packet/af_packet.c:1709:\tif (po-\u003efanout)\nnet/packet/af_packet.c-1710-\t\tgoto out;\n--\nnet/packet/af_packet.c-1727-\t\t}\nnet/packet/af_packet.c:1728:\t\tif (!fanout_find_new_id(sk, \u0026id)) {\nnet/packet/af_packet.c-1729-\t\t\terr = -ENOMEM;\n--\nnet/packet/af_packet.c-1736-\tmatch = NULL;\nnet/packet/af_packet.c:1737:\tlist_for_each_entry(f, \u0026fanout_list, list) {\nnet/packet/af_packet.c-1738-\t\tif (f-\u003eid == id \u0026\u0026\n--\nnet/packet/af_packet.c-1767-\t\trefcount_set(\u0026match-\u003esk_ref, 0);\nnet/packet/af_packet.c:1768:\t\tfanout_init_data(match);\nnet/packet/af_packet.c-1769-\t\tmatch-\u003eprot_hook.type = po-\u003eprot_hook.type;\nnet/packet/af_packet.c-1770-\t\tmatch-\u003eprot_hook.dev = po-\u003eprot_hook.dev;\nnet/packet/af_packet.c:1771:\t\tmatch-\u003eprot_hook.func = packet_rcv_fanout;\nnet/packet/af_packet.c-1772-\t\tmatch-\u003eprot_hook.af_packet_priv = match;\nnet/packet/af_packet.c-1773-\t\tmatch-\u003eprot_hook.af_packet_net = read_pnet(\u0026match-\u003enet);\nnet/packet/af_packet.c:1774:\t\tmatch-\u003eprot_hook.id_match = match_fanout_group;\nnet/packet/af_packet.c-1775-\t\tmatch-\u003emax_num_members = args-\u003emax_num_members;\nnet/packet/af_packet.c-1776-\t\tmatch-\u003eprot_hook.ignore_outgoing = type_flags \u0026 PACKET_FANOUT_FLAG_IGNORE_OUTGOING;\nnet/packet/af_packet.c:1777:\t\tlist_add(\u0026match-\u003elist, \u0026fanout_list);\nnet/packet/af_packet.c-1778-\t}\n--\nnet/packet/af_packet.c-1788-\t\t\t/* Paired with packet_setsockopt(PACKET_FANOUT_DATA) */\nnet/packet/af_packet.c:1789:\t\t\tWRITE_ONCE(po-\u003efanout, match);\nnet/packet/af_packet.c-1790-\n--\nnet/packet/af_packet.c-1795-\t\t\t\t__dev_remove_pack(\u0026po-\u003eprot_hook);\nnet/packet/af_packet.c:1796:\t\t\t\t__fanout_link(sk, po);\nnet/packet/af_packet.c-1797-\t\t\t}\n--\nnet/packet/af_packet.c-1809-\tkfree(rollover);\nnet/packet/af_packet.c:1810:\tmutex_unlock(\u0026fanout_mutex);\nnet/packet/af_packet.c-1811-\treturn err;\n--\nnet/packet/af_packet.c-1813-\nnet/packet/af_packet.c:1814:/* If pkt_sk(sk)-\u003efanout-\u003esk_ref is zero, this function removes\nnet/packet/af_packet.c:1815: * pkt_sk(sk)-\u003efanout from fanout_list and returns pkt_sk(sk)-\u003efanout.\nnet/packet/af_packet.c:1816: * It is the responsibility of the caller to call fanout_release_data() and\nnet/packet/af_packet.c:1817: * free the returned packet_fanout (after synchronize_net())\nnet/packet/af_packet.c-1818- */\nnet/packet/af_packet.c:1819:static struct packet_fanout *fanout_release(struct sock *sk)\nnet/packet/af_packet.c-1820-{\nnet/packet/af_packet.c-1821-\tstruct packet_sock *po = pkt_sk(sk);\nnet/packet/af_packet.c:1822:\tstruct packet_fanout *f;\nnet/packet/af_packet.c-1823-\nnet/packet/af_packet.c:1824:\tmutex_lock(\u0026fanout_mutex);\nnet/packet/af_packet.c:1825:\tf = po-\u003efanout;\nnet/packet/af_packet.c-1826-\tif (f) {\nnet/packet/af_packet.c:1827:\t\tpo-\u003efanout = NULL;\nnet/packet/af_packet.c-1828-\n--\nnet/packet/af_packet.c-1833-\t}\nnet/packet/af_packet.c:1834:\tmutex_unlock(\u0026fanout_mutex);\nnet/packet/af_packet.c-1835-\n--\nnet/packet/af_packet.c=3122=static int packet_release(struct socket *sock)\n--\nnet/packet/af_packet.c-3125-\tstruct packet_sock *po;\nnet/packet/af_packet.c:3126:\tstruct packet_fanout *f;\nnet/packet/af_packet.c-3127-\tstruct net *net;\n--\nnet/packet/af_packet.c-3166-\nnet/packet/af_packet.c:3167:\tf = fanout_release(sk);\nnet/packet/af_packet.c-3168-\n--\nnet/packet/af_packet.c-3172-\tif (f) {\nnet/packet/af_packet.c:3173:\t\tfanout_release_data(f);\nnet/packet/af_packet.c-3174-\t\tkvfree(f);\n--\nnet/packet/af_packet.c=3195=static int packet_do_bind(struct sock *sk, const char *name, int ifindex,\n--\nnet/packet/af_packet.c-3210-\nnet/packet/af_packet.c:3211:\tif (po-\u003efanout) {\nnet/packet/af_packet.c-3212-\t\tret = -EINVAL;\n--\nnet/packet/af_packet.c=3787=packet_setsockopt(struct socket *sock, int level, int optname, sockptr_t optval,\n--\nnet/packet/af_packet.c-3994-\t{\nnet/packet/af_packet.c:3995:\t\tstruct fanout_args args = { 0 };\nnet/packet/af_packet.c-3996-\n--\nnet/packet/af_packet.c-4001-\nnet/packet/af_packet.c:4002:\t\treturn fanout_add(sk, \u0026args);\nnet/packet/af_packet.c-4003-\t}\n--\nnet/packet/af_packet.c-4005-\t{\nnet/packet/af_packet.c:4006:\t\t/* Paired with the WRITE_ONCE() in fanout_add() */\nnet/packet/af_packet.c:4007:\t\tif (!READ_ONCE(po-\u003efanout))\nnet/packet/af_packet.c-4008-\t\t\treturn -EINVAL;\nnet/packet/af_packet.c-4009-\nnet/packet/af_packet.c:4010:\t\treturn fanout_set_data(po, optval, optlen);\nnet/packet/af_packet.c-4011-\t}\n--\nnet/packet/af_packet.c=4059=static int packet_getsockopt(struct socket *sock, int level, int optname,\n--\nnet/packet/af_packet.c-4148-\tcase PACKET_FANOUT:\nnet/packet/af_packet.c:4149:\t\tval = (po-\u003efanout ?\nnet/packet/af_packet.c:4150:\t\t       ((u32)po-\u003efanout-\u003eid |\nnet/packet/af_packet.c:4151:\t\t\t((u32)po-\u003efanout-\u003etype \u003c\u003c 16) |\nnet/packet/af_packet.c:4152:\t\t\t((u32)po-\u003efanout-\u003eflags \u003c\u003c 24)) :\nnet/packet/af_packet.c-4153-\t\t       0);\n--\nnet/packet/af_packet.c=4416=static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u,\n--\nnet/packet/af_packet.c-4565-\t * NETDEV_UNREGISTER may have invalidated the binding while bind_lock\nnet/packet/af_packet.c:4566:\t * was dropped above.  Do not re-add a fanout hook to a dead device.\nnet/packet/af_packet.c-4567-\t */\n"
}

9/2 2026/07/01 18:01 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 10451
							output: 38
							thoughts: 487
						

Thoughts:
**Analyzing the Bug Fix for Fanout Hooks**

Okay, so the comment explicitly states "Do not re-add a fanout hook to a dead device." The patch's core logic is to prevent the call to `register_prot_hook(sk)` when `READ_ONCE(po->ifindex)` is -1. This specifically happens within `packet_set_ring`.

Therefore, the issue is directly related to `PACKET_FANOUT` and the `packet_set_ring` function. The configuration in question here is `PACKET`, but let's quickly confirm if there are any other relevant configs. Ah, `fanout_set_data_ebpf` is used for `PACKET_FANOUT_EBPF`, but it's not relevant to this bug as it's specifically about `packet_set_ring` and `register_prot_hook`, right? This should apply regardless of whether fanout is actually *used* or not.

Now, let's trace the execution: `register_prot_hook(sk)` calls `__register_prot_hook(sk)`. Looking at the code:

```c
static void __register_prot_hook(struct sock *sk)
{
	struct packet_sock *po = pkt_sk(sk);

	if (!packet_sock_flag(po, PACKET_SOCK_RUNNING)) {
		if (po->fanout)
			__fanout_link(sk, po);
		else
			__dev_add_pack(&po->prot_hook);

		sock_hold(sk);
		packet_sock_flag_set(po, PACKET_SOCK_RUNNING, 1);
	}
}
```

If `po->ifindex` is -1, the device is dead. If `po->fanout` is set, it links to the fanout group. If it's *not* set, it adds the socket to `dev_add_pack`. In either case, whether it's fanout or not, the bug is about *re*-adding the socket to a dead device, which is incorrect. The comment mentions "fanout hook," but it's really the broader issue of `register_prot_hook` that's the problem.

Alright, let's take a look at the `packet_set_ring` function in `net/packet/af_packet.c` to see how this situation can arise.



10/2 2026/07/01 18:01 tool read-file
0m Args:
{
  "File": "net/packet/af_packet.c",
  "FirstLine": 4540,
  "LineCount": 50
}

Results:
{
  "Contents": "4540:\t\t\tspin_lock_bh(\u0026rb_queue-\u003elock);\n4541:\t\t\tswap(rb-\u003epg_vec, pg_vec);\n4542:\t\t\tif (po-\u003etp_version \u003c= TPACKET_V2)\n4543:\t\t\t\tswap(rb-\u003erx_owner_map, rx_owner_map);\n4544:\t\t\trb-\u003eframe_max = (req-\u003etp_frame_nr - 1);\n4545:\t\t\trb-\u003ehead = 0;\n4546:\t\t\trb-\u003eframe_size = req-\u003etp_frame_size;\n4547:\t\t\tspin_unlock_bh(\u0026rb_queue-\u003elock);\n4548:\t\n4549:\t\t\tswap(rb-\u003epg_vec_order, order);\n4550:\t\t\tswap(rb-\u003epg_vec_len, req-\u003etp_block_nr);\n4551:\t\n4552:\t\t\trb-\u003epg_vec_pages = req-\u003etp_block_size/PAGE_SIZE;\n4553:\t\t\tpo-\u003eprot_hook.func = (po-\u003erx_ring.pg_vec) ?\n4554:\t\t\t\t\t\t\ttpacket_rcv : packet_rcv;\n4555:\t\t\tskb_queue_purge(rb_queue);\n4556:\t\t\tif (atomic_long_read(\u0026po-\u003emapped))\n4557:\t\t\t\tpr_err(\"packet_mmap: vma is busy: %ld\\n\",\n4558:\t\t\t\t       atomic_long_read(\u0026po-\u003emapped));\n4559:\t\t}\n4560:\t\tmutex_unlock(\u0026po-\u003epg_vec_lock);\n4561:\t\n4562:\t\tspin_lock(\u0026po-\u003ebind_lock);\n4563:\t\tWRITE_ONCE(po-\u003enum, num);\n4564:\t\t/*\n4565:\t\t * NETDEV_UNREGISTER may have invalidated the binding while bind_lock\n4566:\t\t * was dropped above.  Do not re-add a fanout hook to a dead device.\n4567:\t\t */\n4568:\t\tif (was_running \u0026\u0026 READ_ONCE(po-\u003eifindex) != -1)\n4569:\t\t\tregister_prot_hook(sk);\n4570:\t\n4571:\t\tspin_unlock(\u0026po-\u003ebind_lock);\n4572:\t\tif (pg_vec \u0026\u0026 (po-\u003etp_version \u003e TPACKET_V2)) {\n4573:\t\t\t/* Because we don't support block-based V3 on tx-ring */\n4574:\t\t\tif (!tx_ring)\n4575:\t\t\t\tprb_shutdown_retire_blk_timer(po, rb_queue);\n4576:\t\t}\n4577:\t\n4578:\tout_free_pg_vec:\n4579:\t\tif (pg_vec) {\n4580:\t\t\tbitmap_free(rx_owner_map);\n4581:\t\t\tfree_pg_vec(pg_vec, order, req-\u003etp_block_nr);\n4582:\t\t}\n4583:\tout:\n4584:\t\treturn err;\n4585:\t}\n4586:\t\n4587:\tstatic int packet_mmap(struct file *file, struct socket *sock,\n4588:\t\t\tstruct vm_area_struct *vma)\n4589:\t{\n"
}

11/2 2026/07/01 18:01 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 12365
							output: 103
							thoughts: 145
						

Thoughts:
**My Assessment of the Patch's Significance**

Okay, so I've examined this patch, and I'm confident it's addressing a genuine functional issue. The key function to focus on is `packet_set_ring`. From the outset, I've got `PACKET` enabled.

My quick check confirms that `CONFIG_PACKET` is indeed sufficient for this. Nothing else seems to be required.

Therefore, I'm going to determine this patch is worth fuzzing and will return the following: `WorthFuzzing: true`, along with `FocusSymbols`: `["packet_set_ring"]` and `EnableConfigs: ["PACKET"]`.

My reasoning is straightforward: this patch rectifies a bug within the core AF_PACKET logic. Specifically, it prevents a fanout hook from being re-added to a device that is already dead within `packet_set_ring`. The fix involves a check to ensure the device is still valid ( `ifindex != -1`) before calling `register_prot_hook`. This is a clear functional change that needs further scrutiny.



12/2 2026/07/01 18:02 tool set-results
0m Args:
{
  "EnableConfigs": [
    "PACKET"
  ],
  "FocusSymbols": [
    "packet_set_ring"
  ],
  "Reasoning": "The patch fixes a bug where a fanout hook could be re-added to a dead device in packet_set_ring by checking if the device is dead (ifindex != -1) before calling register_prot_hook. This is a functional change in the core AF_PACKET logic.",
  "WorthFuzzing": true
}

Results:
{
  "EnableConfigs": [
    "PACKET"
  ],
  "FocusSymbols": [
    "packet_set_ring"
  ],
  "Reasoning": "The patch fixes a bug where a fanout hook could be re-added to a dead device in packet_set_ring by checking if the device is dead (ifindex != -1) before calling register_prot_hook. This is a functional change in the core AF_PACKET logic.",
  "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)