Commit f05713e0 authored by Eric Dumazet's avatar Eric Dumazet Committed by David S. Miller
Browse files

ipv6: convert fib6_ref to refcount_t



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: default avatarEric Dumazet <edumazet@google.com>
Cc: Wei Wang <weiwan@google.com>
Acked-by: default avatarWei Wang <weiwan@google.com>
Reviewed-by: default avatarDavid Ahern <dsahern@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 5ea71528
Loading
Loading
Loading
Loading
+4 −4
Original line number Diff line number Diff line
@@ -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);
}

+3 −3
Original line number Diff line number Diff line
@@ -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;
+1 −1
Original line number Diff line number Diff line
@@ -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,
};