From nobody Fri Aug 14 16:00:14 2026 Received: from mail-wm1-f44.google.com (mail-wm1-f44.google.com [209.85.128.44]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1BD5F3043CF for ; Fri, 14 Aug 2026 13:47:12 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.44 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786715234; cv=none; b=KDlYztNk0ZWXUY8AsUSafwGngktqQgkS0Tpcbl+Ctdm9SpFhBKFUOamvZdJfpLrXYm/t6LUcgToAGqxNPMg3kT/amWL5z0jRxbmyNdMNIgSTzyObjtANom70ryQkzQD4tUMrvy4Pg9+qsfbAF7VD6+K6VyAGXwBEWcT/A3+obpc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786715234; c=relaxed/simple; bh=JBMowbALXN1jE7/AQew047fyFfMm2Zhn/Kx/LD/R+jM=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=JlDWhvz4fqbwiO+tCycwaANmmaR/P/FkZKab2izplsnTN1ocRw4mQn/u+fRypj7hfID+nkE+39LiDamFCcwfRcJHTMMC6QIeyGBX+qWebFo1+cpSQiLi5BBNt1xQej/e3sjXy5qFNhZmRD6/lglyzUniYpP7DtOKn2cowgK3grg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=fail (p=none dis=none) header.from=0sec.ai; spf=pass smtp.mailfrom=0.security; dkim=temperror (0-bit key) header.d=0sec.ai header.i=@0sec.ai header.b=LJQcp5da; arc=none smtp.client-ip=209.85.128.44 Authentication-Results: smtp.subspace.kernel.org; dmarc=fail (p=none dis=none) header.from=0sec.ai Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=0.security Authentication-Results: smtp.subspace.kernel.org; dkim=temperror (0-bit key) header.d=0sec.ai header.i=@0sec.ai header.b="LJQcp5da" Received: by mail-wm1-f44.google.com with SMTP id 5b1f17b1804b1-496bb7cdf51so14172025e9.2 for ; Fri, 14 Aug 2026 06:47:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=0sec.ai; s=google; t=1786715231; x=1787320031; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to:content-type; bh=qmRPONQIeS1c8qTvxKNt6o0AVizi+U1D7QhZyeiIky0=; b=LJQcp5datWly0tWT1cCRRg7+DHbe9fLxtMTdtu3+CWxv9kqzJTr+9qA14DLHFRqmQO lBl6dErluf6XghHQv010u7tXeJDKTbhTPzlIegqu1gDTnxNCtDHZgvvk5gxoZxnfNx5N DkQX0SBjno0QcCCsuY+MfIt1zhYQ7y8RPG0oVCrglxZTrJaICWGM4FUJq+SjZxErtq1o UNE0H2zOqUD7vrKQ95rvziibQqcFYs3yq+rkeP0TO5p0UsafEWUc0dKI+O79a/LP0QdF KHZhSiR1eKCo0lvDduWusOWi3KPJcvOBjpcmWgO3cDRvLL14EOwnMzEWmVs2WLjlZ2+Z d3cg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1786715231; x=1787320031; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to:content-type; bh=qmRPONQIeS1c8qTvxKNt6o0AVizi+U1D7QhZyeiIky0=; b=I0LwN9nqKTqbMra8pIb53+E3e09OxcSKoNPjLFrJvD+OjPTTH7T8OCBn6VZIRsH1no k7ErJ12iojLakEUBfILd+gia6q/9vc9ayrpsGKbm/fIHYHtMaXam6GD6W3A7iuuumzSf Erl+iOyVt2gyEZ7g4kiCVRfAp9oqMlmyqPEoeXFuXhoEt2kddtjXvlg6pnW64UBJDz+A S3QuQkURStC6EcxHbcXqjpAjX0rF5WXoZGgnZazCnyExFx0QwbHXE4a+E7S6t8Kyrxeu uNMHW+l7ld5R2PNSe+agYUqcvLZEXyZUpWQP1P6OVySGI+ndJmZHZVspBxMu7xHHykY3 psHQ== X-Forwarded-Encrypted: i=1; AHgh+RpCx9cmvtgilbJ1LYRb9hqpcQQ8303PV/c9uXIUk8fZeTEhtn0iywnyLHhAwkn67AT4mRER7qICEPwu0Pw=@vger.kernel.org X-Gm-Message-State: AOJu0Yzh48u0athWrINHPgkN2Wv8sz9WUAch/THa9SksYGDmtvu3XXMW BsCMzyPBvpUFFAZJ8R1EV7E9Fv4/WD6PLz9jlN2+tFP0FLzVWeUzghdMh/GNsPOQWpED X-Gm-Gg: AR+sD13MQ8zJhkVt19nqcYdPcaPq/DFUMUFUPu4CsE5IQj3WcwZGllSSYLs8fkflgFL /qgJA/elk7mF/xMwicGbPmOUgUO8reSjGZDe2502fI0yhmdurFyZvNNZsy34Ns5cFVKhWnHFsV0 LxVy6gIlbVYJveMLMY5EhO6cJAbLo0/IV9g6dZN7hURiX75jQuJL2oX6TI1Ht/WXmz4DckVsW5G m3U6nJHIR9c9xOfyWGioJmF26goCLNKSO3tbbzCpGH52Sf+exMQ7GP5KA/xuil/UH3ZcunaDSLb AWQFhau5ydLVVNc8jR80EBtzlPnEyvwiMGqj3Diial5deOh6CKKbd48r9J5F6VuPjvY1ysygTh9 4sHpYGXmzG7Tf8w4ZRLBOApV4kZ9ju1KrOtbeVMMdmY5kdn7fUoADMH877hdn4y/WEL67dsqZZd Z9bFGy6dqOL0C4V0DY01zZcBzFPfFM28KdkK9hefkk7YLgxIoTPIzyKNc1tSKHV73uoC42Ltlzp Rah9j0VuMW6MV9Qza83cu/M1GNHDlzKGgXwawrP/ReZhHCx5CiiceaQO7KtEjdozmuq/ypUTKA9 rYKwxg== X-Received: by 2002:a05:600c:600a:b0:495:52a5:8829 with SMTP id 5b1f17b1804b1-49987981e14mr60442135e9.11.1786715231112; Fri, 14 Aug 2026 06:47:11 -0700 (PDT) Received: from PeakBook-Mini.tail8e484.ts.net ([178.197.218.158]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-49988ae8facsm48742685e9.6.2026.08.14.06.47.09 (version=TLS1_3 cipher=TLS_CHACHA20_POLY1305_SHA256 bits=256/256); Fri, 14 Aug 2026 06:47:09 -0700 (PDT) From: Doruk Tan Ozturk To: briannorris@chromium.org Cc: francesco@dolcini.it, kees@kernel.org, linux-wireless@vger.kernel.org, linux-kernel@vger.kernel.org, stable@vger.kernel.org, Doruk Tan Ozturk Subject: [PATCH v4] wifi: mwifiex: validate HT/VHT capability and operation IE lengths Date: Fri, 14 Aug 2026 15:47:07 +0200 Message-ID: <20260814134707.85925-1-doruk@0sec.ai> X-Mailer: git-send-email 2.53.0 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" mwifiex_update_bss_desc_with_ie() stores pointers to the HT and VHT capability and operation elements, and to the operating-mode notification, taken from a beacon/probe response without checking that each element is long enough for the fixed-size structure the driver later dereferences it as. The beacon buffer is a tight kmemdup() of the on-air IEs, so a truncated element leaves the stored pointer short of the structure and triggers a slab out-of-bounds read when the BSS descriptor is consumed at association time -- e.g. mwifiex_cmd_append_11n_tlv() memcpy()s sizeof(struct ieee80211_ht_cap) from bcn_ht_cap. A nearby AP (rogue / evil-twin; an open SSID needs no credentials) can trigger this on the victim's association attempt. mwifiex_set_sta_ht_cap() has the same missing-length pattern in uAP mode: it reads ieee80211_ht_cap.cap_info from a cfg80211_find_ie(WLAN_EID_HT_CAPABILITY) result without checking the element length. Reject the frame with -EINVAL when any of these elements is shorter than the structure the driver later reads, matching the length validation the FH/DS/CF/IBSS parameter-set cases in the same parser already perform. The operating-mode notification pointer includes the element header, so it is checked against total_ie_len; the HT/VHT pointers skip the header and are checked against element_len. mwifiex_set_sta_ht_cap() returns void, so there the too-short element is skipped instead. No dynamic reproducer: mwifiex is a fullmac driver for Marvell hardware with no mac80211_hwsim equivalent, so this was confirmed by source and structure-offset analysis, and compile-tested only. Found by 0sec automated security-research tooling (https://0sec.ai). Fixes: 5e6e3a92b9a4 ("wireless: mwifiex: initial commit for Marvell mwifiex= driver") Cc: stable@vger.kernel.org Assisted-by: 0sec:multi-model Signed-off-by: Doruk Tan Ozturk --- Changes in v4 (per Brian Norris's review of v3): - Use sizeof(*ptr) for the length checks instead of naming the struct type, so a check cannot drift from the type the pointer is dereferenced as. bcn_ht_cap/bcn_ht_oper/bcn_vht_cap/bcn_vht_oper/ oper_mode are all typed pointers. - Check WLAN_EID_OPMODE_NOTIF against total_ie_len using sizeof(*oper_mode): struct ieee_types_oper_mode_ntf includes the element header and oper_mode points at the header, so a non-zero length test was not sufficient. - Keep -EINVAL on a too-short element (not break), matching the FH/DS/CF/IBSS cases in the same function as introduced in v2. Changes in v3 (per Francesco Dolcini's review of v2): - Commit message only: spell out why ht_cap_ie->len is safe to test against, and restore the no-dynamic-reproducer note. Changes in v2 (per Francesco Dolcini's review of v1): - Return -EINVAL on a too-short element instead of break, matching the FH/DS/CF/IBSS and VENDOR_SPECIFIC cases. mwifiex_set_sta_ht_cap() returns void, so there it stays a skip. - Switch the Assisted-by trailer to 0sec:multi-model. v1: https://lore.kernel.org/all/20260709100800.7026-1-doruk@0sec.ai/ v2: https://lore.kernel.org/all/20260715185543.14478-1-doruk@0sec.ai/ drivers/net/wireless/marvell/mwifiex/scan.c | 12 ++++++++++++ drivers/net/wireless/marvell/mwifiex/util.c | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/marvell/mwifiex/scan.c b/drivers/net/wire= less/marvell/mwifiex/scan.c index 97c0ec3b822e7..80572989bc81c 100644 --- a/drivers/net/wireless/marvell/mwifiex/scan.c +++ b/drivers/net/wireless/marvell/mwifiex/scan.c @@ -1384,6 +1384,8 @@ int mwifiex_update_bss_desc_with_ie(struct mwifiex_ad= apter *adapter, bss_entry->beacon_buf); break; case WLAN_EID_HT_CAPABILITY: + if (element_len < sizeof(*bss_entry->bcn_ht_cap)) + return -EINVAL; bss_entry->bcn_ht_cap =3D (struct ieee80211_ht_cap *) (current_ptr + sizeof(struct ieee_types_header)); @@ -1392,6 +1394,8 @@ int mwifiex_update_bss_desc_with_ie(struct mwifiex_ad= apter *adapter, bss_entry->beacon_buf); break; case WLAN_EID_HT_OPERATION: + if (element_len < sizeof(*bss_entry->bcn_ht_oper)) + return -EINVAL; bss_entry->bcn_ht_oper =3D (struct ieee80211_ht_operation *)(current_ptr + sizeof(struct ieee_types_header)); @@ -1400,6 +1404,8 @@ int mwifiex_update_bss_desc_with_ie(struct mwifiex_ad= apter *adapter, bss_entry->beacon_buf); break; case WLAN_EID_VHT_CAPABILITY: + if (element_len < sizeof(*bss_entry->bcn_vht_cap)) + return -EINVAL; bss_entry->disable_11ac =3D false; bss_entry->bcn_vht_cap =3D (void *)(current_ptr + @@ -1409,6 +1415,8 @@ int mwifiex_update_bss_desc_with_ie(struct mwifiex_ad= apter *adapter, bss_entry->beacon_buf); break; case WLAN_EID_VHT_OPERATION: + if (element_len < sizeof(*bss_entry->bcn_vht_oper)) + return -EINVAL; bss_entry->bcn_vht_oper =3D (void *)(current_ptr + sizeof(struct ieee_types_header)); @@ -1417,6 +1425,8 @@ int mwifiex_update_bss_desc_with_ie(struct mwifiex_ad= apter *adapter, bss_entry->beacon_buf); break; case WLAN_EID_BSS_COEX_2040: + if (!element_len) + return -EINVAL; bss_entry->bcn_bss_co_2040 =3D current_ptr; bss_entry->bss_co_2040_offset =3D (u16) (current_ptr - bss_entry->beacon_buf); @@ -1427,6 +1437,8 @@ int mwifiex_update_bss_desc_with_ie(struct mwifiex_ad= apter *adapter, (u16) (current_ptr - bss_entry->beacon_buf); break; case WLAN_EID_OPMODE_NOTIF: + if (total_ie_len < sizeof(*bss_entry->oper_mode)) + return -EINVAL; bss_entry->oper_mode =3D (void *)current_ptr; bss_entry->oper_mode_offset =3D (u16)((u8 *)bss_entry->oper_mode - diff --git a/drivers/net/wireless/marvell/mwifiex/util.c b/drivers/net/wire= less/marvell/mwifiex/util.c index 7d3631d212236..844223c04e2ef 100644 --- a/drivers/net/wireless/marvell/mwifiex/util.c +++ b/drivers/net/wireless/marvell/mwifiex/util.c @@ -721,7 +721,7 @@ mwifiex_set_sta_ht_cap(struct mwifiex_private *priv, co= nst u8 *ies, =20 ht_cap_ie =3D (void *)cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, ies, ies_len); - if (ht_cap_ie) { + if (ht_cap_ie && ht_cap_ie->len >=3D sizeof(struct ieee80211_ht_cap)) { ht_cap =3D (void *)(ht_cap_ie + 1); node->is_11n_enabled =3D 1; node->max_amsdu =3D le16_to_cpu(ht_cap->cap_info) & --=20 2.43.0