From nobody Sat Jul 25 23:03:59 2026 Received: from mail-qk1-f172.google.com (mail-qk1-f172.google.com [209.85.222.172]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id F30662E737F for ; Sat, 11 Jul 2026 15:19:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.222.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783783184; cv=none; b=D/1wsqoX52e+oP7WaWsvqnnf5ev4tEJVIfe21S0qTeN+jFBY7c6q+vI/Ik5jOxlNHhXMrllQA3+7+IZVz0dn7yTnuVwgi77sQdhbZ12DNqZizaF8MMYUcaxtIk5eA0frNAbYAlY+k4Vf2C9yZ1+Lte4dF/Z0ZuGNqytTCX5xH2Q= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783783184; c=relaxed/simple; bh=dlKAj3dMiX9DLGe1f8spk9e/hnyrKnbLT1vU+suSV8Y=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=AAp2+C6Afm9yQk8phik6QLZhpnlxO3UrWZgpmyVv2X1gG6Gu39U9MfFFeGImR0RpAdXC0oDV9+Uq3wRlGmOXvUp9iwQ/Jyzaz1bWEtMzu8pZazHZ3eQS47P7Rd6jG8m7eBksp3weiko9ai6/uUb3M2xRUV/M/7LlcF6voUf+a0k= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=G7HlGQyp; arc=none smtp.client-ip=209.85.222.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="G7HlGQyp" Received: by mail-qk1-f172.google.com with SMTP id af79cd13be357-92eafc94c9cso100138285a.0 for ; Sat, 11 Jul 2026 08:19:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1783783181; x=1784387981; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=nTbm3Lr0XkPh/S+BCtju0biWGy5LzIEgciPBWhK2qnY=; b=G7HlGQypqNGt9F0E3MN9ByHNvJk/iYg+IpgCHHhUzpK8dI8TKHZjF0euqm08ja9eq6 GjhIQ3FSN8RXmvmHQ/LFFtfUxIlmS/iHdy2U+0XCwkR1mWImhE2PRePnPG701cJSl0Ok Kj6nw4H1yknwA/HbaxeMXIIMB/WR5oGkoXfd83kok07b5MB7M1VdrHzI6bDptF1ErPg+ dfrlBNvb3Uh+6vR7ythvVsSfCoc3pP1+feJ7BYHIZZn+2pia7SOPAJPaYu/emd3Wkkbm pnVajr7Ht2uBXacmejY/wetsOKt/MtoZ0RIH4F5EnVrrX35oC6XtkKZdSIsxgowOojBR WSqA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1783783181; x=1784387981; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=nTbm3Lr0XkPh/S+BCtju0biWGy5LzIEgciPBWhK2qnY=; b=hX025IVdV5Rq4TaV9zO0lLl3Gy6M7hjMwCfhC3isXmFJtW/CfSrpRZx5vgJphT6/qO PzsK5MzLyeSP3fcwSNQY09aLeHFu/wVDMFPJ5DuPA9a4T9nXEwgvTTYQEn+7rbMfzPl5 X5SImuc4u6Y12Nl/TXJdqnRgUlV7jU8wnZHtyO6tY8u16Je2Fe5bFfpKpFehwy4mZVRc RGEdohtCzSEEBq84MBxhc49RH+LO+w8gq9o3ema/pijpYOT2BhrFv+PAn6MYaQnPdVBZ cK2Pdmtltl0yfGNHFMn96D4AmcoPQHgeYNfEQuUZBm8XuxhoJ72LBXsm3vLj7Fv/Lplt 0RDA== X-Forwarded-Encrypted: i=1; AHgh+RpQfNX6ifTssbh+DQjTgYX/kTv6+RWHcaSi85TYOy+e58jT753xrGKy3H7KRmlVYrO5FKLwfXyFixZNN7U=@vger.kernel.org X-Gm-Message-State: AOJu0Yy8lU+KgIzC76v3/Sk3fYWo6xq5YB8sfsvH/8oahy48CVapO6ix 0321SkpS3I1Rni50d8X+7ZEGeUBino+ob9tGlFJCDWdokFhbL1ACQQnR X-Gm-Gg: AfdE7cma9ugUp8ykFtX2w/iWDIQxfWJ6jhPkoROuREi0HSCfitvSGN3CH+HqNlIRtq+ B//hVz/rJeRABqEIHqP2jhkMVj5UBpyIcc4IX2/JRRgWfZVe2kwDpudM1AuMaeqIArN9ZLIZu1A bM23SC62zpZ3D8LTnLkjRgrMrUG6LGRAYxqlMoOXTN9SjoyOLTM7CyAI+9ChICG+/XTYDBBiIeF pXvtEwdFvYzlXXnTE56oVQpHuBxRDpeJ+b8n/R1/905PuzI/JTGE1DKWvima02/1N/V7LS+KtsK s+nVSto9hcpQAhuff8VwZ2JTkC5ZDVfyxlge+zUt7eajl3NOaTk2ZeVnRkiIELCM97K8tLgPcDA WW8lLJ5UJOeNP941fCIJNwxaAXgycZdRCrTPUqwNbkq5/bKupB+yj0I4Dyrzr3rmluwO2oNiqwE VU30LKXS2GZzBV4kdwAylVxVS65sVvQ1f2x9RcSgKh5uGhjzOuiYFOM7JLBSeyIFh9WvaUDAcKG GF/qdchbA== X-Received: by 2002:a05:620a:31a3:b0:92e:bca0:6308 with SMTP id af79cd13be357-92ef2b11b00mr365636285a.20.1783783180759; Sat, 11 Jul 2026 08:19:40 -0700 (PDT) Received: from server0 (c-68-48-65-54.hsd1.mi.comcast.net. [68.48.65.54]) by smtp.gmail.com with ESMTPSA id af79cd13be357-92ee5b4a082sm467704685a.7.2026.07.11.08.19.39 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 11 Jul 2026 08:19:40 -0700 (PDT) From: Michael Bommarito To: Taehee Yoo , Andrew Lunn , "David S . Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH net v5 1/2] amt: re-read skb header pointers after every pull Date: Sat, 11 Jul 2026 11:19:33 -0400 Message-ID: <20260711151934.2955226-2-michael.bommarito@gmail.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260711151934.2955226-1-michael.bommarito@gmail.com> References: <20260711151934.2955226-1-michael.bommarito@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Several AMT receive and transmit paths cache a pointer into the skb head (ip_hdr(), ipv6_hdr(), eth_hdr() or the AMT message header) and then call a helper that can reallocate that head before the cached pointer is used again. pskb_may_pull(), ip_mc_may_pull(), ipv6_mc_may_pull(), iptunnel_pull_header(), ip_mc_check_igmp() and ipv6_mc_check_mld() can all free the old head and move the data, so a pointer taken before the call dangles afterwards and the later access is a use-after-free of the freed head. The affected sites are: amt_rcv() caches ip_hdr() before amt_parse_type() pulls, then reads iph->saddr. amt_dev_xmit() caches ip_hdr()/ipv6_hdr() before ip_mc_check_igmp()/ ipv6_mc_check_mld() and pskb_may_pull(), then reads the group address. amt_multicast_data_handler() caches eth_hdr() before pskb_may_pull(), then writes the L2 header. amt_membership_query_handler() caches the AMT header, the outer and inner eth_hdr() and ip_hdr() before iptunnel_pull_header() and several pulls, then reads and writes them. amt_igmpv3_report_handler() and amt_mldv2_report_handler() cache ip_hdr()/ipv6_hdr() and the current group record and read the record count from the report header inside the record loop, across the *_mc_may_pull() calls. amt_update_handler() caches ip_hdr() and the AMT membership-update header before pskb_may_pull(), iptunnel_pull_header(), ip_mc_check_igmp() and the report handler, then reads iph->daddr and amtmu->nonce / amtmu->response_mac. Fix each site by either snapshotting the scalar that is used after the pull before the first pull runs, or re-deriving the header pointer from the skb after the last pull that can move the head. Values that are stable across the pull (source and group address, the response MAC and nonce, the record count, the outer source MAC) are snapshotted; pointers that are written through or read repeatedly are re-derived. Fixes: cbc21dc1cfe9 ("amt: add data plane of amt interface") Assisted-by: Claude:claude-opus-4-8 Signed-off-by: Michael Bommarito Reviewed-by: Simon Horman Reviewed-by: Taehee Yoo --- drivers/net/amt.c | 79 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 55 insertions(+), 24 deletions(-) diff --git a/drivers/net/amt.c b/drivers/net/amt.c index 951dd10e192b7..35e77af76bd9d 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 =3D true; } v6 =3D false; - group.ip4 =3D iph->daddr; + group.ip4 =3D ip_hdr(skb)->daddr; #if IS_ENABLED(CONFIG_IPV6) } else if (iph->version =3D=3D 6) { ip6h =3D ipv6_hdr(skb); @@ -1235,7 +1235,7 @@ static netdev_tx_t amt_dev_xmit(struct sk_buff *skb, = struct net_device *dev) data =3D true; } v6 =3D true; - group.ip6 =3D ip6h->daddr; + group.ip6 =3D 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 =3D=3D iph->daddr) + if (gnode->group_addr.ip4 =3D=3D 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,18 @@ static void amt_igmpv3_report_handler(struct amt_de= v *amt, struct sk_buff *skb, struct igmpv3_report *ihrv3 =3D igmpv3_report_hdr(skb); int len =3D skb_transport_offset(skb) + sizeof(*ihrv3); void *zero_grec =3D (void *)&igmpv3_zero_grec; - struct iphdr *iph =3D 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; =20 - for (i =3D 0; i < ntohs(ihrv3->ngrec); i++) { + saddr =3D ip_hdr(skb)->saddr; + ngrec =3D ntohs(ihrv3->ngrec); + + for (i =3D 0; i < ngrec; i++) { len +=3D sizeof(*grec); if (!ip_mc_may_pull(skb, len)) break; @@ -2019,10 +2023,13 @@ static void amt_igmpv3_report_handler(struct amt_de= v *amt, struct sk_buff *skb, if (!ip_mc_may_pull(skb, len)) break; =20 + grec =3D (void *)(skb->data + len - sizeof(*grec) - + nsrcs * sizeof(__be32)); + memset(&group, 0, sizeof(union amt_addr)); group.ip4 =3D grec->grec_mca; memset(&host, 0, sizeof(union amt_addr)); - host.ip4 =3D iph->saddr; + host.ip4 =3D saddr; gnode =3D amt_lookup_group(tunnel, &group, &host, false); if (!gnode) { gnode =3D amt_add_group(amt, tunnel, &group, &host, @@ -2162,14 +2169,18 @@ static void amt_mldv2_report_handler(struct amt_dev= *amt, struct sk_buff *skb, struct mld2_report *mld2r =3D (struct mld2_report *)icmp6_hdr(skb); int len =3D skb_transport_offset(skb) + sizeof(*mld2r); void *zero_grec =3D (void *)&mldv2_zero_grec; - struct ipv6hdr *ip6h =3D 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; =20 - for (i =3D 0; i < ntohs(mld2r->mld2r_ngrec); i++) { + saddr =3D ipv6_hdr(skb)->saddr; + ngrec =3D ntohs(mld2r->mld2r_ngrec); + + for (i =3D 0; i < ngrec; i++) { len +=3D sizeof(*grec); if (!ipv6_mc_may_pull(skb, len)) break; @@ -2181,10 +2192,13 @@ static void amt_mldv2_report_handler(struct amt_dev= *amt, struct sk_buff *skb, if (!ipv6_mc_may_pull(skb, len)) break; =20 + grec =3D (void *)(skb->data + len - sizeof(*grec) - + nsrcs * sizeof(struct in6_addr)); + memset(&group, 0, sizeof(union amt_addr)); group.ip6 =3D grec->grec_mca; memset(&host, 0, sizeof(union amt_addr)); - host.ip6 =3D ip6h->saddr; + host.ip6 =3D saddr; gnode =3D amt_lookup_group(tunnel, &group, &host, true); if (!gnode) { gnode =3D amt_add_group(amt, tunnel, &group, &host, @@ -2305,7 +2319,6 @@ 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 =3D eth_hdr(skb); =20 if (!pskb_may_pull(skb, sizeof(*iph))) return true; @@ -2315,6 +2328,7 @@ static bool amt_multicast_data_handler(struct amt_dev= *amt, struct sk_buff *skb) if (!ipv4_is_multicast(iph->daddr)) return true; skb->protocol =3D htons(ETH_P_IP); + eth =3D eth_hdr(skb); eth->h_proto =3D htons(ETH_P_IP); ip_eth_mc_map(iph->daddr, eth->h_dest); #if IS_ENABLED(CONFIG_IPV6) @@ -2328,6 +2342,7 @@ 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 =3D htons(ETH_P_IPV6); + eth =3D eth_hdr(skb); eth->h_proto =3D htons(ETH_P_IPV6); ipv6_eth_mc_map(&ip6h->daddr, eth->h_dest); #endif @@ -2351,10 +2366,12 @@ static bool amt_membership_query_handler(struct amt= _dev *amt, struct sk_buff *skb) { struct amt_header_membership_query *amtmq; - struct igmpv3_query *ihv3; struct ethhdr *eth, *oeth; + struct igmpv3_query *ihv3; + u8 h_source[ETH_ALEN]; struct iphdr *iph; int hdr_size, len; + u64 response_mac; =20 hdr_size =3D sizeof(*amtmq) + sizeof(struct udphdr); if (!pskb_may_pull(skb, hdr_size)) @@ -2367,6 +2384,8 @@ static bool amt_membership_query_handler(struct amt_d= ev *amt, if (amtmq->nonce !=3D amt->nonce) return true; =20 + response_mac =3D amtmq->response_mac; + hdr_size -=3D sizeof(*eth); if (iptunnel_pull_header(skb, hdr_size, htons(ETH_P_TEB), false)) return true; @@ -2376,6 +2395,7 @@ static bool amt_membership_query_handler(struct amt_d= ev *amt, skb_pull(skb, sizeof(*eth)); skb_reset_network_header(skb); eth =3D eth_hdr(skb); + ether_addr_copy(h_source, oeth->h_source); if (!pskb_may_pull(skb, sizeof(*iph))) return true; =20 @@ -2388,6 +2408,7 @@ static bool amt_membership_query_handler(struct amt_d= ev *amt, sizeof(*ihv3))) return true; =20 + iph =3D ip_hdr(skb); if (!ipv4_is_multicast(iph->daddr)) return true; =20 @@ -2395,10 +2416,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 =3D amtmq->response_mac; + amt->mac =3D response_mac; amt->req_cnt =3D 0; amt->qi =3D ihv3->qqic; skb->protocol =3D htons(ETH_P_IP); + eth =3D eth_hdr(skb); eth->h_proto =3D htons(ETH_P_IP); ip_eth_mc_map(iph->daddr, eth->h_dest); #if IS_ENABLED(CONFIG_IPV6) @@ -2421,10 +2443,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 =3D amtmq->response_mac; + amt->mac =3D response_mac; amt->req_cnt =3D 0; amt->qi =3D mld2q->mld2q_qqic; skb->protocol =3D htons(ETH_P_IPV6); + eth =3D eth_hdr(skb); eth->h_proto =3D htons(ETH_P_IPV6); ipv6_eth_mc_map(&ip6h->daddr, eth->h_dest); #endif @@ -2432,7 +2455,7 @@ static bool amt_membership_query_handler(struct amt_d= ev *amt, return true; } =20 - ether_addr_copy(eth->h_source, oeth->h_source); + ether_addr_copy(eth->h_source, h_source); skb->pkt_type =3D PACKET_MULTICAST; skb->ip_summed =3D CHECKSUM_NONE; len =3D skb->len; @@ -2455,8 +2478,11 @@ static bool amt_update_handler(struct amt_dev *amt, = struct sk_buff *skb) struct ethhdr *eth; struct iphdr *iph; int len, hdr_size; + u64 response_mac; + __be32 saddr; + __be32 nonce; =20 - iph =3D ip_hdr(skb); + saddr =3D ip_hdr(skb)->saddr; =20 hdr_size =3D sizeof(*amtmu) + sizeof(struct udphdr); if (!pskb_may_pull(skb, hdr_size)) @@ -2466,15 +2492,18 @@ static bool amt_update_handler(struct amt_dev *amt,= struct sk_buff *skb) if (amtmu->reserved || amtmu->version) return true; =20 + nonce =3D amtmu->nonce; + response_mac =3D amtmu->response_mac; + if (iptunnel_pull_header(skb, hdr_size, skb->protocol, false)) return true; =20 skb_reset_network_header(skb); =20 list_for_each_entry_rcu(tunnel, &amt->tunnel_list, list) { - if (tunnel->ip4 =3D=3D iph->saddr) { - if ((amtmu->nonce =3D=3D tunnel->nonce && - amtmu->response_mac =3D=3D tunnel->mac)) { + if (tunnel->ip4 =3D=3D saddr) { + if ((nonce =3D=3D tunnel->nonce && + response_mac =3D=3D tunnel->mac)) { mod_delayed_work(amt_wq, &tunnel->gc_wq, msecs_to_jiffies(amt_gmi(amt)) * 3); @@ -2508,6 +2537,7 @@ static bool amt_update_handler(struct amt_dev *amt, s= truct sk_buff *skb) eth =3D eth_hdr(skb); skb->protocol =3D htons(ETH_P_IP); eth->h_proto =3D htons(ETH_P_IP); + iph =3D ip_hdr(skb); ip_eth_mc_map(iph->daddr, eth->h_dest); #if IS_ENABLED(CONFIG_IPV6) } else if (iph->version =3D=3D 6) { @@ -2527,6 +2557,7 @@ static bool amt_update_handler(struct amt_dev *amt, s= truct sk_buff *skb) eth =3D eth_hdr(skb); skb->protocol =3D htons(ETH_P_IPV6); eth->h_proto =3D htons(ETH_P_IPV6); + ip6h =3D ipv6_hdr(skb); ipv6_eth_mc_map(&ip6h->daddr, eth->h_dest); #endif } else { @@ -2772,7 +2803,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; =20 @@ -2785,7 +2816,7 @@ static int amt_rcv(struct sock *sk, struct sk_buff *s= kb) } =20 skb->dev =3D amt->dev; - iph =3D ip_hdr(skb); + saddr =3D ip_hdr(skb)->saddr; type =3D amt_parse_type(skb); if (type =3D=3D -1) { err =3D true; @@ -2795,7 +2826,7 @@ static int amt_rcv(struct sock *sk, struct sk_buff *s= kb) if (amt->mode =3D=3D AMT_MODE_GATEWAY) { switch (type) { case AMT_MSG_ADVERTISEMENT: - if (iph->saddr !=3D amt->discovery_ip) { + if (saddr !=3D amt->discovery_ip) { netdev_dbg(amt->dev, "Invalid Relay IP\n"); err =3D true; goto drop; @@ -2807,7 +2838,7 @@ static int amt_rcv(struct sock *sk, struct sk_buff *s= kb) } goto out; case AMT_MSG_MULTICAST_DATA: - if (iph->saddr !=3D amt->remote_ip) { + if (saddr !=3D amt->remote_ip) { netdev_dbg(amt->dev, "Invalid Relay IP\n"); err =3D true; goto drop; @@ -2818,7 +2849,7 @@ static int amt_rcv(struct sock *sk, struct sk_buff *s= kb) else goto out; case AMT_MSG_MEMBERSHIP_QUERY: - if (iph->saddr !=3D amt->remote_ip) { + if (saddr !=3D amt->remote_ip) { netdev_dbg(amt->dev, "Invalid Relay IP\n"); err =3D true; goto drop; base-commit: 2c7c88a412aa6d09cd04b414211b4ef8553b5309 --=20 2.53.0 From nobody Sat Jul 25 23:03:59 2026 Received: from mail-qk1-f180.google.com (mail-qk1-f180.google.com [209.85.222.180]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id C146D37A853 for ; Sat, 11 Jul 2026 15:19:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.222.180 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783783185; cv=none; b=fyv5aSib8qrWgrt4t/dP/nLBmaE4y0t135MC8hTepaVe+/AE2n2LKfei//kFvQFBG4EBF5nyoMcRc2Uom4OpZ25SnLm8nxVpsi6IL/7KubTmjolt8DQlfAIxPvc9XDzUX7dPYW0kJ/O2azrwjjPvqaCpnFjr1HkWSmJolCyryww= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1783783185; c=relaxed/simple; bh=LQIM3sBGvUqM9efCOb/AIjOUmu6tNvZEUwHUeE2z90I=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=BhN7HcoBPAahu6VDePy5kJ+GuPx8GwgPJyuZMd92pRSf9CaWdsEpGw54tdnxciLcq0qBslpS0BBNwBcCUuyUwSb41EGSTtE3MyouMGVMRUoco1z5wSUoH/MqeOPYq3lYo7qDORvDDZnvP/JLMkiS8vHKIy9YgskK7CXDosTQEY0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=dsyq3Cga; arc=none smtp.client-ip=209.85.222.180 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="dsyq3Cga" Received: by mail-qk1-f180.google.com with SMTP id af79cd13be357-92e5d6f35c1so151030785a.0 for ; Sat, 11 Jul 2026 08:19:43 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1783783183; x=1784387983; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=BG2xjmjBbV5AQK/a/AQpxcpCL6NEh8yOHX50gnWQjos=; b=dsyq3Cga9QBG6oV17iVpysC04tH+/KvLCcOnz45NsPkoGMV3inV3L7FVledU/uxZ1N rtphRWj8QFYGGxfAbk0WPd3i4kNb0NDXrfgx/eFjw7qCBEJiQ1YlaVFd158Omn+3j6ep KDmnGPFpUjqw2tLCCzJ/ZgMgs/trhxYIFuWfvR8+K9QC6327iHNGGoCXX/o/SCIwIJzm Dj8gNLRrXkQwmnqfsYefBayJLzK3HfzMH07z8o/HHmUu9MImyZJd4edfOBdklNXkbgSs AyrzPp3LKEqlqfCD3zC7wc6oODaVsoOBq6ZV1eI5m0K0Da2RcSwVtTuKf3BMvsNA4iQx keEQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1783783183; x=1784387983; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=BG2xjmjBbV5AQK/a/AQpxcpCL6NEh8yOHX50gnWQjos=; b=lbq6dsIMZbzr2kTVU/r57W+AiSZXNy7fNi5I9/81eIIZlq4yAtWUam6bSN8UXD6tnM Z7TahWzXWzi0fDC0Tug42+K3ynoUb9px1p5KN5m0nG+usa+dvVbvvYF/ot0TerpHYgkq cMQ4OEpw3uA5+0p1Q1shuJmTzQaa/LaCMaS0rm2XX7SzZFIEC29R46KbdmrccukWkrEZ KkIFnm4gB3yZhPC9oBrhqTl6xzdJketMQO692lRrnP8P0kgAPnn+sZr+yXvwrkedty6V Yxh11l2/aAgqlN+sFtmpSdrt2oZqPjpWyd54oPyZXi3cuu+ct/1yylhmYz5YdlTTYEQI NHew== X-Forwarded-Encrypted: i=1; AHgh+RpMwH0vuX9DgJYDHW47X8ckVdaoPFnr3bdW7YMsy5VMBhzazVqmPZ70bOXXNABmLNbYYVaPVQp8oxmArxM=@vger.kernel.org X-Gm-Message-State: AOJu0YwVSRMw3hE5eLzcysDdS55nV6fWHedaiUz0bQFriC7oTb8qlZDN R5SIrrKuDPTxSFJfJw0UtlJeo4OJu5v0VwdxKSeNOp2bMxw8sZ/mhlWp X-Gm-Gg: AfdE7clS6Gh3ssjtlOwn/SOCAU7f2WoQeDX0TqYa1rweY2Mellz3664N5a7Fqkwhvjr JDVbUh3dPqiQ5rC4oWg4ocGq+CAE5y9I+IgOWc72Wr1MX/zDIxT6loqa8I57793sPz0PrFCQYeN mydprciL6AW6wGHDH2c6oek8uHGrV4l7bSLYhPvjX2xTIZfG+J0GrWlYMS/4edTaIz/4iViQHZr FfOrvjvTfJUhtUX2VbEOQJ6LH85vfmfEbbDjNnVgLHuzYESbBuZ+GMXexO7dqpZbvisAr6bQyWG deQixIvS+zf+NXwRdUGHoS0IEuuDnS3t5oNZFdKY4KOhl/Gr5uOCDgfxLNMXZSW1Y1US+4ZD0ey 4gwuilr2N0y0/lIyEOgsD8iw8LqXKfBE5mMkqsQ6de1GPF/skG1W5yCwRkl7muA5o3le+r6fiTD 1bBpv2dxwK2fEFj3a4k9W3XWzCqcuqonsxjt3Zf/MVDGN73eFFfHJ6oIUNpIwr2vtotoi9SYD1n v+BaVRjHQ== X-Received: by 2002:a05:620a:2995:b0:92e:c118:18b8 with SMTP id af79cd13be357-92ef2d01681mr351641285a.87.1783783182650; Sat, 11 Jul 2026 08:19:42 -0700 (PDT) Received: from server0 (c-68-48-65-54.hsd1.mi.comcast.net. [68.48.65.54]) by smtp.gmail.com with ESMTPSA id af79cd13be357-92ee5b4a082sm467704685a.7.2026.07.11.08.19.40 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 11 Jul 2026 08:19:41 -0700 (PDT) From: Michael Bommarito To: Taehee Yoo , Andrew Lunn , "David S . Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni Cc: netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH net v5 2/2] amt: make the head writable before rewriting the L2 header Date: Sat, 11 Jul 2026 11:19:34 -0400 Message-ID: <20260711151934.2955226-3-michael.bommarito@gmail.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260711151934.2955226-1-michael.bommarito@gmail.com> References: <20260711151934.2955226-1-michael.bommarito@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" amt_multicast_data_handler(), amt_membership_query_handler() and amt_update_handler() rewrite the ethernet header of the decapsulated skb in place (eth->h_proto, eth->h_dest and, for the query, also eth->h_source) before handing it up the stack. The skb head may be shared, for example when a packet tap has cloned it on the underlay interface, so writing through it corrupts the other reader's copy. Call skb_cow_head() before the rewrite so the head is private. It is placed before the pointers into the head are (re-)derived, so a reallocation caused by the copy is picked up by those derivations. Fixes: cbc21dc1cfe9 ("amt: add data plane of amt interface") Assisted-by: Claude:claude-opus-4-8 Signed-off-by: Michael Bommarito Reviewed-by: Simon Horman Reviewed-by: Taehee Yoo --- drivers/net/amt.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/net/amt.c b/drivers/net/amt.c index 35e77af76bd9d..b733309b866ff 100644 --- a/drivers/net/amt.c +++ b/drivers/net/amt.c @@ -2320,6 +2320,9 @@ static bool amt_multicast_data_handler(struct amt_dev= *amt, struct sk_buff *skb) skb_reset_mac_header(skb); skb_pull(skb, sizeof(*eth)); =20 + if (skb_cow_head(skb, 0)) + return true; + if (!pskb_may_pull(skb, sizeof(*iph))) return true; iph =3D ip_hdr(skb); @@ -2396,6 +2399,8 @@ static bool amt_membership_query_handler(struct amt_d= ev *amt, skb_reset_network_header(skb); eth =3D eth_hdr(skb); ether_addr_copy(h_source, oeth->h_source); + if (skb_cow_head(skb, 0)) + return true; if (!pskb_may_pull(skb, sizeof(*iph))) return true; =20 @@ -2521,6 +2526,9 @@ static bool amt_update_handler(struct amt_dev *amt, s= truct sk_buff *skb) if (!pskb_may_pull(skb, sizeof(*iph))) return true; =20 + if (skb_cow_head(skb, 0)) + return true; + iph =3D ip_hdr(skb); if (iph->version =3D=3D 4) { if (ip_mc_check_igmp(skb)) { --=20 2.53.0