diff options
| author | David S. Miller <[email protected]> | 2019-01-19 10:09:59 -0800 |
|---|---|---|
| committer | David S. Miller <[email protected]> | 2019-01-19 10:09:59 -0800 |
| commit | e266afa9c7afc51deaaf1e1566a8dfbc6f632b07 (patch) | |
| tree | 706b013a6ff1715d81bd3054721a8ecdaf9aa16d /net/ipv6/route.c | |
| parent | 133bbb18ab1a2f5549435c5a3126413344ddbcb8 (diff) | |
| parent | 0c4056ee8433487cfcc19621b85586c88ec927c0 (diff) | |
Merge branch 'net-use-strict-checks-in-doit-handlers'
Jakub Kicinski says:
====================
net: use strict checks in doit handlers
This series extends strict argument checking to doit handlers
of the GET* nature. This is a bit tricky since strict checking
flag has already been released..
iproute2 did not have a release with strick checks enabled,
and it will only need a minor one-liner to pass strick checks
after all the work that DaveA has already done.
Big thanks to Dave Ahern for help and guidence.
v2:
- remove unnecessary check in patch 5 (Nicolas);
- add path 7 (DaveA);
- improve messages in patch 8 (DaveA).
====================
Signed-off-by: David S. Miller <[email protected]>
Diffstat (limited to 'net/ipv6/route.c')
| -rw-r--r-- | net/ipv6/route.c | 70 |
1 files changed, 68 insertions, 2 deletions
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 40b225f87d5e..8e11f9a557b1 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -4822,6 +4822,73 @@ int rt6_dump_route(struct fib6_info *rt, void *p_arg) arg->cb->nlh->nlmsg_seq, flags); } +static int inet6_rtm_valid_getroute_req(struct sk_buff *skb, + const struct nlmsghdr *nlh, + struct nlattr **tb, + struct netlink_ext_ack *extack) +{ + struct rtmsg *rtm; + int i, err; + + if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*rtm))) { + NL_SET_ERR_MSG_MOD(extack, + "Invalid header for get route request"); + return -EINVAL; + } + + if (!netlink_strict_get_check(skb)) + return nlmsg_parse(nlh, sizeof(*rtm), tb, RTA_MAX, + rtm_ipv6_policy, extack); + + rtm = nlmsg_data(nlh); + if ((rtm->rtm_src_len && rtm->rtm_src_len != 128) || + (rtm->rtm_dst_len && rtm->rtm_dst_len != 128) || + rtm->rtm_table || rtm->rtm_protocol || rtm->rtm_scope || + rtm->rtm_type) { + NL_SET_ERR_MSG_MOD(extack, "Invalid values in header for get route request"); + return -EINVAL; + } + if (rtm->rtm_flags & ~RTM_F_FIB_MATCH) { + NL_SET_ERR_MSG_MOD(extack, + "Invalid flags for get route request"); + return -EINVAL; + } + + err = nlmsg_parse_strict(nlh, sizeof(*rtm), tb, RTA_MAX, + rtm_ipv6_policy, extack); + if (err) + return err; + + if ((tb[RTA_SRC] && !rtm->rtm_src_len) || + (tb[RTA_DST] && !rtm->rtm_dst_len)) { + NL_SET_ERR_MSG_MOD(extack, "rtm_src_len and rtm_dst_len must be 128 for IPv6"); + return -EINVAL; + } + + for (i = 0; i <= RTA_MAX; i++) { + if (!tb[i]) + continue; + + switch (i) { + case RTA_SRC: + case RTA_DST: + case RTA_IIF: + case RTA_OIF: + case RTA_MARK: + case RTA_UID: + case RTA_SPORT: + case RTA_DPORT: + case RTA_IP_PROTO: + break; + default: + NL_SET_ERR_MSG_MOD(extack, "Unsupported attribute in get route request"); + return -EINVAL; + } + } + + return 0; +} + static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh, struct netlink_ext_ack *extack) { @@ -4836,8 +4903,7 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh, struct flowi6 fl6 = {}; bool fibmatch; - err = nlmsg_parse(nlh, sizeof(*rtm), tb, RTA_MAX, rtm_ipv6_policy, - extack); + err = inet6_rtm_valid_getroute_req(in_skb, nlh, tb, extack); if (err < 0) goto errout; |