mirror of
https://github.com/torvalds/linux.git
synced 2026-09-23 13:14:02 +02:00
wifi: ipw2x00: bound management frame length to the receive buffer
Both management receive paths establish a lower bound on the frame length and no upper bound, even though the length originates from the device. ipw2100_corruption_check() returns 0 without inspecting frame_size for management frames, and __ipw2100_rx_process() only rejects a frame smaller than the three-address header, so any reported size up to the u32 limit reaches libipw_rx_mgt() against a receive allocation of IPW_RX_NIC_BUFFER_LENGTH bytes. Check frame_size itself rather than stats.len, which is a u16: a size of 65566 truncates to 30 on assignment and would pass a check made afterwards. ipw_rx() likewise only rejects a frame shorter than the header length. Bound it against the DMA mapped receive buffer. The size passed to alloc_skb() is rounded up by the allocator, so skb_tailroom() can exceed IPW_RX_BUF_SIZE and is not a usable bound here; the existing uses of that idiom in the data paths are too permissive for the same reason. libipw then hands the remainder to libipw_parse_info_param(), which walks information elements for as long as the length allows, so an over-long reported length reads past the receive buffer without any wraparound being involved. The length is device-reported, so per Documentation/process/threat-model.rst this is a robustness fix rather than a vulnerability. Found by an AI-assisted review of length arithmetic in management frame parsers. Compile-tested only for these two hunks; I do not have the hardware, so they are not tested on a real device. Assisted-by: Claude:claude-opus-5 Signed-off-by: Shmulik Cohen <anuk909@gmail.com> Link: https://patch.msgid.link/20260812190412.18333-4-anuk909@gmail.com Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
parent
adb7118b7d
commit
c46cfaf8db
|
|
@ -2712,7 +2712,9 @@ static void __ipw2100_rx_process(struct ipw2100_priv *priv)
|
|||
break;
|
||||
}
|
||||
#endif
|
||||
if (stats.len < sizeof(struct libipw_hdr_3addr))
|
||||
if (sq->drv[i].frame_size <
|
||||
sizeof(struct libipw_hdr_3addr) ||
|
||||
sq->drv[i].frame_size > IPW_RX_NIC_BUFFER_LENGTH)
|
||||
break;
|
||||
switch (WLAN_FC_GET_TYPE(le16_to_cpu(u->rx_data.header.frame_ctl))) {
|
||||
case IEEE80211_FTYPE_MGMT:
|
||||
|
|
|
|||
|
|
@ -8322,6 +8322,15 @@ static void ipw_rx(struct ipw_priv *priv)
|
|||
break;
|
||||
}
|
||||
|
||||
if (unlikely(le16_to_cpu(pkt->u.frame.length) >
|
||||
IPW_RX_BUF_SIZE -
|
||||
IPW_RX_FRAME_SIZE)) {
|
||||
IPW_DEBUG_DROP("Received oversized packet. Dropping.\n");
|
||||
priv->net_dev->stats.rx_errors++;
|
||||
priv->wstats.discard.misc++;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (WLAN_FC_GET_TYPE
|
||||
(le16_to_cpu(header->frame_ctl))) {
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user