From nobody Sat Aug 1 21:31:41 2026 Received: from mail-pg1-f174.google.com (mail-pg1-f174.google.com [209.85.215.174]) (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 209F73546C8 for ; Sat, 1 Aug 2026 17:46:16 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.215.174 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785606379; cv=none; b=C2JrbDqAowMFhWW51gvgdrkDIOWckvuBwE21WTQ55N28GStgifWtM2EzttAt6eNOIrk02tu3/iSt2I2stvWSWvQAdx4NfdSyuSkFnoo3+HLl9NEFw/g2ybBzCVxoCXSNwVh/lDUR8O1cgsIo9dRXqnd2h1adOeGr91wNlJZsXLA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785606379; c=relaxed/simple; bh=FUZ4q1G7NLlYH4FBldchmQ9rFmJHtFQ5OSLYMtOJVGs=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=mFH3htVrfAhxm7v6ZRIHcPjVw2vxXpx+C1xXd1ypMHDxD3008mdjXHbiU5dGZisH49SmJ6f7PoJqcB+pEzi+DOVfW5hDHqlZ2LgIgS+JaWTw6Llq9abuES6a+AWykC/iylAN54NXOZoCSDuRHRamG7BtM+clh6/iwAL9g8yYSlw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=G9GTRhyL; arc=none smtp.client-ip=209.85.215.174 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="G9GTRhyL" Received: by mail-pg1-f174.google.com with SMTP id 41be03b00d2f7-ca7c1176317so1827557a12.1 for ; Sat, 01 Aug 2026 10:46:16 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1785606376; x=1786211176; 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=ExlG7ok7P5AUsQgKkv2/C0UDicaYRTTkOfSkDIupq6E=; b=G9GTRhyLRnRGX5s1eRaZG6vUeRGuK/+ZzKz7VOot+sUhIeI3rbicX+jHpPVJTB+QxD GM75buaQP1jiuHURycrKKF/D8MGRgBZNwbzq3eXmvKq3p39ee0C+19jIE3z4Tk2CxR5u H+bZvrLg0ltqTI7/rJnR4swNpj/1617zoxrbOdvIkIeEtAYNAK12jOzaCPg6N/yqZxzp 2BnCBOuNuJGEdCUXhD9t3vN2G3oXlzYm0SxOzCroEvl2+7N2ncFD2gtqxb//vWrlJLjS ZmBtMrkh5/wwP04gilprrAYNBonKVB7eg0JzGK7mAOulClJVY+T1RP1WGB8e1fMijNaD ZYdw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1785606376; x=1786211176; 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=ExlG7ok7P5AUsQgKkv2/C0UDicaYRTTkOfSkDIupq6E=; b=R2S18xQr/Zx9EsnEBppuDJF2x5lvpuW+09s+LMmvruYHCYCyCEBXEuW0PvsKzKE6HR 280Bxw2rHSidWXmzXuSXnVdX0qcI/9Qsflkzulwlg506P3RJDqM59N0Jhll/0JyX8gT7 PfXLu6L6oJVufuBpHJ/L17pVs2fpInmATgHMOV9MxD9PAYTUgPIYqVLA9FpYRT3xybkp uFSqWJgvfAyTkrZODXuNFdSkHmj6aC0BbIhopIP+CZa9GWMNccpBb7gfAYMxg8j7HzyV 1POAGolBB5tqiTV2EPLeD8NlCv20wvHuBFfEnaqtp6Z7ETryO1hLj+TkdtxO0kQlOT7Y gmOg== X-Forwarded-Encrypted: i=1; AHgh+RqvYi6uDqk29KNpqffRMbe1MPF//1csaMeoc/kqsi+9iNeEKecF0/yQJGEawUtgDb5ImWV1oXC9iUrmS8I=@vger.kernel.org X-Gm-Message-State: AOJu0YyICj5+iffZQIwVbEtmrwlBV9FQV36M70+OQtQVzTVNh0fctW10 n2li2mvfEik7+9KlBh/QaJeVgQ7uq8KPdHRDSdyWlhCV0/qsWmpV/T+l X-Gm-Gg: AR+sD118uJ4/6GAGspbwZjfLVlGyeo8NlK8QHXHhPqmvl1CvK4JugqI9V9XHKDD9A/T bhsELCbdzRIhTyQD9Effhy/zAswKOsBgNxLLeq0rzvqSmKj6lJg4S3OzcDUJpkBVk6YZa+243q1 20VHhpjQgTcAgAX/zSoeM9ZGSSxG8ZA61ncXgS2UDJeNkIeEJMwwoahvyeNHFFF/pc1Dk89hSS8 4Hc40c053FD68MDrP/COHbPeeULhW99f5MW9TZxslMuiG8T1JAaapUPfYnfhldHOu+7+fYvkQVD hnPSYt/v2QYknuTbcFLtIPEhMaumPplOMUQJAOKn86KBt7Q7FFREyYcL+GXie0gpFG8VY4UdHIf QtEggg7yxY1OyFcmWbwL8paxtYRB3SuUDS68v54EUu/ZwaIGWiUHvDwX1+6ZAHa5SIVpm65d7hl ND68QEyVZH0L3iaBdkOPwMuMyGkKf3VAo95MQU3nB9spWJgeWd0WNBJQZi1XJRci9Gq8rppEYvl jBC6rl3Nzi9/PhcUU0A8xloHV3gszR2zvPqIu9pzifiHCwDygWagb+zoLwS/1OCC6IfhsPuTrkR vR4TsjTfdJcwVuL8s0Y= X-Received: by 2002:a05:6a20:7f9a:b0:3c3:64cc:c1fc with SMTP id adf61e73a8af0-3c92a99434cmr4132810637.73.1785606376416; Sat, 01 Aug 2026 10:46:16 -0700 (PDT) Received: from localhost.localdomain ([2405:acc0:1306:9d5b:7865:f907:f2bf:8664]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-3153dd4e5b0sm17817768eec.1.2026.08.01.10.46.14 (version=TLS1_3 cipher=TLS_CHACHA20_POLY1305_SHA256 bits=256/256); Sat, 01 Aug 2026 10:46:16 -0700 (PDT) From: Laxman Acharya Padhya To: Greg Kroah-Hartman , Hans de Goede Cc: linux-staging@lists.linux.dev, linux-kernel@vger.kernel.org Subject: [PATCH] staging: rtl8723bs: validate WPS attribute lengths Date: Sat, 1 Aug 2026 23:31:11 +0545 Message-ID: <20260801174611.49470-1-acharyalaxman8848@gmail.com> X-Mailer: git-send-email 2.51.2 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" rtw_get_wps_attr() checks that the four-byte attribute header fits in the WPS information element, but trusts the payload length from that header when copying the attribute and advancing to the next one. A malformed attribute can therefore make the driver read beyond a received management frame. Storing the total attribute length in u16 also allows the addition of the header size to wrap. rtw_get_wps_attr_content() also copies the full payload without knowing the destination size. Its callers copy the Selected Registrar attribute into one-byte objects, so an oversized payload can overwrite the stack even when the payload itself fits inside the information element. Store the total attribute length in u32 and reject attributes extending past the information element. Add destination lengths to the copy helpers and reject attributes that do not fit before copying them. Fixes: 554c0a3abf21 ("staging: Add rtl8723bs sdio wifi driver") Cc: stable@vger.kernel.org Signed-off-by: Laxman Acharya Padhya diff --git a/drivers/staging/rtl8723bs/core/rtw_ieee80211.c b/drivers/stagi= ng/rtl8723bs/core/rtw_ieee80211.c index 863ddf846..4889c7247 100644 --- a/drivers/staging/rtl8723bs/core/rtw_ieee80211.c +++ b/drivers/staging/rtl8723bs/core/rtw_ieee80211.c @@ -702,11 +702,13 @@ u8 *rtw_get_wps_ie(u8 *in_ie, uint in_len, u8 *wps_ie= , uint *wps_ielen) * @wps_ielen: Length limit from wps_ie * @target_attr_id: The attribute ID of WPS attribute to search * @buf_attr: If not NULL and the WPS attribute is found, WPS attribute wi= ll be copied to the buf starting from buf_attr + * @buf_attr_len: Length of buf_attr * @len_attr: If not NULL and the WPS attribute is found, will set to the = length of the entire WPS attribute * * Returns: the address of the specific WPS attribute found, or NULL */ -u8 *rtw_get_wps_attr(u8 *wps_ie, uint wps_ielen, u16 target_attr_id, u8 *b= uf_attr, u32 *len_attr) +u8 *rtw_get_wps_attr(u8 *wps_ie, uint wps_ielen, u16 target_attr_id, + u8 *buf_attr, u32 buf_attr_len, u32 *len_attr) { u8 *attr_ptr =3D NULL; u8 *target_attr_ptr =3D NULL; @@ -732,13 +734,19 @@ u8 *rtw_get_wps_attr(u8 *wps_ie, uint wps_ielen, u16 = target_attr_id, u8 *buf_att break; u16 attr_id =3D get_unaligned_be16(attr_ptr); u16 attr_data_len =3D get_unaligned_be16(attr_ptr + 2); - u16 attr_len =3D attr_data_len + 4; + u32 attr_len =3D attr_data_len + 4; + + if (attr_len > wps_ie + wps_ielen - attr_ptr) + break; =20 if (attr_id =3D=3D target_attr_id) { target_attr_ptr =3D attr_ptr; =20 - if (buf_attr) + if (buf_attr) { + if (attr_len > buf_attr_len) + return NULL; memcpy(buf_attr, attr_ptr, attr_len); + } =20 if (len_attr) *len_attr =3D attr_len; @@ -757,26 +765,35 @@ u8 *rtw_get_wps_attr(u8 *wps_ie, uint wps_ielen, u16 = target_attr_id, u8 *buf_att * @wps_ielen: Length limit from wps_ie * @target_attr_id: The attribute ID of WPS attribute to search * @buf_content: If not NULL and the WPS attribute is found, WPS attribute= content will be copied to the buf starting from buf_content + * @buf_content_len: Length of buf_content * @len_content: If not NULL and the WPS attribute is found, will set to t= he length of the WPS attribute content * * Returns: the address of the specific WPS attribute content found, or NU= LL */ -u8 *rtw_get_wps_attr_content(u8 *wps_ie, uint wps_ielen, u16 target_attr_i= d, u8 *buf_content, uint *len_content) +u8 *rtw_get_wps_attr_content(u8 *wps_ie, uint wps_ielen, u16 target_attr_i= d, + u8 *buf_content, uint buf_content_len, + uint *len_content) { u8 *attr_ptr; u32 attr_len; + u32 content_len; =20 if (len_content) *len_content =3D 0; =20 - attr_ptr =3D rtw_get_wps_attr(wps_ie, wps_ielen, target_attr_id, NULL, &a= ttr_len); + attr_ptr =3D rtw_get_wps_attr(wps_ie, wps_ielen, target_attr_id, NULL, 0, + &attr_len); =20 if (attr_ptr && attr_len) { - if (buf_content) - memcpy(buf_content, attr_ptr + 4, attr_len - 4); + content_len =3D attr_len - 4; + if (buf_content) { + if (content_len > buf_content_len) + return NULL; + memcpy(buf_content, attr_ptr + 4, content_len); + } =20 if (len_content) - *len_content =3D attr_len - 4; + *len_content =3D content_len; =20 return attr_ptr + 4; } diff --git a/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c b/drivers/stagin= g/rtl8723bs/core/rtw_mlme_ext.c index a443b3530..ab620231c 100644 --- a/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c +++ b/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c @@ -1113,7 +1113,11 @@ unsigned int OnAssocReq(struct adapter *padapter, un= ion recv_frame *precv_frame) if (pmlmepriv->wps_beacon_ie) { u8 selected_registrar =3D 0; =20 - rtw_get_wps_attr_content(pmlmepriv->wps_beacon_ie, pmlmepriv->wps_beac= on_ie_len, WPS_ATTR_SELECTED_REGISTRAR, &selected_registrar, NULL); + rtw_get_wps_attr_content(pmlmepriv->wps_beacon_ie, + pmlmepriv->wps_beacon_ie_len, + WPS_ATTR_SELECTED_REGISTRAR, + &selected_registrar, + sizeof(selected_registrar), NULL); =20 if (!selected_registrar) { status =3D WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA; @@ -2116,7 +2120,9 @@ void issue_beacon(struct adapter *padapter, int timeo= ut_ms) wps_ie =3D rtw_get_wps_ie(pmgntframe->buf_addr+TXDESC_OFFSET+sizeof(str= uct ieee80211_hdr_3addr)+_BEACON_IE_OFFSET_, pattrib->pktlen-sizeof(struct ieee80211_hdr_3addr)-_BEACON_IE_OFFSET_,= NULL, &wps_ielen); if (wps_ie && wps_ielen > 0) - rtw_get_wps_attr_content(wps_ie, wps_ielen, WPS_ATTR_SELECTED_REGISTR= AR, (u8 *)(&sr), NULL); + rtw_get_wps_attr_content(wps_ie, wps_ielen, + WPS_ATTR_SELECTED_REGISTRAR, + &sr, sizeof(sr), NULL); if (sr !=3D 0) set_fwstate(pmlmepriv, WIFI_UNDER_WPS); else diff --git a/drivers/staging/rtl8723bs/include/ieee80211.h b/drivers/stagin= g/rtl8723bs/include/ieee80211.h index 39ee139f1..114d73a91 100644 --- a/drivers/staging/rtl8723bs/include/ieee80211.h +++ b/drivers/staging/rtl8723bs/include/ieee80211.h @@ -735,8 +735,11 @@ int rtw_parse_wpa2_ie(u8 *wpa_ie, int wpa_ie_len, int = *group_cipher, int *pairwi void rtw_get_sec_ie(u8 *in_ie, uint in_len, u8 *rsn_ie, u16 *rsn_len, u8 *= wpa_ie, u16 *wpa_len); =20 u8 *rtw_get_wps_ie(u8 *in_ie, uint in_len, u8 *wps_ie, uint *wps_ielen); -u8 *rtw_get_wps_attr(u8 *wps_ie, uint wps_ielen, u16 target_attr_id, u8 *b= uf_attr, u32 *len_attr); -u8 *rtw_get_wps_attr_content(u8 *wps_ie, uint wps_ielen, u16 target_attr_i= d, u8 *buf_content, uint *len_content); +u8 *rtw_get_wps_attr(u8 *wps_ie, uint wps_ielen, u16 target_attr_id, + u8 *buf_attr, u32 buf_attr_len, u32 *len_attr); +u8 *rtw_get_wps_attr_content(u8 *wps_ie, uint wps_ielen, u16 target_attr_i= d, + u8 *buf_content, uint buf_content_len, + uint *len_content); =20 /** * for_each_ie - iterate over continuous IEs diff --git a/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c b/drivers/st= aging/rtl8723bs/os_dep/ioctl_cfg80211.c index 967cd1b34..60c27b4fd 100644 --- a/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c +++ b/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c @@ -251,7 +251,9 @@ struct cfg80211_bss *rtw_cfg80211_inform_bss(struct ada= pter *padapter, struct wl wpsie =3D rtw_get_wps_ie(pnetwork->network.ies + _FIXED_IE_LENGTH_, pnet= work->network.ie_length - _FIXED_IE_LENGTH_, NULL, &wpsielen); =20 if (wpsie && wpsielen > 0) - psr =3D rtw_get_wps_attr_content(wpsie, wpsielen, WPS_ATTR_SELECTED_REG= ISTRAR, (u8 *)(&sr), NULL); + psr =3D rtw_get_wps_attr_content(wpsie, wpsielen, + WPS_ATTR_SELECTED_REGISTRAR, + &sr, sizeof(sr), NULL); =20 if (sr !=3D 0) { /* it means under processing WPS */ --=20 2.51.2