Commit 580da35a31f91a594f3090b7a2c39b85cb051a12

Authored by Eric Dumazet
Committed by Roland Dreier
1 parent 1ea6b8f489

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>

Showing 6 changed files with 35 additions and 14 deletions Side-by-side Diff

drivers/infiniband/core/addr.c
... ... @@ -216,7 +216,9 @@
216 216  
217 217 neigh = neigh_lookup(&arp_tbl, &rt->rt_gateway, rt->dst.dev);
218 218 if (!neigh || !(neigh->nud_state & NUD_VALID)) {
  219 + rcu_read_lock();
219 220 neigh_event_send(dst_get_neighbour(&rt->dst), NULL);
  221 + rcu_read_unlock();
220 222 ret = -ENODATA;
221 223 if (neigh)
222 224 goto release;
223 225  
224 226  
... ... @@ -274,15 +276,16 @@
274 276 goto put;
275 277 }
276 278  
  279 + rcu_read_lock();
277 280 neigh = dst_get_neighbour(dst);
278 281 if (!neigh || !(neigh->nud_state & NUD_VALID)) {
279 282 if (neigh)
280 283 neigh_event_send(neigh, NULL);
281 284 ret = -ENODATA;
282   - goto put;
  285 + } else {
  286 + ret = rdma_copy_addr(addr, dst->dev, neigh->ha);
283 287 }
284   -
285   - ret = rdma_copy_addr(addr, dst->dev, neigh->ha);
  288 + rcu_read_unlock();
286 289 put:
287 290 dst_release(dst);
288 291 return ret;
drivers/infiniband/hw/cxgb3/iwch_cm.c
... ... @@ -1375,8 +1375,10 @@
1375 1375 goto reject;
1376 1376 }
1377 1377 dst = &rt->dst;
  1378 + rcu_read_lock();
1378 1379 neigh = dst_get_neighbour(dst);
1379 1380 l2t = t3_l2t_get(tdev, neigh, neigh->dev);
  1381 + rcu_read_unlock();
1380 1382 if (!l2t) {
1381 1383 printk(KERN_ERR MOD "%s - failed to allocate l2t entry!\n",
1382 1384 __func__);
1383 1385  
... ... @@ -1946,10 +1948,12 @@
1946 1948 }
1947 1949 ep->dst = &rt->dst;
1948 1950  
  1951 + rcu_read_lock();
1949 1952 neigh = dst_get_neighbour(ep->dst);
1950 1953  
1951 1954 /* get a l2t entry */
1952 1955 ep->l2t = t3_l2t_get(ep->com.tdev, neigh, neigh->dev);
  1956 + rcu_read_unlock();
1953 1957 if (!ep->l2t) {
1954 1958 printk(KERN_ERR MOD "%s - cannot alloc l2e.\n", __func__);
1955 1959 err = -ENOMEM;
drivers/infiniband/hw/cxgb4/cm.c
... ... @@ -1594,6 +1594,7 @@
1594 1594 goto reject;
1595 1595 }
1596 1596 dst = &rt->dst;
  1597 + rcu_read_lock();
1597 1598 neigh = dst_get_neighbour(dst);
1598 1599 if (neigh->dev->flags & IFF_LOOPBACK) {
1599 1600 pdev = ip_dev_find(&init_net, peer_ip);
... ... @@ -1620,6 +1621,7 @@
1620 1621 rss_qid = dev->rdev.lldi.rxq_ids[
1621 1622 cxgb4_port_idx(neigh->dev) * step];
1622 1623 }
  1624 + rcu_read_unlock();
1623 1625 if (!l2t) {
1624 1626 printk(KERN_ERR MOD "%s - failed to allocate l2t entry!\n",
1625 1627 __func__);
... ... @@ -1820,6 +1822,7 @@
1820 1822 }
1821 1823 ep->dst = &rt->dst;
1822 1824  
  1825 + rcu_read_lock();
1823 1826 neigh = dst_get_neighbour(ep->dst);
1824 1827  
1825 1828 /* get a l2t entry */
... ... @@ -1856,6 +1859,7 @@
1856 1859 ep->rss_qid = ep->com.dev->rdev.lldi.rxq_ids[
1857 1860 cxgb4_port_idx(neigh->dev) * step];
1858 1861 }
  1862 + rcu_read_unlock();
1859 1863 if (!ep->l2t) {
1860 1864 printk(KERN_ERR MOD "%s - cannot alloc l2e.\n", __func__);
1861 1865 err = -ENOMEM;
... ... @@ -2301,6 +2305,7 @@
2301 2305 }
2302 2306 ep->dst = &rt->dst;
2303 2307  
  2308 + rcu_read_lock();
2304 2309 neigh = dst_get_neighbour(ep->dst);
2305 2310  
2306 2311 /* get a l2t entry */
... ... @@ -2339,6 +2344,7 @@
2339 2344 ep->retry_with_mpa_v1 = 0;
2340 2345 ep->tried_with_mpa_v1 = 0;
2341 2346 }
  2347 + rcu_read_unlock();
2342 2348 if (!ep->l2t) {
2343 2349 printk(KERN_ERR MOD "%s - cannot alloc l2e.\n", __func__);
2344 2350 err = -ENOMEM;
drivers/infiniband/hw/nes/nes_cm.c
... ... @@ -1377,9 +1377,11 @@
1377 1377 neigh_release(neigh);
1378 1378 }
1379 1379  
1380   - if ((neigh == NULL) || (!(neigh->nud_state & NUD_VALID)))
  1380 + if ((neigh == NULL) || (!(neigh->nud_state & NUD_VALID))) {
  1381 + rcu_read_lock();
1381 1382 neigh_event_send(dst_get_neighbour(&rt->dst), NULL);
1382   -
  1383 + rcu_read_unlock();
  1384 + }
1383 1385 ip_rt_put(rt);
1384 1386 return rc;
1385 1387 }
drivers/infiniband/ulp/ipoib/ipoib_main.c
... ... @@ -555,6 +555,7 @@
555 555 return 0;
556 556 }
557 557  
  558 +/* called with rcu_read_lock */
558 559 static void neigh_add_path(struct sk_buff *skb, struct net_device *dev)
559 560 {
560 561 struct ipoib_dev_priv *priv = netdev_priv(dev);
... ... @@ -636,6 +637,7 @@
636 637 spin_unlock_irqrestore(&priv->lock, flags);
637 638 }
638 639  
  640 +/* called with rcu_read_lock */
639 641 static void ipoib_path_lookup(struct sk_buff *skb, struct net_device *dev)
640 642 {
641 643 struct ipoib_dev_priv *priv = netdev_priv(skb->dev);
642 644  
... ... @@ -720,13 +722,14 @@
720 722 struct neighbour *n = NULL;
721 723 unsigned long flags;
722 724  
  725 + rcu_read_lock();
723 726 if (likely(skb_dst(skb)))
724 727 n = dst_get_neighbour(skb_dst(skb));
725 728  
726 729 if (likely(n)) {
727 730 if (unlikely(!*to_ipoib_neigh(n))) {
728 731 ipoib_path_lookup(skb, dev);
729   - return NETDEV_TX_OK;
  732 + goto unlock;
730 733 }
731 734  
732 735 neigh = *to_ipoib_neigh(n);
733 736  
734 737  
... ... @@ -749,17 +752,17 @@
749 752 ipoib_neigh_free(dev, neigh);
750 753 spin_unlock_irqrestore(&priv->lock, flags);
751 754 ipoib_path_lookup(skb, dev);
752   - return NETDEV_TX_OK;
  755 + goto unlock;
753 756 }
754 757  
755 758 if (ipoib_cm_get(neigh)) {
756 759 if (ipoib_cm_up(neigh)) {
757 760 ipoib_cm_send(dev, skb, ipoib_cm_get(neigh));
758   - return NETDEV_TX_OK;
  761 + goto unlock;
759 762 }
760 763 } else if (neigh->ah) {
761 764 ipoib_send(dev, skb, neigh->ah, IPOIB_QPN(n->ha));
762   - return NETDEV_TX_OK;
  765 + goto unlock;
763 766 }
764 767  
765 768 if (skb_queue_len(&neigh->queue) < IPOIB_MAX_PATH_REC_QUEUE) {
766 769  
... ... @@ -793,13 +796,14 @@
793 796 phdr->hwaddr + 4);
794 797 dev_kfree_skb_any(skb);
795 798 ++dev->stats.tx_dropped;
796   - return NETDEV_TX_OK;
  799 + goto unlock;
797 800 }
798 801  
799 802 unicast_arp_send(skb, dev, phdr);
800 803 }
801 804 }
802   -
  805 +unlock:
  806 + rcu_read_unlock();
803 807 return NETDEV_TX_OK;
804 808 }
805 809  
... ... @@ -837,7 +841,7 @@
837 841 dst = skb_dst(skb);
838 842 n = NULL;
839 843 if (dst)
840   - n = dst_get_neighbour(dst);
  844 + n = dst_get_neighbour_raw(dst);
841 845 if ((!dst || !n) && daddr) {
842 846 struct ipoib_pseudoheader *phdr =
843 847 (struct ipoib_pseudoheader *) skb_push(skb, sizeof *phdr);
drivers/infiniband/ulp/ipoib/ipoib_multicast.c
... ... @@ -266,7 +266,7 @@
266 266  
267 267 skb->dev = dev;
268 268 if (dst)
269   - n = dst_get_neighbour(dst);
  269 + n = dst_get_neighbour_raw(dst);
270 270 if (!dst || !n) {
271 271 /* put pseudoheader back on for next time */
272 272 skb_push(skb, sizeof (struct ipoib_pseudoheader));
... ... @@ -722,6 +722,8 @@
722 722 if (mcast && mcast->ah) {
723 723 struct dst_entry *dst = skb_dst(skb);
724 724 struct neighbour *n = NULL;
  725 +
  726 + rcu_read_lock();
725 727 if (dst)
726 728 n = dst_get_neighbour(dst);
727 729 if (n && !*to_ipoib_neigh(n)) {
... ... @@ -734,7 +736,7 @@
734 736 list_add_tail(&neigh->list, &mcast->neigh_list);
735 737 }
736 738 }
737   -
  739 + rcu_read_unlock();
738 740 spin_unlock_irqrestore(&priv->lock, flags);
739 741 ipoib_send(dev, skb, mcast->ah, IB_MULTICAST_QPN);
740 742 return;