diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index ba439664c2e0..4d708cea390f 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -47,22 +47,21 @@ static struct genl_family nl80211_fam = { }; /* internal helper: get rdev and dev */ -static int get_rdev_dev_by_info_ifindex(struct genl_info *info, - struct cfg80211_registered_device **rdev, - struct net_device **dev) +static int get_rdev_dev_by_ifindex(struct net *netns, struct nlattr **attrs, + struct cfg80211_registered_device **rdev, + struct net_device **dev) { - struct nlattr **attrs = info->attrs; int ifindex; if (!attrs[NL80211_ATTR_IFINDEX]) return -EINVAL; ifindex = nla_get_u32(attrs[NL80211_ATTR_IFINDEX]); - *dev = dev_get_by_index(genl_info_net(info), ifindex); + *dev = dev_get_by_index(netns, ifindex); if (!*dev) return -ENODEV; - *rdev = cfg80211_get_dev_from_ifindex(genl_info_net(info), ifindex); + *rdev = cfg80211_get_dev_from_ifindex(netns, ifindex); if (IS_ERR(*rdev)) { dev_put(*dev); return PTR_ERR(*rdev); @@ -4795,7 +4794,7 @@ static int nl80211_testmode_do(struct sk_buff *skb, struct genl_info *info) static int nl80211_testmode_dump(struct sk_buff *skb, struct netlink_callback *cb) { - struct cfg80211_registered_device *dev; + struct cfg80211_registered_device *rdev; int err; long phy_idx; void *data = NULL; @@ -4813,9 +4812,21 @@ static int nl80211_testmode_dump(struct sk_buff *skb, nl80211_policy); if (err) return err; - if (!nl80211_fam.attrbuf[NL80211_ATTR_WIPHY]) - return -EINVAL; - phy_idx = nla_get_u32(nl80211_fam.attrbuf[NL80211_ATTR_WIPHY]); + if (nl80211_fam.attrbuf[NL80211_ATTR_WIPHY]) { + phy_idx = nla_get_u32( + nl80211_fam.attrbuf[NL80211_ATTR_WIPHY]); + } else { + struct net_device *netdev; + + err = get_rdev_dev_by_ifindex(sock_net(skb->sk), + nl80211_fam.attrbuf, + &rdev, &netdev); + if (err) + return err; + dev_put(netdev); + phy_idx = rdev->wiphy_idx; + cfg80211_unlock_rdev(rdev); + } if (nl80211_fam.attrbuf[NL80211_ATTR_TESTDATA]) cb->args[1] = (long)nl80211_fam.attrbuf[NL80211_ATTR_TESTDATA]; @@ -4827,15 +4838,15 @@ static int nl80211_testmode_dump(struct sk_buff *skb, } mutex_lock(&cfg80211_mutex); - dev = cfg80211_rdev_by_wiphy_idx(phy_idx); - if (!dev) { + rdev = cfg80211_rdev_by_wiphy_idx(phy_idx); + if (!rdev) { mutex_unlock(&cfg80211_mutex); return -ENOENT; } - cfg80211_lock_rdev(dev); + cfg80211_lock_rdev(rdev); mutex_unlock(&cfg80211_mutex); - if (!dev->ops->testmode_dump) { + if (!rdev->ops->testmode_dump) { err = -EOPNOTSUPP; goto out_err; } @@ -4846,7 +4857,7 @@ static int nl80211_testmode_dump(struct sk_buff *skb, NL80211_CMD_TESTMODE); struct nlattr *tmdata; - if (nla_put_u32(skb, NL80211_ATTR_WIPHY, dev->wiphy_idx) < 0) { + if (nla_put_u32(skb, NL80211_ATTR_WIPHY, phy_idx) < 0) { genlmsg_cancel(skb, hdr); break; } @@ -4856,8 +4867,8 @@ static int nl80211_testmode_dump(struct sk_buff *skb, genlmsg_cancel(skb, hdr); break; } - err = dev->ops->testmode_dump(&dev->wiphy, skb, cb, - data, data_len); + err = rdev->ops->testmode_dump(&rdev->wiphy, skb, cb, + data, data_len); nla_nest_end(skb, tmdata); if (err == -ENOBUFS || err == -ENOENT) { @@ -4875,7 +4886,7 @@ static int nl80211_testmode_dump(struct sk_buff *skb, /* see above */ cb->args[0] = phy_idx + 1; out_err: - cfg80211_unlock_rdev(dev); + cfg80211_unlock_rdev(rdev); return err; } @@ -6110,7 +6121,8 @@ static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb, } info->user_ptr[0] = rdev; } else if (ops->internal_flags & NL80211_FLAG_NEED_NETDEV) { - err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev); + err = get_rdev_dev_by_ifindex(genl_info_net(info), info->attrs, + &rdev, &dev); if (err) { if (rtnl) rtnl_unlock();