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