neigh: Explicitly declare RCU-bh read side critical section in neigh_xmit()
[firefly-linux-kernel-4.4.55.git] / net / core / neighbour.c
index e6af42da28d9552643751a1af7dfcd96cad05c3d..769cece9b00b3829bdb3d56e707703c90c459a2e 100644 (file)
@@ -2215,7 +2215,7 @@ static int pneigh_fill_info(struct sk_buff *skb, struct pneigh_entry *pn,
        ndm->ndm_pad2    = 0;
        ndm->ndm_flags   = pn->flags | NTF_PROXY;
        ndm->ndm_type    = RTN_UNICAST;
-       ndm->ndm_ifindex = pn->dev->ifindex;
+       ndm->ndm_ifindex = pn->dev ? pn->dev->ifindex : 0;
        ndm->ndm_state   = NUD_NONE;
 
        if (nla_put(skb, NDA_DST, tbl->key_len, pn->key))
@@ -2333,7 +2333,7 @@ static int pneigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
                if (h > s_h)
                        s_idx = 0;
                for (n = tbl->phash_buckets[h], idx = 0; n; n = n->next) {
-                       if (dev_net(n->dev) != net)
+                       if (pneigh_net(n) != net)
                                continue;
                        if (idx < s_idx)
                                goto next;
@@ -2467,13 +2467,17 @@ int neigh_xmit(int index, struct net_device *dev,
                tbl = neigh_tables[index];
                if (!tbl)
                        goto out;
+               rcu_read_lock_bh();
                neigh = __neigh_lookup_noref(tbl, addr, dev);
                if (!neigh)
                        neigh = __neigh_create(tbl, addr, dev, false);
                err = PTR_ERR(neigh);
-               if (IS_ERR(neigh))
+               if (IS_ERR(neigh)) {
+                       rcu_read_unlock_bh();
                        goto out_kfree_skb;
+               }
                err = neigh->output(neigh, skb);
+               rcu_read_unlock_bh();
        }
        else if (index == NEIGH_LINK_TABLE) {
                err = dev_hard_header(skb, dev, ntohs(skb->protocol),