wifi: mwifiex: Fix tlv_buf_left calculation and replace one-element array
cover wifi: mwifiex: Fix tlv_buf_left calculation and replace one-element array
Hi all!
This small series is aimed at fixing a bug in the tlv_buf_left calculation, doing a flexible-array transformation, and adding a couple of sanity checks.
Thanks
Gustavo A. R. Silva (3):
wifi: mwifiex: Fix tlv_buf_left calculation
wifi: mwifiex: Replace one-element array with flexible-array member in
struct mwifiex_ie_types_rxba_sync
wifi: mwifiex: Sanity check tlv_len and tlv_bitmap_len
.../wireless/marvell/mwifiex/11n_rxreorder.c | 22 ++++++++++++++++--- drivers/net/wireless/marvell/mwifiex/fw.h | 2 +- 2 files changed, 20 insertions(+), 4 deletions(-)
Signature · 1 line
2.34.1
PATCH 1/3 wifi: mwifiex: Fix tlv_buf_left calculation
In a TLV encoding scheme, the Length part represents the length after the header containing the values for type and length. In this case, tlv_len should be:
tlv_len == (sizeof(*tlv_rxba) - 1) - sizeof(tlv_rxba->header) + tlv_bitmap_len
Notice that the - 1 accounts for the one-element array bitmap, which 1-byte size is already included in sizeof(*tlv_rxba).
So, if the above is correct, there is a double-counting of some members in struct mwifiex_ie_types_rxba_sync, when tlv_buf_left and tmp are calculated:
968 tlv_buf_left -= (sizeof(*tlv_rxba) + tlv_len);
969 tmp = (u8 *)tlv_rxba + tlv_len + sizeof(*tlv_rxba);
in specific, members:
drivers/net/wireless/marvell/mwifiex/fw.h:777
777 u8 mac[ETH_ALEN]; 778 u8 tid; 779 u8 reserved; 780 __le16 seq_num; 781 __le16 bitmap_len;
This is clearly wrong, and affects the subsequent decoding of data from event_buf through tlv_rxba:
970 tlv_rxba = (struct mwifiex_ie_types_rxba_sync *)tmp;
Fix this by using sizeof(tlv_rxba->header) instead of sizeof(*tlv_rxba) in the calculation of tlv_buf_left and tmp.
This results in the following binary differences before/after changes:
| drivers/net/wireless/marvell/mwifiex/11n_rxreorder.o | @@ -4698,11 +4698,11 @@ | tlv_buf_left -= (sizeof(tlv_rxba->header) + tlv_len); | - 1da7: lea -0x11(%rbx),%edx | + 1da7: lea -0x4(%rbx),%edx | 1daa: movzwl %bp,%eax | drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c:969 | tmp = (u8 *)tlv_rxba + sizeof(tlv_rxba->header) + tlv_len; | - 1dad: lea 0x11(%r15,%rbp,1),%r15 | + 1dad: lea 0x4(%r15,%rbp,1),%r15 | drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c:968 | tlv_buf_left -= (sizeof(tlv_rxba->header) + tlv_len); | 1db2: mov %edx,%ebx
The above reflects the desired change: avoid counting 13 too bytes; which is the total size of the double-counted members in struct mwifiex_ie_types_rxba_sync:
$ pahole -C mwifiex_ie_types_rxba_sync drivers/net/wireless/marvell/mwifiex/11n_rxreorder.o
struct mwifiex_ie_types_rxba_sync {
struct mwifiex_ie_types_header header; /* 0 4 */ |-----------------------------------------------------------------------
| u8 mac[6]; /* 4 6 */ |
| u8 tid; /* 10 1 */ |
| u8 reserved; /* 11 1 */ |
| __le16 seq_num; /* 12 2 */ |
| __le16 bitmap_len; /* 14 2 */ |
| u8 bitmap[1]; /* 16 1 */ |
|----------------------------------------------------------------------|
| 13 bytes|
-----------
/* size: 17, cachelines: 1, members: 7 */
/* last cacheline: 17 bytes */
} __attribute__((__packed__));--- drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c +2 -2
@@ -965,8 +965,8 @@ void mwifiex_11n_rxba_sync_event(struct mwifiex_private *priv, } } - tlv_buf_left -= (sizeof (*tlv_rxba) + tlv_len); - tmp = (u8 *)tlv_rxba + tlv_len +sizeof (*tlv_rxba); + tlv_buf_left -= (sizeof (tlv_rxba->header) + tlv_len); + tmp = (u8 *)tlv_rxba +sizeof (tlv_rxba->header) + tlv_len; tlv_rxba = (struct mwifiex_ie_types_rxba_sync *)tmp; } }
Signature · 1 line
2.34.1
Re: [PATCH 1/3] wifi: mwifiex: Fix tlv_buf_left calculation
Quoted 73 lines · Gustavo A. R. Silva
In a TLV encoding scheme, the Length part represents the length after the header containing the values for type and length. In this case,
tlv_lenshould be:
tlv_len== (sizeof(*tlv_rxba)- 1) -sizeof(tlv_rxba->header)+tlv_bitmap_lenNotice that the
- 1accounts for the one-element arraybitmap, which 1-byte size is already included insizeof(*tlv_rxba).So, if the above is correct, there is a double-counting of some members in
struct mwifiex_ie_types_rxba_sync, whentlv_buf_leftandtmpare calculated:968
tlv_buf_left-= (sizeof(*tlv_rxba)+tlv_len);
969 tmp = (u8 *)tlv_rxba +tlv_len+sizeof(*tlv_rxba);in specific, members:
drivers/net/wireless/marvell/mwifiex/fw.h:777777 u8 mac[ETH_ALEN]; 778 u8 tid; 779 u8 reserved; 780 __le16 seq_num; 781 __le16 bitmap_len;This is clearly wrong, and affects the subsequent decoding of data from
event_bufthroughtlv_rxba:970
tlv_rxba= (structmwifiex_ie_types_rxba_sync*)tmp;Fix this by using
sizeof(tlv_rxba->header)instead ofsizeof(*tlv_rxba)in the calculation oftlv_buf_leftandtmp.This results in the following binary differences before/after changes:
| drivers/net/wireless/marvell/mwifiex/11n_rxreorder.o | @@ -4698,11 +4698,11 @@ | tlv_buf_left -= (sizeof(tlv_rxba->header) + tlv_len); | - 1da7: lea -0x11(%rbx),%edx | + 1da7: lea -0x4(%rbx),%edx | 1daa: movzwl %bp,%eax | drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c:969 | tmp = (u8 *)tlv_rxba + sizeof(tlv_rxba->header) + tlv_len; | - 1dad: lea 0x11(%r15,%rbp,1),%r15 | + 1dad: lea 0x4(%r15,%rbp,1),%r15 | drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c:968 | tlv_buf_left -= (sizeof(tlv_rxba->header) + tlv_len); | 1db2: mov %edx,%ebxThe above reflects the desired change: avoid counting 13 too bytes; which is the total size of the double-counted members in
struct mwifiex_ie_types_rxba_sync:$ pahole -C mwifiex_ie_types_rxba_sync drivers/net/wireless/marvell/mwifiex/11n_rxreorder.o struct mwifiex_ie_types_rxba_sync { struct mwifiex_ie_types_header header; /* 0 4 */|----------------------------------------------------------------------- | u8 mac[6]; /* 4 6 */ | | u8 tid; /* 10 1 */ | | u8 reserved; /* 11 1 */ | | __le16 seq_num; /* 12 2 */ | | __le16 bitmap_len; /* 14 2 */ | | u8 bitmap[1]; /* 16 1 */ | |----------------------------------------------------------------------| | 13 bytes| ----------- /* size: 17, cachelines: 1, members: 7 */ /* last cacheline: 17 bytes */ } __attribute__((__packed__));
Quoted 3 lines
Fixes 99ffe72cdae4 ("mwifiex: process rxba_sync event")Signed-off-by Gustavo A. R. Silva <[email protected]>
Quoted 22 lines
--- drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c +2
-3@@ -965,8 +965,8 @@ void mwifiex_11n_rxba_sync_event(struct mwifiex_private *priv, } } - tlv_buf_left -= (sizeof (*tlv_rxba) + tlv_len); - tmp = (u8 *)tlv_rxba + tlv_len +sizeof (*tlv_rxba); + tlv_buf_left -= (sizeof (tlv_rxba->header) + tlv_len); + tmp = (u8 *)tlv_rxba +sizeof (tlv_rxba->header) + tlv_len; tlv_rxba = (struct mwifiex_ie_types_rxba_sync *)tmp; } } --2.34.1
PATCH 2/3 wifi: mwifiex: Replace one-element array with flexible-array member in struct mwifiex_ie_types_rxba_sync
In reply to Gustavo A. R. SilvaOne-element and zero-length arrays are deprecated. So, replace one-element array in struct mwifiex_ie_types_rxba_sync with flexible-array member, and refactor the rest of the code, accordingly.
This results in no differences in binary output.
--- drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c | 2 +- drivers/net/wireless/marvell/mwifiex/fw.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c +1 -1
@@ -918,7 +918,7 @@ void mwifiex_11n_rxba_sync_event(struct mwifiex_private *priv,mwifiex_dbg_dump (priv->adapter,EVT_D ,"RXBA_SYNC event:" , event_buf, len); -while (tlv_buf_left >=sizeof (*tlv_rxba)) { +while (tlv_buf_left >sizeof (*tlv_rxba)) { tlv_type =le16_to_cpu (tlv_rxba->header.type); tlv_len =le16_to_cpu (tlv_rxba->header.len);if (tlv_type !=TLV_TYPE_RXBA_SYNC ) {
drivers/net/wireless/marvell/mwifiex/fw.h +1 -1
@@ -779,7 +779,7 @@ struct mwifiex_ie_types_rxba_sync {u8 reserved;__le16 seq_num;__le16 bitmap_len; -u8 bitmap[1 ]; +u8 bitmap[]; } __packed;struct chan_band_param_set {
Signature · 1 line
2.34.1
Re: [PATCH 2/3] wifi: mwifiex: Replace one-element array with flexible-array member in struct mwifiex_ie_types_rxba_sync
Quoted 8 lines · Gustavo A. R. Silva
One-element and zero-length arrays are deprecated. So, replace one-element array in struct
mwifiex_ie_types_rxba_syncwith flexible-array member, and refactor the rest of the code, accordingly.This results in no differences in binary output.
Signed-off-by Gustavo A. R. Silva <[email protected]>
Quoted 34 lines
--- drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c | 2 +- drivers/net/wireless/marvell/mwifiex/fw.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c +1
-1@@ -918,7 +918,7 @@ void mwifiex_11n_rxba_sync_event(struct mwifiex_private *priv,mwifiex_dbg_dump (priv->adapter,EVT_D ,"RXBA_SYNC event:" , event_buf, len); -while (tlv_buf_left >=sizeof (*tlv_rxba)) { +while (tlv_buf_left >sizeof (*tlv_rxba)) { tlv_type =le16_to_cpu (tlv_rxba->header.type); tlv_len =le16_to_cpu (tlv_rxba->header.len);if (tlv_type !=TLV_TYPE_RXBA_SYNC ) {drivers/net/wireless/marvell/mwifiex/fw.h +1
-2@@ -779,7 +779,7 @@ struct mwifiex_ie_types_rxba_sync {u8 reserved;__le16 seq_num;__le16 bitmap_len; -u8 bitmap[1 ]; +u8 bitmap[]; } __packed;struct chan_band_param_set { --2.34.1
PATCH 3/3 wifi: mwifiex: Sanity check tlv_len and tlv_bitmap_len
In reply to Gustavo A. R. SilvaAdd sanity checks for both tlv_len and tlv_bitmap_len before decoding data from event_buf.
This prevents any malicious or buggy firmware from overflowing event_buf through large values for tlv_len or tlv_bitmap_len.
--- .../net/wireless/marvell/mwifiex/11n_rxreorder.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+)
drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c +16 -0
@@ -921,6 +921,14 @@ void mwifiex_11n_rxba_sync_event(struct mwifiex_private *priv,while (tlv_buf_left >sizeof (*tlv_rxba)) { tlv_type =le16_to_cpu (tlv_rxba->header.type); tlv_len =le16_to_cpu (tlv_rxba->header.len); +if (size_add (sizeof (tlv_rxba->header), tlv_len) > tlv_buf_left) { +mwifiex_dbg (priv->adapter,WARN , +"TLV size (%ld) overflows event_buf (%d)\n" , +size_add (sizeof (tlv_rxba->header), tlv_len), + tlv_buf_left); +return ; + } +if (tlv_type !=TLV_TYPE_RXBA_SYNC ) {mwifiex_dbg (priv->adapter,ERROR ,"Wrong TLV id=0x%x\n" , tlv_type);
@@ -929,6 +937,14 @@ void mwifiex_11n_rxba_sync_event(struct mwifiex_private *priv, tlv_seq_num =le16_to_cpu (tlv_rxba->seq_num); tlv_bitmap_len =le16_to_cpu (tlv_rxba->bitmap_len); +if (size_add (sizeof (*tlv_rxba), tlv_bitmap_len) > tlv_buf_left) { +mwifiex_dbg (priv->adapter,WARN , +"TLV size (%ld) overflows event_buf (%d)\n" , +size_add (sizeof (*tlv_rxba), tlv_bitmap_len), + tlv_buf_left); +return ; + } + mwifiex_dbg(priv->adapter, INFO, "%pM tid=%d seq_num=%d bitmap_len=%d\n", tlv_rxba->mac, tlv_rxba->tid, tlv_seq_num,
Signature · 1 line
2.34.1
Re: [PATCH 3/3] wifi: mwifiex: Sanity check tlv_len and tlv_bitmap_len
Quoted 9 lines · Gustavo A. R. Silva
Add sanity checks for both
tlv_lenandtlv_bitmap_lenbefore decoding data fromevent_buf.This prevents any malicious or buggy firmware from overflowing
event_bufthrough large values fortlv_lenortlv_bitmap_len.Suggested-by Dan Williams <[email protected]>Signed-off-by Gustavo A. R. Silva <[email protected]>
Quoted 41 lines
--- .../net/wireless/marvell/mwifiex/11n_rxreorder.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+)drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c +16
-1@@ -921,6 +921,14 @@ void mwifiex_11n_rxba_sync_event(struct mwifiex_private *priv,while (tlv_buf_left >sizeof (*tlv_rxba)) { tlv_type =le16_to_cpu (tlv_rxba->header.type); tlv_len =le16_to_cpu (tlv_rxba->header.len); +if (size_add (sizeof (tlv_rxba->header), tlv_len) > tlv_buf_left) { +mwifiex_dbg (priv->adapter,WARN , +"TLV size (%ld) overflows event_buf (%d)\n" , +size_add (sizeof (tlv_rxba->header), tlv_len), + tlv_buf_left); +return ; + } +if (tlv_type !=TLV_TYPE_RXBA_SYNC ) {mwifiex_dbg (priv->adapter,ERROR ,"Wrong TLV id=0x%x\n" , tlv_type);@@ -929,6 +937,14 @@ void mwifiex_11n_rxba_sync_event(struct mwifiex_private *priv, tlv_seq_num =le16_to_cpu (tlv_rxba->seq_num); tlv_bitmap_len =le16_to_cpu (tlv_rxba->bitmap_len); +if (size_add (sizeof (*tlv_rxba), tlv_bitmap_len) > tlv_buf_left) { +mwifiex_dbg (priv->adapter,WARN , +"TLV size (%ld) overflows event_buf (%d)\n" , +size_add (sizeof (*tlv_rxba), tlv_bitmap_len), + tlv_buf_left); +return ; + } + mwifiex_dbg(priv->adapter, INFO, "%pM tid=%d seq_num=%d bitmap_len=%d\n", tlv_rxba->mac, tlv_rxba->tid, tlv_seq_num, --2.34.1
kernel test robot
build botRe: [PATCH 3/3] wifi: mwifiex: Sanity check tlv_len and tlv_bitmap_len
In reply to Gustavo A. R. Silvakernel test robot noticed the following build warnings:
Hi Gustavo,
kernel test robot noticed the following build warnings:
[auto build test WARNING on linus/master]
[also build test WARNING on v6.5-rc7 next-20230823]
[If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Gustavo-A-R-Silva/wifi-mwifiex-Fix-tlv_buf_left-calculation/20230824-063517 base: linus/master patch link: https://lore.kernel.org/r/587423b0737108effe82aefed4407daca39e9a51.1692829410.git.gustavoars%40kernel.org patch subject: [PATCH 3/3] wifi: mwifiex: Sanity check tlv_len and tlv_bitmap_len config: m68k-allyesconfig (https://download.01.org/0day-ci/archive/20230824/[email protected]/config) compiler: m68k-linux-gcc (GCC) 13.2.0 reproduce: (https://download.01.org/0day-ci/archive/20230824/[email protected]/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <[email protected]>
| Closes: https://lore.kernel.org/oe-kbuild-all/[email protected]/
All warnings (new ones prefixed by >>):
In file included from drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c:12:
drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c: In function 'mwifiex_11n_rxba_sync_event':
>> drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c:926:37: warning: format '%ld' expects argument of type 'long int', but argument 4 has type 'size_t' {aka 'unsigned int'} [-Wformat=]
926 | "TLV size (%ld) overflows event_buf (%d)\n",
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
927 | size_add(sizeof(tlv_rxba->header), tlv_len),
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| |
| size_t {aka unsigned int}
drivers/net/wireless/marvell/mwifiex/main.h:199:51: note: in definition of macro 'mwifiex_dbg'
199 | _mwifiex_dbg(adapter, MWIFIEX_DBG_##mask, fmt, ##__VA_ARGS__)
| ^~~
drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c:926:50: note: format string is defined here
926 | "TLV size (%ld) overflows event_buf (%d)\n",
| ~~^
| |
| long int
| %d
drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c:942:37: warning: format '%ld' expects argument of type 'long int', but argument 4 has type 'size_t' {aka 'unsigned int'} [-Wformat=]
942 | "TLV size (%ld) overflows event_buf (%d)\n",
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
943 | size_add(sizeof(*tlv_rxba), tlv_bitmap_len),
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| |
| size_t {aka unsigned int}
drivers/net/wireless/marvell/mwifiex/main.h:199:51: note: in definition of macro 'mwifiex_dbg'
199 | _mwifiex_dbg(adapter, MWIFIEX_DBG_##mask, fmt, ##__VA_ARGS__)
| ^~~
drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c:942:50: note: format string is defined here
942 | "TLV size (%ld) overflows event_buf (%d)\n",
| ~~^
| |
| long int
| %dvim +926 drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c
904
905 /* This function handles rxba_sync event
906 */
907 void mwifiex_11n_rxba_sync_event(struct mwifiex_private *priv,
908 u8 *event_buf, u16 len)
909 {
910 struct mwifiex_ie_types_rxba_sync *tlv_rxba = (void *)event_buf;
911 u16 tlv_type, tlv_len;
912 struct mwifiex_rx_reorder_tbl *rx_reor_tbl_ptr;
913 u8 i, j;
914 u16 seq_num, tlv_seq_num, tlv_bitmap_len;
915 int tlv_buf_left = len;
916 int ret;
917 u8 *tmp;
918
919 mwifiex_dbg_dump(priv->adapter, EVT_D, "RXBA_SYNC event:",
920 event_buf, len);
921 while (tlv_buf_left > sizeof(*tlv_rxba)) {
922 tlv_type = le16_to_cpu(tlv_rxba->header.type);
923 tlv_len = le16_to_cpu(tlv_rxba->header.len);
924 if (size_add(sizeof(tlv_rxba->header), tlv_len) > tlv_buf_left) {
925 mwifiex_dbg(priv->adapter, WARN,
> 926 "TLV size (%ld) overflows event_buf (%d)\n",
Signature · 2 lines
0-DAY CI Kernel Test Service https://github.com/intel/lkp-tests/wiki