diff options
author | Roopa Prabhu <roopa@cumulusnetworks.com> | 2018-04-21 18:41:31 +0200 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2018-04-23 16:21:24 +0200 |
commit | b16fb418b1bf2a9f14d5d2a4fe29bde1f5550b37 (patch) | |
tree | 27d935b093ea81e976b6b14778d462c2bcf87d32 /net/core/fib_rules.c | |
parent | fib_rules: move common handling of newrule delrule msgs into fib_nl2rule (diff) | |
download | linux-b16fb418b1bf2a9f14d5d2a4fe29bde1f5550b37.tar.xz linux-b16fb418b1bf2a9f14d5d2a4fe29bde1f5550b37.zip |
net: fib_rules: add extack support
Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core/fib_rules.c')
-rw-r--r-- | net/core/fib_rules.c | 55 |
1 files changed, 42 insertions, 13 deletions
diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c index 67801104e9a8..ebd9351b213a 100644 --- a/net/core/fib_rules.c +++ b/net/core/fib_rules.c @@ -469,14 +469,18 @@ static int fib_nl2rule(struct sk_buff *skb, struct nlmsghdr *nlh, if (frh->src_len) if (!tb[FRA_SRC] || frh->src_len > (ops->addr_size * 8) || - nla_len(tb[FRA_SRC]) != ops->addr_size) + nla_len(tb[FRA_SRC]) != ops->addr_size) { + NL_SET_ERR_MSG(extack, "Invalid source address"); goto errout; + } if (frh->dst_len) if (!tb[FRA_DST] || frh->dst_len > (ops->addr_size * 8) || - nla_len(tb[FRA_DST]) != ops->addr_size) + nla_len(tb[FRA_DST]) != ops->addr_size) { + NL_SET_ERR_MSG(extack, "Invalid dst address"); goto errout; + } nlrule = kzalloc(ops->rule_size, GFP_KERNEL); if (!nlrule) { @@ -537,6 +541,7 @@ static int fib_nl2rule(struct sk_buff *skb, struct nlmsghdr *nlh, nlrule->l3mdev = nla_get_u8(tb[FRA_L3MDEV]); if (nlrule->l3mdev != 1) #endif + NL_SET_ERR_MSG(extack, "Invalid l3mdev"); goto errout_free; } @@ -554,31 +559,41 @@ static int fib_nl2rule(struct sk_buff *skb, struct nlmsghdr *nlh, nlrule->suppress_ifgroup = -1; if (tb[FRA_GOTO]) { - if (nlrule->action != FR_ACT_GOTO) + if (nlrule->action != FR_ACT_GOTO) { + NL_SET_ERR_MSG(extack, "Unexpected goto"); goto errout_free; + } nlrule->target = nla_get_u32(tb[FRA_GOTO]); /* Backward jumps are prohibited to avoid endless loops */ - if (nlrule->target <= nlrule->pref) + if (nlrule->target <= nlrule->pref) { + NL_SET_ERR_MSG(extack, "Backward goto not supported"); goto errout_free; + } } else if (nlrule->action == FR_ACT_GOTO) { + NL_SET_ERR_MSG(extack, "Missing goto target for action goto"); goto errout_free; } - if (nlrule->l3mdev && nlrule->table) + if (nlrule->l3mdev && nlrule->table) { + NL_SET_ERR_MSG(extack, "l3mdev and table are mutually exclusive"); goto errout_free; + } if (tb[FRA_UID_RANGE]) { if (current_user_ns() != net->user_ns) { err = -EPERM; + NL_SET_ERR_MSG(extack, "No permission to set uid"); goto errout_free; } nlrule->uid_range = nla_get_kuid_range(tb); if (!uid_range_set(&nlrule->uid_range) || - !uid_lte(nlrule->uid_range.start, nlrule->uid_range.end)) + !uid_lte(nlrule->uid_range.start, nlrule->uid_range.end)) { + NL_SET_ERR_MSG(extack, "Invalid uid range"); goto errout_free; + } } else { nlrule->uid_range = fib_kuid_range_unset; } @@ -589,15 +604,19 @@ static int fib_nl2rule(struct sk_buff *skb, struct nlmsghdr *nlh, if (tb[FRA_SPORT_RANGE]) { err = nla_get_port_range(tb[FRA_SPORT_RANGE], &nlrule->sport_range); - if (err) + if (err) { + NL_SET_ERR_MSG(extack, "Invalid sport range"); goto errout_free; + } } if (tb[FRA_DPORT_RANGE]) { err = nla_get_port_range(tb[FRA_DPORT_RANGE], &nlrule->dport_range); - if (err) + if (err) { + NL_SET_ERR_MSG(extack, "Invalid dport range"); goto errout_free; + } } *rule = nlrule; @@ -621,18 +640,23 @@ int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr *nlh, int err = -EINVAL, unresolved = 0; bool user_priority = false; - if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*frh))) + if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*frh))) { + NL_SET_ERR_MSG(extack, "Invalid msg length"); goto errout; + } ops = lookup_rules_ops(net, frh->family); if (!ops) { err = -EAFNOSUPPORT; + NL_SET_ERR_MSG(extack, "Rule family not supported"); goto errout; } err = nlmsg_parse(nlh, sizeof(*frh), tb, FRA_MAX, ops->policy, extack); - if (err < 0) + if (err < 0) { + NL_SET_ERR_MSG(extack, "Error parsing msg"); goto errout; + } err = fib_nl2rule(skb, nlh, extack, ops, tb, &rule, &user_priority); if (err) @@ -644,7 +668,7 @@ int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr *nlh, goto errout_free; } - err = ops->configure(rule, skb, frh, tb); + err = ops->configure(rule, skb, frh, tb, extack); if (err < 0) goto errout_free; @@ -723,18 +747,23 @@ int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr *nlh, int err = -EINVAL; bool user_priority = false; - if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*frh))) + if (nlh->nlmsg_len < nlmsg_msg_size(sizeof(*frh))) { + NL_SET_ERR_MSG(extack, "Invalid msg length"); goto errout; + } ops = lookup_rules_ops(net, frh->family); if (ops == NULL) { err = -EAFNOSUPPORT; + NL_SET_ERR_MSG(extack, "Rule family not supported"); goto errout; } err = nlmsg_parse(nlh, sizeof(*frh), tb, FRA_MAX, ops->policy, extack); - if (err < 0) + if (err < 0) { + NL_SET_ERR_MSG(extack, "Error parsing msg"); goto errout; + } err = fib_nl2rule(skb, nlh, extack, ops, tb, &nlrule, &user_priority); if (err) |