diff options
| author | Muhammad Bilal <meatuni001@gmail.com> | 2026-07-28 17:54:55 +0500 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2026-09-01 12:15:16 +0200 |
| commit | ff917923f4fb9c83717ba135ee47d7e4c1567bb7 (patch) | |
| tree | c38fd8fcf58e1937b17fdbc6518b6f8b797fc15a /tools/firewire/nosy-dump.h | |
| download | linux-stable-ff917923f4fb9c83717ba135ee47d7e4c1567bb7.tar.gz linux-stable-ff917923f4fb9c83717ba135ee47d7e4c1567bb7.zip | |
staging: rtl8723bs: fix OOB read in rtw_action_frame_parse()grafted
rtw_action_frame_parse() takes a frame_len parameter but never
actually checks it before indexing into the frame body:
const u8 *frame_body = frame + sizeof(struct ieee80211_hdr_3addr);
...
c = frame_body[0];
...
a = frame_body[1];
frame_body already points 24 bytes (sizeof(struct
ieee80211_hdr_3addr)) into frame, so reading frame_body[0] and
frame_body[1] requires frame_len >= 26. A management action frame
shorter than that (e.g. exactly 24 bytes, the minimum a malicious
peer can send) causes a 1-2 byte out-of-bounds read.
This is reachable from rtw_cfg80211_monitor_if_xmit_entry() and
cfg80211_rtw_mgmt_tx() in ioctl_cfg80211.c, both of which pass
attacker/user-influenced frame buffers and lengths straight through.
Add the missing length check before frame_body is dereferenced.
Fixes: 554c0a3abf216 ("staging: Add rtl8723bs sdio wifi driver")
Cc: stable@vger.kernel.org
Signed-off-by: Muhammad Bilal <meatuni001@gmail.com>
Link: https://patch.msgid.link/20260728125456.32359-3-meatuni001@gmail.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'tools/firewire/nosy-dump.h')
| -rw-r--r-- | tools/firewire/nosy-dump.h | 174 |
1 files changed, 174 insertions, 0 deletions
diff --git a/tools/firewire/nosy-dump.h b/tools/firewire/nosy-dump.h new file mode 100644 index 000000000..69e5e594f --- /dev/null +++ b/tools/firewire/nosy-dump.h @@ -0,0 +1,174 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __nosy_dump_h__ +#define __nosy_dump_h__ + +#define array_length(array) (sizeof(array) / sizeof(array[0])) + +#define ACK_NO_ACK 0x0 +#define ACK_DONE(a) ((a >> 2) == 0) +#define ACK_BUSY(a) ((a >> 2) == 1) +#define ACK_ERROR(a) ((a >> 2) == 3) + +#include <stdint.h> + +struct phy_packet { + uint32_t timestamp; + union { + struct { + uint32_t zero:24; + uint32_t phy_id:6; + uint32_t identifier:2; + } common, link_on; + + struct { + uint32_t zero:16; + uint32_t gap_count:6; + uint32_t set_gap_count:1; + uint32_t set_root:1; + uint32_t root_id:6; + uint32_t identifier:2; + } phy_config; + + struct { + uint32_t more_packets:1; + uint32_t initiated_reset:1; + uint32_t port2:2; + uint32_t port1:2; + uint32_t port0:2; + uint32_t power_class:3; + uint32_t contender:1; + uint32_t phy_delay:2; + uint32_t phy_speed:2; + uint32_t gap_count:6; + uint32_t link_active:1; + uint32_t extended:1; + uint32_t phy_id:6; + uint32_t identifier:2; + } self_id; + + struct { + uint32_t more_packets:1; + uint32_t reserved1:1; + uint32_t porth:2; + uint32_t portg:2; + uint32_t portf:2; + uint32_t porte:2; + uint32_t portd:2; + uint32_t portc:2; + uint32_t portb:2; + uint32_t porta:2; + uint32_t reserved0:2; + uint32_t sequence:3; + uint32_t extended:1; + uint32_t phy_id:6; + uint32_t identifier:2; + } ext_self_id; + }; + uint32_t inverted; + uint32_t ack; +}; + +#define TCODE_PHY_PACKET 0x10 + +#define PHY_PACKET_CONFIGURATION 0x00 +#define PHY_PACKET_LINK_ON 0x01 +#define PHY_PACKET_SELF_ID 0x02 + +struct link_packet { + uint32_t timestamp; + union { + struct { + uint32_t priority:4; + uint32_t tcode:4; + uint32_t rt:2; + uint32_t tlabel:6; + uint32_t destination:16; + + uint32_t offset_high:16; + uint32_t source:16; + + uint32_t offset_low; + } common; + + struct { + uint32_t common[3]; + uint32_t crc; + } read_quadlet; + + struct { + uint32_t common[3]; + uint32_t data; + uint32_t crc; + } read_quadlet_response; + + struct { + uint32_t common[3]; + uint32_t extended_tcode:16; + uint32_t data_length:16; + uint32_t crc; + } read_block; + + struct { + uint32_t common[3]; + uint32_t extended_tcode:16; + uint32_t data_length:16; + uint32_t crc; + uint32_t data[0]; + /* crc and ack follows. */ + } read_block_response; + + struct { + uint32_t common[3]; + uint32_t data; + uint32_t crc; + } write_quadlet; + + struct { + uint32_t common[3]; + uint32_t extended_tcode:16; + uint32_t data_length:16; + uint32_t crc; + uint32_t data[0]; + /* crc and ack follows. */ + } write_block; + + struct { + uint32_t common[3]; + uint32_t crc; + } write_response; + + struct { + uint32_t common[3]; + uint32_t data; + uint32_t crc; + } cycle_start; + + struct { + uint32_t sy:4; + uint32_t tcode:4; + uint32_t channel:6; + uint32_t tag:2; + uint32_t data_length:16; + + uint32_t crc; + } iso_data; + }; +}; + +struct subaction { + uint32_t ack; + size_t length; + struct list link; + struct link_packet packet; +}; + +struct link_transaction { + int request_node, response_node, tlabel; + struct subaction *request, *response; + struct list request_list, response_list; + struct list link; +}; + +int decode_fcp(struct link_transaction *t); + +#endif /* __nosy_dump_h__ */ |
