diff options
Diffstat (limited to 'net/core/fib_rules.c')
-rw-r--r-- | net/core/fib_rules.c | 34 |
1 files changed, 32 insertions, 2 deletions
diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c index 215f1bff048f..7174ced75efc 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, | |||
143 | } | 143 | } |
144 | } | 144 | } |
145 | 145 | ||
146 | err = -ENETUNREACH; | 146 | err = -ESRCH; |
147 | out: | 147 | out: |
148 | rcu_read_unlock(); | 148 | rcu_read_unlock(); |
149 | 149 | ||
@@ -152,6 +152,28 @@ out: | |||
152 | 152 | ||
153 | EXPORT_SYMBOL_GPL(fib_rules_lookup); | 153 | EXPORT_SYMBOL_GPL(fib_rules_lookup); |
154 | 154 | ||
155 | static int validate_rulemsg(struct fib_rule_hdr *frh, struct nlattr **tb, | ||
156 | struct fib_rules_ops *ops) | ||
157 | { | ||
158 | int err = -EINVAL; | ||
159 | |||
160 | if (frh->src_len) | ||
161 | if (tb[FRA_SRC] == NULL || | ||
162 | frh->src_len > (ops->addr_size * 8) || | ||
163 | nla_len(tb[FRA_SRC]) != ops->addr_size) | ||
164 | goto errout; | ||
165 | |||
166 | if (frh->dst_len) | ||
167 | if (tb[FRA_DST] == NULL || | ||
168 | frh->dst_len > (ops->addr_size * 8) || | ||
169 | nla_len(tb[FRA_DST]) != ops->addr_size) | ||
170 | goto errout; | ||
171 | |||
172 | err = 0; | ||
173 | errout: | ||
174 | return err; | ||
175 | } | ||
176 | |||
155 | int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) | 177 | int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) |
156 | { | 178 | { |
157 | struct fib_rule_hdr *frh = nlmsg_data(nlh); | 179 | 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) | |||
173 | if (err < 0) | 195 | if (err < 0) |
174 | goto errout; | 196 | goto errout; |
175 | 197 | ||
198 | err = validate_rulemsg(frh, tb, ops); | ||
199 | if (err < 0) | ||
200 | goto errout; | ||
201 | |||
176 | rule = kzalloc(ops->rule_size, GFP_KERNEL); | 202 | rule = kzalloc(ops->rule_size, GFP_KERNEL); |
177 | if (rule == NULL) { | 203 | if (rule == NULL) { |
178 | err = -ENOMEM; | 204 | err = -ENOMEM; |
@@ -260,6 +286,10 @@ int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) | |||
260 | if (err < 0) | 286 | if (err < 0) |
261 | goto errout; | 287 | goto errout; |
262 | 288 | ||
289 | err = validate_rulemsg(frh, tb, ops); | ||
290 | if (err < 0) | ||
291 | goto errout; | ||
292 | |||
263 | list_for_each_entry(rule, ops->rules_list, list) { | 293 | list_for_each_entry(rule, ops->rules_list, list) { |
264 | if (frh->action && (frh->action != rule->action)) | 294 | if (frh->action && (frh->action != rule->action)) |
265 | continue; | 295 | continue; |
@@ -374,7 +404,7 @@ int fib_rules_dump(struct sk_buff *skb, struct netlink_callback *cb, int family) | |||
374 | return -EAFNOSUPPORT; | 404 | return -EAFNOSUPPORT; |
375 | 405 | ||
376 | rcu_read_lock(); | 406 | rcu_read_lock(); |
377 | list_for_each_entry(rule, ops->rules_list, list) { | 407 | list_for_each_entry_rcu(rule, ops->rules_list, list) { |
378 | if (idx < cb->args[0]) | 408 | if (idx < cb->args[0]) |
379 | goto skip; | 409 | goto skip; |
380 | 410 | ||