Search Linux Wireless

[PATCH] wifi: mac80211: make debugfs locking interruptible

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Johannes Berg <johannes.berg@xxxxxxxxx>

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@xxxxxxxxxxxxxxx>
Signed-off-by: Johannes Berg <johannes.berg@xxxxxxxxx>
---
 net/mac80211/debugfs_netdev.c | 26 +++++++++++++++++---------
 net/mac80211/debugfs_sta.c    |  6 ++++--
 2 files changed, 21 insertions(+), 11 deletions(-)

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;
 }
-- 
2.41.0




[Index of Archives]     [Linux Host AP]     [ATH6KL]     [Linux Wireless Personal Area Network]     [Linux Bluetooth]     [Wireless Regulations]     [Linux Netdev]     [Kernel Newbies]     [Linux Kernel]     [IDE]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite Hiking]     [MIPS Linux]     [ARM Linux]     [Linux RAID]

  Powered by Linux