diff mbox series

wifi: mac80211: make debugfs locking interruptible

Message ID 20231108195820.f3f4bb4214d3.I33acae0718c86722ae6d416b89a59f3527a77b33@changeid
State New
Headers show
Series wifi: mac80211: make debugfs locking interruptible | expand

Commit Message

Johannes Berg Nov. 8, 2023, 6:58 p.m. UTC
From: Johannes Berg <johannes.berg@intel.com>

Due to the locking changes, debugfs accesses can deadlock
because we may delete a debugfs file under wiphy_lock(),
but also acquire it inside the read/write handlers, and
debugfs file removal waits for those to finish.

While we're debating ways to fix this, at least make the
locking interruptible so you can recover from this rather
than having a hard deadlock.

Reported-by: Ben Greear <greearb@candelatech.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/debugfs_netdev.c | 26 +++++++++++++++++---------
 net/mac80211/debugfs_sta.c    |  6 ++++--
 2 files changed, 21 insertions(+), 11 deletions(-)
diff mbox series

Patch

diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c
index ec91e131b29e..db7516487225 100644
--- a/net/mac80211/debugfs_netdev.c
+++ b/net/mac80211/debugfs_netdev.c
@@ -29,11 +29,13 @@  static ssize_t ieee80211_if_read_sdata(
 	ssize_t (*format)(const struct ieee80211_sub_if_data *sdata, char *, int))
 {
 	char buf[200];
-	ssize_t ret = -EINVAL;
+	ssize_t ret;
 
-	wiphy_lock(sdata->local->hw.wiphy);
+	ret = mutex_lock_interruptible(&sdata->local->hw.wiphy->mtx);
+	if (ret)
+		return ret;
 	ret = (*format)(sdata, buf, sizeof(buf));
-	wiphy_unlock(sdata->local->hw.wiphy);
+	mutex_unlock(&sdata->local->hw.wiphy->mtx);
 
 	if (ret >= 0)
 		ret = simple_read_from_buffer(userbuf, count, ppos, buf, ret);
@@ -57,9 +59,11 @@  static ssize_t ieee80211_if_write_sdata(
 		return -EFAULT;
 	buf[count] = '\0';
 
-	wiphy_lock(sdata->local->hw.wiphy);
+	ret = mutex_lock_interruptible(&sdata->local->hw.wiphy->mtx);
+	if (ret)
+		return ret;
 	ret = (*write)(sdata, buf, count);
-	wiphy_unlock(sdata->local->hw.wiphy);
+	mutex_unlock(&sdata->local->hw.wiphy->mtx);
 
 	return ret;
 }
@@ -73,9 +77,11 @@  static ssize_t ieee80211_if_read_link(
 	char buf[200];
 	ssize_t ret = -EINVAL;
 
-	wiphy_lock(link->sdata->local->hw.wiphy);
+	ret = mutex_lock_interruptible(&link->sdata->local->hw.wiphy->mtx);
+	if (ret)
+		return ret;
 	ret = (*format)(link, buf, sizeof(buf));
-	wiphy_unlock(link->sdata->local->hw.wiphy);
+	mutex_unlock(&link->sdata->local->hw.wiphy->mtx);
 
 	if (ret >= 0)
 		ret = simple_read_from_buffer(userbuf, count, ppos, buf, ret);
@@ -99,9 +105,11 @@  static ssize_t ieee80211_if_write_link(
 		return -EFAULT;
 	buf[count] = '\0';
 
-	wiphy_lock(link->sdata->local->hw.wiphy);
+	ret = mutex_lock_interruptible(&link->sdata->local->hw.wiphy->mtx);
+	if (ret)
+		return ret;
 	ret = (*write)(link, buf, count);
-	wiphy_unlock(link->sdata->local->hw.wiphy);
+	mutex_unlock(&link->sdata->local->hw.wiphy->mtx);
 
 	return ret;
 }
diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c
index 06e3613bf46b..a0b9b5980910 100644
--- a/net/mac80211/debugfs_sta.c
+++ b/net/mac80211/debugfs_sta.c
@@ -420,7 +420,9 @@  static ssize_t sta_agg_status_write(struct file *file, const char __user *userbu
 	if (ret || tid >= IEEE80211_NUM_TIDS)
 		return -EINVAL;
 
-	wiphy_lock(sta->local->hw.wiphy);
+	ret = mutex_lock_interruptible(&sta->local->hw.wiphy->mtx);
+	if (ret)
+		return ret;
 	if (tx) {
 		if (start)
 			ret = ieee80211_start_tx_ba_session(&sta->sta, tid,
@@ -432,7 +434,7 @@  static ssize_t sta_agg_status_write(struct file *file, const char __user *userbu
 					       3, true);
 		ret = 0;
 	}
-	wiphy_unlock(sta->local->hw.wiphy);
+	mutex_unlock(&sta->local->hw.wiphy->mtx);
 
 	return ret ?: count;
 }