aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc/netlink_compat.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2019-04-26 08:07:28 -0400
committerDavid S. Miller <davem@davemloft.net>2019-04-27 17:07:21 -0400
commit8cb081746c031fb164089322e2336a0bf5b3070c (patch)
tree1404b16c0859f9d67e67247a10833050c870a3cf /net/tipc/netlink_compat.c
parent6f455f5f4e9c28aefaefbe18ce7304b499645d75 (diff)
netlink: make validation more configurable for future strictness
We currently have two levels of strict validation: 1) liberal (default) - undefined (type >= max) & NLA_UNSPEC attributes accepted - attribute length >= expected accepted - garbage at end of message accepted 2) strict (opt-in) - NLA_UNSPEC attributes accepted - attribute length >= expected accepted Split out parsing strictness into four different options: * TRAILING - check that there's no trailing data after parsing attributes (in message or nested) * MAXTYPE - reject attrs > max known type * UNSPEC - reject attributes with NLA_UNSPEC policy entries * STRICT_ATTRS - strictly validate attribute size The default for future things should be *everything*. The current *_strict() is a combination of TRAILING and MAXTYPE, and is renamed to _deprecated_strict(). The current regular parsing has none of this, and is renamed to *_parse_deprecated(). Additionally it allows us to selectively set one of the new flags even on old policies. Notably, the UNSPEC flag could be useful in this case, since it can be arranged (by filling in the policy) to not be an incompatible userspace ABI change, but would then going forward prevent forgetting attribute entries. Similar can apply to the POLICY flag. We end up with the following renames: * nla_parse -> nla_parse_deprecated * nla_parse_strict -> nla_parse_deprecated_strict * nlmsg_parse -> nlmsg_parse_deprecated * nlmsg_parse_strict -> nlmsg_parse_deprecated_strict * nla_parse_nested -> nla_parse_nested_deprecated * nla_validate_nested -> nla_validate_nested_deprecated Using spatch, of course: @@ expression TB, MAX, HEAD, LEN, POL, EXT; @@ -nla_parse(TB, MAX, HEAD, LEN, POL, EXT) +nla_parse_deprecated(TB, MAX, HEAD, LEN, POL, EXT) @@ expression NLH, HDRLEN, TB, MAX, POL, EXT; @@ -nlmsg_parse(NLH, HDRLEN, TB, MAX, POL, EXT) +nlmsg_parse_deprecated(NLH, HDRLEN, TB, MAX, POL, EXT) @@ expression NLH, HDRLEN, TB, MAX, POL, EXT; @@ -nlmsg_parse_strict(NLH, HDRLEN, TB, MAX, POL, EXT) +nlmsg_parse_deprecated_strict(NLH, HDRLEN, TB, MAX, POL, EXT) @@ expression TB, MAX, NLA, POL, EXT; @@ -nla_parse_nested(TB, MAX, NLA, POL, EXT) +nla_parse_nested_deprecated(TB, MAX, NLA, POL, EXT) @@ expression START, MAX, POL, EXT; @@ -nla_validate_nested(START, MAX, POL, EXT) +nla_validate_nested_deprecated(START, MAX, POL, EXT) @@ expression NLH, HDRLEN, MAX, POL, EXT; @@ -nlmsg_validate(NLH, HDRLEN, MAX, POL, EXT) +nlmsg_validate_deprecated(NLH, HDRLEN, MAX, POL, EXT) For this patch, don't actually add the strict, non-renamed versions yet so that it breaks compile if I get it wrong. Also, while at it, make nla_validate and nla_parse go down to a common __nla_validate_parse() function to avoid code duplication. Ultimately, this allows us to have very strict validation for every new caller of nla_parse()/nlmsg_parse() etc as re-introduced in the next patch, while existing things will continue to work as is. In effect then, this adds fully strict validation for any new command. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/tipc/netlink_compat.c')
-rw-r--r--net/tipc/netlink_compat.c63
1 files changed, 34 insertions, 29 deletions
diff --git a/net/tipc/netlink_compat.c b/net/tipc/netlink_compat.c
index 36fe2dbb6d87..f7269ce934b5 100644
--- a/net/tipc/netlink_compat.c
+++ b/net/tipc/netlink_compat.c
@@ -328,9 +328,9 @@ static int __tipc_nl_compat_doit(struct tipc_nl_compat_cmd_doit *cmd,
328 if (err) 328 if (err)
329 goto doit_out; 329 goto doit_out;
330 330
331 err = nla_parse(attrbuf, tipc_genl_family.maxattr, 331 err = nla_parse_deprecated(attrbuf, tipc_genl_family.maxattr,
332 (const struct nlattr *)trans_buf->data, 332 (const struct nlattr *)trans_buf->data,
333 trans_buf->len, NULL, NULL); 333 trans_buf->len, NULL, NULL);
334 if (err) 334 if (err)
335 goto doit_out; 335 goto doit_out;
336 336
@@ -378,8 +378,8 @@ static int tipc_nl_compat_bearer_dump(struct tipc_nl_compat_msg *msg,
378 if (!attrs[TIPC_NLA_BEARER]) 378 if (!attrs[TIPC_NLA_BEARER])
379 return -EINVAL; 379 return -EINVAL;
380 380
381 err = nla_parse_nested(bearer, TIPC_NLA_BEARER_MAX, 381 err = nla_parse_nested_deprecated(bearer, TIPC_NLA_BEARER_MAX,
382 attrs[TIPC_NLA_BEARER], NULL, NULL); 382 attrs[TIPC_NLA_BEARER], NULL, NULL);
383 if (err) 383 if (err)
384 return err; 384 return err;
385 385
@@ -514,24 +514,26 @@ static int tipc_nl_compat_link_stat_dump(struct tipc_nl_compat_msg *msg,
514 if (!attrs[TIPC_NLA_LINK]) 514 if (!attrs[TIPC_NLA_LINK])
515 return -EINVAL; 515 return -EINVAL;
516 516
517 err = nla_parse_nested(link, TIPC_NLA_LINK_MAX, attrs[TIPC_NLA_LINK], 517 err = nla_parse_nested_deprecated(link, TIPC_NLA_LINK_MAX,
518 NULL, NULL); 518 attrs[TIPC_NLA_LINK], NULL, NULL);
519 if (err) 519 if (err)
520 return err; 520 return err;
521 521
522 if (!link[TIPC_NLA_LINK_PROP]) 522 if (!link[TIPC_NLA_LINK_PROP])
523 return -EINVAL; 523 return -EINVAL;
524 524
525 err = nla_parse_nested(prop, TIPC_NLA_PROP_MAX, 525 err = nla_parse_nested_deprecated(prop, TIPC_NLA_PROP_MAX,
526 link[TIPC_NLA_LINK_PROP], NULL, NULL); 526 link[TIPC_NLA_LINK_PROP], NULL,
527 NULL);
527 if (err) 528 if (err)
528 return err; 529 return err;
529 530
530 if (!link[TIPC_NLA_LINK_STATS]) 531 if (!link[TIPC_NLA_LINK_STATS])
531 return -EINVAL; 532 return -EINVAL;
532 533
533 err = nla_parse_nested(stats, TIPC_NLA_STATS_MAX, 534 err = nla_parse_nested_deprecated(stats, TIPC_NLA_STATS_MAX,
534 link[TIPC_NLA_LINK_STATS], NULL, NULL); 535 link[TIPC_NLA_LINK_STATS], NULL,
536 NULL);
535 if (err) 537 if (err)
536 return err; 538 return err;
537 539
@@ -645,8 +647,8 @@ static int tipc_nl_compat_link_dump(struct tipc_nl_compat_msg *msg,
645 if (!attrs[TIPC_NLA_LINK]) 647 if (!attrs[TIPC_NLA_LINK])
646 return -EINVAL; 648 return -EINVAL;
647 649
648 err = nla_parse_nested(link, TIPC_NLA_LINK_MAX, attrs[TIPC_NLA_LINK], 650 err = nla_parse_nested_deprecated(link, TIPC_NLA_LINK_MAX,
649 NULL, NULL); 651 attrs[TIPC_NLA_LINK], NULL, NULL);
650 if (err) 652 if (err)
651 return err; 653 return err;
652 654
@@ -869,16 +871,18 @@ static int tipc_nl_compat_name_table_dump(struct tipc_nl_compat_msg *msg,
869 if (!attrs[TIPC_NLA_NAME_TABLE]) 871 if (!attrs[TIPC_NLA_NAME_TABLE])
870 return -EINVAL; 872 return -EINVAL;
871 873
872 err = nla_parse_nested(nt, TIPC_NLA_NAME_TABLE_MAX, 874 err = nla_parse_nested_deprecated(nt, TIPC_NLA_NAME_TABLE_MAX,
873 attrs[TIPC_NLA_NAME_TABLE], NULL, NULL); 875 attrs[TIPC_NLA_NAME_TABLE], NULL,
876 NULL);
874 if (err) 877 if (err)
875 return err; 878 return err;
876 879
877 if (!nt[TIPC_NLA_NAME_TABLE_PUBL]) 880 if (!nt[TIPC_NLA_NAME_TABLE_PUBL])
878 return -EINVAL; 881 return -EINVAL;
879 882
880 err = nla_parse_nested(publ, TIPC_NLA_PUBL_MAX, 883 err = nla_parse_nested_deprecated(publ, TIPC_NLA_PUBL_MAX,
881 nt[TIPC_NLA_NAME_TABLE_PUBL], NULL, NULL); 884 nt[TIPC_NLA_NAME_TABLE_PUBL], NULL,
885 NULL);
882 if (err) 886 if (err)
883 return err; 887 return err;
884 888
@@ -937,8 +941,8 @@ static int __tipc_nl_compat_publ_dump(struct tipc_nl_compat_msg *msg,
937 if (!attrs[TIPC_NLA_PUBL]) 941 if (!attrs[TIPC_NLA_PUBL])
938 return -EINVAL; 942 return -EINVAL;
939 943
940 err = nla_parse_nested(publ, TIPC_NLA_PUBL_MAX, attrs[TIPC_NLA_PUBL], 944 err = nla_parse_nested_deprecated(publ, TIPC_NLA_PUBL_MAX,
941 NULL, NULL); 945 attrs[TIPC_NLA_PUBL], NULL, NULL);
942 if (err) 946 if (err)
943 return err; 947 return err;
944 948
@@ -1007,8 +1011,8 @@ static int tipc_nl_compat_sk_dump(struct tipc_nl_compat_msg *msg,
1007 if (!attrs[TIPC_NLA_SOCK]) 1011 if (!attrs[TIPC_NLA_SOCK])
1008 return -EINVAL; 1012 return -EINVAL;
1009 1013
1010 err = nla_parse_nested(sock, TIPC_NLA_SOCK_MAX, attrs[TIPC_NLA_SOCK], 1014 err = nla_parse_nested_deprecated(sock, TIPC_NLA_SOCK_MAX,
1011 NULL, NULL); 1015 attrs[TIPC_NLA_SOCK], NULL, NULL);
1012 if (err) 1016 if (err)
1013 return err; 1017 return err;
1014 1018
@@ -1019,8 +1023,9 @@ static int tipc_nl_compat_sk_dump(struct tipc_nl_compat_msg *msg,
1019 u32 node; 1023 u32 node;
1020 struct nlattr *con[TIPC_NLA_CON_MAX + 1]; 1024 struct nlattr *con[TIPC_NLA_CON_MAX + 1];
1021 1025
1022 err = nla_parse_nested(con, TIPC_NLA_CON_MAX, 1026 err = nla_parse_nested_deprecated(con, TIPC_NLA_CON_MAX,
1023 sock[TIPC_NLA_SOCK_CON], NULL, NULL); 1027 sock[TIPC_NLA_SOCK_CON],
1028 NULL, NULL);
1024 1029
1025 if (err) 1030 if (err)
1026 return err; 1031 return err;
@@ -1059,8 +1064,8 @@ static int tipc_nl_compat_media_dump(struct tipc_nl_compat_msg *msg,
1059 if (!attrs[TIPC_NLA_MEDIA]) 1064 if (!attrs[TIPC_NLA_MEDIA])
1060 return -EINVAL; 1065 return -EINVAL;
1061 1066
1062 err = nla_parse_nested(media, TIPC_NLA_MEDIA_MAX, 1067 err = nla_parse_nested_deprecated(media, TIPC_NLA_MEDIA_MAX,
1063 attrs[TIPC_NLA_MEDIA], NULL, NULL); 1068 attrs[TIPC_NLA_MEDIA], NULL, NULL);
1064 if (err) 1069 if (err)
1065 return err; 1070 return err;
1066 1071
@@ -1079,8 +1084,8 @@ static int tipc_nl_compat_node_dump(struct tipc_nl_compat_msg *msg,
1079 if (!attrs[TIPC_NLA_NODE]) 1084 if (!attrs[TIPC_NLA_NODE])
1080 return -EINVAL; 1085 return -EINVAL;
1081 1086
1082 err = nla_parse_nested(node, TIPC_NLA_NODE_MAX, attrs[TIPC_NLA_NODE], 1087 err = nla_parse_nested_deprecated(node, TIPC_NLA_NODE_MAX,
1083 NULL, NULL); 1088 attrs[TIPC_NLA_NODE], NULL, NULL);
1084 if (err) 1089 if (err)
1085 return err; 1090 return err;
1086 1091
@@ -1126,8 +1131,8 @@ static int tipc_nl_compat_net_dump(struct tipc_nl_compat_msg *msg,
1126 if (!attrs[TIPC_NLA_NET]) 1131 if (!attrs[TIPC_NLA_NET])
1127 return -EINVAL; 1132 return -EINVAL;
1128 1133
1129 err = nla_parse_nested(net, TIPC_NLA_NET_MAX, attrs[TIPC_NLA_NET], 1134 err = nla_parse_nested_deprecated(net, TIPC_NLA_NET_MAX,
1130 NULL, NULL); 1135 attrs[TIPC_NLA_NET], NULL, NULL);
1131 if (err) 1136 if (err)
1132 return err; 1137 return err;
1133 1138