summaryrefslogtreecommitdiffstats
path: root/net/ethtool/netlink.c
diff options
context:
space:
mode:
authorJakub Kicinski <kuba@kernel.org>2020-10-05 15:07:39 -0700
committerDavid S. Miller <davem@davemloft.net>2020-10-06 06:25:55 -0700
commita0de1cd3568749d3410c89b1c8bb70e90d61659f (patch)
tree09c011ae2e2e53713b8d3ee0e531fdfa4dbf29bd /net/ethtool/netlink.c
parentbdbb4e29df8b790db50cb73ce25d23543329f05f (diff)
downloadlinux-a0de1cd3568749d3410c89b1c8bb70e90d61659f.tar.gz
linux-a0de1cd3568749d3410c89b1c8bb70e90d61659f.tar.bz2
linux-a0de1cd3568749d3410c89b1c8bb70e90d61659f.zip
ethtool: specify which header flags are supported per command
Perform header flags validation through the policy. Only pause command supports ETHTOOL_FLAG_STATS. Create a separate policy to be able to express that in policy dumps to user space. Note that even though the core will validate the header policy, it cannot record multiple layers of attributes and we have to re-parse header sub-attrs. When doing so we could skip attribute validation, or use most permissive policy. Opt for the former. We will no longer return the extack cookie for flags but since we only added first new flag in this release it's not expected that any user space had a chance to make use of it. v2: - remove the re-validation in ethnl_parse_header_dev_get() Signed-off-by: Jakub Kicinski <kuba@kernel.org> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ethtool/netlink.c')
-rw-r--r--net/ethtool/netlink.c29
1 files changed, 19 insertions, 10 deletions
diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c
index 10567e6ec034..8a85a4e6be9b 100644
--- a/net/ethtool/netlink.c
+++ b/net/ethtool/netlink.c
@@ -9,11 +9,24 @@ static struct genl_family ethtool_genl_family;
static bool ethnl_ok __read_mostly;
static u32 ethnl_bcast_seq;
+#define ETHTOOL_FLAGS_BASIC (ETHTOOL_FLAG_COMPACT_BITSETS | \
+ ETHTOOL_FLAG_OMIT_REPLY)
+#define ETHTOOL_FLAGS_STATS (ETHTOOL_FLAGS_BASIC | ETHTOOL_FLAG_STATS)
+
const struct nla_policy ethnl_header_policy[] = {
[ETHTOOL_A_HEADER_DEV_INDEX] = { .type = NLA_U32 },
[ETHTOOL_A_HEADER_DEV_NAME] = { .type = NLA_NUL_STRING,
.len = ALTIFNAMSIZ - 1 },
- [ETHTOOL_A_HEADER_FLAGS] = { .type = NLA_U32 },
+ [ETHTOOL_A_HEADER_FLAGS] = NLA_POLICY_MASK(NLA_U32,
+ ETHTOOL_FLAGS_BASIC),
+};
+
+const struct nla_policy ethnl_header_policy_stats[] = {
+ [ETHTOOL_A_HEADER_DEV_INDEX] = { .type = NLA_U32 },
+ [ETHTOOL_A_HEADER_DEV_NAME] = { .type = NLA_NUL_STRING,
+ .len = ALTIFNAMSIZ - 1 },
+ [ETHTOOL_A_HEADER_FLAGS] = NLA_POLICY_MASK(NLA_U32,
+ ETHTOOL_FLAGS_STATS),
};
/**
@@ -46,19 +59,15 @@ int ethnl_parse_header_dev_get(struct ethnl_req_info *req_info,
NL_SET_ERR_MSG(extack, "request header missing");
return -EINVAL;
}
+ /* No validation here, command policy should have a nested policy set
+ * for the header, therefore validation should have already been done.
+ */
ret = nla_parse_nested(tb, ARRAY_SIZE(ethnl_header_policy) - 1, header,
- ethnl_header_policy, extack);
+ NULL, extack);
if (ret < 0)
return ret;
- if (tb[ETHTOOL_A_HEADER_FLAGS]) {
+ if (tb[ETHTOOL_A_HEADER_FLAGS])
flags = nla_get_u32(tb[ETHTOOL_A_HEADER_FLAGS]);
- if (flags & ~ETHTOOL_FLAG_ALL) {
- NL_SET_ERR_MSG_ATTR(extack, tb[ETHTOOL_A_HEADER_FLAGS],
- "unrecognized request flags");
- nl_set_extack_cookie_u32(extack, ETHTOOL_FLAG_ALL);
- return -EOPNOTSUPP;
- }
- }
devname_attr = tb[ETHTOOL_A_HEADER_DEV_NAME];
if (tb[ETHTOOL_A_HEADER_DEV_INDEX]) {