This patch was committed last night but contains a bug: I forgot to adjust
error paths to avoid a double-free. Please check the follow-up fix below. Ok?

(This double-free wouldn't trigger under normal conditions even in -current,
unless we receive crafted packets that would also need to pass decryption
if we're not on an open network)

On Wed, Dec 09, 2020 at 03:34:05PM +0100, Stefan Sperling wrote:
> With A-MSDUs enabled in -current people are seeing a lot of
> 
>       input packet decapsulations failed
> 
> events in netstat -W iwm0.
> 
> This fixes the issue on iwm 8265 for me. There are between 6 and 8 bytes of
> trailing data in the A-MSDU frame buffer. This results in a decap failure
> being counted when m_pullup() fails to fetch ETHER_HDR_LEN + LLC_SNAPFRAMELEN
> bytes.
> 
> I suppose such bytes are padding left by the hardware, most likely due to
> decryption. It should be safe to ignore these. A TCP stream that uses
> A-MSDUs looks clean, so we're not losing any packets. This problem is
> just a cosmetic one.
> 
> ok?

> iwm(4) 9260+ and iwx(4) have another issue because these devices actually
> decapsulate A-MSDUs in hardware and our code doesn't handle that yet.
> I will send a separate patch for this soon.

Regarding the above paragraph, I have changed my mind and am shelving
further work on A-MSDU support for now due to lack of time. I will try
to pick this up again later. I would have time to review patches, though,
if anyone else wants to continue this work.

Double-free fix:

diff 22c79bfc5a343ef1dfe575157d8cd8a0dc743910 /usr/src
blob - 924608b6724ca4d3939200dd9f1bc19024870f42
file + sys/net80211/ieee80211_input.c
--- sys/net80211/ieee80211_input.c
+++ sys/net80211/ieee80211_input.c
@@ -1158,7 +1158,7 @@ ieee80211_amsdu_decap(struct ieee80211com *ic, struct 
                m = m_pullup(m, ETHER_HDR_LEN + LLC_SNAPFRAMELEN);
                if (m == NULL) {
                        ic->ic_stats.is_rx_decap++;
-                       break;
+                       return;
                }
                eh = mtod(m, struct ether_header *);
                /* examine 802.3 header */
@@ -1168,7 +1168,7 @@ ieee80211_amsdu_decap(struct ieee80211com *ic, struct 
                        /* stop processing A-MSDU subframes */
                        ic->ic_stats.is_rx_decap++;
                        m_freem(m);
-                       break;
+                       return;
                }
                llc = (struct llc *)&eh[1];
                /* examine 802.2 LLC header */
@@ -1192,7 +1192,7 @@ ieee80211_amsdu_decap(struct ieee80211com *ic, struct 
                        DPRINTF(("A-MSDU subframe too long (%d)\n", len));
                        ic->ic_stats.is_rx_decap++;
                        m_freem(m);
-                       break;
+                       return;
                }
 
                /* "detach" our A-MSDU subframe from the others */
@@ -1201,7 +1201,7 @@ ieee80211_amsdu_decap(struct ieee80211com *ic, struct 
                        /* stop processing A-MSDU subframes */
                        ic->ic_stats.is_rx_decap++;
                        m_freem(m);
-                       break;
+                       return;
                }
                ieee80211_enqueue_data(ic, m, ni, mcast, ml);
 

Reply via email to