| From a5a89cdca84092cb7119b2f77ad627a2b1397126 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Fri, 22 Jan 2021 17:11:16 +0100 |
| Subject: mac80211: pause TX while changing interface type |
| |
| From: Johannes Berg <johannes.berg@intel.com> |
| |
| [ 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> |
| --- |
| net/mac80211/ieee80211_i.h | 1 + |
| net/mac80211/iface.c | 6 ++++++ |
| 2 files changed, 7 insertions(+) |
| |
| diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h |
| index a991d1df6774d..1046520d726d8 100644 |
| --- a/net/mac80211/ieee80211_i.h |
| +++ b/net/mac80211/ieee80211_i.h |
| @@ -1027,6 +1027,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 519def0e15f17..6d12a893eb11c 100644 |
| --- a/net/mac80211/iface.c |
| +++ b/net/mac80211/iface.c |
| @@ -1507,6 +1507,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); |
| @@ -1527,6 +1531,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; |
| } |
| |
| -- |
| 2.27.0 |
| |