aboutsummaryrefslogtreecommitdiff
path: root/net/core/fib_rules.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/core/fib_rules.c')
-rw-r--r--net/core/fib_rules.c34
1 files changed, 32 insertions, 2 deletions
diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c
index 215f1bff048..7174ced75ef 100644
--- a/net/core/fib_rules.c
+++ b/net/core/fib_rules.c
@@ -143,7 +143,7 @@ int fib_rules_lookup(struct fib_rules_ops *ops, struct flowi *fl,
}
}
- err = -ENETUNREACH;
+ err = -ESRCH;
out:
rcu_read_unlock();
@@ -152,6 +152,28 @@ out:
EXPORT_SYMBOL_GPL(fib_rules_lookup);
+static int validate_rulemsg(struct fib_rule_hdr *frh, struct nlattr **tb,
+ struct fib_rules_ops *ops)
+{
+ int err = -EINVAL;
+
+ if (frh->src_len)
+ if (tb[FRA_SRC] == NULL ||
+ frh->src_len > (ops->addr_size * 8) ||
+ nla_len(tb[FRA_SRC]) != ops->addr_size)
+ goto errout;
+
+ if (frh->dst_len)
+ if (tb[FRA_DST] == NULL ||
+ frh->dst_len > (ops->addr_size * 8) ||
+ nla_len(tb[FRA_DST]) != ops->addr_size)
+ goto errout;
+
+ err = 0;
+errout:
+ return err;
+}
+
int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
{
struct fib_rule_hdr *frh = nlmsg_data(nlh);
@@ -173,6 +195,10 @@ int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
if (err < 0)
goto errout;
+ err = validate_rulemsg(frh, tb, ops);
+ if (err < 0)
+ goto errout;
+
rule = kzalloc(ops->rule_size, GFP_KERNEL);
if (rule == NULL) {
err = -ENOMEM;
@@ -260,6 +286,10 @@ int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
if (err < 0)
goto errout;
+ err = validate_rulemsg(frh, tb, ops);
+ if (err < 0)
+ goto errout;
+
list_for_each_entry(rule, ops->rules_list, list) {
if (frh->action && (frh->action != rule->action))
continue;
@@ -374,7 +404,7 @@ int fib_rules_dump(struct sk_buff *skb, struct netlink_callback *cb, int family)
return -EAFNOSUPPORT;
rcu_read_lock();
- list_for_each_entry(rule, ops->rules_list, list) {
+ list_for_each_entry_rcu(rule, ops->rules_list, list) {
if (idx < cb->args[0])
goto skip;