161c7d6c8fb7d392f3402d0f859be2bbb1d28f0a
[openwrt/staging/981213.git] /
1 From: Felix Fietkau <nbd@nbd.name>
2 Date: Fri, 7 Oct 2022 10:54:47 +0200
3 Subject: [PATCH] wifi: cfg80211: fix ieee80211_data_to_8023_exthdr
4 handling of small packets
5
6 STP topology change notification packets only have a payload of 7 bytes,
7 so they get dropped due to the skb->len < hdrlen + 8 check.
8 Fix this by removing skb->len based checks and instead check the return code
9 on the skb_copy_bits calls.
10
11 Fixes: 2d1c304cb2d5 ("cfg80211: add function for 802.3 conversion with separate output buffer")
12 Reported-by: Chad Monroe <chad.monroe@smartrg.com>
13 Signed-off-by: Felix Fietkau <nbd@nbd.name>
14 ---
15
16 --- a/net/wireless/util.c
17 +++ b/net/wireless/util.c
18 @@ -557,7 +557,7 @@ int ieee80211_data_to_8023_exthdr(struct
19 return -1;
20
21 hdrlen = ieee80211_hdrlen(hdr->frame_control) + data_offset;
22 - if (skb->len < hdrlen + 8)
23 + if (skb->len < hdrlen)
24 return -1;
25
26 /* convert IEEE 802.11 header + possible LLC headers into Ethernet
27 @@ -572,8 +572,9 @@ int ieee80211_data_to_8023_exthdr(struct
28 memcpy(tmp.h_dest, ieee80211_get_DA(hdr), ETH_ALEN);
29 memcpy(tmp.h_source, ieee80211_get_SA(hdr), ETH_ALEN);
30
31 - if (iftype == NL80211_IFTYPE_MESH_POINT)
32 - skb_copy_bits(skb, hdrlen, &mesh_flags, 1);
33 + if (iftype == NL80211_IFTYPE_MESH_POINT &&
34 + skb_copy_bits(skb, hdrlen, &mesh_flags, 1) < 0)
35 + return -1;
36
37 mesh_flags &= MESH_FLAGS_AE;
38
39 @@ -593,11 +594,12 @@ int ieee80211_data_to_8023_exthdr(struct
40 if (iftype == NL80211_IFTYPE_MESH_POINT) {
41 if (mesh_flags == MESH_FLAGS_AE_A4)
42 return -1;
43 - if (mesh_flags == MESH_FLAGS_AE_A5_A6) {
44 - skb_copy_bits(skb, hdrlen +
45 - offsetof(struct ieee80211s_hdr, eaddr1),
46 - tmp.h_dest, 2 * ETH_ALEN);
47 - }
48 + if (mesh_flags == MESH_FLAGS_AE_A5_A6 &&
49 + skb_copy_bits(skb, hdrlen +
50 + offsetof(struct ieee80211s_hdr, eaddr1),
51 + tmp.h_dest, 2 * ETH_ALEN) < 0)
52 + return -1;
53 +
54 hdrlen += __ieee80211_get_mesh_hdrlen(mesh_flags);
55 }
56 break;
57 @@ -611,10 +613,11 @@ int ieee80211_data_to_8023_exthdr(struct
58 if (iftype == NL80211_IFTYPE_MESH_POINT) {
59 if (mesh_flags == MESH_FLAGS_AE_A5_A6)
60 return -1;
61 - if (mesh_flags == MESH_FLAGS_AE_A4)
62 - skb_copy_bits(skb, hdrlen +
63 - offsetof(struct ieee80211s_hdr, eaddr1),
64 - tmp.h_source, ETH_ALEN);
65 + if (mesh_flags == MESH_FLAGS_AE_A4 &&
66 + skb_copy_bits(skb, hdrlen +
67 + offsetof(struct ieee80211s_hdr, eaddr1),
68 + tmp.h_source, ETH_ALEN) < 0)
69 + return -1;
70 hdrlen += __ieee80211_get_mesh_hdrlen(mesh_flags);
71 }
72 break;
73 @@ -626,18 +629,18 @@ int ieee80211_data_to_8023_exthdr(struct
74 break;
75 }
76
77 - skb_copy_bits(skb, hdrlen, &payload, sizeof(payload));
78 - tmp.h_proto = payload.proto;
79 -
80 - if (likely((!is_amsdu && ether_addr_equal(payload.hdr, rfc1042_header) &&
81 - tmp.h_proto != htons(ETH_P_AARP) &&
82 - tmp.h_proto != htons(ETH_P_IPX)) ||
83 - ether_addr_equal(payload.hdr, bridge_tunnel_header)))
84 + if (likely(skb_copy_bits(skb, hdrlen, &payload, sizeof(payload)) == 0 &&
85 + ((!is_amsdu && ether_addr_equal(payload.hdr, rfc1042_header) &&
86 + payload.proto != htons(ETH_P_AARP) &&
87 + payload.proto != htons(ETH_P_IPX)) ||
88 + ether_addr_equal(payload.hdr, bridge_tunnel_header)))) {
89 /* remove RFC1042 or Bridge-Tunnel encapsulation and
90 * replace EtherType */
91 hdrlen += ETH_ALEN + 2;
92 - else
93 + tmp.h_proto = payload.proto;
94 + } else {
95 tmp.h_proto = htons(skb->len - hdrlen);
96 + }
97
98 pskb_pull(skb, hdrlen);
99