diff options
author | Johannes Berg <johannes.berg@intel.com> | 2024-02-28 09:55:42 +0100 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2024-03-04 14:33:51 +0100 |
commit | 8ade3356b25ab2522892a21832a709e7ad5f8168 (patch) | |
tree | 1e62fa0ea57e1bb3e46d600230c050b3ac2c24f2 | |
parent | 22667035e5ddb7b68c7d473693b321fb9e20a397 (diff) |
wifi: cfg80211: allow cfg80211_defragment_element() without output
If we just want to determine the length of the fragmented
data, we basically need the same logic, and really we want
it to be _literally_ the same logic, so it cannot be out
of sync in any way.
Allow calling cfg80211_defragment_element() without an output
buffer, where it then just returns the required output size.
Also add this to the tests, just to exercise it, using the
pre-calculated length to really do the defragmentation, which
checks that this is sufficient.
Reviewed-by: Miriam Rachel Korenblit <miriam.rachel.korenblit@intel.com>
Reviewed-by: Benjamin Berg <benjamin.berg@intel.com>
Link: https://msgid.link/20240228095718.6d6565b9e3f2.Ib441903f4b8644ba04b1c766f90580ee6f54fc66@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-rw-r--r-- | include/net/cfg80211.h | 4 | ||||
-rw-r--r-- | net/wireless/scan.c | 27 | ||||
-rw-r--r-- | net/wireless/tests/fragmentation.c | 30 |
3 files changed, 45 insertions, 16 deletions
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index 53653d234d39..2e2be4fd2bb6 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h @@ -6908,8 +6908,8 @@ bool cfg80211_iter_rnr(const u8 *elems, size_t elems_len, * @elem: the element to defragment * @ies: elements where @elem is contained * @ieslen: length of @ies - * @data: buffer to store element data - * @data_len: length of @data + * @data: buffer to store element data, or %NULL to just determine size + * @data_len: length of @data, or 0 * @frag_id: the element ID of fragments * * Return: length of @data, or -EINVAL on error diff --git a/net/wireless/scan.c b/net/wireless/scan.c index 9377a43aa5f7..5a5dd3ce497f 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c @@ -2504,16 +2504,22 @@ ssize_t cfg80211_defragment_element(const struct element *elem, const u8 *ies, if (elem->id == WLAN_EID_EXTENSION) { copied = elem->datalen - 1; - if (copied > data_len) - return -ENOSPC; - memmove(data, elem->data + 1, copied); + if (data) { + if (copied > data_len) + return -ENOSPC; + + memmove(data, elem->data + 1, copied); + } } else { copied = elem->datalen; - if (copied > data_len) - return -ENOSPC; - memmove(data, elem->data, copied); + if (data) { + if (copied > data_len) + return -ENOSPC; + + memmove(data, elem->data, copied); + } } /* Fragmented elements must have 255 bytes */ @@ -2532,10 +2538,13 @@ ssize_t cfg80211_defragment_element(const struct element *elem, const u8 *ies, elem_datalen = elem->datalen; - if (copied + elem_datalen > data_len) - return -ENOSPC; + if (data) { + if (copied + elem_datalen > data_len) + return -ENOSPC; + + memmove(data + copied, elem->data, elem_datalen); + } - memmove(data + copied, elem->data, elem_datalen); copied += elem_datalen; /* Only the last fragment may be short */ diff --git a/net/wireless/tests/fragmentation.c b/net/wireless/tests/fragmentation.c index 49a339ca8880..411fae18cd88 100644 --- a/net/wireless/tests/fragmentation.c +++ b/net/wireless/tests/fragmentation.c @@ -2,7 +2,7 @@ /* * KUnit tests for element fragmentation * - * Copyright (C) 2023 Intel Corporation + * Copyright (C) 2023-2024 Intel Corporation */ #include <linux/ieee80211.h> #include <net/cfg80211.h> @@ -27,7 +27,12 @@ static void defragment_0(struct kunit *test) ret = cfg80211_defragment_element((void *)input, input, sizeof(input), - data, sizeof(input), + NULL, 0, + WLAN_EID_FRAGMENT); + KUNIT_EXPECT_EQ(test, ret, 253); + ret = cfg80211_defragment_element((void *)input, + input, sizeof(input), + data, ret, WLAN_EID_FRAGMENT); KUNIT_EXPECT_EQ(test, ret, 253); KUNIT_EXPECT_MEMEQ(test, data, input + 3, 253); @@ -63,7 +68,12 @@ static void defragment_1(struct kunit *test) ret = cfg80211_defragment_element((void *)input, input, sizeof(input), - data, sizeof(input), + NULL, 0, + WLAN_EID_FRAGMENT); + KUNIT_EXPECT_EQ(test, ret, 254 + 7); + ret = cfg80211_defragment_element((void *)input, + input, sizeof(input), + data, ret, WLAN_EID_FRAGMENT); /* this means the last fragment was not used */ KUNIT_EXPECT_EQ(test, ret, 254 + 7); @@ -106,10 +116,15 @@ static void defragment_2(struct kunit *test) ret = cfg80211_defragment_element((void *)input, input, sizeof(input), - data, sizeof(input), + NULL, 0, WLAN_EID_FRAGMENT); /* this means the last fragment was not used */ KUNIT_EXPECT_EQ(test, ret, 254 + 255 + 1); + ret = cfg80211_defragment_element((void *)input, + input, sizeof(input), + data, ret, + WLAN_EID_FRAGMENT); + KUNIT_EXPECT_EQ(test, ret, 254 + 255 + 1); KUNIT_EXPECT_MEMEQ(test, data, input + 3, 254); KUNIT_EXPECT_MEMEQ(test, data + 254, input + 257 + 2, 255); KUNIT_EXPECT_MEMEQ(test, data + 254 + 255, input + 2 * 257 + 2, 1); @@ -134,7 +149,12 @@ static void defragment_at_end(struct kunit *test) ret = cfg80211_defragment_element((void *)input, input, sizeof(input), - data, sizeof(input), + NULL, 0, + WLAN_EID_FRAGMENT); + KUNIT_EXPECT_EQ(test, ret, 254 + 7); + ret = cfg80211_defragment_element((void *)input, + input, sizeof(input), + data, ret, WLAN_EID_FRAGMENT); KUNIT_EXPECT_EQ(test, ret, 254 + 7); KUNIT_EXPECT_MEMEQ(test, data, input + 3, 254); |