wifi: mac80211: hold wiphy lock in netdev/link debugfs

It's no longer really needed to ensure that the debugfs
file isn't going away, debugfs handles that. So there's
no point in holding dev_base_lock or RTNL here, but we
should instead hold the wiphy lock since drivers will
be allowed to depend on that. Do that, which requires
splitting the sdata and link macros a bit.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
Johannes Berg 2023-08-28 13:59:30 +02:00
parent 629ebb8532
commit 0ab6cba069

View file

@ -22,18 +22,18 @@
#include "debugfs_netdev.h" #include "debugfs_netdev.h"
#include "driver-ops.h" #include "driver-ops.h"
static ssize_t ieee80211_if_read( static ssize_t ieee80211_if_read_sdata(
void *data, struct ieee80211_sub_if_data *sdata,
char __user *userbuf, char __user *userbuf,
size_t count, loff_t *ppos, size_t count, loff_t *ppos,
ssize_t (*format)(const void *, char *, int)) ssize_t (*format)(const struct ieee80211_sub_if_data *sdata, char *, int))
{ {
char buf[200]; char buf[200];
ssize_t ret = -EINVAL; ssize_t ret = -EINVAL;
read_lock(&dev_base_lock); wiphy_lock(sdata->local->hw.wiphy);
ret = (*format)(data, buf, sizeof(buf)); ret = (*format)(sdata, buf, sizeof(buf));
read_unlock(&dev_base_lock); wiphy_unlock(sdata->local->hw.wiphy);
if (ret >= 0) if (ret >= 0)
ret = simple_read_from_buffer(userbuf, count, ppos, buf, ret); ret = simple_read_from_buffer(userbuf, count, ppos, buf, ret);
@ -41,11 +41,11 @@ static ssize_t ieee80211_if_read(
return ret; return ret;
} }
static ssize_t ieee80211_if_write( static ssize_t ieee80211_if_write_sdata(
void *data, struct ieee80211_sub_if_data *sdata,
const char __user *userbuf, const char __user *userbuf,
size_t count, loff_t *ppos, size_t count, loff_t *ppos,
ssize_t (*write)(void *, const char *, int)) ssize_t (*write)(struct ieee80211_sub_if_data *sdata, const char *, int))
{ {
char buf[64]; char buf[64];
ssize_t ret; ssize_t ret;
@ -57,9 +57,51 @@ static ssize_t ieee80211_if_write(
return -EFAULT; return -EFAULT;
buf[count] = '\0'; buf[count] = '\0';
rtnl_lock(); wiphy_lock(sdata->local->hw.wiphy);
ret = (*write)(data, buf, count); ret = (*write)(sdata, buf, count);
rtnl_unlock(); wiphy_unlock(sdata->local->hw.wiphy);
return ret;
}
static ssize_t ieee80211_if_read_link(
struct ieee80211_link_data *link,
char __user *userbuf,
size_t count, loff_t *ppos,
ssize_t (*format)(const struct ieee80211_link_data *link, char *, int))
{
char buf[200];
ssize_t ret = -EINVAL;
wiphy_lock(link->sdata->local->hw.wiphy);
ret = (*format)(link, buf, sizeof(buf));
wiphy_unlock(link->sdata->local->hw.wiphy);
if (ret >= 0)
ret = simple_read_from_buffer(userbuf, count, ppos, buf, ret);
return ret;
}
static ssize_t ieee80211_if_write_link(
struct ieee80211_link_data *link,
const char __user *userbuf,
size_t count, loff_t *ppos,
ssize_t (*write)(struct ieee80211_link_data *link, const char *, int))
{
char buf[64];
ssize_t ret;
if (count >= sizeof(buf))
return -E2BIG;
if (copy_from_user(buf, userbuf, count))
return -EFAULT;
buf[count] = '\0';
wiphy_lock(link->sdata->local->hw.wiphy);
ret = (*write)(link, buf, count);
wiphy_unlock(link->sdata->local->hw.wiphy);
return ret; return ret;
} }
@ -126,41 +168,37 @@ static const struct file_operations name##_ops = { \
.llseek = generic_file_llseek, \ .llseek = generic_file_llseek, \
} }
#define _IEEE80211_IF_FILE_R_FN(name, type) \ #define _IEEE80211_IF_FILE_R_FN(name) \
static ssize_t ieee80211_if_read_##name(struct file *file, \ static ssize_t ieee80211_if_read_##name(struct file *file, \
char __user *userbuf, \ char __user *userbuf, \
size_t count, loff_t *ppos) \ size_t count, loff_t *ppos) \
{ \ { \
ssize_t (*fn)(const void *, char *, int) = (void *) \ return ieee80211_if_read_sdata(file->private_data, \
((ssize_t (*)(const type, char *, int)) \ userbuf, count, ppos, \
ieee80211_if_fmt_##name); \ ieee80211_if_fmt_##name); \
return ieee80211_if_read(file->private_data, \
userbuf, count, ppos, fn); \
} }
#define _IEEE80211_IF_FILE_W_FN(name, type) \ #define _IEEE80211_IF_FILE_W_FN(name) \
static ssize_t ieee80211_if_write_##name(struct file *file, \ static ssize_t ieee80211_if_write_##name(struct file *file, \
const char __user *userbuf, \ const char __user *userbuf, \
size_t count, loff_t *ppos) \ size_t count, loff_t *ppos) \
{ \ { \
ssize_t (*fn)(void *, const char *, int) = (void *) \ return ieee80211_if_write_sdata(file->private_data, userbuf, \
((ssize_t (*)(type, const char *, int)) \ count, ppos, \
ieee80211_if_parse_##name); \ ieee80211_if_parse_##name); \
return ieee80211_if_write(file->private_data, userbuf, count, \
ppos, fn); \
} }
#define IEEE80211_IF_FILE_R(name) \ #define IEEE80211_IF_FILE_R(name) \
_IEEE80211_IF_FILE_R_FN(name, struct ieee80211_sub_if_data *) \ _IEEE80211_IF_FILE_R_FN(name) \
_IEEE80211_IF_FILE_OPS(name, ieee80211_if_read_##name, NULL) _IEEE80211_IF_FILE_OPS(name, ieee80211_if_read_##name, NULL)
#define IEEE80211_IF_FILE_W(name) \ #define IEEE80211_IF_FILE_W(name) \
_IEEE80211_IF_FILE_W_FN(name, struct ieee80211_sub_if_data *) \ _IEEE80211_IF_FILE_W_FN(name) \
_IEEE80211_IF_FILE_OPS(name, NULL, ieee80211_if_write_##name) _IEEE80211_IF_FILE_OPS(name, NULL, ieee80211_if_write_##name)
#define IEEE80211_IF_FILE_RW(name) \ #define IEEE80211_IF_FILE_RW(name) \
_IEEE80211_IF_FILE_R_FN(name, struct ieee80211_sub_if_data *) \ _IEEE80211_IF_FILE_R_FN(name) \
_IEEE80211_IF_FILE_W_FN(name, struct ieee80211_sub_if_data *) \ _IEEE80211_IF_FILE_W_FN(name) \
_IEEE80211_IF_FILE_OPS(name, ieee80211_if_read_##name, \ _IEEE80211_IF_FILE_OPS(name, ieee80211_if_read_##name, \
ieee80211_if_write_##name) ieee80211_if_write_##name)
@ -168,18 +206,37 @@ static ssize_t ieee80211_if_write_##name(struct file *file, \
IEEE80211_IF_FMT_##format(name, struct ieee80211_sub_if_data, field) \ IEEE80211_IF_FMT_##format(name, struct ieee80211_sub_if_data, field) \
IEEE80211_IF_FILE_R(name) IEEE80211_IF_FILE_R(name)
/* Same but with a link_ prefix in the ops variable name and different type */ #define _IEEE80211_IF_LINK_R_FN(name) \
static ssize_t ieee80211_if_read_##name(struct file *file, \
char __user *userbuf, \
size_t count, loff_t *ppos) \
{ \
return ieee80211_if_read_link(file->private_data, \
userbuf, count, ppos, \
ieee80211_if_fmt_##name); \
}
#define _IEEE80211_IF_LINK_W_FN(name) \
static ssize_t ieee80211_if_write_##name(struct file *file, \
const char __user *userbuf, \
size_t count, loff_t *ppos) \
{ \
return ieee80211_if_write_link(file->private_data, userbuf, \
count, ppos, \
ieee80211_if_parse_##name); \
}
#define IEEE80211_IF_LINK_FILE_R(name) \ #define IEEE80211_IF_LINK_FILE_R(name) \
_IEEE80211_IF_FILE_R_FN(name, struct ieee80211_link_data *) \ _IEEE80211_IF_LINK_R_FN(name) \
_IEEE80211_IF_FILE_OPS(link_##name, ieee80211_if_read_##name, NULL) _IEEE80211_IF_FILE_OPS(link_##name, ieee80211_if_read_##name, NULL)
#define IEEE80211_IF_LINK_FILE_W(name) \ #define IEEE80211_IF_LINK_FILE_W(name) \
_IEEE80211_IF_FILE_W_FN(name) \ _IEEE80211_IF_LINK_W_FN(name) \
_IEEE80211_IF_FILE_OPS(link_##name, NULL, ieee80211_if_write_##name) _IEEE80211_IF_FILE_OPS(link_##name, NULL, ieee80211_if_write_##name)
#define IEEE80211_IF_LINK_FILE_RW(name) \ #define IEEE80211_IF_LINK_FILE_RW(name) \
_IEEE80211_IF_FILE_R_FN(name, struct ieee80211_link_data *) \ _IEEE80211_IF_LINK_R_FN(name) \
_IEEE80211_IF_FILE_W_FN(name, struct ieee80211_link_data *) \ _IEEE80211_IF_LINK_W_FN(name) \
_IEEE80211_IF_FILE_OPS(link_##name, ieee80211_if_read_##name, \ _IEEE80211_IF_FILE_OPS(link_##name, ieee80211_if_read_##name, \
ieee80211_if_write_##name) ieee80211_if_write_##name)