mt76: do not pass the received frame with decryption error
authorXing Song <xing.song@mediatek.com>
Fri, 19 Nov 2021 06:37:06 +0000 (14:37 +0800)
committerFelix Fietkau <nbd@nbd.name>
Sun, 19 Dec 2021 14:23:59 +0000 (15:23 +0100)
MAC80211 doesn't care any decryption error in 802.3 path, so received
frame will be dropped if HW tell us that the cipher configuration is not
matched as well as the header has been translated to 802.3. This case only
appears when IEEE80211_FCTL_PROTECTED is 0 and cipher suit is not none in
the corresponding HW entry.

The received frame is only reported to monitor interface if HW decryption
block tell us there is ICV error or CCMP/BIP/WPI MIC error. Note in this
case the reported frame is decrypted 802.11 frame and the payload may be
malformed due to mismatched key.

Signed-off-by: Xing Song <xing.song@mediatek.com>
Signed-off-by: Felix Fietkau <nbd@nbd.name>
drivers/net/wireless/mediatek/mt76/mt7603/mac.c
drivers/net/wireless/mediatek/mt76/mt7615/mac.c
drivers/net/wireless/mediatek/mt76/mt7915/mac.c
drivers/net/wireless/mediatek/mt76/mt7921/mac.c

index fe03e31989bb14ad6c6bf14e88b37739bd926fa5..a9ac61b9f854a5ce03f07483522ecd4547914d3c 100644 (file)
@@ -525,6 +525,10 @@ mt7603_mac_fill_rx(struct mt7603_dev *dev, struct sk_buff *skb)
        if (rxd2 & MT_RXD2_NORMAL_TKIP_MIC_ERR)
                status->flag |= RX_FLAG_MMIC_ERROR;
 
+       /* ICV error or CCMP/BIP/WPI MIC error */
+       if (rxd2 & MT_RXD2_NORMAL_ICV_ERR)
+               status->flag |= RX_FLAG_ONLY_MONITOR;
+
        if (FIELD_GET(MT_RXD2_NORMAL_SEC_MODE, rxd2) != 0 &&
            !(rxd2 & (MT_RXD2_NORMAL_CLM | MT_RXD2_NORMAL_CM))) {
                status->flag |= RX_FLAG_DECRYPTED;
index bd361c19557d525e3fa67773494c6e45a20a66fc..e2b99b6163e1dc92b3597fb91f2873a2d9192229 100644 (file)
@@ -363,9 +363,16 @@ static int mt7615_mac_fill_rx(struct mt7615_dev *dev, struct sk_buff *skb)
        if (rxd2 & MT_RXD2_NORMAL_AMSDU_ERR)
                return -EINVAL;
 
+       hdr_trans = rxd1 & MT_RXD1_NORMAL_HDR_TRANS;
+       if (hdr_trans && (rxd2 & MT_RXD2_NORMAL_CM))
+               return -EINVAL;
+
+       /* ICV error or CCMP/BIP/WPI MIC error */
+       if (rxd2 & MT_RXD2_NORMAL_ICV_ERR)
+               status->flag |= RX_FLAG_ONLY_MONITOR;
+
        unicast = (rxd1 & MT_RXD1_NORMAL_ADDR_TYPE) == MT_RXD1_NORMAL_U2M;
        idx = FIELD_GET(MT_RXD2_NORMAL_WLAN_IDX, rxd2);
-       hdr_trans = rxd1 & MT_RXD1_NORMAL_HDR_TRANS;
        status->wcid = mt7615_rx_get_wcid(dev, idx, unicast);
 
        if (status->wcid) {
index 280f6084ee8b17b5962a7fd1a39c027e9179f777..2e156c8bf86a977e4d8c97ac5ef063adc6865140 100644 (file)
@@ -504,9 +504,16 @@ mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb)
        if (rxd2 & MT_RXD2_NORMAL_AMSDU_ERR)
                return -EINVAL;
 
+       hdr_trans = rxd2 & MT_RXD2_NORMAL_HDR_TRANS;
+       if (hdr_trans && (rxd1 & MT_RXD1_NORMAL_CM))
+               return -EINVAL;
+
+       /* ICV error or CCMP/BIP/WPI MIC error */
+       if (rxd1 & MT_RXD1_NORMAL_ICV_ERR)
+               status->flag |= RX_FLAG_ONLY_MONITOR;
+
        unicast = FIELD_GET(MT_RXD3_NORMAL_ADDR_TYPE, rxd3) == MT_RXD3_NORMAL_U2M;
        idx = FIELD_GET(MT_RXD1_NORMAL_WLAN_IDX, rxd1);
-       hdr_trans = rxd2 & MT_RXD2_NORMAL_HDR_TRANS;
        status->wcid = mt7915_rx_get_wcid(dev, idx, unicast);
 
        if (status->wcid) {
index 401f91c1657a9e5307cd04a08eb345635e883d1e..30cce5743731967963a261ec2c5a2c268234b6c4 100644 (file)
@@ -506,10 +506,17 @@ mt7921_mac_fill_rx(struct mt7921_dev *dev, struct sk_buff *skb)
        if (rxd2 & MT_RXD2_NORMAL_AMSDU_ERR)
                return -EINVAL;
 
+       hdr_trans = rxd2 & MT_RXD2_NORMAL_HDR_TRANS;
+       if (hdr_trans && (rxd1 & MT_RXD1_NORMAL_CM))
+               return -EINVAL;
+
+       /* ICV error or CCMP/BIP/WPI MIC error */
+       if (rxd1 & MT_RXD1_NORMAL_ICV_ERR)
+               status->flag |= RX_FLAG_ONLY_MONITOR;
+
        chfreq = FIELD_GET(MT_RXD3_NORMAL_CH_FREQ, rxd3);
        unicast = FIELD_GET(MT_RXD3_NORMAL_ADDR_TYPE, rxd3) == MT_RXD3_NORMAL_U2M;
        idx = FIELD_GET(MT_RXD1_NORMAL_WLAN_IDX, rxd1);
-       hdr_trans = rxd2 & MT_RXD2_NORMAL_HDR_TRANS;
        status->wcid = mt7921_rx_get_wcid(dev, idx, unicast);
 
        if (status->wcid) {