Skip to content

Commit 63f55ac

Browse files
Florian Westphalummakynes
authored andcommitted
netfilter: ecache: document extension area access rules
Once ct->ext gets free'd via kfree() rather than kfree_rcu we can't access the extension area anymore without owning the conntrack. This is a special case: The worker is walking the pcpu dying list while holding dying list lock: Neither ct nor ct->ext can be free'd until after the walk has completed. Signed-off-by: Florian Westphal <[email protected]> Signed-off-by: Pablo Neira Ayuso <[email protected]>
1 parent f8615bf commit 63f55ac

File tree

1 file changed

+15
-2
lines changed

1 file changed

+15
-2
lines changed

net/netfilter/nf_conntrack_ecache.c

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
static DEFINE_MUTEX(nf_ct_ecache_mutex);
3131

3232
#define ECACHE_RETRY_WAIT (HZ/10)
33+
#define ECACHE_STACK_ALLOC (256 / sizeof(void *))
3334

3435
enum retry_state {
3536
STATE_CONGESTED,
@@ -39,11 +40,11 @@ enum retry_state {
3940

4041
static enum retry_state ecache_work_evict_list(struct ct_pcpu *pcpu)
4142
{
42-
struct nf_conn *refs[16];
43+
struct nf_conn *refs[ECACHE_STACK_ALLOC];
44+
enum retry_state ret = STATE_DONE;
4345
struct nf_conntrack_tuple_hash *h;
4446
struct hlist_nulls_node *n;
4547
unsigned int evicted = 0;
46-
enum retry_state ret = STATE_DONE;
4748

4849
spin_lock(&pcpu->lock);
4950

@@ -54,10 +55,22 @@ static enum retry_state ecache_work_evict_list(struct ct_pcpu *pcpu)
5455
if (!nf_ct_is_confirmed(ct))
5556
continue;
5657

58+
/* This ecache access is safe because the ct is on the
59+
* pcpu dying list and we hold the spinlock -- the entry
60+
* cannot be free'd until after the lock is released.
61+
*
62+
* This is true even if ct has a refcount of 0: the
63+
* cpu that is about to free the entry must remove it
64+
* from the dying list and needs the lock to do so.
65+
*/
5766
e = nf_ct_ecache_find(ct);
5867
if (!e || e->state != NFCT_ECACHE_DESTROY_FAIL)
5968
continue;
6069

70+
/* ct is in NFCT_ECACHE_DESTROY_FAIL state, this means
71+
* the worker owns this entry: the ct will remain valid
72+
* until the worker puts its ct reference.
73+
*/
6174
if (nf_conntrack_event(IPCT_DESTROY, ct)) {
6275
ret = STATE_CONGESTED;
6376
break;

0 commit comments

Comments
 (0)