|
|
@@ -0,0 +1,97 @@
|
|
|
+From: Felix Fietkau <[email protected]>
|
|
|
+Date: Fri, 7 Oct 2022 10:54:47 +0200
|
|
|
+Subject: [PATCH] wifi: cfg80211: fix ieee80211_data_to_8023_exthdr
|
|
|
+ handling of small packets
|
|
|
+
|
|
|
+STP topology change notification packets only have a payload of 7 bytes,
|
|
|
+so they get dropped due to the skb->len < hdrlen + 8 check.
|
|
|
+Fix this by removing skb->len based checks and instead check the return code
|
|
|
+on the skb_copy_bits calls.
|
|
|
+
|
|
|
+Fixes: 2d1c304cb2d5 ("cfg80211: add function for 802.3 conversion with separate output buffer")
|
|
|
+Reported-by: Chad Monroe <[email protected]>
|
|
|
+Signed-off-by: Felix Fietkau <[email protected]>
|
|
|
+---
|
|
|
+
|
|
|
+--- a/net/wireless/util.c
|
|
|
++++ b/net/wireless/util.c
|
|
|
+@@ -557,8 +557,6 @@ int ieee80211_data_to_8023_exthdr(struct
|
|
|
+ return -1;
|
|
|
+
|
|
|
+ hdrlen = ieee80211_hdrlen(hdr->frame_control) + data_offset;
|
|
|
+- if (skb->len < hdrlen + 8)
|
|
|
+- return -1;
|
|
|
+
|
|
|
+ /* convert IEEE 802.11 header + possible LLC headers into Ethernet
|
|
|
+ * header
|
|
|
+@@ -572,8 +570,9 @@ int ieee80211_data_to_8023_exthdr(struct
|
|
|
+ memcpy(tmp.h_dest, ieee80211_get_DA(hdr), ETH_ALEN);
|
|
|
+ memcpy(tmp.h_source, ieee80211_get_SA(hdr), ETH_ALEN);
|
|
|
+
|
|
|
+- if (iftype == NL80211_IFTYPE_MESH_POINT)
|
|
|
+- skb_copy_bits(skb, hdrlen, &mesh_flags, 1);
|
|
|
++ if (iftype == NL80211_IFTYPE_MESH_POINT &&
|
|
|
++ skb_copy_bits(skb, hdrlen, &mesh_flags, 1) < 0)
|
|
|
++ return -1;
|
|
|
+
|
|
|
+ mesh_flags &= MESH_FLAGS_AE;
|
|
|
+
|
|
|
+@@ -593,11 +592,12 @@ int ieee80211_data_to_8023_exthdr(struct
|
|
|
+ if (iftype == NL80211_IFTYPE_MESH_POINT) {
|
|
|
+ if (mesh_flags == MESH_FLAGS_AE_A4)
|
|
|
+ return -1;
|
|
|
+- if (mesh_flags == MESH_FLAGS_AE_A5_A6) {
|
|
|
+- skb_copy_bits(skb, hdrlen +
|
|
|
+- offsetof(struct ieee80211s_hdr, eaddr1),
|
|
|
+- tmp.h_dest, 2 * ETH_ALEN);
|
|
|
+- }
|
|
|
++ if (mesh_flags == MESH_FLAGS_AE_A5_A6 &&
|
|
|
++ skb_copy_bits(skb, hdrlen +
|
|
|
++ offsetof(struct ieee80211s_hdr, eaddr1),
|
|
|
++ tmp.h_dest, 2 * ETH_ALEN) < 0)
|
|
|
++ return -1;
|
|
|
++
|
|
|
+ hdrlen += __ieee80211_get_mesh_hdrlen(mesh_flags);
|
|
|
+ }
|
|
|
+ break;
|
|
|
+@@ -611,10 +611,11 @@ int ieee80211_data_to_8023_exthdr(struct
|
|
|
+ if (iftype == NL80211_IFTYPE_MESH_POINT) {
|
|
|
+ if (mesh_flags == MESH_FLAGS_AE_A5_A6)
|
|
|
+ return -1;
|
|
|
+- if (mesh_flags == MESH_FLAGS_AE_A4)
|
|
|
+- skb_copy_bits(skb, hdrlen +
|
|
|
+- offsetof(struct ieee80211s_hdr, eaddr1),
|
|
|
+- tmp.h_source, ETH_ALEN);
|
|
|
++ if (mesh_flags == MESH_FLAGS_AE_A4 &&
|
|
|
++ skb_copy_bits(skb, hdrlen +
|
|
|
++ offsetof(struct ieee80211s_hdr, eaddr1),
|
|
|
++ tmp.h_source, ETH_ALEN) < 0)
|
|
|
++ return -1;
|
|
|
+ hdrlen += __ieee80211_get_mesh_hdrlen(mesh_flags);
|
|
|
+ }
|
|
|
+ break;
|
|
|
+@@ -626,18 +627,18 @@ int ieee80211_data_to_8023_exthdr(struct
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+- skb_copy_bits(skb, hdrlen, &payload, sizeof(payload));
|
|
|
+- tmp.h_proto = payload.proto;
|
|
|
+-
|
|
|
+- if (likely((!is_amsdu && ether_addr_equal(payload.hdr, rfc1042_header) &&
|
|
|
++ if (likely(skb_copy_bits(skb, hdrlen, &payload, sizeof(payload)) == 0) &&
|
|
|
++ likely((!is_amsdu && ether_addr_equal(payload.hdr, rfc1042_header) &&
|
|
|
+ tmp.h_proto != htons(ETH_P_AARP) &&
|
|
|
+ tmp.h_proto != htons(ETH_P_IPX)) ||
|
|
|
+- ether_addr_equal(payload.hdr, bridge_tunnel_header)))
|
|
|
++ ether_addr_equal(payload.hdr, bridge_tunnel_header))) {
|
|
|
+ /* remove RFC1042 or Bridge-Tunnel encapsulation and
|
|
|
+ * replace EtherType */
|
|
|
+ hdrlen += ETH_ALEN + 2;
|
|
|
+- else
|
|
|
++ tmp.h_proto = payload.proto;
|
|
|
++ } else {
|
|
|
+ tmp.h_proto = htons(skb->len - hdrlen);
|
|
|
++ }
|
|
|
+
|
|
|
+ pskb_pull(skb, hdrlen);
|
|
|
+
|