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>
This commit is contained in:
parent
22667035e5
commit
8ade3356b2
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue