Skip to content

Commit

Permalink
wifi: cfg80211: Fix use after free for wext
Browse files Browse the repository at this point in the history
Key information in wext.connect is not reset on (re)connect and can hold
data from a previous connection.

Reset key data to avoid that drivers or mac80211 incorrectly detect a
WEP connection request and access the freed or already reused memory.

Additionally optimize cfg80211_sme_connect() and avoid an useless
schedule of conn_work.

Fixes: fffd093 ("cfg80211: rework key operation")
Cc: stable@vger.kernel.org
Link: https://lore.kernel.org/r/20230124141856.356646-1-alexander@wetzel-home.de
Signed-off-by: Alexander Wetzel <alexander@wetzel-home.de>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
  • Loading branch information
Alexander Wetzel authored and Johannes Berg committed Feb 14, 2023
1 parent 9a47c1e commit 015b8cc
Showing 1 changed file with 26 additions and 5 deletions.
31 changes: 26 additions & 5 deletions net/wireless/sme.c
Original file line number Diff line number Diff line change
@@ -285,6 +285,15 @@ void cfg80211_conn_work(struct work_struct *work)
wiphy_unlock(&rdev->wiphy);
}

static void cfg80211_step_auth_next(struct cfg80211_conn *conn,
struct cfg80211_bss *bss)
{
memcpy(conn->bssid, bss->bssid, ETH_ALEN);
conn->params.bssid = conn->bssid;
conn->params.channel = bss->channel;
conn->state = CFG80211_CONN_AUTHENTICATE_NEXT;
}

/* Returned bss is reference counted and must be cleaned up appropriately. */
static struct cfg80211_bss *cfg80211_get_conn_bss(struct wireless_dev *wdev)
{
@@ -302,10 +311,7 @@ static struct cfg80211_bss *cfg80211_get_conn_bss(struct wireless_dev *wdev)
if (!bss)
return NULL;

memcpy(wdev->conn->bssid, bss->bssid, ETH_ALEN);
wdev->conn->params.bssid = wdev->conn->bssid;
wdev->conn->params.channel = bss->channel;
wdev->conn->state = CFG80211_CONN_AUTHENTICATE_NEXT;
cfg80211_step_auth_next(wdev->conn, bss);
schedule_work(&rdev->conn_work);

return bss;
@@ -597,7 +603,12 @@ static int cfg80211_sme_connect(struct wireless_dev *wdev,
wdev->conn->params.ssid_len = wdev->u.client.ssid_len;

/* see if we have the bss already */
bss = cfg80211_get_conn_bss(wdev);
bss = cfg80211_get_bss(wdev->wiphy, wdev->conn->params.channel,
wdev->conn->params.bssid,
wdev->conn->params.ssid,
wdev->conn->params.ssid_len,
wdev->conn_bss_type,
IEEE80211_PRIVACY(wdev->conn->params.privacy));

if (prev_bssid) {
memcpy(wdev->conn->prev_bssid, prev_bssid, ETH_ALEN);
@@ -608,6 +619,7 @@ static int cfg80211_sme_connect(struct wireless_dev *wdev,
if (bss) {
enum nl80211_timeout_reason treason;

cfg80211_step_auth_next(wdev->conn, bss);
err = cfg80211_conn_do_work(wdev, &treason);
cfg80211_put_bss(wdev->wiphy, bss);
} else {
@@ -1464,6 +1476,15 @@ int cfg80211_connect(struct cfg80211_registered_device *rdev,
} else {
if (WARN_ON(connkeys))
return -EINVAL;

/* connect can point to wdev->wext.connect which
* can hold key data from a previous connection
*/
connect->key = NULL;
connect->key_len = 0;
connect->key_idx = 0;
connect->crypto.cipher_group = 0;
connect->crypto.n_ciphers_pairwise = 0;
}

wdev->connect_keys = connkeys;

0 comments on commit 015b8cc

Please sign in to comment.