mac80211: fix memory leaks with element parsing
authorJohannes Berg <johannes.berg@intel.com>
Thu, 13 Oct 2022 18:16:00 +0000 (20:16 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 15 Oct 2022 05:59:05 +0000 (07:59 +0200)
commit 8223ac199a3849257e86ec27865dc63f034b1cf1 upstream.

My previous commit 5d24828d05f3 ("mac80211: always allocate
struct ieee802_11_elems") had a few bugs and leaked the new
allocated struct in a few error cases, fix that.

Fixes: 5d24828d05f3 ("mac80211: always allocate struct ieee802_11_elems")
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Link: https://lore.kernel.org/r/20211001211108.9839928e42e0.Ib81ca187d3d3af7ed1bfeac2e00d08a4637c8025@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Cc: Felix Fietkau <nbd@nbd.name>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
net/mac80211/agg-rx.c
net/mac80211/ibss.c
net/mac80211/mlme.c

index ffa4f31..0d2bab9 100644 (file)
@@ -499,13 +499,14 @@ void ieee80211_process_addba_request(struct ieee80211_local *local,
                elems = ieee802_11_parse_elems(mgmt->u.action.u.addba_req.variable,
                                               ies_len, true, mgmt->bssid, NULL);
                if (!elems || elems->parse_error)
-                       return;
+                       goto free;
        }
 
        __ieee80211_start_rx_ba_session(sta, dialog_token, timeout,
                                        start_seq_num, ba_policy, tid,
                                        buf_size, true, false,
                                        elems ? elems->addba_ext_ie : NULL);
+free:
        kfree(elems);
 }
 
index 4b721b4..48e0260 100644 (file)
@@ -1663,11 +1663,11 @@ void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
                                mgmt->u.action.u.chan_switch.variable,
                                ies_len, true, mgmt->bssid, NULL);
 
-                       if (!elems || elems->parse_error)
-                               break;
-
-                       ieee80211_rx_mgmt_spectrum_mgmt(sdata, mgmt, skb->len,
-                                                       rx_status, elems);
+                       if (elems && !elems->parse_error)
+                               ieee80211_rx_mgmt_spectrum_mgmt(sdata, mgmt,
+                                                               skb->len,
+                                                               rx_status,
+                                                               elems);
                        kfree(elems);
                        break;
                }
index 45efa1d..cc6d38a 100644 (file)
@@ -3374,8 +3374,10 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
                        bss_ies = kmemdup(ies, sizeof(*ies) + ies->len,
                                          GFP_ATOMIC);
                rcu_read_unlock();
-               if (!bss_ies)
-                       return false;
+               if (!bss_ies) {
+                       ret = false;
+                       goto out;
+               }
 
                bss_elems = ieee802_11_parse_elems(bss_ies->data, bss_ies->len,
                                                   false, mgmt->bssid,
@@ -4358,13 +4360,11 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
                                        mgmt->u.action.u.chan_switch.variable,
                                        ies_len, true, mgmt->bssid, NULL);
 
-                       if (!elems || elems->parse_error)
-                               break;
-
-                       ieee80211_sta_process_chanswitch(sdata,
-                                                rx_status->mactime,
-                                                rx_status->device_timestamp,
-                                                elems, false);
+                       if (elems && !elems->parse_error)
+                               ieee80211_sta_process_chanswitch(sdata,
+                                                                rx_status->mactime,
+                                                                rx_status->device_timestamp,
+                                                                elems, false);
                        kfree(elems);
                } else if (mgmt->u.action.category == WLAN_CATEGORY_PUBLIC) {
                        struct ieee802_11_elems *elems;
@@ -4384,17 +4384,17 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
                                        mgmt->u.action.u.ext_chan_switch.variable,
                                        ies_len, true, mgmt->bssid, NULL);
 
-                       if (!elems || elems->parse_error)
-                               break;
+                       if (elems && !elems->parse_error) {
+                               /* for the handling code pretend it was an IE */
+                               elems->ext_chansw_ie =
+                                       &mgmt->u.action.u.ext_chan_switch.data;
 
-                       /* for the handling code pretend this was also an IE */
-                       elems->ext_chansw_ie =
-                               &mgmt->u.action.u.ext_chan_switch.data;
+                               ieee80211_sta_process_chanswitch(sdata,
+                                                                rx_status->mactime,
+                                                                rx_status->device_timestamp,
+                                                                elems, false);
+                       }
 
-                       ieee80211_sta_process_chanswitch(sdata,
-                                                rx_status->mactime,
-                                                rx_status->device_timestamp,
-                                                elems, false);
                        kfree(elems);
                }
                break;