| From 7c285ed4c567e14b06cfbb5d92d770c62655c292 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Thu, 26 Jun 2025 14:46:19 +0300 |
| Subject: wifi: zd1211rw: Fix potential NULL pointer dereference in |
| zd_mac_tx_to_dev() |
| |
| From: Daniil Dulov <d.dulov@aladdin.ru> |
| |
| [ Upstream commit 74b1ec9f5d627d2bdd5e5b6f3f81c23317657023 ] |
| |
| There is a potential NULL pointer dereference in zd_mac_tx_to_dev(). For |
| example, the following is possible: |
| |
| T0 T1 |
| zd_mac_tx_to_dev() |
| /* len == skb_queue_len(q) */ |
| while (len > ZD_MAC_MAX_ACK_WAITERS) { |
| |
| filter_ack() |
| spin_lock_irqsave(&q->lock, flags); |
| /* position == skb_queue_len(q) */ |
| for (i=1; i<position; i++) |
| skb = __skb_dequeue(q) |
| |
| if (mac->type == NL80211_IFTYPE_AP) |
| skb = __skb_dequeue(q); |
| spin_unlock_irqrestore(&q->lock, flags); |
| |
| skb_dequeue() -> NULL |
| |
| Since there is a small gap between checking skb queue length and skb being |
| unconditionally dequeued in zd_mac_tx_to_dev(), skb_dequeue() can return NULL. |
| Then the pointer is passed to zd_mac_tx_status() where it is dereferenced. |
| |
| In order to avoid potential NULL pointer dereference due to situations like |
| above, check if skb is not NULL before passing it to zd_mac_tx_status(). |
| |
| Found by Linux Verification Center (linuxtesting.org) with SVACE. |
| |
| Fixes: 459c51ad6e1f ("zd1211rw: port to mac80211") |
| Signed-off-by: Daniil Dulov <d.dulov@aladdin.ru> |
| Link: https://patch.msgid.link/20250626114619.172631-1-d.dulov@aladdin.ru |
| Signed-off-by: Johannes Berg <johannes.berg@intel.com> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/net/wireless/zydas/zd1211rw/zd_mac.c | 6 +++++- |
| 1 file changed, 5 insertions(+), 1 deletion(-) |
| |
| diff --git a/drivers/net/wireless/zydas/zd1211rw/zd_mac.c b/drivers/net/wireless/zydas/zd1211rw/zd_mac.c |
| index 5d534e15a844f..278875c02f41f 100644 |
| --- a/drivers/net/wireless/zydas/zd1211rw/zd_mac.c |
| +++ b/drivers/net/wireless/zydas/zd1211rw/zd_mac.c |
| @@ -583,7 +583,11 @@ void zd_mac_tx_to_dev(struct sk_buff *skb, int error) |
| |
| skb_queue_tail(q, skb); |
| while (skb_queue_len(q) > ZD_MAC_MAX_ACK_WAITERS) { |
| - zd_mac_tx_status(hw, skb_dequeue(q), |
| + skb = skb_dequeue(q); |
| + if (!skb) |
| + break; |
| + |
| + zd_mac_tx_status(hw, skb, |
| mac->ack_pending ? mac->ack_signal : 0, |
| NULL); |
| mac->ack_pending = 0; |
| -- |
| 2.39.5 |
| |