All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH nf] netfilter: nf_conntrack: move expectation hlist_head on ct extension realloc
@ 2026-07-29  0:16 Pablo Neira Ayuso
  2026-07-29  0:39 ` Pablo Neira Ayuso
  0 siblings, 1 reply; 2+ messages in thread
From: Pablo Neira Ayuso @ 2026-07-29  0:16 UTC (permalink / raw)
  To: netfilter-devel

Commit 7c9664351980 ("netfilter: move nat hlist_head to nf_conn") moved
the nat hlist_head to nf_conn and it removes the .move callback for ct
extensions. This commit description already points to the same problem
that is being addressed for expectations by this patch:

 1. ...
 2. When reallocation of extension area occurs we need to fixup the
    bysource hash head via hlist_replace_rcu.

This means that the .pprev pointer of the first expectation might refer
to a stale hlist_head after reallocation.

This bug is now easier to trigger since the introduction of the commit
857b46027d6f ("netfilter: nft_ct: add ct expectations support") which
allows to create expectations before the ct extension area have been
fully set up for unconfirmed conntracks.

This patch uses hlist_move_list() because this conntrack is unconfirmed,
ie. not yet in the hashes, and it is neither visible to the conntrack
garbage collector nor ctnetlink.

Fixes: 857b46027d6f ("netfilter: nft_ct: add ct expectations support")
Reported-by: Jaeyeong Lee <iostreampy@proton.me>
Link: https://patch.msgid.link/20260715144755.00ea7dfcd9f@proton.me
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
---
 net/netfilter/nf_conntrack_extend.c | 33 ++++++++++++++++++++++++++++-
 1 file changed, 32 insertions(+), 1 deletion(-)

diff --git a/net/netfilter/nf_conntrack_extend.c b/net/netfilter/nf_conntrack_extend.c
index 0da105e1ded9..ea7795a2461f 100644
--- a/net/netfilter/nf_conntrack_extend.c
+++ b/net/netfilter/nf_conntrack_extend.c
@@ -87,9 +87,34 @@ static __always_inline unsigned int total_extension_size(void)
 	;
 }
 
+static void nf_ct_ext_helper_save(struct nf_conn *ct,
+				  struct hlist_head *expectations)
+{
+	struct nf_conn_help *help;
+
+	help = nf_ct_ext_find(ct, NF_CT_EXT_HELPER);
+	if (!help)
+		return;
+
+	hlist_move_list(&help->expectations, expectations);
+}
+
+static void nf_ct_ext_helper_restore(struct nf_conn *ct,
+				     struct hlist_head *expectations)
+{
+	struct nf_conn_help *help;
+
+	help = nf_ct_ext_find(ct, NF_CT_EXT_HELPER);
+	if (!help)
+		return;
+
+	hlist_move_list(expectations, &help->expectations);
+}
+
 void *nf_ct_ext_add(struct nf_conn *ct, enum nf_ct_ext_id id, gfp_t gfp)
 {
 	unsigned int newlen, newoff, oldlen, alloc;
+	HLIST_HEAD(expectations);
 	struct nf_ct_ext *new;
 
 	/* Conntrack must not be confirmed to avoid races on reallocation. */
@@ -108,13 +133,17 @@ void *nf_ct_ext_add(struct nf_conn *ct, enum nf_ct_ext_id id, gfp_t gfp)
 		oldlen = sizeof(*new);
 	}
 
+	nf_ct_ext_helper_save(ct, &expectations);
+
 	newoff = ALIGN(oldlen, __alignof__(struct nf_ct_ext));
 	newlen = newoff + nf_ct_ext_type_len[id];
 
 	alloc = max(newlen, NF_CT_EXT_PREALLOC);
 	new = krealloc(ct->ext, alloc, gfp);
-	if (!new)
+	if (!new) {
+		nf_ct_ext_helper_restore(ct, &expectations);
 		return NULL;
+	}
 
 	if (!ct->ext)
 		memset(new->offset, 0, sizeof(new->offset));
@@ -124,6 +153,8 @@ void *nf_ct_ext_add(struct nf_conn *ct, enum nf_ct_ext_id id, gfp_t gfp)
 	memset((void *)new + newoff, 0, newlen - newoff);
 
 	ct->ext = new;
+	nf_ct_ext_helper_restore(ct, &expectations);
+
 	return (void *)new + newoff;
 }
 EXPORT_SYMBOL(nf_ct_ext_add);
-- 
2.47.3


^ permalink raw reply related	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2026-07-29  0:39 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-29  0:16 [PATCH nf] netfilter: nf_conntrack: move expectation hlist_head on ct extension realloc Pablo Neira Ayuso
2026-07-29  0:39 ` Pablo Neira Ayuso

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.