]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
wifi: wilc1000: validate assoc response length before subtracting header
authorHuihui Huang <hhhuang@smu.edu.sg>
Tue, 14 Jul 2026 09:17:58 +0000 (17:17 +0800)
committerJohannes Berg <johannes.berg@intel.com>
Tue, 21 Jul 2026 11:25:06 +0000 (13:25 +0200)
wilc_parse_assoc_resp_info() computes the trailing IE length as

ies_len = buffer_len - sizeof(*res);

without first checking that buffer_len is at least sizeof(struct
wilc_assoc_resp) (6 bytes). buffer_len is the length reported for a
received association response (host_int_parse_assoc_resp_info() passes
hif_drv->assoc_resp / assoc_resp_info_len straight in) and must be
validated before the driver accesses the fixed header.

For a frame shorter than the 6-byte fixed header, the subtraction wraps.
For a four-byte response the result is truncated to a u16 ies_len of
65534, so kmemdup() then attempts to copy 65534 bytes starting at
buffer + sizeof(*res), beyond the valid association-response data
(CWE-125). A response shorter than four bytes can also cause an
out-of-bounds read of res->status_code at offsets 2 and 3.

Reject frames too short to hold the fixed header before touching the
header or computing ies_len. Also set the connection status to a failure
on this path: the caller falls through to a
"conn_info->status == WLAN_STATUS_SUCCESS" check after the parser
returns, so leaving the status untouched could let a malformed short
response be treated as a successful association.

Fixes: c5c77ba18ea6 ("staging: wilc1000: Add SDIO/SPI 802.11 driver")
Cc: stable@vger.kernel.org
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Huihui Huang <hhhuang@smu.edu.sg>
Link: https://patch.msgid.link/20260714091811.3596126-1-hhhuang@smu.edu.sg
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
drivers/net/wireless/microchip/wilc1000/hif.c

index 009c4770a6f95b9e315f43fdeeb6afb268b3f3ed..60fe5f08964f39a922ec3db82ea711bb566aefc3 100644 (file)
@@ -600,6 +600,11 @@ static s32 wilc_parse_assoc_resp_info(u8 *buffer, u32 buffer_len,
        u16 ies_len;
        struct wilc_assoc_resp *res = (struct wilc_assoc_resp *)buffer;
 
+       if (buffer_len < sizeof(*res)) {
+               ret_conn_info->status = WLAN_STATUS_UNSPECIFIED_FAILURE;
+               return -EINVAL;
+       }
+
        ret_conn_info->status = le16_to_cpu(res->status_code);
        if (ret_conn_info->status == WLAN_STATUS_SUCCESS) {
                ies = &buffer[sizeof(*res)];