aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Dumazet <eric.dumazet@gmail.com>2011-05-25 03:34:04 -0400
committerDavid S. Miller <davem@davemloft.net>2011-05-25 17:55:32 -0400
commit2907c35ff64708065e5a7fd54e8ded8263eb3074 (patch)
treeb5046b08b0b4b13c45a2fffef4ad3218c9db07d8
parent1dcb14d9e874d12bab9ceeba776b742f1682b0a6 (diff)
net: hold rtnl again in dump callbacks
Commit e67f88dd12f6 (dont hold rtnl mutex during netlink dump callbacks) missed fact that rtnl_fill_ifinfo() must be called with rtnl held. Because of possible deadlocks between two mutexes (cb_mutex and rtnl), its not easy to solve this problem, so revert this part of the patch. It also forgot one rcu_read_unlock() in FIB dump_rules() Add one ASSERT_RTNL() in rtnl_fill_ifinfo() to remind us the rule. Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com> CC: Patrick McHardy <kaber@trash.net> CC: Stephen Hemminger <shemminger@vyatta.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/core/fib_rules.c1
-rw-r--r--net/core/rtnetlink.c9
2 files changed, 8 insertions, 2 deletions
diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c
index 3911586e12e4..008dc70b064b 100644
--- a/net/core/fib_rules.c
+++ b/net/core/fib_rules.c
@@ -602,6 +602,7 @@ static int dump_rules(struct sk_buff *skb, struct netlink_callback *cb,
602skip: 602skip:
603 idx++; 603 idx++;
604 } 604 }
605 rcu_read_unlock();
605 cb->args[1] = idx; 606 cb->args[1] = idx;
606 rules_ops_put(ops); 607 rules_ops_put(ops);
607 608
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index d1644e317e70..2d56cb9b0b94 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -850,6 +850,7 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
850 struct nlattr *attr, *af_spec; 850 struct nlattr *attr, *af_spec;
851 struct rtnl_af_ops *af_ops; 851 struct rtnl_af_ops *af_ops;
852 852
853 ASSERT_RTNL();
853 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ifm), flags); 854 nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ifm), flags);
854 if (nlh == NULL) 855 if (nlh == NULL)
855 return -EMSGSIZE; 856 return -EMSGSIZE;
@@ -1876,6 +1877,7 @@ static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
1876 int min_len; 1877 int min_len;
1877 int family; 1878 int family;
1878 int type; 1879 int type;
1880 int err;
1879 1881
1880 type = nlh->nlmsg_type; 1882 type = nlh->nlmsg_type;
1881 if (type > RTM_MAX) 1883 if (type > RTM_MAX)
@@ -1902,8 +1904,11 @@ static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
1902 if (dumpit == NULL) 1904 if (dumpit == NULL)
1903 return -EOPNOTSUPP; 1905 return -EOPNOTSUPP;
1904 1906
1907 __rtnl_unlock();
1905 rtnl = net->rtnl; 1908 rtnl = net->rtnl;
1906 return netlink_dump_start(rtnl, skb, nlh, dumpit, NULL); 1909 err = netlink_dump_start(rtnl, skb, nlh, dumpit, NULL);
1910 rtnl_lock();
1911 return err;
1907 } 1912 }
1908 1913
1909 memset(rta_buf, 0, (rtattr_max * sizeof(struct rtattr *))); 1914 memset(rta_buf, 0, (rtattr_max * sizeof(struct rtattr *)));
@@ -1975,7 +1980,7 @@ static int __net_init rtnetlink_net_init(struct net *net)
1975{ 1980{
1976 struct sock *sk; 1981 struct sock *sk;
1977 sk = netlink_kernel_create(net, NETLINK_ROUTE, RTNLGRP_MAX, 1982 sk = netlink_kernel_create(net, NETLINK_ROUTE, RTNLGRP_MAX,
1978 rtnetlink_rcv, NULL, THIS_MODULE); 1983 rtnetlink_rcv, &rtnl_mutex, THIS_MODULE);
1979 if (!sk) 1984 if (!sk)
1980 return -ENOMEM; 1985 return -ENOMEM;
1981 net->rtnl = sk; 1986 net->rtnl = sk;