nl80211: fix radio statistics in survey dump
Even if userspace specifies the NL80211_ATTR_SURVEY_RADIO_STATS
attribute, we cannot get the statistics because we're not really
parsing the incoming attributes properly any more.
Fix this by passing the attrbuf to nl80211_prepare_wdev_dump()
and filling it there, if given, and using a local version only
if no output is desired.
Since I'm touching it anyway, make nl80211_prepare_wdev_dump()
static.
Fixes: 50508d941c
("cfg80211: use parallel_ops for genl")
Reported-by: Jan Fuchs <jf@simonwunderlich.de>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Tested-by: Sven Eckelmann <sven@narfation.org>
Link: https://lore.kernel.org/r/20211029092539.2851b4799386.If9736d4575ee79420cbec1bd930181e1d53c7317@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
parent
563fbefed4
commit
ce6b697499
|
@ -936,33 +936,37 @@ nl80211_packet_pattern_policy[MAX_NL80211_PKTPAT + 1] = {
|
|||
[NL80211_PKTPAT_OFFSET] = { .type = NLA_U32 },
|
||||
};
|
||||
|
||||
int nl80211_prepare_wdev_dump(struct netlink_callback *cb,
|
||||
struct cfg80211_registered_device **rdev,
|
||||
struct wireless_dev **wdev)
|
||||
static int nl80211_prepare_wdev_dump(struct netlink_callback *cb,
|
||||
struct cfg80211_registered_device **rdev,
|
||||
struct wireless_dev **wdev,
|
||||
struct nlattr **attrbuf)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (!cb->args[0]) {
|
||||
struct nlattr **attrbuf;
|
||||
struct nlattr **attrbuf_free = NULL;
|
||||
|
||||
attrbuf = kcalloc(NUM_NL80211_ATTR, sizeof(*attrbuf),
|
||||
GFP_KERNEL);
|
||||
if (!attrbuf)
|
||||
return -ENOMEM;
|
||||
if (!attrbuf) {
|
||||
attrbuf = kcalloc(NUM_NL80211_ATTR, sizeof(*attrbuf),
|
||||
GFP_KERNEL);
|
||||
if (!attrbuf)
|
||||
return -ENOMEM;
|
||||
attrbuf_free = attrbuf;
|
||||
}
|
||||
|
||||
err = nlmsg_parse_deprecated(cb->nlh,
|
||||
GENL_HDRLEN + nl80211_fam.hdrsize,
|
||||
attrbuf, nl80211_fam.maxattr,
|
||||
nl80211_policy, NULL);
|
||||
if (err) {
|
||||
kfree(attrbuf);
|
||||
kfree(attrbuf_free);
|
||||
return err;
|
||||
}
|
||||
|
||||
rtnl_lock();
|
||||
*wdev = __cfg80211_wdev_from_attrs(NULL, sock_net(cb->skb->sk),
|
||||
attrbuf);
|
||||
kfree(attrbuf);
|
||||
kfree(attrbuf_free);
|
||||
if (IS_ERR(*wdev)) {
|
||||
rtnl_unlock();
|
||||
return PTR_ERR(*wdev);
|
||||
|
@ -6197,7 +6201,7 @@ static int nl80211_dump_station(struct sk_buff *skb,
|
|||
int sta_idx = cb->args[2];
|
||||
int err;
|
||||
|
||||
err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev);
|
||||
err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev, NULL);
|
||||
if (err)
|
||||
return err;
|
||||
/* nl80211_prepare_wdev_dump acquired it in the successful case */
|
||||
|
@ -7092,7 +7096,7 @@ static int nl80211_dump_mpath(struct sk_buff *skb,
|
|||
int path_idx = cb->args[2];
|
||||
int err;
|
||||
|
||||
err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev);
|
||||
err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev, NULL);
|
||||
if (err)
|
||||
return err;
|
||||
/* nl80211_prepare_wdev_dump acquired it in the successful case */
|
||||
|
@ -7292,7 +7296,7 @@ static int nl80211_dump_mpp(struct sk_buff *skb,
|
|||
int path_idx = cb->args[2];
|
||||
int err;
|
||||
|
||||
err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev);
|
||||
err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev, NULL);
|
||||
if (err)
|
||||
return err;
|
||||
/* nl80211_prepare_wdev_dump acquired it in the successful case */
|
||||
|
@ -9718,7 +9722,7 @@ static int nl80211_dump_scan(struct sk_buff *skb, struct netlink_callback *cb)
|
|||
int start = cb->args[2], idx = 0;
|
||||
int err;
|
||||
|
||||
err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev);
|
||||
err = nl80211_prepare_wdev_dump(cb, &rdev, &wdev, NULL);
|
||||
if (err)
|
||||
return err;
|
||||
/* nl80211_prepare_wdev_dump acquired it in the successful case */
|
||||
|
@ -9851,7 +9855,7 @@ static int nl80211_dump_survey(struct sk_buff *skb, struct netlink_callback *cb)
|
|||
if (!attrbuf)
|
||||
return -ENOMEM;
|
||||
|
||||
res = nl80211_prepare_wdev_dump(cb, &rdev, &wdev);
|
||||
res = nl80211_prepare_wdev_dump(cb, &rdev, &wdev, attrbuf);
|
||||
if (res) {
|
||||
kfree(attrbuf);
|
||||
return res;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Portions of this file
|
||||
* Copyright (C) 2018, 2020 Intel Corporation
|
||||
* Copyright (C) 2018, 2020-2021 Intel Corporation
|
||||
*/
|
||||
#ifndef __NET_WIRELESS_NL80211_H
|
||||
#define __NET_WIRELESS_NL80211_H
|
||||
|
@ -22,10 +22,6 @@ static inline u64 wdev_id(struct wireless_dev *wdev)
|
|||
((u64)wiphy_to_rdev(wdev->wiphy)->wiphy_idx << 32);
|
||||
}
|
||||
|
||||
int nl80211_prepare_wdev_dump(struct netlink_callback *cb,
|
||||
struct cfg80211_registered_device **rdev,
|
||||
struct wireless_dev **wdev);
|
||||
|
||||
int nl80211_parse_chandef(struct cfg80211_registered_device *rdev,
|
||||
struct genl_info *info,
|
||||
struct cfg80211_chan_def *chandef);
|
||||
|
|
Loading…
Reference in New Issue