AI Trajectory


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

Results:
{
  "EnableConfigs": [
    "AMT",
    "IPV6"
  ],
  "FocusSymbols": [
    "amt_dev_xmit",
    "amt_igmpv3_report_handler",
    "amt_mldv2_report_handler",
    "amt_multicast_data_handler",
    "amt_membership_query_handler",
    "amt_update_handler",
    "amt_rcv"
  ],
  "Reasoning": "The patch fixes multiple use-after-free and dangling pointer bugs in the AMT (Automatic Multicast Tunneling) driver caused by `pskb_may_pull` and similar functions reallocating the skb head while holding pointers to network headers. It also adds `skb_cow_head` to prevent modifying cloned skbs. These are functional changes in reachable network driver code that should be fuzzed to ensure no further memory corruption issues exist.",
  "WorthFuzzing": true
}

1/1 2026/07/08 05:25 action read-patch-diff
0m Args:
null

Results:
{
  "PatchDiff": "commit 53fbf635769609f34ad9c450f015eef463647c78\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate:   Wed Jul 8 05:25:11 2026 +0000\n\n    syz-cluster: applied patch under review\n\ndiff --git a/drivers/net/amt.c b/drivers/net/amt.c\nindex f2f3139e38a599..f7375e40bc8f21 100644\n--- a/drivers/net/amt.c\n+++ b/drivers/net/amt.c\n@@ -1211,7 +1211,7 @@ static netdev_tx_t amt_dev_xmit(struct sk_buff *skb, struct net_device *dev)\n \t\t\tdata = true;\n \t\t}\n \t\tv6 = false;\n-\t\tgroup.ip4 = iph-\u003edaddr;\n+\t\tgroup.ip4 = ip_hdr(skb)-\u003edaddr;\n #if IS_ENABLED(CONFIG_IPV6)\n \t} else if (iph-\u003eversion == 6) {\n \t\tip6h = ipv6_hdr(skb);\n@@ -1235,7 +1235,7 @@ static netdev_tx_t amt_dev_xmit(struct sk_buff *skb, struct net_device *dev)\n \t\t\tdata = true;\n \t\t}\n \t\tv6 = true;\n-\t\tgroup.ip6 = ip6h-\u003edaddr;\n+\t\tgroup.ip6 = ipv6_hdr(skb)-\u003edaddr;\n #endif\n \t} else {\n \t\tdev-\u003estats.tx_errors++;\n@@ -1278,12 +1278,12 @@ static netdev_tx_t amt_dev_xmit(struct sk_buff *skb, struct net_device *dev)\n \t\t\thlist_for_each_entry_rcu(gnode, \u0026tunnel-\u003egroups[hash],\n \t\t\t\t\t\t node) {\n \t\t\t\tif (!v6) {\n-\t\t\t\t\tif (gnode-\u003egroup_addr.ip4 == iph-\u003edaddr)\n+\t\t\t\t\tif (gnode-\u003egroup_addr.ip4 == group.ip4)\n \t\t\t\t\t\tgoto found;\n #if IS_ENABLED(CONFIG_IPV6)\n \t\t\t\t} else {\n \t\t\t\t\tif (ipv6_addr_equal(\u0026gnode-\u003egroup_addr.ip6,\n-\t\t\t\t\t\t\t    \u0026ip6h-\u003edaddr))\n+\t\t\t\t\t\t\t    \u0026group.ip6))\n \t\t\t\t\t\tgoto found;\n #endif\n \t\t\t\t}\n@@ -2000,14 +2000,22 @@ static void amt_igmpv3_report_handler(struct amt_dev *amt, struct sk_buff *skb,\n \tstruct igmpv3_report *ihrv3 = igmpv3_report_hdr(skb);\n \tint len = skb_transport_offset(skb) + sizeof(*ihrv3);\n \tvoid *zero_grec = (void *)\u0026igmpv3_zero_grec;\n-\tstruct iphdr *iph = ip_hdr(skb);\n \tstruct amt_group_node *gnode;\n \tunion amt_addr group, host;\n \tstruct igmpv3_grec *grec;\n+\t__be32 saddr;\n \tu16 nsrcs;\n+\tu16 ngrec;\n \tint i;\n \n-\tfor (i = 0; i \u003c ntohs(ihrv3-\u003engrec); i++) {\n+\t/* ihrv3 and ip_hdr() point into the skb head, which the\n+\t * ip_mc_may_pull() calls below can reallocate.  Read every field\n+\t * that is used after a pull before the first one runs.\n+\t */\n+\tsaddr = ip_hdr(skb)-\u003esaddr;\n+\tngrec = ntohs(ihrv3-\u003engrec);\n+\n+\tfor (i = 0; i \u003c ngrec; i++) {\n \t\tlen += sizeof(*grec);\n \t\tif (!ip_mc_may_pull(skb, len))\n \t\t\tbreak;\n@@ -2019,10 +2027,14 @@ static void amt_igmpv3_report_handler(struct amt_dev *amt, struct sk_buff *skb,\n \t\tif (!ip_mc_may_pull(skb, len))\n \t\t\tbreak;\n \n+\t\t/* ip_mc_may_pull() may have reallocated the head. */\n+\t\tgrec = (void *)(skb-\u003edata + len - sizeof(*grec) -\n+\t\t\t\tnsrcs * sizeof(__be32));\n+\n \t\tmemset(\u0026group, 0, sizeof(union amt_addr));\n \t\tgroup.ip4 = grec-\u003egrec_mca;\n \t\tmemset(\u0026host, 0, sizeof(union amt_addr));\n-\t\thost.ip4 = iph-\u003esaddr;\n+\t\thost.ip4 = saddr;\n \t\tgnode = amt_lookup_group(tunnel, \u0026group, \u0026host, false);\n \t\tif (!gnode) {\n \t\t\tgnode = amt_add_group(amt, tunnel, \u0026group, \u0026host,\n@@ -2162,14 +2174,22 @@ static void amt_mldv2_report_handler(struct amt_dev *amt, struct sk_buff *skb,\n \tstruct mld2_report *mld2r = (struct mld2_report *)icmp6_hdr(skb);\n \tint len = skb_transport_offset(skb) + sizeof(*mld2r);\n \tvoid *zero_grec = (void *)\u0026mldv2_zero_grec;\n-\tstruct ipv6hdr *ip6h = ipv6_hdr(skb);\n \tstruct amt_group_node *gnode;\n \tunion amt_addr group, host;\n \tstruct mld2_grec *grec;\n+\tstruct in6_addr saddr;\n \tu16 nsrcs;\n+\tu16 ngrec;\n \tint i;\n \n-\tfor (i = 0; i \u003c ntohs(mld2r-\u003emld2r_ngrec); i++) {\n+\t/* mld2r and ipv6_hdr() point into the skb head, which the\n+\t * ipv6_mc_may_pull() calls below can reallocate.  Read every field\n+\t * that is used after a pull before the first one runs.\n+\t */\n+\tsaddr = ipv6_hdr(skb)-\u003esaddr;\n+\tngrec = ntohs(mld2r-\u003emld2r_ngrec);\n+\n+\tfor (i = 0; i \u003c ngrec; i++) {\n \t\tlen += sizeof(*grec);\n \t\tif (!ipv6_mc_may_pull(skb, len))\n \t\t\tbreak;\n@@ -2181,10 +2201,14 @@ static void amt_mldv2_report_handler(struct amt_dev *amt, struct sk_buff *skb,\n \t\tif (!ipv6_mc_may_pull(skb, len))\n \t\t\tbreak;\n \n+\t\t/* ipv6_mc_may_pull() may have reallocated the head. */\n+\t\tgrec = (void *)(skb-\u003edata + len - sizeof(*grec) -\n+\t\t\t\tnsrcs * sizeof(struct in6_addr));\n+\n \t\tmemset(\u0026group, 0, sizeof(union amt_addr));\n \t\tgroup.ip6 = grec-\u003egrec_mca;\n \t\tmemset(\u0026host, 0, sizeof(union amt_addr));\n-\t\thost.ip6 = ip6h-\u003esaddr;\n+\t\thost.ip6 = saddr;\n \t\tgnode = amt_lookup_group(tunnel, \u0026group, \u0026host, true);\n \t\tif (!gnode) {\n \t\t\tgnode = amt_add_group(amt, tunnel, \u0026group, \u0026host,\n@@ -2305,7 +2329,12 @@ static bool amt_multicast_data_handler(struct amt_dev *amt, struct sk_buff *skb)\n \tskb_push(skb, sizeof(*eth));\n \tskb_reset_mac_header(skb);\n \tskb_pull(skb, sizeof(*eth));\n-\teth = eth_hdr(skb);\n+\n+\t/* The L2 header is rewritten below; make the head private first so a\n+\t * cloned skb (for example one taken by a packet tap) is not modified.\n+\t */\n+\tif (skb_cow_head(skb, 0))\n+\t\treturn true;\n \n \tif (!pskb_may_pull(skb, sizeof(*iph)))\n \t\treturn true;\n@@ -2315,6 +2344,8 @@ static bool amt_multicast_data_handler(struct amt_dev *amt, struct sk_buff *skb)\n \t\tif (!ipv4_is_multicast(iph-\u003edaddr))\n \t\t\treturn true;\n \t\tskb-\u003eprotocol = htons(ETH_P_IP);\n+\t\t/* pskb_may_pull() above may have reallocated the head. */\n+\t\teth = eth_hdr(skb);\n \t\teth-\u003eh_proto = htons(ETH_P_IP);\n \t\tip_eth_mc_map(iph-\u003edaddr, eth-\u003eh_dest);\n #if IS_ENABLED(CONFIG_IPV6)\n@@ -2328,6 +2359,8 @@ static bool amt_multicast_data_handler(struct amt_dev *amt, struct sk_buff *skb)\n \t\tif (!ipv6_addr_is_multicast(\u0026ip6h-\u003edaddr))\n \t\t\treturn true;\n \t\tskb-\u003eprotocol = htons(ETH_P_IPV6);\n+\t\t/* pskb_may_pull() above may have reallocated the head. */\n+\t\teth = eth_hdr(skb);\n \t\teth-\u003eh_proto = htons(ETH_P_IPV6);\n \t\tipv6_eth_mc_map(\u0026ip6h-\u003edaddr, eth-\u003eh_dest);\n #endif\n@@ -2353,8 +2386,10 @@ static bool amt_membership_query_handler(struct amt_dev *amt,\n \tstruct amt_header_membership_query *amtmq;\n \tstruct igmpv3_query *ihv3;\n \tstruct ethhdr *eth, *oeth;\n+\tu8 h_source[ETH_ALEN];\n \tstruct iphdr *iph;\n \tint hdr_size, len;\n+\tu64 response_mac;\n \n \thdr_size = sizeof(*amtmq) + sizeof(struct udphdr);\n \tif (!pskb_may_pull(skb, hdr_size))\n@@ -2367,6 +2402,12 @@ static bool amt_membership_query_handler(struct amt_dev *amt,\n \tif (amtmq-\u003enonce != amt-\u003enonce)\n \t\treturn true;\n \n+\t/* iptunnel_pull_header() and the pskb_may_pull() calls below can\n+\t * reallocate the skb head, so amtmq would dangle.  Snapshot the only\n+\t * field used afterwards.\n+\t */\n+\tresponse_mac = amtmq-\u003eresponse_mac;\n+\n \thdr_size -= sizeof(*eth);\n \tif (iptunnel_pull_header(skb, hdr_size, htons(ETH_P_TEB), false))\n \t\treturn true;\n@@ -2376,6 +2417,13 @@ static bool amt_membership_query_handler(struct amt_dev *amt,\n \tskb_pull(skb, sizeof(*eth));\n \tskb_reset_network_header(skb);\n \teth = eth_hdr(skb);\n+\t/* Snapshot the outer source MAC before a later pull can free it. */\n+\tether_addr_copy(h_source, oeth-\u003eh_source);\n+\t/* The L2 header is rewritten below; make the head private first so a\n+\t * cloned skb (for example one taken by a packet tap) is not modified.\n+\t */\n+\tif (skb_cow_head(skb, 0))\n+\t\treturn true;\n \tif (!pskb_may_pull(skb, sizeof(*iph)))\n \t\treturn true;\n \n@@ -2388,6 +2436,8 @@ static bool amt_membership_query_handler(struct amt_dev *amt,\n \t\t\t\t   sizeof(*ihv3)))\n \t\t\treturn true;\n \n+\t\t/* pskb_may_pull() above may have reallocated the head. */\n+\t\tiph = ip_hdr(skb);\n \t\tif (!ipv4_is_multicast(iph-\u003edaddr))\n \t\t\treturn true;\n \n@@ -2395,10 +2445,11 @@ static bool amt_membership_query_handler(struct amt_dev *amt,\n \t\tskb_reset_transport_header(skb);\n \t\tskb_push(skb, sizeof(*iph) + AMT_IPHDR_OPTS);\n \t\tWRITE_ONCE(amt-\u003eready4, true);\n-\t\tamt-\u003emac = amtmq-\u003eresponse_mac;\n+\t\tamt-\u003emac = response_mac;\n \t\tamt-\u003ereq_cnt = 0;\n \t\tamt-\u003eqi = ihv3-\u003eqqic;\n \t\tskb-\u003eprotocol = htons(ETH_P_IP);\n+\t\teth = eth_hdr(skb);\n \t\teth-\u003eh_proto = htons(ETH_P_IP);\n \t\tip_eth_mc_map(iph-\u003edaddr, eth-\u003eh_dest);\n #if IS_ENABLED(CONFIG_IPV6)\n@@ -2421,10 +2472,11 @@ static bool amt_membership_query_handler(struct amt_dev *amt,\n \t\tskb_reset_transport_header(skb);\n \t\tskb_push(skb, sizeof(*ip6h) + AMT_IP6HDR_OPTS);\n \t\tWRITE_ONCE(amt-\u003eready6, true);\n-\t\tamt-\u003emac = amtmq-\u003eresponse_mac;\n+\t\tamt-\u003emac = response_mac;\n \t\tamt-\u003ereq_cnt = 0;\n \t\tamt-\u003eqi = mld2q-\u003emld2q_qqic;\n \t\tskb-\u003eprotocol = htons(ETH_P_IPV6);\n+\t\teth = eth_hdr(skb);\n \t\teth-\u003eh_proto = htons(ETH_P_IPV6);\n \t\tipv6_eth_mc_map(\u0026ip6h-\u003edaddr, eth-\u003eh_dest);\n #endif\n@@ -2432,7 +2484,7 @@ static bool amt_membership_query_handler(struct amt_dev *amt,\n \t\treturn true;\n \t}\n \n-\tether_addr_copy(eth-\u003eh_source, oeth-\u003eh_source);\n+\tether_addr_copy(eth-\u003eh_source, h_source);\n \tskb-\u003epkt_type = PACKET_MULTICAST;\n \tskb-\u003eip_summed = CHECKSUM_NONE;\n \tlen = skb-\u003elen;\n@@ -2455,8 +2507,13 @@ static bool amt_update_handler(struct amt_dev *amt, struct sk_buff *skb)\n \tstruct ethhdr *eth;\n \tstruct iphdr *iph;\n \tint len, hdr_size;\n+\t__be32 saddr;\n \n-\tiph = ip_hdr(skb);\n+\t/* ip_hdr() points into the skb head, which the pskb_may_pull() /\n+\t * iptunnel_pull_header() calls below can reallocate.  Snapshot the\n+\t * source address used for the tunnel lookup before the first pull.\n+\t */\n+\tsaddr = ip_hdr(skb)-\u003esaddr;\n \n \thdr_size = sizeof(*amtmu) + sizeof(struct udphdr);\n \tif (!pskb_may_pull(skb, hdr_size))\n@@ -2472,7 +2529,7 @@ static bool amt_update_handler(struct amt_dev *amt, struct sk_buff *skb)\n \tskb_reset_network_header(skb);\n \n \tlist_for_each_entry_rcu(tunnel, \u0026amt-\u003etunnel_list, list) {\n-\t\tif (tunnel-\u003eip4 == iph-\u003esaddr) {\n+\t\tif (tunnel-\u003eip4 == saddr) {\n \t\t\tif ((amtmu-\u003enonce == tunnel-\u003enonce \u0026\u0026\n \t\t\t     amtmu-\u003eresponse_mac == tunnel-\u003emac)) {\n \t\t\t\tmod_delayed_work(amt_wq, \u0026tunnel-\u003egc_wq,\n@@ -2492,6 +2549,12 @@ static bool amt_update_handler(struct amt_dev *amt, struct sk_buff *skb)\n \tif (!pskb_may_pull(skb, sizeof(*iph)))\n \t\treturn true;\n \n+\t/* The L2 header is rewritten below; make the head private first so a\n+\t * cloned skb (for example one taken by a packet tap) is not modified.\n+\t */\n+\tif (skb_cow_head(skb, 0))\n+\t\treturn true;\n+\n \tiph = ip_hdr(skb);\n \tif (iph-\u003eversion == 4) {\n \t\tif (ip_mc_check_igmp(skb)) {\n@@ -2508,6 +2571,10 @@ static bool amt_update_handler(struct amt_dev *amt, struct sk_buff *skb)\n \t\teth = eth_hdr(skb);\n \t\tskb-\u003eprotocol = htons(ETH_P_IP);\n \t\teth-\u003eh_proto = htons(ETH_P_IP);\n+\t\t/* ip_mc_check_igmp() and the report handler may have\n+\t\t * reallocated the head; re-derive iph.\n+\t\t */\n+\t\tiph = ip_hdr(skb);\n \t\tip_eth_mc_map(iph-\u003edaddr, eth-\u003eh_dest);\n #if IS_ENABLED(CONFIG_IPV6)\n \t} else if (iph-\u003eversion == 6) {\n@@ -2527,6 +2594,10 @@ static bool amt_update_handler(struct amt_dev *amt, struct sk_buff *skb)\n \t\teth = eth_hdr(skb);\n \t\tskb-\u003eprotocol = htons(ETH_P_IPV6);\n \t\teth-\u003eh_proto = htons(ETH_P_IPV6);\n+\t\t/* ipv6_mc_check_mld() and the report handler may have\n+\t\t * reallocated the head; re-derive ip6h.\n+\t\t */\n+\t\tip6h = ipv6_hdr(skb);\n \t\tipv6_eth_mc_map(\u0026ip6h-\u003edaddr, eth-\u003eh_dest);\n #endif\n \t} else {\n@@ -2772,7 +2843,7 @@ static void amt_gw_rcv(struct amt_dev *amt, struct sk_buff *skb)\n static int amt_rcv(struct sock *sk, struct sk_buff *skb)\n {\n \tstruct amt_dev *amt;\n-\tstruct iphdr *iph;\n+\t__be32 saddr;\n \tint type;\n \tbool err;\n \n@@ -2785,7 +2856,11 @@ static int amt_rcv(struct sock *sk, struct sk_buff *skb)\n \t}\n \n \tskb-\u003edev = amt-\u003edev;\n-\tiph = ip_hdr(skb);\n+\t/* amt_parse_type() calls pskb_may_pull(), which can reallocate the\n+\t * skb head and leave a cached ip_hdr() dangling.  Snapshot the source\n+\t * address used below before the pull.\n+\t */\n+\tsaddr = ip_hdr(skb)-\u003esaddr;\n \ttype = amt_parse_type(skb);\n \tif (type == -1) {\n \t\terr = true;\n@@ -2795,7 +2870,7 @@ static int amt_rcv(struct sock *sk, struct sk_buff *skb)\n \tif (amt-\u003emode == AMT_MODE_GATEWAY) {\n \t\tswitch (type) {\n \t\tcase AMT_MSG_ADVERTISEMENT:\n-\t\t\tif (iph-\u003esaddr != amt-\u003ediscovery_ip) {\n+\t\t\tif (saddr != amt-\u003ediscovery_ip) {\n \t\t\t\tnetdev_dbg(amt-\u003edev, \"Invalid Relay IP\\n\");\n \t\t\t\terr = true;\n \t\t\t\tgoto drop;\n@@ -2807,7 +2882,7 @@ static int amt_rcv(struct sock *sk, struct sk_buff *skb)\n \t\t\t}\n \t\t\tgoto out;\n \t\tcase AMT_MSG_MULTICAST_DATA:\n-\t\t\tif (iph-\u003esaddr != amt-\u003eremote_ip) {\n+\t\t\tif (saddr != amt-\u003eremote_ip) {\n \t\t\t\tnetdev_dbg(amt-\u003edev, \"Invalid Relay IP\\n\");\n \t\t\t\terr = true;\n \t\t\t\tgoto drop;\n@@ -2818,7 +2893,7 @@ static int amt_rcv(struct sock *sk, struct sk_buff *skb)\n \t\t\telse\n \t\t\t\tgoto out;\n \t\tcase AMT_MSG_MEMBERSHIP_QUERY:\n-\t\t\tif (iph-\u003esaddr != amt-\u003eremote_ip) {\n+\t\t\tif (saddr != amt-\u003eremote_ip) {\n \t\t\t\tnetdev_dbg(amt-\u003edev, \"Invalid Relay IP\\n\");\n \t\t\t\terr = true;\n \t\t\t\tgoto drop;\n"
}

2/1 2026/07/08 05:25 agent patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
{
  "EnableConfigs": [
    "AMT",
    "IPV6"
  ],
  "FocusSymbols": [
    "amt_dev_xmit",
    "amt_igmpv3_report_handler",
    "amt_mldv2_report_handler",
    "amt_multicast_data_handler",
    "amt_membership_query_handler",
    "amt_update_handler",
    "amt_rcv"
  ],
  "Reasoning": "The patch fixes multiple use-after-free and dangling pointer bugs in the AMT (Automatic Multicast Tunneling) driver caused by `pskb_may_pull` and similar functions reallocating the skb head while holding pointers to network headers. It also adds `skb_cow_head` to prevent modifying cloned skbs. These are functional changes in reachable network driver code that should be fuzzed to ensure no further memory corruption issues exist.",
  "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 53fbf635769609f34ad9c450f015eef463647c78
Author: syz-cluster <triage@syzkaller.com>
Date:   Wed Jul 8 05:25:11 2026 +0000

    syz-cluster: applied patch under review

diff --git a/drivers/net/amt.c b/drivers/net/amt.c
index f2f3139e38a599..f7375e40bc8f21 100644
--- a/drivers/net/amt.c
+++ b/drivers/net/amt.c
@@ -1211,7 +1211,7 @@ static netdev_tx_t amt_dev_xmit(struct sk_buff *skb, struct net_device *dev)
 			data = true;
 		}
 		v6 = false;
-		group.ip4 = iph->daddr;
+		group.ip4 = ip_hdr(skb)->daddr;
 #if IS_ENABLED(CONFIG_IPV6)
 	} else if (iph->version == 6) {
 		ip6h = ipv6_hdr(skb);
@@ -1235,7 +1235,7 @@ static netdev_tx_t amt_dev_xmit(struct sk_buff *skb, struct net_device *dev)
 			data = true;
 		}
 		v6 = true;
-		group.ip6 = ip6h->daddr;
+		group.ip6 = ipv6_hdr(skb)->daddr;
 #endif
 	} else {
 		dev->stats.tx_errors++;
@@ -1278,12 +1278,12 @@ static netdev_tx_t amt_dev_xmit(struct sk_buff *skb, struct net_device *dev)
 			hlist_for_each_entry_rcu(gnode, &tunnel->groups[hash],
 						 node) {
 				if (!v6) {
-					if (gnode->group_addr.ip4 == iph->daddr)
+					if (gnode->group_addr.ip4 == group.ip4)
 						goto found;
 #if IS_ENABLED(CONFIG_IPV6)
 				} else {
 					if (ipv6_addr_equal(&gnode->group_addr.ip6,
-							    &ip6h->daddr))
+							    &group.ip6))
 						goto found;
 #endif
 				}
@@ -2000,14 +2000,22 @@ static void amt_igmpv3_report_handler(struct amt_dev *amt, struct sk_buff *skb,
 	struct igmpv3_report *ihrv3 = igmpv3_report_hdr(skb);
 	int len = skb_transport_offset(skb) + sizeof(*ihrv3);
 	void *zero_grec = (void *)&igmpv3_zero_grec;
-	struct iphdr *iph = ip_hdr(skb);
 	struct amt_group_node *gnode;
 	union amt_addr group, host;
 	struct igmpv3_grec *grec;
+	__be32 saddr;
 	u16 nsrcs;
+	u16 ngrec;
 	int i;
 
-	for (i = 0; i < ntohs(ihrv3->ngrec); i++) {
+	/* ihrv3 and ip_hdr() point into the skb head, which the
+	 * ip_mc_may_pull() calls below can reallocate.  Read every field
+	 * that is used after a pull before the first one runs.
+	 */
+	saddr = ip_hdr(skb)->saddr;
+	ngrec = ntohs(ihrv3->ngrec);
+
+	for (i = 0; i < ngrec; i++) {
 		len += sizeof(*grec);
 		if (!ip_mc_may_pull(skb, len))
 			break;
@@ -2019,10 +2027,14 @@ static void amt_igmpv3_report_handler(struct amt_dev *amt, struct sk_buff *skb,
 		if (!ip_mc_may_pull(skb, len))
 			break;
 
+		/* ip_mc_may_pull() may have reallocated the head. */
+		grec = (void *)(skb->data + len - sizeof(*grec) -
+				nsrcs * sizeof(__be32));
+
 		memset(&group, 0, sizeof(union amt_addr));
 		group.ip4 = grec->grec_mca;
 		memset(&host, 0, sizeof(union amt_addr));
-		host.ip4 = iph->saddr;
+		host.ip4 = saddr;
 		gnode = amt_lookup_group(tunnel, &group, &host, false);
 		if (!gnode) {
 			gnode = amt_add_group(amt, tunnel, &group, &host,
@@ -2162,14 +2174,22 @@ static void amt_mldv2_report_handler(struct amt_dev *amt, struct sk_buff *skb,
 	struct mld2_report *mld2r = (struct mld2_report *)icmp6_hdr(skb);
 	int len = skb_transport_offset(skb) + sizeof(*mld2r);
 	void *zero_grec = (void *)&mldv2_zero_grec;
-	struct ipv6hdr *ip6h = ipv6_hdr(skb);
 	struct amt_group_node *gnode;
 	union amt_addr group, host;
 	struct mld2_grec *grec;
+	struct in6_addr saddr;
 	u16 nsrcs;
+	u16 ngrec;
 	int i;
 
-	for (i = 0; i < ntohs(mld2r->mld2r_ngrec); i++) {
+	/* mld2r and ipv6_hdr() point into the skb head, which the
+	 * ipv6_mc_may_pull() calls below can reallocate.  Read every field
+	 * that is used after a pull before the first one runs.
+	 */
+	saddr = ipv6_hdr(skb)->saddr;
+	ngrec = ntohs(mld2r->mld2r_ngrec);
+
+	for (i = 0; i < ngrec; i++) {
 		len += sizeof(*grec);
 		if (!ipv6_mc_may_pull(skb, len))
 			break;
@@ -2181,10 +2201,14 @@ static void amt_mldv2_report_handler(struct amt_dev *amt, struct sk_buff *skb,
 		if (!ipv6_mc_may_pull(skb, len))
 			break;
 
+		/* ipv6_mc_may_pull() may have reallocated the head. */
+		grec = (void *)(skb->data + len - sizeof(*grec) -
+				nsrcs * sizeof(struct in6_addr));
+
 		memset(&group, 0, sizeof(union amt_addr));
 		group.ip6 = grec->grec_mca;
 		memset(&host, 0, sizeof(union amt_addr));
-		host.ip6 = ip6h->saddr;
+		host.ip6 = saddr;
 		gnode = amt_lookup_group(tunnel, &group, &host, true);
 		if (!gnode) {
 			gnode = amt_add_group(amt, tunnel, &group, &host,
@@ -2305,7 +2329,12 @@ static bool amt_multicast_data_handler(struct amt_dev *amt, struct sk_buff *skb)
 	skb_push(skb, sizeof(*eth));
 	skb_reset_mac_header(skb);
 	skb_pull(skb, sizeof(*eth));
-	eth = eth_hdr(skb);
+
+	/* The L2 header is rewritten below; make the head private first so a
+	 * cloned skb (for example one taken by a packet tap) is not modified.
+	 */
+	if (skb_cow_head(skb, 0))
+		return true;
 
 	if (!pskb_may_pull(skb, sizeof(*iph)))
 		return true;
@@ -2315,6 +2344,8 @@ static bool amt_multicast_data_handler(struct amt_dev *amt, struct sk_buff *skb)
 		if (!ipv4_is_multicast(iph->daddr))
 			return true;
 		skb->protocol = htons(ETH_P_IP);
+		/* pskb_may_pull() above may have reallocated the head. */
+		eth = eth_hdr(skb);
 		eth->h_proto = htons(ETH_P_IP);
 		ip_eth_mc_map(iph->daddr, eth->h_dest);
 #if IS_ENABLED(CONFIG_IPV6)
@@ -2328,6 +2359,8 @@ static bool amt_multicast_data_handler(struct amt_dev *amt, struct sk_buff *skb)
 		if (!ipv6_addr_is_multicast(&ip6h->daddr))
 			return true;
 		skb->protocol = htons(ETH_P_IPV6);
+		/* pskb_may_pull() above may have reallocated the head. */
+		eth = eth_hdr(skb);
 		eth->h_proto = htons(ETH_P_IPV6);
 		ipv6_eth_mc_map(&ip6h->daddr, eth->h_dest);
 #endif
@@ -2353,8 +2386,10 @@ static bool amt_membership_query_handler(struct amt_dev *amt,
 	struct amt_header_membership_query *amtmq;
 	struct igmpv3_query *ihv3;
 	struct ethhdr *eth, *oeth;
+	u8 h_source[ETH_ALEN];
 	struct iphdr *iph;
 	int hdr_size, len;
+	u64 response_mac;
 
 	hdr_size = sizeof(*amtmq) + sizeof(struct udphdr);
 	if (!pskb_may_pull(skb, hdr_size))
@@ -2367,6 +2402,12 @@ static bool amt_membership_query_handler(struct amt_dev *amt,
 	if (amtmq->nonce != amt->nonce)
 		return true;
 
+	/* iptunnel_pull_header() and the pskb_may_pull() calls below can
+	 * reallocate the skb head, so amtmq would dangle.  Snapshot the only
+	 * field used afterwards.
+	 */
+	response_mac = amtmq->response_mac;
+
 	hdr_size -= sizeof(*eth);
 	if (iptunnel_pull_header(skb, hdr_size, htons(ETH_P_TEB), false))
 		return true;
@@ -2376,6 +2417,13 @@ static bool amt_membership_query_handler(struct amt_dev *amt,
 	skb_pull(skb, sizeof(*eth));
 	skb_reset_network_header(skb);
 	eth = eth_hdr(skb);
+	/* Snapshot the outer source MAC before a later pull can free it. */
+	ether_addr_copy(h_source, oeth->h_source);
+	/* The L2 header is rewritten below; make the head private first so a
+	 * cloned skb (for example one taken by a packet tap) is not modified.
+	 */
+	if (skb_cow_head(skb, 0))
+		return true;
 	if (!pskb_may_pull(skb, sizeof(*iph)))
 		return true;
 
@@ -2388,6 +2436,8 @@ static bool amt_membership_query_handler(struct amt_dev *amt,
 				   sizeof(*ihv3)))
 			return true;
 
+		/* pskb_may_pull() above may have reallocated the head. */
+		iph = ip_hdr(skb);
 		if (!ipv4_is_multicast(iph->daddr))
 			return true;
 
@@ -2395,10 +2445,11 @@ static bool amt_membership_query_handler(struct amt_dev *amt,
 		skb_reset_transport_header(skb);
 		skb_push(skb, sizeof(*iph) + AMT_IPHDR_OPTS);
 		WRITE_ONCE(amt->ready4, true);
-		amt->mac = amtmq->response_mac;
+		amt->mac = response_mac;
 		amt->req_cnt = 0;
 		amt->qi = ihv3->qqic;
 		skb->protocol = htons(ETH_P_IP);
+		eth = eth_hdr(skb);
 		eth->h_proto = htons(ETH_P_IP);
 		ip_eth_mc_map(iph->daddr, eth->h_dest);
 #if IS_ENABLED(CONFIG_IPV6)
@@ -2421,10 +2472,11 @@ static bool amt_membership_query_handler(struct amt_dev *amt,
 		skb_reset_transport_header(skb);
 		skb_push(skb, sizeof(*ip6h) + AMT_IP6HDR_OPTS);
 		WRITE_ONCE(amt->ready6, true);
-		amt->mac = amtmq->response_mac;
+		amt->mac = response_mac;
 		amt->req_cnt = 0;
 		amt->qi = mld2q->mld2q_qqic;
 		skb->protocol = htons(ETH_P_IPV6);
+		eth = eth_hdr(skb);
 		eth->h_proto = htons(ETH_P_IPV6);
 		ipv6_eth_mc_map(&ip6h->daddr, eth->h_dest);
 #endif
@@ -2432,7 +2484,7 @@ static bool amt_membership_query_handler(struct amt_dev *amt,
 		return true;
 	}
 
-	ether_addr_copy(eth->h_source, oeth->h_source);
+	ether_addr_copy(eth->h_source, h_source);
 	skb->pkt_type = PACKET_MULTICAST;
 	skb->ip_summed = CHECKSUM_NONE;
 	len = skb->len;
@@ -2455,8 +2507,13 @@ static bool amt_update_handler(struct amt_dev *amt, struct sk_buff *skb)
 	struct ethhdr *eth;
 	struct iphdr *iph;
 	int len, hdr_size;
+	__be32 saddr;
 
-	iph = ip_hdr(skb);
+	/* ip_hdr() points into the skb head, which the pskb_may_pull() /
+	 * iptunnel_pull_header() calls below can reallocate.  Snapshot the
+	 * source address used for the tunnel lookup before the first pull.
+	 */
+	saddr = ip_hdr(skb)->saddr;
 
 	hdr_size = sizeof(*amtmu) + sizeof(struct udphdr);
 	if (!pskb_may_pull(skb, hdr_size))
@@ -2472,7 +2529,7 @@ static bool amt_update_handler(struct amt_dev *amt, struct sk_buff *skb)
 	skb_reset_network_header(skb);
 
 	list_for_each_entry_rcu(tunnel, &amt->tunnel_list, list) {
-		if (tunnel->ip4 == iph->saddr) {
+		if (tunnel->ip4 == saddr) {
 			if ((amtmu->nonce == tunnel->nonce &&
 			     amtmu->response_mac == tunnel->mac)) {
 				mod_delayed_work(amt_wq, &tunnel->gc_wq,
@@ -2492,6 +2549,12 @@ static bool amt_update_handler(struct amt_dev *amt, struct sk_buff *skb)
 	if (!pskb_may_pull(skb, sizeof(*iph)))
 		return true;
 
+	/* The L2 header is rewritten below; make the head private first so a
+	 * cloned skb (for example one taken by a packet tap) is not modified.
+	 */
+	if (skb_cow_head(skb, 0))
+		return true;
+
 	iph = ip_hdr(skb);
 	if (iph->version == 4) {
 		if (ip_mc_check_igmp(skb)) {
@@ -2508,6 +2571,10 @@ static bool amt_update_handler(struct amt_dev *amt, struct sk_buff *skb)
 		eth = eth_hdr(skb);
 		skb->protocol = htons(ETH_P_IP);
 		eth->h_proto = htons(ETH_P_IP);
+		/* ip_mc_check_igmp() and the report handler may have
+		 * reallocated the head; re-derive iph.
+		 */
+		iph = ip_hdr(skb);
 		ip_eth_mc_map(iph->daddr, eth->h_dest);
 #if IS_ENABLED(CONFIG_IPV6)
 	} else if (iph->version == 6) {
@@ -2527,6 +2594,10 @@ static bool amt_update_handler(struct amt_dev *amt, struct sk_buff *skb)
 		eth = eth_hdr(skb);
 		skb->protocol = htons(ETH_P_IPV6);
 		eth->h_proto = htons(ETH_P_IPV6);
+		/* ipv6_mc_check_mld() and the report handler may have
+		 * reallocated the head; re-derive ip6h.
+		 */
+		ip6h = ipv6_hdr(skb);
 		ipv6_eth_mc_map(&ip6h->daddr, eth->h_dest);
 #endif
 	} else {
@@ -2772,7 +2843,7 @@ static void amt_gw_rcv(struct amt_dev *amt, struct sk_buff *skb)
 static int amt_rcv(struct sock *sk, struct sk_buff *skb)
 {
 	struct amt_dev *amt;
-	struct iphdr *iph;
+	__be32 saddr;
 	int type;
 	bool err;
 
@@ -2785,7 +2856,11 @@ static int amt_rcv(struct sock *sk, struct sk_buff *skb)
 	}
 
 	skb->dev = amt->dev;
-	iph = ip_hdr(skb);
+	/* amt_parse_type() calls pskb_may_pull(), which can reallocate the
+	 * skb head and leave a cached ip_hdr() dangling.  Snapshot the source
+	 * address used below before the pull.
+	 */
+	saddr = ip_hdr(skb)->saddr;
 	type = amt_parse_type(skb);
 	if (type == -1) {
 		err = true;
@@ -2795,7 +2870,7 @@ static int amt_rcv(struct sock *sk, struct sk_buff *skb)
 	if (amt->mode == AMT_MODE_GATEWAY) {
 		switch (type) {
 		case AMT_MSG_ADVERTISEMENT:
-			if (iph->saddr != amt->discovery_ip) {
+			if (saddr != amt->discovery_ip) {
 				netdev_dbg(amt->dev, "Invalid Relay IP\n");
 				err = true;
 				goto drop;
@@ -2807,7 +2882,7 @@ static int amt_rcv(struct sock *sk, struct sk_buff *skb)
 			}
 			goto out;
 		case AMT_MSG_MULTICAST_DATA:
-			if (iph->saddr != amt->remote_ip) {
+			if (saddr != amt->remote_ip) {
 				netdev_dbg(amt->dev, "Invalid Relay IP\n");
 				err = true;
 				goto drop;
@@ -2818,7 +2893,7 @@ static int amt_rcv(struct sock *sk, struct sk_buff *skb)
 			else
 				goto out;
 		case AMT_MSG_MEMBERSHIP_QUERY:
-			if (iph->saddr != amt->remote_ip) {
+			if (saddr != amt->remote_ip) {
 				netdev_dbg(amt->dev, "Invalid Relay IP\n");
 				err = true;
 				goto drop;

3/2 2026/07/08 05:25 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 6851
							output: 26
							thoughts: 210
						

Thoughts:
**Analyzing a Kernel Patch: AMT Driver Fix**

Okay, so I'm looking at a patch that targets `drivers/net/amt.c`. The commit message is pretty barebones, just indicating it's a patch from a syz-cluster and under review. That's fine, the code is what matters. This looks like a functional fix, zeroing in on memory issues, specifically within the AMT driver. They're addressing `skb` reallocation problems – that means we're dealing with packet buffer management. I see calls like `pskb_may_pull`, `ip_mc_may_pull`, and `skb_cow_head`, all indicators of potential header pointer invalidation. It seems like the bug involved caching pointers to headers (like `ip_hdr(skb)`) *before* the `pull` operation and subsequently using those stale pointers, resulting in a use-after-free or dangling pointer scenario. Smart – they've added an `skb_cow_head(skb, 0)` call before any L2 header rewriting, effectively creating a copy of the head data to prevent such issues.

This is a good catch, a clean memory corruption fix in a core kernel component, the AMT driver. It’s definitely something that's worth fuzzing to ensure it's robust and to uncover any latent issues. Now, I need to get my hands on the relevant config options and identify the key symbols in this AMT code. Time to dig into the `drivers/net/amt.c` file itself and its associated Kconfig entries. I need to understand exactly how this driver is configured and how it interacts with other parts of the network stack.



4/2 2026/07/08 05:25 tool grepper
0m Args:
{
  "Expression": "config AMT",
  "PathPrefix": "drivers/net/"
}

Results:
{
  "Output": "drivers/net/Kconfig=289=config PFCP\n--\ndrivers/net/Kconfig-301-\ndrivers/net/Kconfig:302:config AMT\ndrivers/net/Kconfig-303-\ttristate \"Automatic Multicast Tunneling (AMT)\"\n"
}

5/2 2026/07/08 05:25 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 7522
							output: 28
							thoughts: 354
						

Thoughts:
**Analyzing the AMT Driver for Fuzzing**

Okay, so I'm looking at this code and we're dealing with the `AMT` configuration. First, I need to see if there are any other related configurations. The presence of `#if IS_ENABLED(CONFIG_IPV6)` suggests that `IPV6` is also going to be a factor here.

Now, let's zero in on the modified functions. It looks like the changes are centered around these functions within `drivers/net/amt.c`: `amt_dev_xmit`, `amt_igmpv3_report_handler`, `amt_mldv2_report_handler`, `amt_multicast_data_handler`, `amt_membership_query_handler`, `amt_update_handler`, and `amt_rcv`.

My next step is to set `FocusSymbols` to those functions so I can concentrate my fuzzing efforts on them.

I just double checked and while these functions are static, that's not a concern for my purposes with `FocusSymbols`.

Now, considering these are data path functions, I need to evaluate whether or not they are hot paths. `amt_dev_xmit` and `amt_rcv` are the transmit and receive functions, respectively, so they are the data path for the AMT driver. However, since AMT is a specialized tunnel, I don't think they're generic hot paths in the same way `ip_rcv` or `dev_queue_xmit` might be. This means fuzzing these specifically is a good idea.

Finally, I need to make sure I verify `AMT` config dependencies.



6/2 2026/07/08 05:25 tool grepper
0m Args:
{
  "Expression": "config AMT",
  "PathPrefix": "drivers/net/Kconfig"
}

Results:
{
  "Output": "drivers/net/Kconfig=289=config PFCP\n--\ndrivers/net/Kconfig-301-\ndrivers/net/Kconfig:302:config AMT\ndrivers/net/Kconfig-303-\ttristate \"Automatic Multicast Tunneling (AMT)\"\n"
}

7/2 2026/07/08 05:25 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 8336
							output: 34
							thoughts: 10
						

Thoughts:
Okay, here's my interpretation of that thought process, assuming I'm already quite familiar with embedded systems, Kconfig, and AMT (Active Management Technology).

**Delving into the AMT Kconfig**

Alright, time to dive in. My mind immediately clicks to action mode – let's dissect the Kconfig for AMT. I'm thinking, "Right, let's get into the nitty-gritty of the configuration options, dependencies, and all the variables related to AMT." I'm mentally preparing to navigate the file, expecting to find the standard configuration structures. I'll be looking for the key settings that control AMT's behavior, features, and how it interacts with the rest of the system. I'm anticipating the usual Kconfig syntax – `config`, `bool`, `tristate`, `select`, `depends on`, `default`, etc. – and I'm ready to parse the logic within. Essentially, I'm mentally preparing for a deep dive to understand how AMT is configured, enabled, and what its specific capabilities are within this context.



8/2 2026/07/08 05:25 tool read-file
0m Args:
{
  "File": "drivers/net/Kconfig",
  "FirstLine": 300,
  "LineCount": 20
}

Results:
{
  "Contents": " 300:\t\t  will be called pfcp.\n 301:\t\n 302:\tconfig AMT\n 303:\t\ttristate \"Automatic Multicast Tunneling (AMT)\"\n 304:\t\tdepends on INET \u0026\u0026 IP_MULTICAST\n 305:\t\tselect NET_UDP_TUNNEL\n 306:\t\thelp\n 307:\t\t  This allows one to create AMT(Automatic Multicast Tunneling)\n 308:\t\t  virtual interfaces that provide multicast tunneling.\n 309:\t\t  There are two roles, Gateway, and Relay.\n 310:\t\t  Gateway Encapsulates IGMP/MLD traffic from listeners to the Relay.\n 311:\t\t  Gateway Decapsulates multicast traffic from the Relay to Listeners.\n 312:\t\t  Relay Encapsulates multicast traffic from Sources to Gateway.\n 313:\t\t  Relay Decapsulates IGMP/MLD traffic from Gateway.\n 314:\t\n 315:\t\t  To compile this drivers as a module, choose M here: the module\n 316:\t\t  will be called amt.\n 317:\t\n 318:\tconfig MACSEC\n 319:\t\ttristate \"IEEE 802.1AE MAC-level encryption (MACsec)\"\n"
}

9/2 2026/07/08 05:25 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 8934
							output: 202
							thoughts: 258
						

Thoughts:
**My Assessment of the AMT Driver Patch**

Okay, so I've got this patch in front of me concerning the AMT (Automatic Multicast Tunneling) driver. The dependencies are `INET` and `IP_MULTICAST`, and it looks like I need to make sure `AMT` and `IPV6` are enabled in the configurations. Good, standard setup.

My immediate takeaway is that this patch addresses a nasty collection of memory safety issues: use-after-free and dangling pointer bugs. They're pinpointing the culprits as `pskb_may_pull` and similar functions, which are reallocating the `skb` header while network header pointers are still active. Sounds like classic race conditions in a network context, and the solution looks to be `skb_cow_head` to prevent modification of cloned `skbs`. It's definitely functional, right off the bat.

So, this clearly warrants some serious fuzzing. This is reachable network driver code, and based on the description, there’s likely potential for more memory corruption issues to still exist.

I need to focus on these symbols to assess the fix thoroughly: `amt_dev_xmit`, `amt_igmpv3_report_handler`, `amt_mldv2_report_handler`, `amt_multicast_data_handler`, `amt_membership_query_handler`, `amt_update_handler`, and `amt_rcv`. First thing I'll do is double-check the name, just to make sure it's correct. Yes, it is in the diff.

Alright, the patch is functional and definitely fixing bugs. I'm going to set it up to call set-results.



10/2 2026/07/08 05:25 tool set-results
0m Args:
{
  "EnableConfigs": [
    "AMT",
    "IPV6"
  ],
  "FocusSymbols": [
    "amt_dev_xmit",
    "amt_igmpv3_report_handler",
    "amt_mldv2_report_handler",
    "amt_multicast_data_handler",
    "amt_membership_query_handler",
    "amt_update_handler",
    "amt_rcv"
  ],
  "Reasoning": "The patch fixes multiple use-after-free and dangling pointer bugs in the AMT (Automatic Multicast Tunneling) driver caused by `pskb_may_pull` and similar functions reallocating the skb head while holding pointers to network headers. It also adds `skb_cow_head` to prevent modifying cloned skbs. These are functional changes in reachable network driver code that should be fuzzed to ensure no further memory corruption issues exist.",
  "WorthFuzzing": true
}

Results:
{
  "EnableConfigs": [
    "AMT",
    "IPV6"
  ],
  "FocusSymbols": [
    "amt_dev_xmit",
    "amt_igmpv3_report_handler",
    "amt_mldv2_report_handler",
    "amt_multicast_data_handler",
    "amt_membership_query_handler",
    "amt_update_handler",
    "amt_rcv"
  ],
  "Reasoning": "The patch fixes multiple use-after-free and dangling pointer bugs in the AMT (Automatic Multicast Tunneling) driver caused by `pskb_may_pull` and similar functions reallocating the skb head while holding pointers to network headers. It also adds `skb_cow_head` to prevent modifying cloned skbs. These are functional changes in reachable network driver code that should be fuzzed to ensure no further memory corruption issues exist.",
  "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)