* FAILED: patch "[PATCH] staging: rtl8723bs: fix protected RX frame validation in" failed to apply to 6.1-stable tree
@ 2026-11-04 14:20 gregkh
2026-11-05 2:02 ` [PATCH 6.1.y 1/3] staging: rtl8723bs: Fix indentation in conditional statements Sasha Levin
0 siblings, 1 reply; 4+ messages in thread
From: gregkh @ 2026-11-04 14:20 UTC (permalink / raw)
To: flynnnchen, gregkh; +Cc: stable
The patch below does not apply to the 6.1-stable tree.
If someone wants it applied there, or to any other stable or longterm
tree, then please email the backport, including the original git commit
id to <stable@vger.kernel.org>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-6.1.y
git checkout FETCH_HEAD
git cherry-pick -x 495cb31c791bdf3f9efef255a9587b05b0526c9d
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<stable@vger.kernel.org>' --in-reply-to '2026110448-heftiness-shed-a845@gregkh' --subject-prefix 'PATCH 6.1.y' 'HEAD^..'
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 495cb31c791bdf3f9efef255a9587b05b0526c9d Mon Sep 17 00:00:00 2001
From: Tianchu Chen <flynnnchen@tencent.com>
Date: Wed, 9 Sep 2026 08:06:26 +0000
Subject: [PATCH] staging: rtl8723bs: fix protected RX frame validation in
decrypt path
The RX software decrypt path mishandles crafted protected frames from a
malicious AP in two ways:
1) decryptor() never checks that a protected frame is long enough to
hold the 802.11 header plus the per-cipher trailer. All of
rtw_wep_decrypt(), rtw_tkip_decrypt() and rtw_aes_decrypt() compute
length = hdr.len - hdrlen - iv_len;
and act on the result, and recvframe_chkmic() similarly computes
datalen = hdr.len - hdrlen - iv_len - icv_len - 8;
for TKIP (the 8-byte Michael MIC is not accounted for in icv_len).
A frame shorter than hdrlen + iv_len + icv_len (+ 8 for TKIP) underflows
these unsigned subtractions, turning into a ~4 GiB iteration count in
aes_decipher()/arc4_crypt()/rtw_seccalctkipmic() or a ~4 GiB crc32_le()
length, causing out-of-bounds reads/writes of up to ~4 GiB starting from
the rx skb. Reject such frames in decryptor() before touching the IV;
this covers all three ciphers and the TKIP MIC check, and also keeps the
unconditional iv[3] access within the frame.
2) validate_80211w_mgmt() keeps using the frame - two memcpys through
the stale rx_data pointer and a pkt_len update - before checking
whether decryptor() returned NULL. On decrypt failure (e.g. a unicast
protected deauth/disassoc/action frame with a bad MIC, which this path
always software-decrypts) the skb has already been freed, so this is a
use-after-free read/write, and the caller's error path frees the frame
a second time, drifting free_recvframe_cnt. Bail out immediately when
decryptor() fails, freeing the temporary mgmt_DATA buffer first.
Discovered by Atuin - Automated Vulnerability Discovery Engine.
Fixes: 554c0a3abf21 ("staging: Add rtl8723bs sdio wifi driver")
Assisted-by: LLM
Cc: stable@vger.kernel.org
Signed-off-by: Tianchu Chen <flynnnchen@tencent.com>
Link: https://patch.msgid.link/8ee3bdd1c45034200cb1aa9a7e9b575b9584643a@linux.dev
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
diff --git a/drivers/staging/rtl8723bs/core/rtw_recv.c b/drivers/staging/rtl8723bs/core/rtw_recv.c
index dde66b68d5e3..0434c2166837 100644
--- a/drivers/staging/rtl8723bs/core/rtw_recv.c
+++ b/drivers/staging/rtl8723bs/core/rtw_recv.c
@@ -416,8 +416,21 @@ static union recv_frame *decryptor(struct adapter *padapter, union recv_frame *p
u32 res = _SUCCESS;
if (prxattrib->encrypt > 0) {
- u8 *iv = precv_frame->u.hdr.rx_data + prxattrib->hdrlen;
+ u8 *iv;
+ u32 min_len = prxattrib->hdrlen + prxattrib->iv_len + prxattrib->icv_len;
+ /* TKIP appends an 8-byte Michael MIC that icv_len doesn't account for */
+ if (prxattrib->encrypt == _TKIP_)
+ min_len += 8;
+
+ /* a protected frame must be long enough to hold the IV and ICV/MIC */
+ if (precv_frame->u.hdr.len < min_len) {
+ rtw_free_recvframe(precv_frame,
+ &padapter->recvpriv.free_recv_queue);
+ return NULL;
+ }
+
+ iv = precv_frame->u.hdr.rx_data + prxattrib->hdrlen;
prxattrib->key_index = (((iv[3]) >> 6) & 0x3);
if (prxattrib->key_index > WEP_KEYS) {
@@ -1358,6 +1371,10 @@ static signed int validate_80211w_mgmt(struct adapter *adapter, union recv_frame
if (!mgmt_DATA)
goto validate_80211w_fail;
precv_frame = decryptor(adapter, precv_frame);
+ if (!precv_frame) {
+ kfree(mgmt_DATA);
+ goto validate_80211w_fail;
+ }
/* save actual management data frame body */
memcpy(mgmt_DATA, ptr + pattrib->hdrlen + pattrib->iv_len, data_len);
/* overwrite the iv field */
@@ -1365,8 +1382,6 @@ static signed int validate_80211w_mgmt(struct adapter *adapter, union recv_frame
/* remove the iv and icv length */
pattrib->pkt_len = pattrib->pkt_len - pattrib->iv_len - pattrib->icv_len;
kfree(mgmt_DATA);
- if (!precv_frame)
- goto validate_80211w_fail;
} else if (is_multicast_ether_addr(GetAddr1Ptr(ptr)) &&
(subtype == WIFI_DEAUTH || subtype == WIFI_DISASSOC)) {
signed int BIP_ret = _SUCCESS;
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH 6.1.y 1/3] staging: rtl8723bs: Fix indentation in conditional statements
2026-11-04 14:20 FAILED: patch "[PATCH] staging: rtl8723bs: fix protected RX frame validation in" failed to apply to 6.1-stable tree gregkh
@ 2026-11-05 2:02 ` Sasha Levin
2026-11-05 2:02 ` [PATCH 6.1.y 2/3] staging: rtl8723bs: fix spacing around operators in rtw_recv.c Sasha Levin
2026-11-05 2:02 ` [PATCH 6.1.y 3/3] staging: rtl8723bs: fix protected RX frame validation in decrypt path Sasha Levin
0 siblings, 2 replies; 4+ messages in thread
From: Sasha Levin @ 2026-11-05 2:02 UTC (permalink / raw)
To: stable; +Cc: Emily Peri, Greg Kroah-Hartman, Sasha Levin
From: Emily Peri <eperi1024@gmail.com>
[ Upstream commit 6e006508f6e20a0f09dd9e64bc23c0592d92cc2d ]
Remove/add tabs in block statements in rtl8723bs/core to fix checkpatch
warnings for suspect code indent for conditionals.
Signed-off-by: Emily Peri <eperi1024@gmail.com>
Link: https://lore.kernel.org/r/Y1cH7br3mMcT4Dm5@marshmallow
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Stable-dep-of: 495cb31c791b ("staging: rtl8723bs: fix protected RX frame validation in decrypt path")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/staging/rtl8723bs/core/rtw_mlme.c | 30 +++++++++----------
drivers/staging/rtl8723bs/core/rtw_mlme_ext.c | 2 +-
drivers/staging/rtl8723bs/core/rtw_recv.c | 6 ++--
drivers/staging/rtl8723bs/core/rtw_sta_mgt.c | 2 +-
4 files changed, 19 insertions(+), 21 deletions(-)
diff --git a/drivers/staging/rtl8723bs/core/rtw_mlme.c b/drivers/staging/rtl8723bs/core/rtw_mlme.c
index 258972f6de3fa..58b3dbee58ad5 100644
--- a/drivers/staging/rtl8723bs/core/rtw_mlme.c
+++ b/drivers/staging/rtl8723bs/core/rtw_mlme.c
@@ -389,7 +389,7 @@ int is_same_network(struct wlan_bssid_ex *src, struct wlan_bssid_ex *dst, u8 fea
__le16 tmps, tmpd;
if (rtw_bug_check(dst, src, &s_cap, &d_cap) == false)
- return false;
+ return false;
memcpy((u8 *)&tmps, rtw_get_capability_from_ie(src->ies), 2);
memcpy((u8 *)&tmpd, rtw_get_capability_from_ie(dst->ies), 2);
@@ -669,7 +669,7 @@ int rtw_is_desired_network(struct adapter *adapter, struct wlan_network *pnetwor
uint ie_len = 0;
if ((desired_encmode == Ndis802_11EncryptionDisabled) && (privacy != 0))
- bselected = false;
+ bselected = false;
if (psecuritypriv->ndisauthtype == Ndis802_11AuthModeWPA2PSK) {
p = rtw_get_ie(pnetwork->network.ies + _BEACON_IE_OFFSET_, WLAN_EID_RSN, &ie_len, (pnetwork->network.ie_length - _BEACON_IE_OFFSET_));
@@ -795,7 +795,7 @@ void rtw_surveydone_event_callback(struct adapter *adapter, u8 *pbuf)
pmlmepriv->to_join = false;
s_ret = rtw_select_and_join_from_scanned_queue(pmlmepriv);
if (s_ret == _SUCCESS) {
- _set_timer(&pmlmepriv->assoc_timer, MAX_JOIN_TIMEOUT);
+ _set_timer(&pmlmepriv->assoc_timer, MAX_JOIN_TIMEOUT);
} else if (s_ret == 2) {/* there is no need to wait for join */
_clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
rtw_indicate_connect(adapter);
@@ -2015,8 +2015,8 @@ int rtw_restruct_wmm_ie(struct adapter *adapter, u8 *in_ie, u8 *out_ie, uint in_
in_ie[i + 3] == 0x50 && in_ie[i + 4] == 0xF2 &&
in_ie[i + 5] == 0x02) {
for (j = i; j < i + 9; j++) {
- out_ie[ielength] = in_ie[j];
- ielength++;
+ out_ie[ielength] = in_ie[j];
+ ielength++;
}
out_ie[initial_out_len + 1] = 0x07;
out_ie[initial_out_len + 6] = 0x00;
@@ -2072,15 +2072,13 @@ static int rtw_append_pmkid(struct adapter *Adapter, int iEntry, u8 *ie, uint ie
if (ie[13] <= 20) {
/* The RSN IE didn't include the PMK ID, append the PMK information */
- ie[ie_len] = 1;
- ie_len++;
- ie[ie_len] = 0; /* PMKID count = 0x0100 */
- ie_len++;
- memcpy(&ie[ie_len], &psecuritypriv->PMKIDList[iEntry].PMKID, 16);
-
- ie_len += 16;
- ie[13] += 18;/* PMKID length = 2+16 */
-
+ ie[ie_len] = 1;
+ ie_len++;
+ ie[ie_len] = 0; /* PMKID count = 0x0100 */
+ ie_len++;
+ memcpy(&ie[ie_len], &psecuritypriv->PMKIDList[iEntry].PMKID, 16);
+ ie_len += 16;
+ ie[13] += 18;/* PMKID length = 2+16 */
}
return ie_len;
}
@@ -2099,9 +2097,9 @@ signed int rtw_restruct_sec_ie(struct adapter *adapter, u8 *in_ie, u8 *out_ie, u
memcpy(out_ie, in_ie, 12);
ielength = 12;
if ((ndisauthmode == Ndis802_11AuthModeWPA) || (ndisauthmode == Ndis802_11AuthModeWPAPSK))
- authmode = WLAN_EID_VENDOR_SPECIFIC;
+ authmode = WLAN_EID_VENDOR_SPECIFIC;
if ((ndisauthmode == Ndis802_11AuthModeWPA2) || (ndisauthmode == Ndis802_11AuthModeWPA2PSK))
- authmode = WLAN_EID_RSN;
+ authmode = WLAN_EID_RSN;
if (check_fwstate(pmlmepriv, WIFI_UNDER_WPS)) {
memcpy(out_ie+ielength, psecuritypriv->wps_ie, psecuritypriv->wps_ie_len);
diff --git a/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c b/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c
index 32fd3cd0a5f77..e07e797144e3a 100644
--- a/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c
+++ b/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c
@@ -5482,7 +5482,7 @@ u8 disconnect_hdl(struct adapter *padapter, unsigned char *pbuf)
u8 val8;
if (is_client_associated_to_ap(padapter))
- issue_deauth_ex(padapter, pnetwork->mac_address, WLAN_REASON_DEAUTH_LEAVING, param->deauth_timeout_ms/100, 100);
+ issue_deauth_ex(padapter, pnetwork->mac_address, WLAN_REASON_DEAUTH_LEAVING, param->deauth_timeout_ms/100, 100);
if (((pmlmeinfo->state&0x03) == WIFI_FW_ADHOC_STATE) || ((pmlmeinfo->state&0x03) == WIFI_FW_AP_STATE)) {
/* Stop BCN */
diff --git a/drivers/staging/rtl8723bs/core/rtw_recv.c b/drivers/staging/rtl8723bs/core/rtw_recv.c
index 2825375bff942..7c7b6495965f5 100644
--- a/drivers/staging/rtl8723bs/core/rtw_recv.c
+++ b/drivers/staging/rtl8723bs/core/rtw_recv.c
@@ -161,7 +161,7 @@ int rtw_free_recvframe(union recv_frame *precvframe, struct __queue *pfree_recv_
if (padapter) {
if (pfree_recv_queue == &precvpriv->free_recv_queue)
- precvpriv->free_recvframe_cnt++;
+ precvpriv->free_recvframe_cnt++;
}
spin_unlock_bh(&pfree_recv_queue->lock);
return _SUCCESS;
@@ -691,8 +691,8 @@ static signed int sta2sta_data_frame(struct adapter *adapter, union recv_frame *
if (bmcast) {
/* For AP mode, if DA == MCAST, then BSSID should be also MCAST */
if (!IS_MCAST(pattrib->bssid)) {
- ret = _FAIL;
- goto exit;
+ ret = _FAIL;
+ goto exit;
}
} else { /* not mc-frame */
/* For AP mode, if DA is non-MCAST, then it must be BSSID, and bssid == BSSID */
diff --git a/drivers/staging/rtl8723bs/core/rtw_sta_mgt.c b/drivers/staging/rtl8723bs/core/rtw_sta_mgt.c
index beb11d89db186..c7de81f21bec0 100644
--- a/drivers/staging/rtl8723bs/core/rtw_sta_mgt.c
+++ b/drivers/staging/rtl8723bs/core/rtw_sta_mgt.c
@@ -551,7 +551,7 @@ u8 rtw_access_ctrl(struct adapter *padapter, u8 *mac_addr)
else if (pacl_list->mode == 2)/* deny unless in accept list */
res = match;
else
- res = true;
+ res = true;
return res;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH 6.1.y 2/3] staging: rtl8723bs: fix spacing around operators in rtw_recv.c
2026-11-05 2:02 ` [PATCH 6.1.y 1/3] staging: rtl8723bs: Fix indentation in conditional statements Sasha Levin
@ 2026-11-05 2:02 ` Sasha Levin
2026-11-05 2:02 ` [PATCH 6.1.y 3/3] staging: rtl8723bs: fix protected RX frame validation in decrypt path Sasha Levin
1 sibling, 0 replies; 4+ messages in thread
From: Sasha Levin @ 2026-11-05 2:02 UTC (permalink / raw)
To: stable; +Cc: Khasar Munkh-Erdene, Greg Kroah-Hartman, Sasha Levin
From: Khasar Munkh-Erdene <02khasar@gmail.com>
[ Upstream commit 393b267e6f04a11d4b18b7dc1423fa59f173f72b ]
Fix coding style issues by adding missing spaces around binary and
ternary operators, as reported by checkpatch.pl.
Signed-off-by: Khasar Munkh-Erdene <02khasar@gmail.com>
Link: https://patch.msgid.link/20260225032909.72799-1-02khasar@gmail.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Omit the operator-spacing hunk for rtw_handle_tkip_mic_err(), which is
implemented separately here. Retain the receive-path spacing changes
needed by the protected-frame validation fix. Use the existing
is_multicast_ether_addr() helper at the adjacent management-frame test
so the subsequent NULL-check removal applies without a conflict.
Stable-dep-of: 495cb31c791b ("staging: rtl8723bs: fix protected RX frame validation in decrypt path")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/staging/rtl8723bs/core/rtw_recv.c | 84 +++++++++++------------
1 file changed, 42 insertions(+), 42 deletions(-)
diff --git a/drivers/staging/rtl8723bs/core/rtw_recv.c b/drivers/staging/rtl8723bs/core/rtw_recv.c
index 7c7b6495965f5..ebec2cff6a2b6 100644
--- a/drivers/staging/rtl8723bs/core/rtw_recv.c
+++ b/drivers/staging/rtl8723bs/core/rtw_recv.c
@@ -333,13 +333,13 @@ static signed int recvframe_chkmic(struct adapter *adapter, union recv_frame *p
mickey = &stainfo->dot11tkiprxmickey.skey[0];
}
- datalen = precvframe->u.hdr.len-prxattrib->hdrlen-prxattrib->iv_len-prxattrib->icv_len-8;/* icv_len included the mic code */
+ datalen = precvframe->u.hdr.len - prxattrib->hdrlen - prxattrib->iv_len - prxattrib->icv_len - 8;/* icv_len included the mic code */
pframe = precvframe->u.hdr.rx_data;
- payload = pframe+prxattrib->hdrlen+prxattrib->iv_len;
+ payload = pframe + prxattrib->hdrlen + prxattrib->iv_len;
rtw_seccalctkipmic(mickey, pframe, payload, datalen, &miccode[0], (unsigned char)prxattrib->priority); /* care the length of the data */
- pframemic = payload+datalen;
+ pframemic = payload + datalen;
bmic_err = false;
@@ -387,9 +387,9 @@ static union recv_frame *decryptor(struct adapter *padapter, union recv_frame *p
u32 res = _SUCCESS;
if (prxattrib->encrypt > 0) {
- u8 *iv = precv_frame->u.hdr.rx_data+prxattrib->hdrlen;
+ u8 *iv = precv_frame->u.hdr.rx_data + prxattrib->hdrlen;
- prxattrib->key_index = (((iv[3])>>6)&0x3);
+ prxattrib->key_index = (((iv[3]) >> 6) & 0x3);
if (prxattrib->key_index > WEP_KEYS) {
switch (prxattrib->encrypt) {
@@ -511,7 +511,7 @@ static signed int recv_decache(union recv_frame *precv_frame, u8 bretry, struct
{
signed int tid = precv_frame->u.hdr.attrib.priority;
- u16 seq_ctrl = ((precv_frame->u.hdr.attrib.seq_num&0xffff) << 4) |
+ u16 seq_ctrl = ((precv_frame->u.hdr.attrib.seq_num & 0xffff) << 4) |
(precv_frame->u.hdr.attrib.frag_num & 0xf);
if (tid > 15)
@@ -575,29 +575,29 @@ static void process_wmmps_data(struct adapter *padapter, union recv_frame *precv
if (!psta->qos_option)
return;
- if (!(psta->qos_info&0xf))
+ if (!(psta->qos_info & 0xf))
return;
- if (psta->state&WIFI_SLEEP_STATE) {
+ if (psta->state & WIFI_SLEEP_STATE) {
u8 wmmps_ac = 0;
switch (pattrib->priority) {
case 1:
case 2:
- wmmps_ac = psta->uapsd_bk&BIT(1);
+ wmmps_ac = psta->uapsd_bk & BIT(1);
break;
case 4:
case 5:
- wmmps_ac = psta->uapsd_vi&BIT(1);
+ wmmps_ac = psta->uapsd_vi & BIT(1);
break;
case 6:
case 7:
- wmmps_ac = psta->uapsd_vo&BIT(1);
+ wmmps_ac = psta->uapsd_vo & BIT(1);
break;
case 0:
case 3:
default:
- wmmps_ac = psta->uapsd_be&BIT(1);
+ wmmps_ac = psta->uapsd_be & BIT(1);
break;
}
@@ -922,20 +922,20 @@ static signed int validate_recv_ctrl_frame(struct adapter *padapter, union recv_
switch (pattrib->priority) {
case 1:
case 2:
- wmmps_ac = psta->uapsd_bk&BIT(0);
+ wmmps_ac = psta->uapsd_bk & BIT(0);
break;
case 4:
case 5:
- wmmps_ac = psta->uapsd_vi&BIT(0);
+ wmmps_ac = psta->uapsd_vi & BIT(0);
break;
case 6:
case 7:
- wmmps_ac = psta->uapsd_vo&BIT(0);
+ wmmps_ac = psta->uapsd_vo & BIT(0);
break;
case 0:
case 3:
default:
- wmmps_ac = psta->uapsd_be&BIT(0);
+ wmmps_ac = psta->uapsd_be & BIT(0);
break;
}
@@ -947,7 +947,7 @@ static signed int validate_recv_ctrl_frame(struct adapter *padapter, union recv_
psta->state ^= WIFI_STA_ALIVE_CHK_STATE;
}
- if ((psta->state&WIFI_SLEEP_STATE) && (pstapriv->sta_dz_bitmap&BIT(psta->aid))) {
+ if ((psta->state & WIFI_SLEEP_STATE) && (pstapriv->sta_dz_bitmap & BIT(psta->aid))) {
struct list_head *xmitframe_plist, *xmitframe_phead;
struct xmit_frame *pxmitframe = NULL;
struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
@@ -991,7 +991,7 @@ static signed int validate_recv_ctrl_frame(struct adapter *padapter, union recv_
/* spin_unlock_bh(&psta->sleep_q.lock); */
spin_unlock_bh(&pxmitpriv->lock);
- if (pstapriv->tim_bitmap&BIT(psta->aid)) {
+ if (pstapriv->tim_bitmap & BIT(psta->aid)) {
if (psta->sleepq_len == 0) {
/* issue nulldata with More data bit = 0 to indicate we have no buffered packets */
issue_nulldata_in_interrupt(padapter, psta->hwaddr);
@@ -1373,15 +1373,15 @@ static signed int validate_80211w_mgmt(struct adapter *adapter, union recv_frame
goto validate_80211w_fail;
precv_frame = decryptor(adapter, precv_frame);
/* save actual management data frame body */
- memcpy(mgmt_DATA, ptr+pattrib->hdrlen+pattrib->iv_len, data_len);
+ memcpy(mgmt_DATA, ptr + pattrib->hdrlen + pattrib->iv_len, data_len);
/* overwrite the iv field */
- memcpy(ptr+pattrib->hdrlen, mgmt_DATA, data_len);
+ memcpy(ptr + pattrib->hdrlen, mgmt_DATA, data_len);
/* remove the iv and icv length */
pattrib->pkt_len = pattrib->pkt_len - pattrib->iv_len - pattrib->icv_len;
kfree(mgmt_DATA);
if (!precv_frame)
goto validate_80211w_fail;
- } else if (IS_MCAST(GetAddr1Ptr(ptr)) &&
+ } else if (is_multicast_ether_addr(GetAddr1Ptr(ptr)) &&
(subtype == WIFI_DEAUTH || subtype == WIFI_DISASSOC)) {
signed int BIP_ret = _SUCCESS;
/* verify BIP MME IE of broadcast/multicast de-auth/disassoc packet */
@@ -1431,7 +1431,7 @@ static signed int validate_recv_frame(struct adapter *adapter, union recv_frame
struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;
u8 *ptr = precv_frame->u.hdr.rx_data;
- u8 ver = (unsigned char) (*ptr)&0x3;
+ u8 ver = (unsigned char) (*ptr) & 0x3;
/* add version chk */
if (ver != 0) {
@@ -1469,7 +1469,7 @@ static signed int validate_recv_frame(struct adapter *adapter, union recv_frame
retval = _FAIL; /* only data frame return _SUCCESS */
break;
case WIFI_DATA_TYPE: /* data */
- pattrib->qos = (subtype & BIT(7)) ? 1:0;
+ pattrib->qos = (subtype & BIT(7)) ? 1 : 0;
retval = validate_recv_data_frame(adapter, precv_frame);
if (retval == _FAIL) {
struct recv_priv *precvpriv = &adapter->recvpriv;
@@ -1514,8 +1514,8 @@ static signed int wlanhdr_to_ethhdr(union recv_frame *precvframe)
if (pattrib->encrypt)
recvframe_pull_tail(precvframe, pattrib->icv_len);
- psnap = (struct ieee80211_snap_hdr *)(ptr+pattrib->hdrlen + pattrib->iv_len);
- psnap_type = ptr+pattrib->hdrlen + pattrib->iv_len+SNAP_SIZE;
+ psnap = (struct ieee80211_snap_hdr *)(ptr + pattrib->hdrlen + pattrib->iv_len);
+ psnap_type = ptr + pattrib->hdrlen + pattrib->iv_len + SNAP_SIZE;
/* convert hdr + possible LLC headers into Ethernet header */
/* eth_type = (psnap_type[0] << 8) | psnap_type[1]; */
if ((!memcmp(psnap, rfc1042_header, SNAP_SIZE) &&
@@ -1529,37 +1529,37 @@ static signed int wlanhdr_to_ethhdr(union recv_frame *precvframe)
/* Leave Ethernet header part of hdr and full payload */
bsnaphdr = false;
- rmv_len = pattrib->hdrlen + pattrib->iv_len + (bsnaphdr?SNAP_SIZE:0);
+ rmv_len = pattrib->hdrlen + pattrib->iv_len + (bsnaphdr ? SNAP_SIZE : 0);
len = precvframe->u.hdr.len - rmv_len;
- memcpy(&be_tmp, ptr+rmv_len, 2);
+ memcpy(&be_tmp, ptr + rmv_len, 2);
eth_type = ntohs(be_tmp); /* pattrib->ether_type */
pattrib->eth_type = eth_type;
if ((check_fwstate(pmlmepriv, WIFI_MP_STATE) == true)) {
ptr += rmv_len;
*ptr = 0x87;
- *(ptr+1) = 0x12;
+ *(ptr + 1) = 0x12;
eth_type = 0x8712;
/* append rx status for mp test packets */
- ptr = recvframe_pull(precvframe, (rmv_len-sizeof(struct ethhdr)+2)-24);
+ ptr = recvframe_pull(precvframe, (rmv_len - sizeof(struct ethhdr) + 2) - 24);
if (!ptr)
return _FAIL;
memcpy(ptr, get_rxmem(precvframe), 24);
ptr += 24;
} else {
- ptr = recvframe_pull(precvframe, (rmv_len-sizeof(struct ethhdr) + (bsnaphdr?2:0)));
+ ptr = recvframe_pull(precvframe, (rmv_len - sizeof(struct ethhdr) + (bsnaphdr ? 2 : 0)));
if (!ptr)
return _FAIL;
}
memcpy(ptr, pattrib->dst, ETH_ALEN);
- memcpy(ptr+ETH_ALEN, pattrib->src, ETH_ALEN);
+ memcpy(ptr + ETH_ALEN, pattrib->src, ETH_ALEN);
if (!bsnaphdr) {
be_tmp = htons(len);
- memcpy(ptr+12, &be_tmp, 2);
+ memcpy(ptr + 12, &be_tmp, 2);
}
return _SUCCESS;
@@ -1610,7 +1610,7 @@ static int amsdu_to_msdu(struct adapter *padapter, union recv_frame *prframe)
pdata += nSubframe_Length;
a_len -= nSubframe_Length;
if (a_len != 0) {
- padding_len = 4 - ((nSubframe_Length + ETH_HLEN) & (4-1));
+ padding_len = 4 - ((nSubframe_Length + ETH_HLEN) & (4 - 1));
if (padding_len == 4)
padding_len = 0;
@@ -1842,7 +1842,7 @@ static int recv_indicatepkt_reorder(struct adapter *padapter, union recv_frame *
rtw_recv_indicatepkt(padapter, prframe);
- preorder_ctrl->indicate_seq = (preorder_ctrl->indicate_seq + 1)%4096;
+ preorder_ctrl->indicate_seq = (preorder_ctrl->indicate_seq + 1) % 4096;
return _SUCCESS;
}
@@ -1852,7 +1852,7 @@ static int recv_indicatepkt_reorder(struct adapter *padapter, union recv_frame *
retval = amsdu_to_msdu(padapter, prframe);
- preorder_ctrl->indicate_seq = (preorder_ctrl->indicate_seq + 1)%4096;
+ preorder_ctrl->indicate_seq = (preorder_ctrl->indicate_seq + 1) % 4096;
if (retval != _SUCCESS) {
}
@@ -2047,7 +2047,7 @@ static int recv_func(struct adapter *padapter, union recv_frame *rframe)
!psecuritypriv->busetkipkey) {
rtw_enqueue_recvframe(rframe, &padapter->recvpriv.uc_swdec_pending_queue);
- if (recvpriv->free_recvframe_cnt < NR_RECVFRAME/4) {
+ if (recvpriv->free_recvframe_cnt < NR_RECVFRAME / 4) {
/* to prevent from recvframe starvation, get recvframe from uc_swdec_pending_queue to free_recvframe_cnt */
rframe = rtw_alloc_recvframe(&padapter->recvpriv.uc_swdec_pending_queue);
if (rframe)
@@ -2136,19 +2136,19 @@ static void rtw_signal_stat_timer_hdl(struct timer_list *t)
}
/* update value of signal_strength, rssi, signal_qual */
- tmp_s = (avg_signal_strength+(_alpha-1)*recvpriv->signal_strength);
+ tmp_s = (avg_signal_strength + (_alpha - 1) * recvpriv->signal_strength);
if (tmp_s % _alpha)
- tmp_s = tmp_s/_alpha + 1;
+ tmp_s = tmp_s / _alpha + 1;
else
- tmp_s = tmp_s/_alpha;
+ tmp_s = tmp_s / _alpha;
if (tmp_s > 100)
tmp_s = 100;
- tmp_q = (avg_signal_qual+(_alpha-1)*recvpriv->signal_qual);
+ tmp_q = (avg_signal_qual + (_alpha - 1) * recvpriv->signal_qual);
if (tmp_q % _alpha)
- tmp_q = tmp_q/_alpha + 1;
+ tmp_q = tmp_q / _alpha + 1;
else
- tmp_q = tmp_q/_alpha;
+ tmp_q = tmp_q / _alpha;
if (tmp_q > 100)
tmp_q = 100;
--
2.53.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH 6.1.y 3/3] staging: rtl8723bs: fix protected RX frame validation in decrypt path
2026-11-05 2:02 ` [PATCH 6.1.y 1/3] staging: rtl8723bs: Fix indentation in conditional statements Sasha Levin
2026-11-05 2:02 ` [PATCH 6.1.y 2/3] staging: rtl8723bs: fix spacing around operators in rtw_recv.c Sasha Levin
@ 2026-11-05 2:02 ` Sasha Levin
1 sibling, 0 replies; 4+ messages in thread
From: Sasha Levin @ 2026-11-05 2:02 UTC (permalink / raw)
To: stable; +Cc: Tianchu Chen, Greg Kroah-Hartman, Sasha Levin
From: Tianchu Chen <flynnnchen@tencent.com>
[ Upstream commit 495cb31c791bdf3f9efef255a9587b05b0526c9d ]
The RX software decrypt path mishandles crafted protected frames from a
malicious AP in two ways:
1) decryptor() never checks that a protected frame is long enough to
hold the 802.11 header plus the per-cipher trailer. All of
rtw_wep_decrypt(), rtw_tkip_decrypt() and rtw_aes_decrypt() compute
length = hdr.len - hdrlen - iv_len;
and act on the result, and recvframe_chkmic() similarly computes
datalen = hdr.len - hdrlen - iv_len - icv_len - 8;
for TKIP (the 8-byte Michael MIC is not accounted for in icv_len).
A frame shorter than hdrlen + iv_len + icv_len (+ 8 for TKIP) underflows
these unsigned subtractions, turning into a ~4 GiB iteration count in
aes_decipher()/arc4_crypt()/rtw_seccalctkipmic() or a ~4 GiB crc32_le()
length, causing out-of-bounds reads/writes of up to ~4 GiB starting from
the rx skb. Reject such frames in decryptor() before touching the IV;
this covers all three ciphers and the TKIP MIC check, and also keeps the
unconditional iv[3] access within the frame.
2) validate_80211w_mgmt() keeps using the frame - two memcpys through
the stale rx_data pointer and a pkt_len update - before checking
whether decryptor() returned NULL. On decrypt failure (e.g. a unicast
protected deauth/disassoc/action frame with a bad MIC, which this path
always software-decrypts) the skb has already been freed, so this is a
use-after-free read/write, and the caller's error path frees the frame
a second time, drifting free_recvframe_cnt. Bail out immediately when
decryptor() fails, freeing the temporary mgmt_DATA buffer first.
Discovered by Atuin - Automated Vulnerability Discovery Engine.
Fixes: 554c0a3abf21 ("staging: Add rtl8723bs sdio wifi driver")
Assisted-by: LLM
Cc: stable@vger.kernel.org
Signed-off-by: Tianchu Chen <flynnnchen@tencent.com>
Link: https://patch.msgid.link/8ee3bdd1c45034200cb1aa9a7e9b575b9584643a@linux.dev
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/staging/rtl8723bs/core/rtw_recv.c | 21 ++++++++++++++++++---
1 file changed, 18 insertions(+), 3 deletions(-)
diff --git a/drivers/staging/rtl8723bs/core/rtw_recv.c b/drivers/staging/rtl8723bs/core/rtw_recv.c
index ebec2cff6a2b6..9004c3952a655 100644
--- a/drivers/staging/rtl8723bs/core/rtw_recv.c
+++ b/drivers/staging/rtl8723bs/core/rtw_recv.c
@@ -387,8 +387,21 @@ static union recv_frame *decryptor(struct adapter *padapter, union recv_frame *p
u32 res = _SUCCESS;
if (prxattrib->encrypt > 0) {
- u8 *iv = precv_frame->u.hdr.rx_data + prxattrib->hdrlen;
+ u8 *iv;
+ u32 min_len = prxattrib->hdrlen + prxattrib->iv_len + prxattrib->icv_len;
+ /* TKIP appends an 8-byte Michael MIC that icv_len doesn't account for */
+ if (prxattrib->encrypt == _TKIP_)
+ min_len += 8;
+
+ /* a protected frame must be long enough to hold the IV and ICV/MIC */
+ if (precv_frame->u.hdr.len < min_len) {
+ rtw_free_recvframe(precv_frame,
+ &padapter->recvpriv.free_recv_queue);
+ return NULL;
+ }
+
+ iv = precv_frame->u.hdr.rx_data + prxattrib->hdrlen;
prxattrib->key_index = (((iv[3]) >> 6) & 0x3);
if (prxattrib->key_index > WEP_KEYS) {
@@ -1372,6 +1385,10 @@ static signed int validate_80211w_mgmt(struct adapter *adapter, union recv_frame
if (!mgmt_DATA)
goto validate_80211w_fail;
precv_frame = decryptor(adapter, precv_frame);
+ if (!precv_frame) {
+ kfree(mgmt_DATA);
+ goto validate_80211w_fail;
+ }
/* save actual management data frame body */
memcpy(mgmt_DATA, ptr + pattrib->hdrlen + pattrib->iv_len, data_len);
/* overwrite the iv field */
@@ -1379,8 +1396,6 @@ static signed int validate_80211w_mgmt(struct adapter *adapter, union recv_frame
/* remove the iv and icv length */
pattrib->pkt_len = pattrib->pkt_len - pattrib->iv_len - pattrib->icv_len;
kfree(mgmt_DATA);
- if (!precv_frame)
- goto validate_80211w_fail;
} else if (is_multicast_ether_addr(GetAddr1Ptr(ptr)) &&
(subtype == WIFI_DEAUTH || subtype == WIFI_DISASSOC)) {
signed int BIP_ret = _SUCCESS;
--
2.53.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-11-05 2:02 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-04 14:20 FAILED: patch "[PATCH] staging: rtl8723bs: fix protected RX frame validation in" failed to apply to 6.1-stable tree gregkh
2026-11-05 2:02 ` [PATCH 6.1.y 1/3] staging: rtl8723bs: Fix indentation in conditional statements Sasha Levin
2026-11-05 2:02 ` [PATCH 6.1.y 2/3] staging: rtl8723bs: fix spacing around operators in rtw_recv.c Sasha Levin
2026-11-05 2:02 ` [PATCH 6.1.y 3/3] staging: rtl8723bs: fix protected RX frame validation in decrypt path Sasha Levin
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.