ipv6: convert fib6_ref to refcount_t
authorEric Dumazet <edumazet@google.com>
Tue, 23 Apr 2019 01:35:03 +0000 (18:35 -0700)
committerDavid S. Miller <davem@davemloft.net>
Wed, 24 Apr 2019 00:19:48 +0000 (17:19 -0700)
We suspect some issues involving fib6_ref 0 -> 1 transitions might
cause strange syzbot reports.

Lets convert fib6_ref to refcount_t to catch them earlier.

Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: Wei Wang <weiwan@google.com>
Acked-by: Wei Wang <weiwan@google.com>
Reviewed-by: David Ahern <dsahern@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/net/ip6_fib.h
net/ipv6/ip6_fib.c
net/ipv6/route.c

index 352f767..5a4a67b 100644 (file)
@@ -146,7 +146,7 @@ struct fib6_info {
        struct list_head                fib6_siblings;
        unsigned int                    fib6_nsiblings;
 
-       atomic_t                        fib6_ref;
+       refcount_t                      fib6_ref;
        unsigned long                   expires;
        struct dst_metrics              *fib6_metrics;
 #define fib6_pmtu              fib6_metrics->metrics[RTAX_MTU-1]
@@ -284,17 +284,17 @@ void fib6_info_destroy_rcu(struct rcu_head *head);
 
 static inline void fib6_info_hold(struct fib6_info *f6i)
 {
-       atomic_inc(&f6i->fib6_ref);
+       refcount_inc(&f6i->fib6_ref);
 }
 
 static inline bool fib6_info_hold_safe(struct fib6_info *f6i)
 {
-       return atomic_inc_not_zero(&f6i->fib6_ref);
+       return refcount_inc_not_zero(&f6i->fib6_ref);
 }
 
 static inline void fib6_info_release(struct fib6_info *f6i)
 {
-       if (f6i && atomic_dec_and_test(&f6i->fib6_ref))
+       if (f6i && refcount_dec_and_test(&f6i->fib6_ref))
                call_rcu(&f6i->rcu, fib6_info_destroy_rcu);
 }
 
index a5e8359..a8919c2 100644 (file)
@@ -162,7 +162,7 @@ struct fib6_info *fib6_info_alloc(gfp_t gfp_flags)
        }
 
        INIT_LIST_HEAD(&f6i->fib6_siblings);
-       atomic_set(&f6i->fib6_ref, 1);
+       refcount_set(&f6i->fib6_ref, 1);
 
        return f6i;
 }
@@ -929,7 +929,7 @@ static void fib6_purge_rt(struct fib6_info *rt, struct fib6_node *fn,
 {
        struct fib6_table *table = rt->fib6_table;
 
-       if (atomic_read(&rt->fib6_ref) != 1) {
+       if (refcount_read(&rt->fib6_ref) != 1) {
                /* This route is used as dummy address holder in some split
                 * nodes. It is not leaked, but it still holds other resources,
                 * which must be released in time. So, scan ascendant nodes
@@ -2311,7 +2311,7 @@ static int ipv6_route_seq_show(struct seq_file *seq, void *v)
 
        dev = rt->fib6_nh.fib_nh_dev;
        seq_printf(seq, " %08x %08x %08x %08x %8s\n",
-                  rt->fib6_metric, atomic_read(&rt->fib6_ref), 0,
+                  rt->fib6_metric, refcount_read(&rt->fib6_ref), 0,
                   flags, dev ? dev->name : "");
        iter->w.leaf = NULL;
        return 0;
index 844b16d..923af51 100644 (file)
@@ -296,7 +296,7 @@ static const struct fib6_info fib6_null_entry_template = {
        .fib6_flags     = (RTF_REJECT | RTF_NONEXTHOP),
        .fib6_protocol  = RTPROT_KERNEL,
        .fib6_metric    = ~(u32)0,
-       .fib6_ref       = ATOMIC_INIT(1),
+       .fib6_ref       = REFCOUNT_INIT(1),
        .fib6_type      = RTN_UNREACHABLE,
        .fib6_metrics   = (struct dst_metrics *)&dst_default_metrics,
 };