On 9/8/20 2:20 AM, Eric Dumazet wrote: > syzbot reported twice a lockdep issue in fib6_del() [1] > which I think is caused by net->ipv6.fib6_null_entry > having a NULL fib6_table pointer. > > fib6_del() already checks for fib6_null_entry special > case, we only need to return earlier. > > Bug seems to occur very rarely, I have thus chosen > a 'bug origin' that makes backports not too complex.
Make sense. > > [1] ... > > Fixes: 421842edeaf6 ("net/ipv6: Add fib6_null_entry") > Signed-off-by: Eric Dumazet <eduma...@google.com> > Cc: David Ahern <dsah...@gmail.com> > --- > net/ipv6/ip6_fib.c | 13 +++++++++---- > 1 file changed, 9 insertions(+), 4 deletions(-) > > diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c > index > 25a90f3f705c7e6d53615f490f36c5722f3bd8b1..4a664ad4f4d4bb2b521f67e8433a06c77bd301ee > 100644 > --- a/net/ipv6/ip6_fib.c > +++ b/net/ipv6/ip6_fib.c > @@ -1993,14 +1993,19 @@ static void fib6_del_route(struct fib6_table *table, > struct fib6_node *fn, > /* Need to own table->tb6_lock */ > int fib6_del(struct fib6_info *rt, struct nl_info *info) > { > - struct fib6_node *fn = rcu_dereference_protected(rt->fib6_node, > - lockdep_is_held(&rt->fib6_table->tb6_lock)); > - struct fib6_table *table = rt->fib6_table; > struct net *net = info->nl_net; > struct fib6_info __rcu **rtp; > struct fib6_info __rcu **rtp_next; > + struct fib6_table *table; > + struct fib6_node *fn; > > - if (!fn || rt == net->ipv6.fib6_null_entry) > + if (rt == net->ipv6.fib6_null_entry) > + return -ENOENT; > + > + table = rt->fib6_table; > + fn = rcu_dereference_protected(rt->fib6_node, > + lockdep_is_held(&table->tb6_lock)); > + if (!fn) > return -ENOENT; > > WARN_ON(!(fn->fn_flags & RTN_RTINFO)); > seems like a reasonable refactoring for the noted problem. Reviewed-by: David Ahern <dsah...@gmail.com>