| From foo@baz Wed Sep 30 05:25:07 CEST 2015 |
| From: Wilson Kok <wkok@cumulusnetworks.com> |
| Date: Tue, 22 Sep 2015 21:40:22 -0700 |
| Subject: fib_rules: fix fib rule dumps across multiple skbs |
| |
| From: Wilson Kok <wkok@cumulusnetworks.com> |
| |
| [ Upstream commit 41fc014332d91ee90c32840bf161f9685b7fbf2b ] |
| |
| dump_rules returns skb length and not error. |
| But when family == AF_UNSPEC, the caller of dump_rules |
| assumes that it returns an error. Hence, when family == AF_UNSPEC, |
| we continue trying to dump on -EMSGSIZE errors resulting in |
| incorrect dump idx carried between skbs belonging to the same dump. |
| This results in fib rule dump always only dumping rules that fit |
| into the first skb. |
| |
| This patch fixes dump_rules to return error so that we exit correctly |
| and idx is correctly maintained between skbs that are part of the |
| same dump. |
| |
| Signed-off-by: Wilson Kok <wkok@cumulusnetworks.com> |
| Signed-off-by: Roopa Prabhu <roopa@cumulusnetworks.com> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| net/core/fib_rules.c | 14 +++++++++----- |
| 1 file changed, 9 insertions(+), 5 deletions(-) |
| |
| --- a/net/core/fib_rules.c |
| +++ b/net/core/fib_rules.c |
| @@ -615,15 +615,17 @@ static int dump_rules(struct sk_buff *sk |
| { |
| int idx = 0; |
| struct fib_rule *rule; |
| + int err = 0; |
| |
| rcu_read_lock(); |
| list_for_each_entry_rcu(rule, &ops->rules_list, list) { |
| if (idx < cb->args[1]) |
| goto skip; |
| |
| - if (fib_nl_fill_rule(skb, rule, NETLINK_CB(cb->skb).portid, |
| - cb->nlh->nlmsg_seq, RTM_NEWRULE, |
| - NLM_F_MULTI, ops) < 0) |
| + err = fib_nl_fill_rule(skb, rule, NETLINK_CB(cb->skb).portid, |
| + cb->nlh->nlmsg_seq, RTM_NEWRULE, |
| + NLM_F_MULTI, ops); |
| + if (err) |
| break; |
| skip: |
| idx++; |
| @@ -632,7 +634,7 @@ skip: |
| cb->args[1] = idx; |
| rules_ops_put(ops); |
| |
| - return skb->len; |
| + return err; |
| } |
| |
| static int fib_nl_dumprule(struct sk_buff *skb, struct netlink_callback *cb) |
| @@ -648,7 +650,9 @@ static int fib_nl_dumprule(struct sk_buf |
| if (ops == NULL) |
| return -EAFNOSUPPORT; |
| |
| - return dump_rules(skb, cb, ops); |
| + dump_rules(skb, cb, ops); |
| + |
| + return skb->len; |
| } |
| |
| rcu_read_lock(); |