mt76: fix possible pktid leak
authorLorenzo Bianconi <lorenzo@kernel.org>
Mon, 22 Nov 2021 17:34:03 +0000 (18:34 +0100)
committerKalle Valo <kvalo@codeaurora.org>
Wed, 24 Nov 2021 17:21:50 +0000 (19:21 +0200)
Fix a possible idr pkt-id leak if the packet is dropped on tx side

Fixes: bd1e3e7b693c ("mt76: introduce packet_id idr")
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
Acked-by: Felix Fietkau <nbd@nbd.name>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Link: https://lore.kernel.org/r/a560caffcc24452fb48af53904bbe5c45ea5db93.1637602268.git.lorenzo@kernel.org
drivers/net/wireless/mediatek/mt76/mt7615/pci_mac.c
drivers/net/wireless/mediatek/mt76/mt7615/usb_sdio.c
drivers/net/wireless/mediatek/mt76/mt76x02_usb_core.c
drivers/net/wireless/mediatek/mt76/mt7915/mac.c
drivers/net/wireless/mediatek/mt76/mt7921/sdio_mac.c

index 5ee52cd70a4b45a1be50b518015a8e0943b71879..d1806f198aed99e866aa9683d8114eba2e92be5c 100644 (file)
@@ -143,8 +143,6 @@ int mt7615_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
        if (!wcid)
                wcid = &dev->mt76.global_wcid;
 
-       pid = mt76_tx_status_skb_add(mdev, wcid, tx_info->skb);
-
        if ((info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) && msta) {
                struct mt7615_phy *phy = &dev->phy;
 
@@ -164,6 +162,7 @@ int mt7615_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
        if (id < 0)
                return id;
 
+       pid = mt76_tx_status_skb_add(mdev, wcid, tx_info->skb);
        mt7615_mac_write_txwi(dev, txwi_ptr, tx_info->skb, wcid, sta,
                              pid, key, false);
 
index bd2939ebcbf4841a4265e162b0cfacdee11a7338..bfe6c1579dc1398634cb392090aafc43831eb713 100644 (file)
@@ -43,17 +43,11 @@ EXPORT_SYMBOL_GPL(mt7663_usb_sdio_reg_map);
 static void
 mt7663_usb_sdio_write_txwi(struct mt7615_dev *dev, struct mt76_wcid *wcid,
                           enum mt76_txq_id qid, struct ieee80211_sta *sta,
-                          struct sk_buff *skb)
+                          int pid, struct sk_buff *skb)
 {
        struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
        struct ieee80211_key_conf *key = info->control.hw_key;
        __le32 *txwi;
-       int pid;
-
-       if (!wcid)
-               wcid = &dev->mt76.global_wcid;
-
-       pid = mt76_tx_status_skb_add(&dev->mt76, wcid, skb);
 
        txwi = (__le32 *)(skb->data - MT_USB_TXD_SIZE);
        memset(txwi, 0, MT_USB_TXD_SIZE);
@@ -195,9 +189,12 @@ int mt7663_usb_sdio_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
        struct sk_buff *skb = tx_info->skb;
        struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
        struct mt7615_sta *msta;
-       int pad;
+       int pad, err, pktid;
 
        msta = wcid ? container_of(wcid, struct mt7615_sta, wcid) : NULL;
+       if (!wcid)
+               wcid = &dev->mt76.global_wcid;
+
        if ((info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) &&
            msta && !msta->rate_probe) {
                /* request to configure sampling rate */
@@ -207,7 +204,8 @@ int mt7663_usb_sdio_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
                spin_unlock_bh(&dev->mt76.lock);
        }
 
-       mt7663_usb_sdio_write_txwi(dev, wcid, qid, sta, skb);
+       pktid = mt76_tx_status_skb_add(&dev->mt76, wcid, skb);
+       mt7663_usb_sdio_write_txwi(dev, wcid, qid, sta, pktid, skb);
        if (mt76_is_usb(mdev)) {
                u32 len = skb->len;
 
@@ -217,7 +215,12 @@ int mt7663_usb_sdio_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
                pad = round_up(skb->len, 4) - skb->len;
        }
 
-       return mt76_skb_adjust_pad(skb, pad);
+       err = mt76_skb_adjust_pad(skb, pad);
+       if (err)
+               /* Release pktid in case of error. */
+               idr_remove(&wcid->pktid, pktid);
+
+       return err;
 }
 EXPORT_SYMBOL_GPL(mt7663_usb_sdio_tx_prepare_skb);
 
index efd70ddc2fd109b754df8e8c12c71c5b2403f9d0..2c6c03809b20eb628b99a22bb851ff07f14be2a6 100644 (file)
@@ -72,6 +72,7 @@ int mt76x02u_tx_prepare_skb(struct mt76_dev *mdev, void *data,
        bool ampdu = IEEE80211_SKB_CB(tx_info->skb)->flags & IEEE80211_TX_CTL_AMPDU;
        enum mt76_qsel qsel;
        u32 flags;
+       int err;
 
        mt76_insert_hdr_pad(tx_info->skb);
 
@@ -106,7 +107,12 @@ int mt76x02u_tx_prepare_skb(struct mt76_dev *mdev, void *data,
                ewma_pktlen_add(&msta->pktlen, tx_info->skb->len);
        }
 
-       return mt76x02u_skb_dma_info(tx_info->skb, WLAN_PORT, flags);
+       err = mt76x02u_skb_dma_info(tx_info->skb, WLAN_PORT, flags);
+       if (err && wcid)
+               /* Release pktid in case of error. */
+               idr_remove(&wcid->pktid, pid);
+
+       return err;
 }
 EXPORT_SYMBOL_GPL(mt76x02u_tx_prepare_skb);
 
index 5fcf35f2d9fbe42760c7ff28b53c3a96f68d62f8..809dc18e5083c21206447e4b8f4e811fd0c3c41f 100644 (file)
@@ -1151,8 +1151,14 @@ int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
                }
        }
 
-       pid = mt76_tx_status_skb_add(mdev, wcid, tx_info->skb);
+       t = (struct mt76_txwi_cache *)(txwi + mdev->drv->txwi_size);
+       t->skb = tx_info->skb;
+
+       id = mt76_token_consume(mdev, &t);
+       if (id < 0)
+               return id;
 
+       pid = mt76_tx_status_skb_add(mdev, wcid, tx_info->skb);
        mt7915_mac_write_txwi(dev, txwi_ptr, tx_info->skb, wcid, pid, key,
                              false);
 
@@ -1178,13 +1184,6 @@ int mt7915_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
                txp->bss_idx = mvif->idx;
        }
 
-       t = (struct mt76_txwi_cache *)(txwi + mdev->drv->txwi_size);
-       t->skb = tx_info->skb;
-
-       id = mt76_token_consume(mdev, &t);
-       if (id < 0)
-               return id;
-
        txp->token = cpu_to_le16(id);
        if (test_bit(MT_WCID_FLAG_4ADDR, &wcid->flags))
                txp->rept_wds_wcid = cpu_to_le16(wcid->idx);
index 137f86a6dbf875d3122c23b2a26e670843a16db4..85b3d88f8eccf0fd78ebe6c0fe5227b1596bd236 100644 (file)
@@ -142,14 +142,12 @@ out:
 static void
 mt7921s_write_txwi(struct mt7921_dev *dev, struct mt76_wcid *wcid,
                   enum mt76_txq_id qid, struct ieee80211_sta *sta,
-                  struct sk_buff *skb)
+                  int pid, struct sk_buff *skb)
 {
        struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
        struct ieee80211_key_conf *key = info->control.hw_key;
        __le32 *txwi;
-       int pid;
 
-       pid = mt76_tx_status_skb_add(&dev->mt76, wcid, skb);
        txwi = (__le32 *)(skb->data - MT_SDIO_TXD_SIZE);
        memset(txwi, 0, MT_SDIO_TXD_SIZE);
        mt7921_mac_write_txwi(dev, txwi, skb, wcid, key, pid, false);
@@ -164,7 +162,7 @@ int mt7921s_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
        struct mt7921_dev *dev = container_of(mdev, struct mt7921_dev, mt76);
        struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx_info->skb);
        struct sk_buff *skb = tx_info->skb;
-       int pad;
+       int err, pad, pktid;
 
        if (unlikely(tx_info->skb->len <= ETH_HLEN))
                return -EINVAL;
@@ -181,12 +179,18 @@ int mt7921s_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
                }
        }
 
-       mt7921s_write_txwi(dev, wcid, qid, sta, skb);
+       pktid = mt76_tx_status_skb_add(&dev->mt76, wcid, skb);
+       mt7921s_write_txwi(dev, wcid, qid, sta, pktid, skb);
 
        mt7921_skb_add_sdio_hdr(skb, MT7921_SDIO_DATA);
        pad = round_up(skb->len, 4) - skb->len;
 
-       return mt76_skb_adjust_pad(skb, pad);
+       err = mt76_skb_adjust_pad(skb, pad);
+       if (err)
+               /* Release pktid in case of error. */
+               idr_remove(&wcid->pktid, pktid);
+
+       return err;
 }
 
 void mt7921s_tx_complete_skb(struct mt76_dev *mdev, struct mt76_queue_entry *e)