Commit 015b8cc5 authored by Alexander Wetzel's avatar Alexander Wetzel Committed by Johannes Berg

wifi: cfg80211: Fix use after free for wext

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: fffd0934 ("cfg80211: rework key operation")
Cc: stable@vger.kernel.org
Link: https://lore.kernel.org/r/20230124141856.356646-1-alexander@wetzel-home.deSigned-off-by: default avatarAlexander Wetzel <alexander@wetzel-home.de>
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 9a47c1ef
...@@ -285,6 +285,15 @@ void cfg80211_conn_work(struct work_struct *work) ...@@ -285,6 +285,15 @@ void cfg80211_conn_work(struct work_struct *work)
wiphy_unlock(&rdev->wiphy); 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. */ /* Returned bss is reference counted and must be cleaned up appropriately. */
static struct cfg80211_bss *cfg80211_get_conn_bss(struct wireless_dev *wdev) 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) ...@@ -302,10 +311,7 @@ static struct cfg80211_bss *cfg80211_get_conn_bss(struct wireless_dev *wdev)
if (!bss) if (!bss)
return NULL; return NULL;
memcpy(wdev->conn->bssid, bss->bssid, ETH_ALEN); cfg80211_step_auth_next(wdev->conn, bss);
wdev->conn->params.bssid = wdev->conn->bssid;
wdev->conn->params.channel = bss->channel;
wdev->conn->state = CFG80211_CONN_AUTHENTICATE_NEXT;
schedule_work(&rdev->conn_work); schedule_work(&rdev->conn_work);
return bss; return bss;
...@@ -597,7 +603,12 @@ static int cfg80211_sme_connect(struct wireless_dev *wdev, ...@@ -597,7 +603,12 @@ static int cfg80211_sme_connect(struct wireless_dev *wdev,
wdev->conn->params.ssid_len = wdev->u.client.ssid_len; wdev->conn->params.ssid_len = wdev->u.client.ssid_len;
/* see if we have the bss already */ /* 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) { if (prev_bssid) {
memcpy(wdev->conn->prev_bssid, prev_bssid, ETH_ALEN); memcpy(wdev->conn->prev_bssid, prev_bssid, ETH_ALEN);
...@@ -608,6 +619,7 @@ static int cfg80211_sme_connect(struct wireless_dev *wdev, ...@@ -608,6 +619,7 @@ static int cfg80211_sme_connect(struct wireless_dev *wdev,
if (bss) { if (bss) {
enum nl80211_timeout_reason treason; enum nl80211_timeout_reason treason;
cfg80211_step_auth_next(wdev->conn, bss);
err = cfg80211_conn_do_work(wdev, &treason); err = cfg80211_conn_do_work(wdev, &treason);
cfg80211_put_bss(wdev->wiphy, bss); cfg80211_put_bss(wdev->wiphy, bss);
} else { } else {
...@@ -1464,6 +1476,15 @@ int cfg80211_connect(struct cfg80211_registered_device *rdev, ...@@ -1464,6 +1476,15 @@ int cfg80211_connect(struct cfg80211_registered_device *rdev,
} else { } else {
if (WARN_ON(connkeys)) if (WARN_ON(connkeys))
return -EINVAL; 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; wdev->connect_keys = connkeys;
......
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