Re: [bug] __nf_ct_refresh_acct(): WARNING: at lib/list_debug.c:30__list_add+0x7d/0xad()

From: Patrick McHardy
Date: Thu Jun 18 2009 - 12:10:04 EST

Eric Dumazet wrote:
In my own analysis, I found death_by_timeout() might be problematic,
with RCU and lockless lookups.

static void death_by_timeout(unsigned long ul_conntrack)
struct nf_conn *ct = (void *)ul_conntrack;

if (!test_bit(IPS_DYING_BIT, &ct->status) &&
unlikely(nf_conntrack_event(IPCT_DESTROY, ct) < 0)) {
/* destroy event was not delivered */
<< HERE >>

set_bit(IPS_DYING_BIT, &ct->status);

We delete ct from a list and insert it in a new list.

I believe a reader could "*catch*" ct while doing a lookup and miss the end
of its chain. (nulls algo check the null value at the end of lookup and can
decide to restart the lookup if the null value is not the expected one)

We need to change nf_conntrack_init_net() and use a different "null" value,
guaranteed not being used in regular lists

Good catch. This is a new bug, but it shouldn't matter in this case
since nf_conntrack_event() can't fail unless you have a userspace
listener that makes use of reliable delivery, which I think hasn't
even been released yet.

Patch follows :

Looks good. If you send me a Signed-off-by: I'll already apply it.
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at
Please read the FAQ at