All of lore.kernel.org
 help / color / mirror / Atom feed
From: Willem de Bruijn <willemdebruijn.kernel@gmail.com>
To: Willem de Bruijn <willemdebruijn.kernel@gmail.com>,
	 Doruk Tan Ozturk <doruk@0sec.ai>,
	 Willem de Bruijn <willemdebruijn.kernel@gmail.com>,
	 "David S . Miller" <davem@davemloft.net>,
	 Eric Dumazet <edumazet@google.com>,
	 Jakub Kicinski <kuba@kernel.org>,
	 Paolo Abeni <pabeni@redhat.com>
Cc: Simon Horman <horms@kernel.org>,
	 Sabrina Dubroca <sd@queasysnail.net>,
	 Vladimir Oltean <olteanv@gmail.com>,
	 netdev@vger.kernel.org,  linux-kernel@vger.kernel.org,
	 stable@vger.kernel.org,  Doruk Tan Ozturk <doruk@0sec.ai>
Subject: Re: [PATCH net] net/packet: reset the MAC header on the packet-socket transmit path
Date: Thu, 23 Jul 2026 17:22:59 -0400	[thread overview]
Message-ID: <willemdebruijn.kernel.36bee22ca53dd@gmail.com> (raw)
In-Reply-To: <willemdebruijn.kernel.4957260f765a@gmail.com>

Willem de Bruijn wrote:
> Doruk Tan Ozturk wrote:
> > packet_parse_headers() resets the MAC header only for a SOCK_RAW frame
> > whose socket did not bind a protocol:
> > 
> > 	if ((!skb->protocol || skb->protocol == htons(ETH_P_ALL)) &&
> > 	    sock->type == SOCK_RAW) {
> > 		skb_reset_mac_header(skb);
> > 		skb->protocol = dev_parse_header_protocol(skb);
> > 	}
> > 
> > Every other outgoing packet-socket frame therefore reaches
> > ndo_start_xmit() with the MAC header unset: a SOCK_RAW socket bound to a
> 
> The normal __dev_queue_xmit calls skb_reset_mac_header.
> 
> This therefore only applies to the dev_direct_xmit path.
> 
> > specific protocol (for example socket(AF_PACKET, SOCK_RAW,
> > htons(ETH_P_IP))), any SOCK_DGRAM frame (its header is built by
> > dev_hard_header(), which does not set mac_header), and the legacy
> > SOCK_PACKET path. A driver that reads eth_hdr(skb) on transmit then
> > dereferences skb->head + (u16)~0, an out-of-bounds access about 64 KiB
> > past the head.
> 
> This is not currently an expected invariant, but I see from a comment
> below the --- that this approach is proposed instead of fixing up the
> buggy drivers.
> 
> > 
> > This is the same class fixed for one consumer in commit f5089008f90c
> > ("macsec: do not read an unset MAC header in macsec_encrypt()"); other
> > TX .xmit paths that read eth_hdr(skb)->h_dest (several DSA taggers,
> > ibmveth, sja1105, the atlantic PTP path) have the same problem.
> > 
> > packet_parse_headers() runs only on the transmit path
> > (packet_sendmsg_spkt(), tpacket_fill_skb(), packet_snd()), and there
> > skb->data is the start of the L2 header for every packet-socket type.
> 
> There are some subtle points with variable length L2 protocols that
> need to be reviewed.

Come to think of it, if __dev_queue_xmit can unconditionally reset the
mac header, then so can other tx paths.

> > Reset the MAC header unconditionally so it is anchored for all of them,
> > fixing the class at the source rather than hardening each consumer.
> > 
> > The protocol probe is unchanged. A CONFIG_DEBUG_NET build stops warning
> > about an unset mac header in skb_mac_header() on these paths, and the
> > out-of-bounds eth_hdr() read no longer occurs.
> > 
> > Found by 0sec (https://0sec.ai) using automated source analysis;
> > verified against source and matched to the macsec KASAN report in
> > f5089008f90c. Compile-tested.
> > 
> > Fixes: 75c65772c3d1 ("net/packet: Ask driver for protocol if not provided by user")
> > Cc: stable@vger.kernel.org
> > Assisted-by: 0sec:multi-model
> > Signed-off-by: Doruk Tan Ozturk <doruk@0sec.ai>
> > ---
> > This supersedes the per-consumer series "[PATCH net 0/3] net: dont read
> > an unset MAC header on the raw/qdisc-bypass TX path"
> > (https://lore.kernel.org/netdev/20260713194010.54642-1-doruk@0sec.ai/),
> > per Jakubs suggestion to fix the problem at the source rather than
> > hardening each driver.  Vladimir Oltean had reviewed 2/3 of that series;
> > this is a different (source) fix, so I have not carried the tags.
> >  net/packet/af_packet.c | 16 +++++++++++++---
> >  1 file changed, 13 insertions(+), 3 deletions(-)
> > 
> > diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
> > index e75d2932475a..adfb9c19a3ca 100644
> > --- a/net/packet/af_packet.c
> > +++ b/net/packet/af_packet.c
> > @@ -1924,11 +1924,21 @@ static void packet_parse_headers(struct sk_buff *skb, struct socket *sock)
> >  {
> >  	int depth;
> >  
> > +	/*
> > +	 * packet_parse_headers() runs only on the transmit path
> > +	 * (packet_sendmsg_spkt(), tpacket_fill_skb(), packet_snd()), where
> > +	 * skb->data is the start of the L2 header for every packet-socket
> > +	 * type: SOCK_RAW and SOCK_PACKET carry a user-supplied header and
> > +	 * SOCK_DGRAM has one built by dev_hard_header(). Anchor the MAC
> > +	 * header for all of them so a frame does not reach ndo_start_xmit()
> > +	 * with the MAC header unset, where a driver reading eth_hdr(skb) on
> > +	 * TX would dereference an out-of-bounds offset (skb->head + (u16)~0).
> > +	 */
> 
> This is too verbose. Better captured in the commit message.
> 
> > +	skb_reset_mac_header(skb);
> > +
> >  	if ((!skb->protocol || skb->protocol == htons(ETH_P_ALL)) &&
> > -	    sock->type == SOCK_RAW) {
> > -		skb_reset_mac_header(skb);
> > +	    sock->type == SOCK_RAW)
> >  		skb->protocol = dev_parse_header_protocol(skb);
> > -	}
> >  
> >  	/* Move network header to the right position for VLAN tagged packets */
> >  	if (likely(skb->dev->type == ARPHRD_ETHER) &&
> > -- 
> > 2.43.0
> > 
> 
> 



      reply	other threads:[~2026-07-23 21:23 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-23  2:03 [PATCH net] net/packet: reset the MAC header on the packet-socket transmit path Doruk Tan Ozturk
2026-07-23 20:52 ` Willem de Bruijn
2026-07-23 21:22   ` Willem de Bruijn [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=willemdebruijn.kernel.36bee22ca53dd@gmail.com \
    --to=willemdebruijn.kernel@gmail.com \
    --cc=davem@davemloft.net \
    --cc=doruk@0sec.ai \
    --cc=edumazet@google.com \
    --cc=horms@kernel.org \
    --cc=kuba@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=olteanv@gmail.com \
    --cc=pabeni@redhat.com \
    --cc=sd@queasysnail.net \
    --cc=stable@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.