ocelot_xmit() reads the Ethernet header via eth_hdr(skb) to test the
destination address against the link-local range.
On the AF_PACKET SOCK_RAW + PACKET_QDISC_BYPASS transmit path the skb
reaches ndo_start_xmit() with the MAC header unset, so eth_hdr(skb)
resolves to skb->head + (u16)~0 and the read is out of bounds.
On the TX path the L2 header is at skb->data, so use skb_eth_hdr(), as
done for the same class by
commit f5089008f90c ("macsec: don't read an unset MAC header in
macsec_encrypt()")
and commit 96cc4b69581d ("macvlan: do not assume mac_header is set in
macvlan_broadcast()").
Fixes: 43ba33b4f143 ("net: dsa: tag_ocelot_8021q: fix inability to inject STP
BPDUs into BLOCKING ports")
Cc: [email protected]
Found by 0sec automated security-research tooling (https://0sec.ai).
Assisted-by: 0sec:claude-opus-4-8
Signed-off-by: Doruk Tan Ozturk <[email protected]>
---
net/dsa/tag_ocelot_8021q.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/dsa/tag_ocelot_8021q.c b/net/dsa/tag_ocelot_8021q.c
index f50f1cd83f16..4514026897d1 100644
--- a/net/dsa/tag_ocelot_8021q.c
+++ b/net/dsa/tag_ocelot_8021q.c
@@ -71,7 +71,7 @@ static struct sk_buff *ocelot_xmit(struct sk_buff *skb,
u16 queue_mapping = skb_get_queue_mapping(skb);
u8 pcp = netdev_txq_to_tc(netdev, queue_mapping);
u16 tx_vid = dsa_tag_8021q_standalone_vid(dp);
- struct ethhdr *hdr = eth_hdr(skb);
+ struct ethhdr *hdr = skb_eth_hdr(skb);
if (ocelot_ptp_rew_op(skb) || is_link_local_ether_addr(hdr->h_dest))
return ocelot_defer_xmit(dp, skb);
--
2.43.0