summaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2021-01-22 17:11:16 +0100
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2021-02-03 23:28:48 +0100
commit1c3b27b05a43745a9dfbb4f4b6a5f9d39f319f20 (patch)
tree349593ac4f590e80b2dc28411f4cd11d1ca13d8b /net
parenta59a7b96dc13e277cb1c3b4f1ce6ea8ae3b4275a (diff)
mac80211: pause TX while changing interface type
[ Upstream commit 054c9939b4800a91475d8d89905827bf9e1ad97a ] syzbot reported a crash that happened when changing the interface type around a lot, and while it might have been easy to fix just the symptom there, a little deeper investigation found that really the reason is that we allowed packets to be transmitted while in the middle of changing the interface type. Disallow TX by stopping the queues while changing the type. Fixes: 34d4bc4d41d2 ("mac80211: support runtime interface type changes") Reported-by: syzbot+d7a3b15976bf7de2238a@syzkaller.appspotmail.com Link: https://lore.kernel.org/r/20210122171115.b321f98f4d4f.I6997841933c17b093535c31d29355be3c0c39628@changeid Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: Sasha Levin <sashal@kernel.org>
Diffstat (limited to 'net')
-rw-r--r--net/mac80211/ieee80211_i.h1
-rw-r--r--net/mac80211/iface.c6
2 files changed, 7 insertions, 0 deletions
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 2a21226fb518..d6913784be2b 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1082,6 +1082,7 @@ enum queue_stop_reason {
IEEE80211_QUEUE_STOP_REASON_FLUSH,
IEEE80211_QUEUE_STOP_REASON_TDLS_TEARDOWN,
IEEE80211_QUEUE_STOP_REASON_RESERVE_TID,
+ IEEE80211_QUEUE_STOP_REASON_IFTYPE_CHANGE,
IEEE80211_QUEUE_STOP_REASONS,
};
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 44154cc596cd..f3c3557a9e4c 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -1654,6 +1654,10 @@ static int ieee80211_runtime_change_iftype(struct ieee80211_sub_if_data *sdata,
if (ret)
return ret;
+ ieee80211_stop_vif_queues(local, sdata,
+ IEEE80211_QUEUE_STOP_REASON_IFTYPE_CHANGE);
+ synchronize_net();
+
ieee80211_do_stop(sdata, false);
ieee80211_teardown_sdata(sdata);
@@ -1676,6 +1680,8 @@ static int ieee80211_runtime_change_iftype(struct ieee80211_sub_if_data *sdata,
err = ieee80211_do_open(&sdata->wdev, false);
WARN(err, "type change: do_open returned %d", err);
+ ieee80211_wake_vif_queues(local, sdata,
+ IEEE80211_QUEUE_STOP_REASON_IFTYPE_CHANGE);
return ret;
}