summaryrefslogtreecommitdiffstats
path: root/net/netlink
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2019-04-26 08:07:31 -0400
committerDavid S. Miller <davem@davemloft.net>2019-04-27 17:07:22 -0400
commitef6243acb4782df587a4d7d6c310fa5b5d82684b (patch)
tree81b4175fc03c61adbb8935f5f7b8ce02589c65dd /net/netlink
parent56738f460841761abc70347c919d5c45f6f05a42 (diff)
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')
-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,
536 if (ops->dumpit == NULL) 536 if (ops->dumpit == NULL)
537 return -EOPNOTSUPP; 537 return -EOPNOTSUPP;
538 538
539 if (!(ops->validate & GENL_DONT_VALIDATE_DUMP)) {
540 unsigned int validate = NL_VALIDATE_STRICT;
541 int hdrlen = GENL_HDRLEN + family->hdrsize;
542
543 if (ops->validate & GENL_DONT_VALIDATE_DUMP_STRICT)
544 validate = NL_VALIDATE_LIBERAL;
545
546 if (nlh->nlmsg_len < nlmsg_msg_size(hdrlen))
547 return -EINVAL;
548
549 rc = __nla_validate(nlmsg_attrdata(nlh, hdrlen),
550 nlmsg_attrlen(nlh, hdrlen),
551 family->maxattr, family->policy,
552 validate, extack);
553 if (rc)
554 return rc;
555 }
556
539 if (!family->parallel_ops) { 557 if (!family->parallel_ops) {
540 struct netlink_dump_control c = { 558 struct netlink_dump_control c = {
541 .module = family->module, 559 .module = family->module,
@@ -577,9 +595,13 @@ static int genl_family_rcv_msg(const struct genl_family *family,
577 attrbuf = family->attrbuf; 595 attrbuf = family->attrbuf;
578 596
579 if (attrbuf) { 597 if (attrbuf) {
580 err = nlmsg_parse_deprecated(nlh, hdrlen, attrbuf, 598 enum netlink_validation validate = NL_VALIDATE_STRICT;
581 family->maxattr, family->policy, 599
582 extack); 600 if (ops->validate & GENL_DONT_VALIDATE_STRICT)
601 validate = NL_VALIDATE_LIBERAL;
602
603 err = __nlmsg_parse(nlh, hdrlen, attrbuf, family->maxattr,
604 family->policy, validate, extack);
583 if (err < 0) 605 if (err < 0)
584 goto out; 606 goto out;
585 } 607 }
@@ -939,6 +961,7 @@ static int genl_ctrl_event(int event, const struct genl_family *family,
939static const struct genl_ops genl_ctrl_ops[] = { 961static const struct genl_ops genl_ctrl_ops[] = {
940 { 962 {
941 .cmd = CTRL_CMD_GETFAMILY, 963 .cmd = CTRL_CMD_GETFAMILY,
964 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
942 .doit = ctrl_getfamily, 965 .doit = ctrl_getfamily,
943 .dumpit = ctrl_dumpfamily, 966 .dumpit = ctrl_dumpfamily,
944 }, 967 },