mac80211: Use flex-array for radiotap header bitmap
authorKees Cook <keescook@chromium.org>
Fri, 6 Aug 2021 21:53:05 +0000 (14:53 -0700)
committerJohannes Berg <johannes.berg@intel.com>
Fri, 13 Aug 2021 07:58:25 +0000 (09:58 +0200)
In preparation for FORTIFY_SOURCE performing compile-time and run-time
field bounds checking for memcpy(), memmove(), and memset(), avoid
intentionally writing across neighboring fields.

The it_present member of struct ieee80211_radiotap_header is treated as a
flexible array (multiple u32s can be conditionally present). In order for
memcpy() to reason (or really, not reason) about the size of operations
against this struct, use of bytes beyond it_present need to be treated
as part of the flexible array. Add a trailing flexible array and
initialize its initial index via pointer arithmetic.

Cc: Johannes Berg <johannes@sipsolutions.net>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: Jakub Kicinski <kuba@kernel.org>
Cc: linux-wireless@vger.kernel.org
Cc: netdev@vger.kernel.org
Signed-off-by: Kees Cook <keescook@chromium.org>
Link: https://lore.kernel.org/r/20210806215305.2875621-1-keescook@chromium.org
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
include/net/ieee80211_radiotap.h
net/mac80211/rx.c
net/wireless/radiotap.c

index c0854933e24f24c82e16821286b314fa3f0574be..11630351c97833185e8eeb3771292d2af4b61042 100644 (file)
@@ -43,6 +43,11 @@ struct ieee80211_radiotap_header {
         * @it_present: (first) present word
         */
        __le32 it_present;
+
+       /**
+        * @it_optional: all remaining presence bitmaps
+        */
+       __le32 it_optional[];
 } __packed;
 
 /* version is always 0 */
index 3eb7b03b23c6e45cfc2d3a8213f6808f869e5dc1..33c56eab07fcd134e611d18af48c9434ad5bc9d2 100644 (file)
@@ -359,7 +359,12 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
 
        put_unaligned_le32(it_present_val, it_present);
 
-       pos = (void *)(it_present + 1);
+       /* This references through an offset into it_optional[] rather
+        * than via it_present otherwise later uses of pos will cause
+        * the compiler to think we have walked past the end of the
+        * struct member.
+        */
+       pos = (void *)&rthdr->it_optional[it_present - rthdr->it_optional];
 
        /* the order of the following fields is important */
 
index 8099c9564a5978038fd1a65b13f308bb7ad22a8d..ae2e1a8964611e3138623b5e9885ed079ab40674 100644 (file)
@@ -115,10 +115,9 @@ 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;