aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6
diff options
context:
space:
mode:
authorMarcelo Ricardo Leitner <marcelo.leitner@gmail.com>2015-03-20 10:37:17 -0400
committerDavid S. Miller <davem@davemloft.net>2015-03-20 13:32:38 -0400
commitc4a6853d8fb2b122686bc6a7c472956e87090f4e (patch)
tree21c8e63f1db8c82c8e5266374a82cc89fff1c270 /net/ipv6
parent149d7549c22045bc777a377720809b108639f9e9 (diff)
ipv6: invert join/leave anycast rtnl/socket locking order
Commit baf606d9c9b1 ("ipv4,ipv6: grab rtnl before locking the socket") missed to update two setsockopt options, IPV6_JOIN_ANYCAST and IPV6_LEAVE_ANYCAST, causing a lock inverstion regarding to the updated ones. As ipv6_sock_ac_join and ipv6_sock_ac_leave are only called from do_ipv6_setsockopt, we are good to just move the rtnl lock upper. Fixes: baf606d9c9b1 ("ipv4,ipv6: grab rtnl before locking the socket") Reported-by: Ying Huang <ying.huang@intel.com> Signed-off-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6')
-rw-r--r--net/ipv6/anycast.c12
-rw-r--r--net/ipv6/ipv6_sockglue.c2
2 files changed, 7 insertions, 7 deletions
diff --git a/net/ipv6/anycast.c b/net/ipv6/anycast.c
index baf2742d1ec4..9e6b0ee563f0 100644
--- a/net/ipv6/anycast.c
+++ b/net/ipv6/anycast.c
@@ -60,6 +60,8 @@ int ipv6_sock_ac_join(struct sock *sk, int ifindex, const struct in6_addr *addr)
60 int ishost = !net->ipv6.devconf_all->forwarding; 60 int ishost = !net->ipv6.devconf_all->forwarding;
61 int err = 0; 61 int err = 0;
62 62
63 ASSERT_RTNL();
64
63 if (!ns_capable(net->user_ns, CAP_NET_ADMIN)) 65 if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
64 return -EPERM; 66 return -EPERM;
65 if (ipv6_addr_is_multicast(addr)) 67 if (ipv6_addr_is_multicast(addr))
@@ -73,7 +75,6 @@ int ipv6_sock_ac_join(struct sock *sk, int ifindex, const struct in6_addr *addr)
73 pac->acl_next = NULL; 75 pac->acl_next = NULL;
74 pac->acl_addr = *addr; 76 pac->acl_addr = *addr;
75 77
76 rtnl_lock();
77 if (ifindex == 0) { 78 if (ifindex == 0) {
78 struct rt6_info *rt; 79 struct rt6_info *rt;
79 80
@@ -130,7 +131,6 @@ int ipv6_sock_ac_join(struct sock *sk, int ifindex, const struct in6_addr *addr)
130 } 131 }
131 132
132error: 133error:
133 rtnl_unlock();
134 if (pac) 134 if (pac)
135 sock_kfree_s(sk, pac, sizeof(*pac)); 135 sock_kfree_s(sk, pac, sizeof(*pac));
136 return err; 136 return err;
@@ -146,7 +146,8 @@ int ipv6_sock_ac_drop(struct sock *sk, int ifindex, const struct in6_addr *addr)
146 struct ipv6_ac_socklist *pac, *prev_pac; 146 struct ipv6_ac_socklist *pac, *prev_pac;
147 struct net *net = sock_net(sk); 147 struct net *net = sock_net(sk);
148 148
149 rtnl_lock(); 149 ASSERT_RTNL();
150
150 prev_pac = NULL; 151 prev_pac = NULL;
151 for (pac = np->ipv6_ac_list; pac; pac = pac->acl_next) { 152 for (pac = np->ipv6_ac_list; pac; pac = pac->acl_next) {
152 if ((ifindex == 0 || pac->acl_ifindex == ifindex) && 153 if ((ifindex == 0 || pac->acl_ifindex == ifindex) &&
@@ -154,10 +155,8 @@ int ipv6_sock_ac_drop(struct sock *sk, int ifindex, const struct in6_addr *addr)
154 break; 155 break;
155 prev_pac = pac; 156 prev_pac = pac;
156 } 157 }
157 if (!pac) { 158 if (!pac)
158 rtnl_unlock();
159 return -ENOENT; 159 return -ENOENT;
160 }
161 if (prev_pac) 160 if (prev_pac)
162 prev_pac->acl_next = pac->acl_next; 161 prev_pac->acl_next = pac->acl_next;
163 else 162 else
@@ -166,7 +165,6 @@ int ipv6_sock_ac_drop(struct sock *sk, int ifindex, const struct in6_addr *addr)
166 dev = __dev_get_by_index(net, pac->acl_ifindex); 165 dev = __dev_get_by_index(net, pac->acl_ifindex);
167 if (dev) 166 if (dev)
168 ipv6_dev_ac_dec(dev, &pac->acl_addr); 167 ipv6_dev_ac_dec(dev, &pac->acl_addr);
169 rtnl_unlock();
170 168
171 sock_kfree_s(sk, pac, sizeof(*pac)); 169 sock_kfree_s(sk, pac, sizeof(*pac));
172 return 0; 170 return 0;
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c
index cc5883791bac..9b2cb1444230 100644
--- a/net/ipv6/ipv6_sockglue.c
+++ b/net/ipv6/ipv6_sockglue.c
@@ -122,6 +122,8 @@ static bool setsockopt_needs_rtnl(int optname)
122 switch (optname) { 122 switch (optname) {
123 case IPV6_ADD_MEMBERSHIP: 123 case IPV6_ADD_MEMBERSHIP:
124 case IPV6_DROP_MEMBERSHIP: 124 case IPV6_DROP_MEMBERSHIP:
125 case IPV6_JOIN_ANYCAST:
126 case IPV6_LEAVE_ANYCAST:
125 case MCAST_JOIN_GROUP: 127 case MCAST_JOIN_GROUP:
126 case MCAST_LEAVE_GROUP: 128 case MCAST_LEAVE_GROUP:
127 case MCAST_JOIN_SOURCE_GROUP: 129 case MCAST_JOIN_SOURCE_GROUP: