summaryrefslogtreecommitdiff
path: root/net/netlink/genetlink.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2019-04-26 14:07:31 +0200
committerDavid S. Miller <davem@davemloft.net>2019-04-27 17:07:22 -0400
commitef6243acb4782df587a4d7d6c310fa5b5d82684b (patch)
tree81b4175fc03c61adbb8935f5f7b8ce02589c65dd /net/netlink/genetlink.c
parent56738f460841761abc70347c919d5c45f6f05a42 (diff)
downloadlwn-ef6243acb4782df587a4d7d6c310fa5b5d82684b.tar.gz
lwn-ef6243acb4782df587a4d7d6c310fa5b5d82684b.zip
genetlink: optionally validate strictly/dumps
Add options to strictly validate messages and dump messages, sometimes perhaps validating dump messages non-strictly may be required, so add an option for that as well. Since none of this can really be applied to existing commands, set the options everwhere using the following spatch: @@ identifier ops; expression X; @@ struct genl_ops ops[] = { ..., { .cmd = X, + .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, ... }, ... }; For new commands one should just not copy the .validate 'opt-out' flags and thus get strict validation. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/netlink/genetlink.c')
-rw-r--r--net/netlink/genetlink.c29
1 files changed, 26 insertions, 3 deletions
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c
index 994d9aff2093..72668759cd2b 100644
--- a/net/netlink/genetlink.c
+++ b/net/netlink/genetlink.c
@@ -536,6 +536,24 @@ static int genl_family_rcv_msg(const struct genl_family *family,
if (ops->dumpit == NULL)
return -EOPNOTSUPP;
+ if (!(ops->validate & GENL_DONT_VALIDATE_DUMP)) {
+ unsigned int validate = NL_VALIDATE_STRICT;
+ int hdrlen = GENL_HDRLEN + family->hdrsize;
+
+ if (ops->validate & GENL_DONT_VALIDATE_DUMP_STRICT)
+ validate = NL_VALIDATE_LIBERAL;
+
+ if (nlh->nlmsg_len < nlmsg_msg_size(hdrlen))
+ return -EINVAL;
+
+ rc = __nla_validate(nlmsg_attrdata(nlh, hdrlen),
+ nlmsg_attrlen(nlh, hdrlen),
+ family->maxattr, family->policy,
+ validate, extack);
+ if (rc)
+ return rc;
+ }
+
if (!family->parallel_ops) {
struct netlink_dump_control c = {
.module = family->module,
@@ -577,9 +595,13 @@ static int genl_family_rcv_msg(const struct genl_family *family,
attrbuf = family->attrbuf;
if (attrbuf) {
- err = nlmsg_parse_deprecated(nlh, hdrlen, attrbuf,
- family->maxattr, family->policy,
- extack);
+ enum netlink_validation validate = NL_VALIDATE_STRICT;
+
+ if (ops->validate & GENL_DONT_VALIDATE_STRICT)
+ validate = NL_VALIDATE_LIBERAL;
+
+ err = __nlmsg_parse(nlh, hdrlen, attrbuf, family->maxattr,
+ family->policy, validate, extack);
if (err < 0)
goto out;
}
@@ -939,6 +961,7 @@ static int genl_ctrl_event(int event, const struct genl_family *family,
static const struct genl_ops genl_ctrl_ops[] = {
{
.cmd = CTRL_CMD_GETFAMILY,
+ .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = ctrl_getfamily,
.dumpit = ctrl_dumpfamily,
},