Hello,

On Tue, 30 May 2017, Sowmini Varadhan wrote:

> @@ -1650,6 +1689,7 @@ static int neigh_delete(struct sk_buff *skb, struct 
> nlmsghdr *nlh,
>                          NEIGH_UPDATE_F_ADMIN,
>                          NETLINK_CB(skb).portid);
>       neigh_release(neigh);
> +     neigh_remove_one(neigh, tbl);

        So, we do not hold reference to neigh while accessing
its fields. I suspect we need to move the table lock from
neigh_remove_one here, for example:

+       write_lock_bh(&tbl->lock);
        neigh_release(neigh);
+       neigh_remove_one(neigh, tbl);
+       write_unlock_bh(&tbl->lock);

        Otherwise, neigh_forced_gc can call neigh_destroy
where neigh is freed (and replaced by another neigh entry) after
RCU grace period (which can end prematurely if there are no
running RCU read-side critical sections) and I'm not sure if
our thread can be delayed, so that such pointer replacement
can happen unnoticed by us.

        Another solution to cause faster removal would be
to cancel the gc_work and to schedule it after 1 jiffie.
It helps when many entries are deleted at once but the
work prefers to just sleep when gc_thresh1 is not reached,
so such solution is not good enough.

Regards

--
Julian Anastasov <j...@ssi.bg>

Reply via email to