[PATCH nf v2 2/2] netfilter: nf_conntrack_expect: reject reinsertion of DEAD expectations

Jaeyeong Lee <[email protected]>
Newsgroups gmane.comp.security.firewalls.netfilter.devel
Message-ID <[email protected]>
Since commit b8b09dc2bf35 ("netfilter: nf_conntrack_expect: use
conntrack GC to reap expectations"), nf_ct_unexpect_related() marks an
expectation as NF_CT_EXPECT_DEAD but leaves it linked until a GC or list
walker unlinks it.

Passing the same object to nf_ct_expect_related() again violates this
terminal-state invariant. If its tuple was changed and hashes to a
different bucket, __nf_ct_expect_check() does not encounter and unlink
the old DEAD entry. The still-linked object can then reach
nf_ct_expect_insert(), which links its hnode and lnode again and takes
another insertion reference, corrupting the expectation hash and the
per-master expectation list.

Reject DEAD expectations immediately after taking the expectation lock,
before the insertion checks can alter any expectation lists. Return
-EINVAL without warning or modifying the object or the lists, so an
invalid reinsertion cannot panic a kernel with panic_on_warn enabled.

Fixes: b8b09dc2bf35 ("netfilter: nf_conntrack_expect: use conntrack GC to reap expectations")
Link: https://lore.kernel.org/netfilter-devel/2026071235-geometric-snowdrift-bb4c@gregkh/
Suggested-by: Florian Westphal <[email protected]>
Signed-off-by: Jaeyeong Lee <[email protected]>
---
Changes in v2:
- New patch, based on a suggestion from Florian Westphal.
- Return -EINVAL without WARN_ON_ONCE to avoid panic_on_warn, as pointed
  out by Greg Kroah-Hartman.

 net/netfilter/nf_conntrack_expect.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c
index 7ae68d60586a..f02f9ecdb08f 100644
--- a/net/netfilter/nf_conntrack_expect.c
+++ b/net/netfilter/nf_conntrack_expect.c
@@ -524,6 +524,11 @@ int nf_ct_expect_related_report(struct nf_conntrack_expect *expect,
 	int ret;
 
 	spin_lock_bh(&nf_conntrack_expect_lock);
+	if (expect->flags & NF_CT_EXPECT_DEAD) {
+		ret = -EINVAL;
+		goto out;
+	}
+
 	master_help = nfct_help(expect->master);
 	if (!master_help) {
 		ret = -ESHUTDOWN;
-- 
2.43.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.