[<prev] [next>] [day] [month] [year] [list]
Message-ID: <20250626114619.172631-1-d.dulov@aladdin.ru>
Date: Thu, 26 Jun 2025 14:46:19 +0300
From: Daniil Dulov <d.dulov@...ddin.ru>
To: Johannes Berg <johannes@...solutions.net>
CC: Daniil Dulov <d.dulov@...ddin.ru>, <linux-wireless@...r.kernel.org>,
<linux-kernel@...r.kernel.org>, <lvc-project@...uxtesting.org>
Subject: [PATCH v2] wifi: zd1211rw: Fix potential NULL pointer dereference in zd_mac_tx_to_dev()
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@...ddin.ru>
---
v2: Replace locking changes with a check for NULL since it has more determined
behavior compared to changing locking logic and might be less harmful in terms
of old code.
Link to v1: https://lore.kernel.org/linux-wireless/20250604101356.6292-1-d.dulov@aladdin.ru/T/#u
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 9653dbaac3c0..21205568374e 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.34.1
Powered by blists - more mailing lists