nl80211: fix radio statistics in survey dump
[ Upstream commit ce6b69749961426c6d822215ded9e67154e1ad4f ] 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: 50508d941c18 ("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> Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
parent
85f4a563c9
commit
1d17f61791
@ -922,33 +922,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);
|
||||
@ -6001,7 +6005,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 */
|
||||
@ -6896,7 +6900,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 */
|
||||
@ -7096,7 +7100,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 */
|
||||
@ -9518,7 +9522,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 */
|
||||
@ -9651,7 +9655,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…
x
Reference in New Issue
Block a user