summaryrefslogtreecommitdiff
path: root/net/wireless/radiotap.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/wireless/radiotap.c')
-rw-r--r--net/wireless/radiotap.c28
1 files changed, 19 insertions, 9 deletions
diff --git a/net/wireless/radiotap.c b/net/wireless/radiotap.c
index 7d604c06c3dc..326faea38ca3 100644
--- a/net/wireless/radiotap.c
+++ b/net/wireless/radiotap.c
@@ -18,7 +18,7 @@
#include <linux/export.h>
#include <net/cfg80211.h>
#include <net/ieee80211_radiotap.h>
-#include <asm/unaligned.h>
+#include <linux/unaligned.h>
/* function prototypes and related defs are in include/net/cfg80211.h */
@@ -43,6 +43,7 @@ static const struct radiotap_align_size rtap_namespace_sizes[] = {
[IEEE80211_RADIOTAP_DATA_RETRIES] = { .align = 1, .size = 1, },
[IEEE80211_RADIOTAP_MCS] = { .align = 1, .size = 3, },
[IEEE80211_RADIOTAP_AMPDU_STATUS] = { .align = 4, .size = 8, },
+ [IEEE80211_RADIOTAP_VHT] = { .align = 2, .size = 12, },
/*
* add more here as they are defined in radiotap.h
*/
@@ -58,6 +59,7 @@ static const struct ieee80211_radiotap_namespace radiotap_ns = {
* @iterator: radiotap_iterator to initialize
* @radiotap_header: radiotap header to parse
* @max_length: total length we can parse into (eg, whole packet length)
+ * @vns: vendor namespaces to parse
*
* Returns: 0 or a negative error code if there is a problem.
*
@@ -89,7 +91,7 @@ static const struct ieee80211_radiotap_namespace radiotap_ns = {
* iterator.this_arg for type "type" safely on all arches.
*
* Example code:
- * See Documentation/networking/radiotap-headers.txt
+ * See Documentation/networking/radiotap-headers.rst
*/
int ieee80211_radiotap_iterator_init(
@@ -97,6 +99,10 @@ int ieee80211_radiotap_iterator_init(
struct ieee80211_radiotap_header *radiotap_header,
int max_length, const struct ieee80211_radiotap_vendor_namespaces *vns)
{
+ /* check the radiotap header can actually be present */
+ if (max_length < sizeof(struct ieee80211_radiotap_header))
+ return -EINVAL;
+
/* Linux only supports version 0 radiotap format */
if (radiotap_header->it_version)
return -EINVAL;
@@ -109,19 +115,22 @@ int ieee80211_radiotap_iterator_init(
iterator->_max_length = get_unaligned_le16(&radiotap_header->it_len);
iterator->_arg_index = 0;
iterator->_bitmap_shifter = get_unaligned_le32(&radiotap_header->it_present);
- iterator->_arg = (uint8_t *)radiotap_header + sizeof(*radiotap_header);
+ iterator->_arg = (uint8_t *)radiotap_header->it_optional;
iterator->_reset_on_ext = 0;
- iterator->_next_bitmap = &radiotap_header->it_present;
- iterator->_next_bitmap++;
+ iterator->_next_bitmap = radiotap_header->it_optional;
iterator->_vns = vns;
iterator->current_namespace = &radiotap_ns;
iterator->is_radiotap_ns = 1;
/* find payload start allowing for extended bitmap(s) */
- if (iterator->_bitmap_shifter & (1<<IEEE80211_RADIOTAP_EXT)) {
+ if (iterator->_bitmap_shifter & (BIT(IEEE80211_RADIOTAP_EXT))) {
+ if ((unsigned long)iterator->_arg -
+ (unsigned long)iterator->_rtheader + sizeof(uint32_t) >
+ (unsigned long)iterator->_max_length)
+ return -EINVAL;
while (get_unaligned_le32(iterator->_arg) &
- (1 << IEEE80211_RADIOTAP_EXT)) {
+ (BIT(IEEE80211_RADIOTAP_EXT))) {
iterator->_arg += sizeof(uint32_t);
/*
@@ -131,7 +140,8 @@ int ieee80211_radiotap_iterator_init(
*/
if ((unsigned long)iterator->_arg -
- (unsigned long)iterator->_rtheader >
+ (unsigned long)iterator->_rtheader +
+ sizeof(uint32_t) >
(unsigned long)iterator->_max_length)
return -EINVAL;
}
@@ -190,7 +200,7 @@ static void find_ns(struct ieee80211_radiotap_iterator *iterator,
* present fields. @this_arg can be changed by the caller (eg,
* incremented to move inside a compound argument like
* IEEE80211_RADIOTAP_CHANNEL). The args pointed to are in
- * little-endian format whatever the endianess of your CPU.
+ * little-endian format whatever the endianness of your CPU.
*
* Alignment Gotcha:
* You must take care when dereferencing iterator.this_arg