wifi: cfg80211: check IP header size in cfg80211_classify8021d()

A frame that looks like IP can be transmitted, but be too short, so
the DS field is read incorrectly:

  BUG: KMSAN: uninit-value in cfg80211_classify8021d+0x99d/0x12b0 net/wireless/util.c:1027
   cfg80211_classify8021d+0x99d/0x12b0 net/wireless/util.c:1027
   ieee80211_select_queue+0x37a/0x9e0 net/mac80211/wme.c:180
   __ieee80211_subif_start_xmit+0x60f/0x1d90 net/mac80211/tx.c:4304
   ieee80211_subif_start_xmit+0xa8/0x6d0 net/mac80211/tx.c:4538
   ...
   packet_sendmsg+0x9173/0xa2a0 net/packet/af_packet.c:3108

Use skb_header_pointer() like the MPLS case.

Assisted-by: LLM
Fixes: e31a16d6f6 ("wireless: move some utility functions from mac80211 to cfg80211")
Reported-by: syzbot+878ddc3962f792e9af59@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=878ddc3962f792e9af59
Link: https://patch.msgid.link/20260904165614.5e61a4c80b92.I37d68d3f406cb3b90b32e6943418d66070b65197@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
Johannes Berg 2026-09-04 16:55:02 +02:00
parent a7783e5853
commit 48b2c5c628

View File

@ -1039,12 +1039,30 @@ unsigned int cfg80211_classify8021d(struct sk_buff *skb,
}
switch (skb->protocol) {
case htons(ETH_P_IP):
dscp = ipv4_get_dsfield(ip_hdr(skb)) & 0xfc;
case htons(ETH_P_IP): {
const struct iphdr *iph;
struct iphdr _iph;
iph = skb_header_pointer(skb, sizeof(struct ethhdr),
sizeof(*iph), &_iph);
if (!iph)
return 0;
dscp = ipv4_get_dsfield(iph) & 0xfc;
break;
case htons(ETH_P_IPV6):
dscp = ipv6_get_dsfield(ipv6_hdr(skb)) & 0xfc;
}
case htons(ETH_P_IPV6): {
const struct ipv6hdr *ip6h;
struct ipv6hdr _ip6h;
ip6h = skb_header_pointer(skb, sizeof(struct ethhdr),
sizeof(*ip6h), &_ip6h);
if (!ip6h)
return 0;
dscp = ipv6_get_dsfield(ip6h) & 0xfc;
break;
}
case htons(ETH_P_MPLS_UC):
case htons(ETH_P_MPLS_MC): {
struct mpls_label mpls_tmp, *mpls;