]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - queue-6.8/wifi-cfg80211-check-a-msdu-format-more-carefully.patch
e59a06c9b1cc906226526682a666af024b7dc7ef
[thirdparty/kernel/stable-queue.git] / queue-6.8 / wifi-cfg80211-check-a-msdu-format-more-carefully.patch
1 From 30198bcfdfc6260770382508b26aa86b174d1b15 Mon Sep 17 00:00:00 2001
2 From: Sasha Levin <sashal@kernel.org>
3 Date: Mon, 26 Feb 2024 20:34:06 +0100
4 Subject: wifi: cfg80211: check A-MSDU format more carefully
5
6 From: Johannes Berg <johannes.berg@intel.com>
7
8 [ Upstream commit 9ad7974856926129f190ffbe3beea78460b3b7cc ]
9
10 If it looks like there's another subframe in the A-MSDU
11 but the header isn't fully there, we can end up reading
12 data out of bounds, only to discard later. Make this a
13 bit more careful and check if the subframe header can
14 even be present.
15
16 Reported-by: syzbot+d050d437fe47d479d210@syzkaller.appspotmail.com
17 Link: https://msgid.link/20240226203405.a731e2c95e38.I82ce7d8c0cc8970ce29d0a39fdc07f1ffc425be4@changeid
18 Signed-off-by: Johannes Berg <johannes.berg@intel.com>
19 Signed-off-by: Sasha Levin <sashal@kernel.org>
20 ---
21 net/wireless/util.c | 14 ++++++++++----
22 1 file changed, 10 insertions(+), 4 deletions(-)
23
24 diff --git a/net/wireless/util.c b/net/wireless/util.c
25 index d1ce3bee27973..b9d15f369378b 100644
26 --- a/net/wireless/util.c
27 +++ b/net/wireless/util.c
28 @@ -791,15 +791,19 @@ ieee80211_amsdu_subframe_length(void *field, u8 mesh_flags, u8 hdr_type)
29
30 bool ieee80211_is_valid_amsdu(struct sk_buff *skb, u8 mesh_hdr)
31 {
32 - int offset = 0, remaining, subframe_len, padding;
33 + int offset = 0, subframe_len, padding;
34
35 for (offset = 0; offset < skb->len; offset += subframe_len + padding) {
36 + int remaining = skb->len - offset;
37 struct {
38 __be16 len;
39 u8 mesh_flags;
40 } hdr;
41 u16 len;
42
43 + if (sizeof(hdr) > remaining)
44 + return false;
45 +
46 if (skb_copy_bits(skb, offset + 2 * ETH_ALEN, &hdr, sizeof(hdr)) < 0)
47 return false;
48
49 @@ -807,7 +811,6 @@ bool ieee80211_is_valid_amsdu(struct sk_buff *skb, u8 mesh_hdr)
50 mesh_hdr);
51 subframe_len = sizeof(struct ethhdr) + len;
52 padding = (4 - subframe_len) & 0x3;
53 - remaining = skb->len - offset;
54
55 if (subframe_len > remaining)
56 return false;
57 @@ -825,7 +828,7 @@ void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list,
58 {
59 unsigned int hlen = ALIGN(extra_headroom, 4);
60 struct sk_buff *frame = NULL;
61 - int offset = 0, remaining;
62 + int offset = 0;
63 struct {
64 struct ethhdr eth;
65 uint8_t flags;
66 @@ -839,10 +842,14 @@ void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list,
67 copy_len = sizeof(hdr);
68
69 while (!last) {
70 + int remaining = skb->len - offset;
71 unsigned int subframe_len;
72 int len, mesh_len = 0;
73 u8 padding;
74
75 + if (copy_len > remaining)
76 + goto purge;
77 +
78 skb_copy_bits(skb, offset, &hdr, copy_len);
79 if (iftype == NL80211_IFTYPE_MESH_POINT)
80 mesh_len = __ieee80211_get_mesh_hdrlen(hdr.flags);
81 @@ -852,7 +859,6 @@ void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list,
82 padding = (4 - subframe_len) & 0x3;
83
84 /* the last MSDU has no padding */
85 - remaining = skb->len - offset;
86 if (subframe_len > remaining)
87 goto purge;
88 /* mitigate A-MSDU aggregation injection attacks */
89 --
90 2.43.0
91