[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250910230841.384545-8-ast@fiberby.net>
Date: Wed, 10 Sep 2025 23:08:29 +0000
From: Asbjørn Sloth Tønnesen <ast@...erby.net>
To: "Jason A. Donenfeld" <Jason@...c4.com>,
"David S. Miller" <davem@...emloft.net>,
Eric Dumazet <edumazet@...gle.com>,
Jakub Kicinski <kuba@...nel.org>,
Paolo Abeni <pabeni@...hat.com>
Cc: Asbjørn Sloth Tønnesen <ast@...erby.net>,
Donald Hunter <donald.hunter@...il.com>,
Simon Horman <horms@...nel.org>,
Jacob Keller <jacob.e.keller@...el.com>,
Andrew Lunn <andrew+netdev@...n.ch>,
Sabrina Dubroca <sd@...asysnail.net>,
wireguard@...ts.zx2c4.com,
netdev@...r.kernel.org,
linux-kernel@...r.kernel.org
Subject: [PATCH net-next v2 07/12] tools: ynl-gen: only validate nested array payload
In nested arrays don't require that the intermediate attribute
type should be a valid attribute type, it might just be zero
or an incrementing index, it is often not even used.
See include/net/netlink.h about NLA_NESTED_ARRAY:
> The difference to NLA_NESTED is the structure:
> NLA_NESTED has the nested attributes directly inside
> while an array has the nested attributes at another
> level down and the attribute types directly in the
> nesting don't matter.
Example based on include/uapi/linux/wireguard.h:
> WGDEVICE_A_PEERS: NLA_NESTED
> 0: NLA_NESTED
> WGPEER_A_PUBLIC_KEY: NLA_EXACT_LEN, len WG_KEY_LEN
> [..]
> 0: NLA_NESTED
> ...
> ...
Previous the check required that the nested type was valid in
the parent attribute set, which in this case resolves to
WGDEVICE_A_UNSPEC, which is YNL_PT_REJECT, and it took the
early exit and returned YNL_PARSE_CB_ERROR.
This patch adds a new helper, ynl_attr_validate_payload(),
which we can use to validate the payload of the nested
attribute, in the context of the parents attribute type,
and it's policy, which in the above case is generated as:
[WGDEVICE_A_PEERS] = {
.name = "peers",
.type = YNL_PT_NEST,
.nest = &wireguard_wgpeer_nest,
},
Some other examples are NL80211_BAND_ATTR_FREQS (nest) and
NL80211_ATTR_SUPPORTED_COMMANDS (u32).
Signed-off-by: Asbjørn Sloth Tønnesen <ast@...erby.net>
---
tools/net/ynl/lib/ynl-priv.h | 2 ++
tools/net/ynl/lib/ynl.c | 17 ++++++++++++++---
tools/net/ynl/pyynl/ynl_gen_c.py | 2 +-
3 files changed, 17 insertions(+), 4 deletions(-)
diff --git a/tools/net/ynl/lib/ynl-priv.h b/tools/net/ynl/lib/ynl-priv.h
index 824777d7e05e..70ea14c0a0e9 100644
--- a/tools/net/ynl/lib/ynl-priv.h
+++ b/tools/net/ynl/lib/ynl-priv.h
@@ -107,6 +107,8 @@ struct nlmsghdr *
ynl_gemsg_start_dump(struct ynl_sock *ys, __u32 id, __u8 cmd, __u8 version);
int ynl_attr_validate(struct ynl_parse_arg *yarg, const struct nlattr *attr);
+int ynl_attr_validate_payload(struct ynl_parse_arg *yarg,
+ const struct nlattr *attr, unsigned int type);
int ynl_submsg_failed(struct ynl_parse_arg *yarg, const char *field_name,
const char *sel_name);
diff --git a/tools/net/ynl/lib/ynl.c b/tools/net/ynl/lib/ynl.c
index 2a169c3c0797..d52aa188401f 100644
--- a/tools/net/ynl/lib/ynl.c
+++ b/tools/net/ynl/lib/ynl.c
@@ -360,15 +360,15 @@ static int ynl_cb_done(const struct nlmsghdr *nlh, struct ynl_parse_arg *yarg)
/* Attribute validation */
-int ynl_attr_validate(struct ynl_parse_arg *yarg, const struct nlattr *attr)
+int __ynl_attr_validate(struct ynl_parse_arg *yarg, const struct nlattr *attr,
+ unsigned int type)
{
const struct ynl_policy_attr *policy;
- unsigned int type, len;
unsigned char *data;
+ unsigned int len;
data = ynl_attr_data(attr);
len = ynl_attr_data_len(attr);
- type = ynl_attr_type(attr);
if (type > yarg->rsp_policy->max_attr) {
yerr(yarg->ys, YNL_ERROR_INTERNAL,
"Internal error, validating unknown attribute");
@@ -450,6 +450,17 @@ int ynl_attr_validate(struct ynl_parse_arg *yarg, const struct nlattr *attr)
return 0;
}
+int ynl_attr_validate(struct ynl_parse_arg *yarg, const struct nlattr *attr)
+{
+ return __ynl_attr_validate(yarg, attr, ynl_attr_type(attr));
+}
+
+int ynl_attr_validate_payload(struct ynl_parse_arg *yarg,
+ const struct nlattr *attr, unsigned int type)
+{
+ return __ynl_attr_validate(yarg, attr, type);
+}
+
int ynl_submsg_failed(struct ynl_parse_arg *yarg, const char *field_name,
const char *sel_name)
{
diff --git a/tools/net/ynl/pyynl/ynl_gen_c.py b/tools/net/ynl/pyynl/ynl_gen_c.py
index f149c68ae84e..e93f5d724b42 100755
--- a/tools/net/ynl/pyynl/ynl_gen_c.py
+++ b/tools/net/ynl/pyynl/ynl_gen_c.py
@@ -836,7 +836,7 @@ class TypeArrayNest(Type):
local_vars = ['const struct nlattr *attr2;']
get_lines = [f'attr_{self.c_name} = attr;',
'ynl_attr_for_each_nested(attr2, attr) {',
- '\tif (ynl_attr_validate(yarg, attr2))',
+ '\tif (ynl_attr_validate_payload(yarg, attr2, type))',
'\t\treturn YNL_PARSE_CB_ERROR;',
f'\tn_{self.c_name}++;',
'}']
--
2.51.0
Powered by blists - more mailing lists