Commit a72c01a9 authored by Jiasheng Jiang's avatar Jiasheng Jiang Committed by Johannes Berg

mac80211: mlme: check for null after calling kmemdup

As the possible failure of the alloc, the ifmgd->assoc_req_ies might be
NULL pointer returned from kmemdup().
Therefore it might be better to free the skb and return error in order
to fail the association, like ieee80211_assoc_success().
Also, the caller, ieee80211_do_assoc(), needs to deal with the return
value from ieee80211_send_assoc().

Fixes: 4d9ec73d ("cfg80211: Report Association Request frame IEs in association events")
Signed-off-by: default avatarJiasheng Jiang <jiasheng@iscas.ac.cn>
Link: https://lore.kernel.org/r/20220105081559.2387083-1-jiasheng@iscas.ac.cn
[fix some paths to be errors, not success]
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 665408f4
...@@ -666,7 +666,7 @@ static void ieee80211_add_he_ie(struct ieee80211_sub_if_data *sdata, ...@@ -666,7 +666,7 @@ static void ieee80211_add_he_ie(struct ieee80211_sub_if_data *sdata,
ieee80211_ie_build_he_6ghz_cap(sdata, skb); ieee80211_ie_build_he_6ghz_cap(sdata, skb);
} }
static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) static int ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
{ {
struct ieee80211_local *local = sdata->local; struct ieee80211_local *local = sdata->local;
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
...@@ -686,6 +686,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) ...@@ -686,6 +686,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
enum nl80211_iftype iftype = ieee80211_vif_type_p2p(&sdata->vif); enum nl80211_iftype iftype = ieee80211_vif_type_p2p(&sdata->vif);
const struct ieee80211_sband_iftype_data *iftd; const struct ieee80211_sband_iftype_data *iftd;
struct ieee80211_prep_tx_info info = {}; struct ieee80211_prep_tx_info info = {};
int ret;
/* we know it's writable, cast away the const */ /* we know it's writable, cast away the const */
if (assoc_data->ie_len) if (assoc_data->ie_len)
...@@ -699,7 +700,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) ...@@ -699,7 +700,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
if (WARN_ON(!chanctx_conf)) { if (WARN_ON(!chanctx_conf)) {
rcu_read_unlock(); rcu_read_unlock();
return; return -EINVAL;
} }
chan = chanctx_conf->def.chan; chan = chanctx_conf->def.chan;
rcu_read_unlock(); rcu_read_unlock();
...@@ -750,7 +751,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) ...@@ -750,7 +751,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
(iftd ? iftd->vendor_elems.len : 0), (iftd ? iftd->vendor_elems.len : 0),
GFP_KERNEL); GFP_KERNEL);
if (!skb) if (!skb)
return; return -ENOMEM;
skb_reserve(skb, local->hw.extra_tx_headroom); skb_reserve(skb, local->hw.extra_tx_headroom);
...@@ -1031,15 +1032,22 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) ...@@ -1031,15 +1032,22 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
skb_put_data(skb, assoc_data->ie + offset, noffset - offset); skb_put_data(skb, assoc_data->ie + offset, noffset - offset);
} }
if (assoc_data->fils_kek_len && if (assoc_data->fils_kek_len) {
fils_encrypt_assoc_req(skb, assoc_data) < 0) { ret = fils_encrypt_assoc_req(skb, assoc_data);
if (ret < 0) {
dev_kfree_skb(skb); dev_kfree_skb(skb);
return; return ret;
}
} }
pos = skb_tail_pointer(skb); pos = skb_tail_pointer(skb);
kfree(ifmgd->assoc_req_ies); kfree(ifmgd->assoc_req_ies);
ifmgd->assoc_req_ies = kmemdup(ie_start, pos - ie_start, GFP_ATOMIC); ifmgd->assoc_req_ies = kmemdup(ie_start, pos - ie_start, GFP_ATOMIC);
if (!ifmgd->assoc_req_ies) {
dev_kfree_skb(skb);
return -ENOMEM;
}
ifmgd->assoc_req_ies_len = pos - ie_start; ifmgd->assoc_req_ies_len = pos - ie_start;
drv_mgd_prepare_tx(local, sdata, &info); drv_mgd_prepare_tx(local, sdata, &info);
...@@ -1049,6 +1057,8 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) ...@@ -1049,6 +1057,8 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS |
IEEE80211_TX_INTFL_MLME_CONN_TX; IEEE80211_TX_INTFL_MLME_CONN_TX;
ieee80211_tx_skb(sdata, skb); ieee80211_tx_skb(sdata, skb);
return 0;
} }
void ieee80211_send_pspoll(struct ieee80211_local *local, void ieee80211_send_pspoll(struct ieee80211_local *local,
...@@ -4497,6 +4507,7 @@ static int ieee80211_do_assoc(struct ieee80211_sub_if_data *sdata) ...@@ -4497,6 +4507,7 @@ static int ieee80211_do_assoc(struct ieee80211_sub_if_data *sdata)
{ {
struct ieee80211_mgd_assoc_data *assoc_data = sdata->u.mgd.assoc_data; struct ieee80211_mgd_assoc_data *assoc_data = sdata->u.mgd.assoc_data;
struct ieee80211_local *local = sdata->local; struct ieee80211_local *local = sdata->local;
int ret;
sdata_assert_lock(sdata); sdata_assert_lock(sdata);
...@@ -4517,7 +4528,9 @@ static int ieee80211_do_assoc(struct ieee80211_sub_if_data *sdata) ...@@ -4517,7 +4528,9 @@ static int ieee80211_do_assoc(struct ieee80211_sub_if_data *sdata)
sdata_info(sdata, "associate with %pM (try %d/%d)\n", sdata_info(sdata, "associate with %pM (try %d/%d)\n",
assoc_data->bss->bssid, assoc_data->tries, assoc_data->bss->bssid, assoc_data->tries,
IEEE80211_ASSOC_MAX_TRIES); IEEE80211_ASSOC_MAX_TRIES);
ieee80211_send_assoc(sdata); ret = ieee80211_send_assoc(sdata);
if (ret)
return ret;
if (!ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS)) { if (!ieee80211_hw_check(&local->hw, REPORTS_TX_ACK_STATUS)) {
assoc_data->timeout = jiffies + IEEE80211_ASSOC_TIMEOUT; assoc_data->timeout = jiffies + IEEE80211_ASSOC_TIMEOUT;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment