diff options
author | Eric Dumazet <eric.dumazet@gmail.com> | 2011-11-29 16:31:23 -0500 |
---|---|---|
committer | Roland Dreier <roland@purestorage.com> | 2011-11-29 16:37:11 -0500 |
commit | 580da35a31f91a594f3090b7a2c39b85cb051a12 (patch) | |
tree | 8cb8f106fe3c5df725dbde3efd2bfd19e0f38a2e /drivers/infiniband/core | |
parent | 1ea6b8f48918282bdca0b32a34095504ee65bab5 (diff) |
IB: Fix RCU lockdep splats
Commit f2c31e32b37 ("net: fix NULL dereferences in check_peer_redir()")
forgot to take care of infiniband uses of dst neighbours.
Many thanks to Marc Aurele who provided a nice bug report and feedback.
Reported-by: Marc Aurele La France <tsi@ualberta.ca>
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
Cc: David Miller <davem@davemloft.net>
Cc: <stable@kernel.org>
Signed-off-by: Roland Dreier <roland@purestorage.com>
Diffstat (limited to 'drivers/infiniband/core')
-rw-r--r-- | drivers/infiniband/core/addr.c | 9 |
1 files changed, 6 insertions, 3 deletions
diff --git a/drivers/infiniband/core/addr.c b/drivers/infiniband/core/addr.c index 691276bafd78..e9cf51b1343b 100644 --- a/drivers/infiniband/core/addr.c +++ b/drivers/infiniband/core/addr.c | |||
@@ -216,7 +216,9 @@ static int addr4_resolve(struct sockaddr_in *src_in, | |||
216 | 216 | ||
217 | neigh = neigh_lookup(&arp_tbl, &rt->rt_gateway, rt->dst.dev); | 217 | neigh = neigh_lookup(&arp_tbl, &rt->rt_gateway, rt->dst.dev); |
218 | if (!neigh || !(neigh->nud_state & NUD_VALID)) { | 218 | if (!neigh || !(neigh->nud_state & NUD_VALID)) { |
219 | rcu_read_lock(); | ||
219 | neigh_event_send(dst_get_neighbour(&rt->dst), NULL); | 220 | neigh_event_send(dst_get_neighbour(&rt->dst), NULL); |
221 | rcu_read_unlock(); | ||
220 | ret = -ENODATA; | 222 | ret = -ENODATA; |
221 | if (neigh) | 223 | if (neigh) |
222 | goto release; | 224 | goto release; |
@@ -274,15 +276,16 @@ static int addr6_resolve(struct sockaddr_in6 *src_in, | |||
274 | goto put; | 276 | goto put; |
275 | } | 277 | } |
276 | 278 | ||
279 | rcu_read_lock(); | ||
277 | neigh = dst_get_neighbour(dst); | 280 | neigh = dst_get_neighbour(dst); |
278 | if (!neigh || !(neigh->nud_state & NUD_VALID)) { | 281 | if (!neigh || !(neigh->nud_state & NUD_VALID)) { |
279 | if (neigh) | 282 | if (neigh) |
280 | neigh_event_send(neigh, NULL); | 283 | neigh_event_send(neigh, NULL); |
281 | ret = -ENODATA; | 284 | ret = -ENODATA; |
282 | goto put; | 285 | } else { |
286 | ret = rdma_copy_addr(addr, dst->dev, neigh->ha); | ||
283 | } | 287 | } |
284 | 288 | rcu_read_unlock(); | |
285 | ret = rdma_copy_addr(addr, dst->dev, neigh->ha); | ||
286 | put: | 289 | put: |
287 | dst_release(dst); | 290 | dst_release(dst); |
288 | return ret; | 291 | return ret; |