Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6f1959c1 authored by Alexander Wetzel's avatar Alexander Wetzel Committed by Greg Kroah-Hartman
Browse files

wifi: cfg80211: Fix use after free for wext

commit 015b8cc5e7c4d7bb671f1984d7b7338c310b185b upstream.

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.de


Signed-off-by: default avatarAlexander Wetzel <alexander@wetzel-home.de>
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 342cb34c
Loading
Loading
Loading
Loading
+26 −5
Original line number Diff line number Diff line
@@ -269,6 +269,15 @@ void cfg80211_conn_work(struct work_struct *work)
	rtnl_unlock();
}

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)
{
@@ -286,10 +295,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;
@@ -568,7 +574,12 @@ static int cfg80211_sme_connect(struct wireless_dev *wdev,
	wdev->conn->params.ssid_len = wdev->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);
@@ -579,6 +590,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 {
@@ -1233,6 +1245,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;