2019-07-22 12:43:34

by Denis Kenzior

[permalink] [raw]
Subject: [PATCH v4 1/3] nl80211: Update uapi for CMD_FRAME_WAIT_CANCEL

Commit 1c38c7f22068 ("nl80211: send event when CMD_FRAME duration
expires") added the possibility of NL80211_CMD_FRAME_WAIT_CANCEL
being sent whenever the off-channel wait time associated with a
CMD_FRAME completes. Document this in the uapi/linux/nl80211.h file.

Signed-off-by: Denis Kenzior <[email protected]>
---
include/uapi/linux/nl80211.h | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)

Changes in v4:
- None

Changes in v3:
- None

Changes in v2:
- update commit formatting
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 8fc3a43cac75..0d9aad98c983 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -657,7 +657,9 @@
* is used during CSA period.
* @NL80211_CMD_FRAME_WAIT_CANCEL: When an off-channel TX was requested, this
* command may be used with the corresponding cookie to cancel the wait
- * time if it is known that it is no longer necessary.
+ * time if it is known that it is no longer necessary. This command is
+ * also sent as an event whenever the driver has completed the off-channel
+ * wait time.
* @NL80211_CMD_ACTION: Alias for @NL80211_CMD_FRAME for backward compatibility.
* @NL80211_CMD_FRAME_TX_STATUS: Report TX status of a management frame
* transmitted with %NL80211_CMD_FRAME. %NL80211_ATTR_COOKIE identifies
--
2.21.0


2019-07-22 12:43:38

by Denis Kenzior

[permalink] [raw]
Subject: [PATCH v4 2/3] nl80211: Limit certain commands to interface owner

If the wdev object has been created (via NEW_INTERFACE) with
SOCKET_OWNER attribute set, then limit certain commands only to the
process that created that wdev.

This can be used to make sure no other process on the system interferes
by sending unwanted scans, action frames or any other funny business.

This patch introduces a new internal flag, and checks that flag in the
pre_doit hook.

Signed-off-by: Denis Kenzior <[email protected]>
---
net/wireless/nl80211.c | 78 ++++++++++++++++++++++++++++++++----------
1 file changed, 60 insertions(+), 18 deletions(-)

Changes in v4:
- Minor restructuring suggested by Arend

Changes in v3:
- Fix minor locking mistake reported by kernel test robot

Changes in v2:
- None
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index fc83dd179c1a..a075d86a52f6 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -13602,6 +13602,7 @@ static int nl80211_probe_mesh_link(struct sk_buff *skb, struct genl_info *info)
#define NL80211_FLAG_NEED_WDEV_UP (NL80211_FLAG_NEED_WDEV |\
NL80211_FLAG_CHECK_NETDEV_UP)
#define NL80211_FLAG_CLEAR_SKB 0x20
+#define NL80211_FLAG_OWNER_ONLY 0x40

static int nl80211_pre_doit(const struct genl_ops *ops, struct sk_buff *skb,
struct genl_info *info)
@@ -13610,6 +13611,7 @@ static int nl80211_pre_doit(const struct genl_ops *ops, struct sk_buff *skb,
struct wireless_dev *wdev;
struct net_device *dev;
bool rtnl = ops->internal_flags & NL80211_FLAG_NEED_RTNL;
+ int ret;

if (rtnl)
rtnl_lock();
@@ -13617,10 +13619,10 @@ static int nl80211_pre_doit(const struct genl_ops *ops, struct sk_buff *skb,
if (ops->internal_flags & NL80211_FLAG_NEED_WIPHY) {
rdev = cfg80211_get_dev_from_info(genl_info_net(info), info);
if (IS_ERR(rdev)) {
- if (rtnl)
- rtnl_unlock();
- return PTR_ERR(rdev);
+ ret = PTR_ERR(rdev);
+ goto fail;
}
+
info->user_ptr[0] = rdev;
} else if (ops->internal_flags & NL80211_FLAG_NEED_NETDEV ||
ops->internal_flags & NL80211_FLAG_NEED_WDEV) {
@@ -13629,32 +13631,33 @@ static int nl80211_pre_doit(const struct genl_ops *ops, struct sk_buff *skb,
wdev = __cfg80211_wdev_from_attrs(genl_info_net(info),
info->attrs);
if (IS_ERR(wdev)) {
- if (rtnl)
- rtnl_unlock();
- return PTR_ERR(wdev);
+ ret = PTR_ERR(wdev);
+ goto fail;
}

dev = wdev->netdev;
rdev = wiphy_to_rdev(wdev->wiphy);

+ ret = -EINVAL;
if (ops->internal_flags & NL80211_FLAG_NEED_NETDEV) {
- if (!dev) {
- if (rtnl)
- rtnl_unlock();
- return -EINVAL;
- }
+ if (!dev)
+ goto fail;

info->user_ptr[1] = dev;
} else {
info->user_ptr[1] = wdev;
}

+ ret = -ENETDOWN;
if (ops->internal_flags & NL80211_FLAG_CHECK_NETDEV_UP &&
- !wdev_running(wdev)) {
- if (rtnl)
- rtnl_unlock();
- return -ENETDOWN;
- }
+ !wdev_running(wdev))
+ goto fail;
+
+ ret = -EPERM;
+ if (ops->internal_flags & NL80211_FLAG_OWNER_ONLY &&
+ wdev->owner_nlportid &&
+ wdev->owner_nlportid != info->snd_portid)
+ goto fail;

if (dev)
dev_hold(dev);
@@ -13663,6 +13666,12 @@ static int nl80211_pre_doit(const struct genl_ops *ops, struct sk_buff *skb,
}

return 0;
+
+fail:
+ if (rtnl)
+ rtnl_unlock();
+
+ return ret;
}

static void nl80211_post_doit(const struct genl_ops *ops, struct sk_buff *skb,
@@ -13727,7 +13736,8 @@ static const struct genl_ops nl80211_ops[] = {
.doit = nl80211_set_interface,
.flags = GENL_UNS_ADMIN_PERM,
.internal_flags = NL80211_FLAG_NEED_NETDEV |
- NL80211_FLAG_NEED_RTNL,
+ NL80211_FLAG_NEED_RTNL |
+ NL80211_FLAG_OWNER_ONLY,
},
{
.cmd = NL80211_CMD_NEW_INTERFACE,
@@ -13743,7 +13753,8 @@ static const struct genl_ops nl80211_ops[] = {
.doit = nl80211_del_interface,
.flags = GENL_UNS_ADMIN_PERM,
.internal_flags = NL80211_FLAG_NEED_WDEV |
- NL80211_FLAG_NEED_RTNL,
+ NL80211_FLAG_NEED_RTNL |
+ NL80211_FLAG_OWNER_ONLY,
},
{
.cmd = NL80211_CMD_GET_KEY,
@@ -13760,6 +13771,7 @@ static const struct genl_ops nl80211_ops[] = {
.flags = GENL_UNS_ADMIN_PERM,
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
NL80211_FLAG_NEED_RTNL |
+ NL80211_FLAG_OWNER_ONLY |
NL80211_FLAG_CLEAR_SKB,
},
{
@@ -13769,6 +13781,7 @@ static const struct genl_ops nl80211_ops[] = {
.flags = GENL_UNS_ADMIN_PERM,
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
NL80211_FLAG_NEED_RTNL |
+ NL80211_FLAG_OWNER_ONLY |
NL80211_FLAG_CLEAR_SKB,
},
{
@@ -13777,6 +13790,7 @@ static const struct genl_ops nl80211_ops[] = {
.doit = nl80211_del_key,
.flags = GENL_UNS_ADMIN_PERM,
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
+ NL80211_FLAG_OWNER_ONLY |
NL80211_FLAG_NEED_RTNL,
},
{
@@ -13793,6 +13807,7 @@ static const struct genl_ops nl80211_ops[] = {
.flags = GENL_UNS_ADMIN_PERM,
.doit = nl80211_start_ap,
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
+ NL80211_FLAG_OWNER_ONLY |
NL80211_FLAG_NEED_RTNL,
},
{
@@ -13801,6 +13816,7 @@ static const struct genl_ops nl80211_ops[] = {
.flags = GENL_UNS_ADMIN_PERM,
.doit = nl80211_stop_ap,
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
+ NL80211_FLAG_OWNER_ONLY |
NL80211_FLAG_NEED_RTNL,
},
{
@@ -13817,6 +13833,7 @@ static const struct genl_ops nl80211_ops[] = {
.doit = nl80211_set_station,
.flags = GENL_UNS_ADMIN_PERM,
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
+ NL80211_FLAG_OWNER_ONLY |
NL80211_FLAG_NEED_RTNL,
},
{
@@ -13825,6 +13842,7 @@ static const struct genl_ops nl80211_ops[] = {
.doit = nl80211_new_station,
.flags = GENL_UNS_ADMIN_PERM,
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
+ NL80211_FLAG_OWNER_ONLY |
NL80211_FLAG_NEED_RTNL,
},
{
@@ -13833,6 +13851,7 @@ static const struct genl_ops nl80211_ops[] = {
.doit = nl80211_del_station,
.flags = GENL_UNS_ADMIN_PERM,
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
+ NL80211_FLAG_OWNER_ONLY |
NL80211_FLAG_NEED_RTNL,
},
{
@@ -13936,6 +13955,7 @@ static const struct genl_ops nl80211_ops[] = {
.doit = nl80211_trigger_scan,
.flags = GENL_UNS_ADMIN_PERM,
.internal_flags = NL80211_FLAG_NEED_WDEV_UP |
+ NL80211_FLAG_OWNER_ONLY |
NL80211_FLAG_NEED_RTNL,
},
{
@@ -13944,6 +13964,7 @@ static const struct genl_ops nl80211_ops[] = {
.doit = nl80211_abort_scan,
.flags = GENL_UNS_ADMIN_PERM,
.internal_flags = NL80211_FLAG_NEED_WDEV_UP |
+ NL80211_FLAG_OWNER_ONLY |
NL80211_FLAG_NEED_RTNL,
},
{
@@ -13957,6 +13978,7 @@ static const struct genl_ops nl80211_ops[] = {
.doit = nl80211_start_sched_scan,
.flags = GENL_UNS_ADMIN_PERM,
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
+ NL80211_FLAG_OWNER_ONLY |
NL80211_FLAG_NEED_RTNL,
},
{
@@ -13965,6 +13987,7 @@ static const struct genl_ops nl80211_ops[] = {
.doit = nl80211_stop_sched_scan,
.flags = GENL_UNS_ADMIN_PERM,
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
+ NL80211_FLAG_OWNER_ONLY |
NL80211_FLAG_NEED_RTNL,
},
{
@@ -13973,6 +13996,7 @@ static const struct genl_ops nl80211_ops[] = {
.doit = nl80211_authenticate,
.flags = GENL_UNS_ADMIN_PERM,
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
+ NL80211_FLAG_OWNER_ONLY |
NL80211_FLAG_NEED_RTNL |
NL80211_FLAG_CLEAR_SKB,
},
@@ -13982,6 +14006,7 @@ static const struct genl_ops nl80211_ops[] = {
.doit = nl80211_associate,
.flags = GENL_UNS_ADMIN_PERM,
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
+ NL80211_FLAG_OWNER_ONLY |
NL80211_FLAG_NEED_RTNL |
NL80211_FLAG_CLEAR_SKB,
},
@@ -13991,6 +14016,7 @@ static const struct genl_ops nl80211_ops[] = {
.doit = nl80211_deauthenticate,
.flags = GENL_UNS_ADMIN_PERM,
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
+ NL80211_FLAG_OWNER_ONLY |
NL80211_FLAG_NEED_RTNL,
},
{
@@ -13999,6 +14025,7 @@ static const struct genl_ops nl80211_ops[] = {
.doit = nl80211_disassociate,
.flags = GENL_UNS_ADMIN_PERM,
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
+ NL80211_FLAG_OWNER_ONLY |
NL80211_FLAG_NEED_RTNL,
},
{
@@ -14007,6 +14034,7 @@ static const struct genl_ops nl80211_ops[] = {
.doit = nl80211_join_ibss,
.flags = GENL_UNS_ADMIN_PERM,
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
+ NL80211_FLAG_OWNER_ONLY |
NL80211_FLAG_NEED_RTNL,
},
{
@@ -14015,6 +14043,7 @@ static const struct genl_ops nl80211_ops[] = {
.doit = nl80211_leave_ibss,
.flags = GENL_UNS_ADMIN_PERM,
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
+ NL80211_FLAG_OWNER_ONLY |
NL80211_FLAG_NEED_RTNL,
},
#ifdef CONFIG_NL80211_TESTMODE
@@ -14034,6 +14063,7 @@ static const struct genl_ops nl80211_ops[] = {
.doit = nl80211_connect,
.flags = GENL_UNS_ADMIN_PERM,
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
+ NL80211_FLAG_OWNER_ONLY |
NL80211_FLAG_NEED_RTNL |
NL80211_FLAG_CLEAR_SKB,
},
@@ -14043,6 +14073,7 @@ static const struct genl_ops nl80211_ops[] = {
.doit = nl80211_update_connect_params,
.flags = GENL_ADMIN_PERM,
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
+ NL80211_FLAG_OWNER_ONLY |
NL80211_FLAG_NEED_RTNL |
NL80211_FLAG_CLEAR_SKB,
},
@@ -14052,6 +14083,7 @@ static const struct genl_ops nl80211_ops[] = {
.doit = nl80211_disconnect,
.flags = GENL_UNS_ADMIN_PERM,
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
+ NL80211_FLAG_OWNER_ONLY |
NL80211_FLAG_NEED_RTNL,
},
{
@@ -14098,6 +14130,7 @@ static const struct genl_ops nl80211_ops[] = {
.doit = nl80211_remain_on_channel,
.flags = GENL_UNS_ADMIN_PERM,
.internal_flags = NL80211_FLAG_NEED_WDEV_UP |
+ NL80211_FLAG_OWNER_ONLY |
NL80211_FLAG_NEED_RTNL,
},
{
@@ -14106,6 +14139,7 @@ static const struct genl_ops nl80211_ops[] = {
.doit = nl80211_cancel_remain_on_channel,
.flags = GENL_UNS_ADMIN_PERM,
.internal_flags = NL80211_FLAG_NEED_WDEV_UP |
+ NL80211_FLAG_OWNER_ONLY |
NL80211_FLAG_NEED_RTNL,
},
{
@@ -14130,6 +14164,7 @@ static const struct genl_ops nl80211_ops[] = {
.doit = nl80211_tx_mgmt,
.flags = GENL_UNS_ADMIN_PERM,
.internal_flags = NL80211_FLAG_NEED_WDEV_UP |
+ NL80211_FLAG_OWNER_ONLY |
NL80211_FLAG_NEED_RTNL,
},
{
@@ -14138,6 +14173,7 @@ static const struct genl_ops nl80211_ops[] = {
.doit = nl80211_tx_mgmt_cancel_wait,
.flags = GENL_UNS_ADMIN_PERM,
.internal_flags = NL80211_FLAG_NEED_WDEV_UP |
+ NL80211_FLAG_OWNER_ONLY |
NL80211_FLAG_NEED_RTNL,
},
{
@@ -14162,6 +14198,7 @@ static const struct genl_ops nl80211_ops[] = {
.doit = nl80211_set_cqm,
.flags = GENL_UNS_ADMIN_PERM,
.internal_flags = NL80211_FLAG_NEED_NETDEV |
+ NL80211_FLAG_OWNER_ONLY |
NL80211_FLAG_NEED_RTNL,
},
{
@@ -14236,6 +14273,7 @@ static const struct genl_ops nl80211_ops[] = {
.doit = nl80211_set_rekey_data,
.flags = GENL_UNS_ADMIN_PERM,
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
+ NL80211_FLAG_OWNER_ONLY |
NL80211_FLAG_NEED_RTNL |
NL80211_FLAG_CLEAR_SKB,
},
@@ -14293,6 +14331,7 @@ static const struct genl_ops nl80211_ops[] = {
.doit = nl80211_start_p2p_device,
.flags = GENL_UNS_ADMIN_PERM,
.internal_flags = NL80211_FLAG_NEED_WDEV |
+ NL80211_FLAG_OWNER_ONLY |
NL80211_FLAG_NEED_RTNL,
},
{
@@ -14301,6 +14340,7 @@ static const struct genl_ops nl80211_ops[] = {
.doit = nl80211_stop_p2p_device,
.flags = GENL_UNS_ADMIN_PERM,
.internal_flags = NL80211_FLAG_NEED_WDEV_UP |
+ NL80211_FLAG_OWNER_ONLY |
NL80211_FLAG_NEED_RTNL,
},
{
@@ -14386,6 +14426,7 @@ static const struct genl_ops nl80211_ops[] = {
.doit = nl80211_crit_protocol_start,
.flags = GENL_UNS_ADMIN_PERM,
.internal_flags = NL80211_FLAG_NEED_WDEV_UP |
+ NL80211_FLAG_OWNER_ONLY |
NL80211_FLAG_NEED_RTNL,
},
{
@@ -14394,6 +14435,7 @@ static const struct genl_ops nl80211_ops[] = {
.doit = nl80211_crit_protocol_stop,
.flags = GENL_UNS_ADMIN_PERM,
.internal_flags = NL80211_FLAG_NEED_WDEV_UP |
+ NL80211_FLAG_OWNER_ONLY |
NL80211_FLAG_NEED_RTNL,
},
{
--
2.21.0

2019-07-22 12:44:12

by Denis Kenzior

[permalink] [raw]
Subject: [PATCH v4 3/3] nl80211: Include wiphy address setup in NEW_WIPHY

Include wiphy address setup in wiphy dumps and new wiphy events. The
wiphy permanent address is exposed as ATTR_MAC. If addr_mask is setup,
then it is included as ATTR_MAC_MASK attribute. If multiple addresses
are available, then their are exposed in a nested ATTR_MAC_ADDRS array.

This information is already exposed via sysfs, but it makes sense to
include it in the wiphy dump as well.

Signed-off-by: Denis Kenzior <[email protected]>
---
net/wireless/nl80211.c | 25 +++++++++++++++++++++++++
1 file changed, 25 insertions(+)

Changes in v4:
- None

Changes in v3:
- None

Changes in v2:
- Move from case 0 to 9
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index a075d86a52f6..3fc4a9006155 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -2172,6 +2172,31 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev,
rdev->wiphy.vht_capa_mod_mask))
goto nla_put_failure;

+ if (nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN,
+ rdev->wiphy.perm_addr))
+ goto nla_put_failure;
+
+ if (!is_zero_ether_addr(rdev->wiphy.addr_mask) &&
+ nla_put(msg, NL80211_ATTR_MAC_MASK, ETH_ALEN,
+ rdev->wiphy.addr_mask))
+ goto nla_put_failure;
+
+ if (rdev->wiphy.n_addresses > 1) {
+ void *attr;
+
+ attr = nla_nest_start_noflag(msg,
+ NL80211_ATTR_MAC_ADDRS);
+ if (!attr)
+ goto nla_put_failure;
+
+ for (i = 0; i < rdev->wiphy.n_addresses; i++)
+ if (nla_put(msg, i + 1, ETH_ALEN,
+ rdev->wiphy.addresses[i].addr))
+ goto nla_put_failure;
+
+ nla_nest_end(msg, attr);
+ }
+
state->split_start++;
break;
case 10:
--
2.21.0

2019-07-29 16:30:57

by Johannes Berg

[permalink] [raw]
Subject: Re: [PATCH v4 2/3] nl80211: Limit certain commands to interface owner

Hi,

> I noticed that the other patches in this series got applied. Was this
> one left out on purpose?

Yeah, I left out a few that I wanted to review more carefully.

I'll get to it this week (because I'm on vacation after that).

johannes

2019-07-29 16:34:41

by Denis Kenzior

[permalink] [raw]
Subject: Re: [PATCH v4 2/3] nl80211: Limit certain commands to interface owner

Hi Johannes,

On 7/22/19 6:33 AM, Denis Kenzior wrote:
> If the wdev object has been created (via NEW_INTERFACE) with
> SOCKET_OWNER attribute set, then limit certain commands only to the
> process that created that wdev.
>
> This can be used to make sure no other process on the system interferes
> by sending unwanted scans, action frames or any other funny business.
>
> This patch introduces a new internal flag, and checks that flag in the
> pre_doit hook.
>
> Signed-off-by: Denis Kenzior <[email protected]>
> ---
> net/wireless/nl80211.c | 78 ++++++++++++++++++++++++++++++++----------
> 1 file changed, 60 insertions(+), 18 deletions(-)
>
> Changes in v4:
> - Minor restructuring suggested by Arend
>
> Changes in v3:
> - Fix minor locking mistake reported by kernel test robot
>
> Changes in v2:
> - None

I noticed that the other patches in this series got applied. Was this
one left out on purpose?

Regards,
-Denis