[PATCH AUTOSEL 6.18-5.10] netfilter: nf_conntrack_expect: zero at allocation time

Sasha Levin <[email protected]>
Newsgroups gmane.linux.kernel.stable,gmane.comp.security.firewalls.netfilter.devel,gmane.linux.network,gmane.linux.kernel
Message-ID <[email protected]>
From: Florian Westphal <[email protected]>

[ Upstream commit 241ccd2fed9051db443aadce248fc0ab30f55e97 ]

There are occasional LLM hints wrt. leaking uninitialized data to
userspace via ctnetlink.  Just zero at allocation time,
expectations are not frequently used these days.

Intentionally keeps _init as-is because we could theoretically
support re-init, so add the missing exp->dir there.

Signed-off-by: Florian Westphal <[email protected]>
Signed-off-by: Sasha Levin <[email protected]>
---

LLM Generated explanations, may be completely bogus:

## Phase 1: Commit Message Forensics

**Step 1.1 — Subject line**

Record: `[netfilter: nf_conntrack_expect]` `[zero]` — zero expectation
objects at allocation time to avoid leaking uninitialized slab data.

**Step 1.2 — Tags**

Record:
- Signed-off-by: Florian Westphal \<[email protected]\>
- No Fixes:, Reported-by:, Tested-by:, Reviewed-by:, Acked-by:, Link:,
  or Cc: stable tags

Notable: no formal bug report or syzbot link; author cites “occasional
LLM hints” about ctnetlink leaks.

**Step 1.3 — Body analysis**

Record:
- Bug: `nf_ct_expect_alloc()` uses non-zeroing `kmem_cache_alloc()`;
  fields not explicitly initialized can retain stale slab contents and
  be exposed to userspace via ctnetlink expectation dumps.
- Symptom: spurious or stale data in netlink expectation dumps
  (especially NAT-related attributes).
- Root cause: per-field initialization is incomplete across allocation
  paths; centralized zeroing at alloc is safer.
- Author notes expectations are rarely used today; keeps
  `nf_ct_expect_init()` behavior but adds missing `exp->dir`
  initialization there.

**Step 1.4 — Hidden bug fix?**

Record: Yes. Despite the soft wording, this is a kernel heap
information-leak fix, not a style change. The `kmem_cache_alloc` →
`kmem_cache_zalloc` change and `exp->dir = 0` addition address
uninitialized memory exposure.

---

## Phase 2: Diff Analysis

**Step 2.1 — Inventory**

Record:
- `net/netfilter/nf_conntrack_expect.c`: +2 / -1 (3 lines touched)
- `net/netfilter/nf_conntrack_netlink.c`: +1 / -10 (11 lines removed)
- Functions: `nf_ct_expect_alloc()`, `nf_ct_expect_init()`,
  `ctnetlink_alloc_expect()`
- Scope: small, two-file, surgical fix

**Step 2.2 — Code flow per hunk**

Record:
1. `nf_ct_expect_alloc()`: `kmem_cache_alloc` → `kmem_cache_zalloc` —
   all struct fields start zeroed.
2. `nf_ct_expect_init()`: adds `exp->dir = 0` under `CONFIG_NF_NAT`
   alongside existing `saved_addr`/`saved_proto` zeroing.
3. `ctnetlink_alloc_expect()`: removes redundant `else` branches that
   zeroed `flags`, `expectfn`, and NAT fields — now handled by zalloc.

**Step 2.3 — Bug mechanism**

Record: **Uninitialized data / information leak (category 8)**. Slab
reuse leaves stale kernel data in `struct nf_conntrack_expect` fields.
`ctnetlink_exp_dump_expect()` reads `exp->flags`, and under
`CONFIG_NF_NAT` emits `CTA_EXPECT_NAT` when `saved_addr`/`saved_proto`
look non-zero, leaking stale addresses/ports/direction to userspace.

**Step 2.4 — Fix quality**

Record: Fix is obviously correct and minimal. `kmem_cache_zalloc` is the
standard pattern for objects with many partially-initialized fields.
Regression risk is very low; expectations are infrequent and zeroing
cost is negligible.

---

## Phase 3: Git History Investigation

**Step 3.1 — Blame**

Record: `kmem_cache_alloc(nf_ct_expect_cachep, GFP_ATOMIC)` dates to
Patrick McHardy (2007). Bug has existed since expectations used a non-
zeroing slab allocator. `nf_ct_expect_init()` has zeroed
`saved_addr`/`saved_proto` since NAT support was added, but never
`exp->dir`.

**Step 3.2 — Fixes: tag**

Record: N/A — no Fixes: tag in this commit.

**Step 3.3 — Related file history**

Record: Related commit already in this tree:
- `929f7a9a7aad9` — “netfilter: ctnetlink: zero expect NAT fields when
  CTA_EXPECT_NAT absent” — targeted partial fix for the ctnetlink
  userspace creation path only, with a concrete reproduction (kernel
  test robot).

This commit generalizes the fix to all allocation paths and removes the
now-redundant ctnetlink `else` branches.

**Step 3.4 — Author context**

Record: Florian Westphal is an active netfilter contributor/maintainer.
Similar leak fix `7e23965d44f06` (“nft_meta_bridge: fix
NFT_META_BRI_IIFPVID stack leak”) is already in this 6.18.y tree.

**Step 3.5 — Dependencies**

Record: Standalone; no series prerequisites. `git apply --check` on
commit `241ccd2fed905` succeeds cleanly against HEAD.

---

## Phase 4: Mailing List and External Research

**Step 4.1 — Original discussion**

Record: `b4 dig -c 241ccd2fed905` found v1 only at
https://patch.msgid.link/[email protected]. Lore fetch
blocked by bot protection; no reviewer replies retrieved.

**Step 4.2 — Reviewers**

Record: `b4 dig -w` shows recipients: Florian Westphal, netfilter-
[email protected]. No explicit maintainer Acked-by in commit.

**Step 4.3 — Bug report**

Record: No formal Reported-by in this commit. Related bug in
`929f7a9a7aad9` was Reported-by: kernel test robot with demonstrated
stale `CTA_EXPECT_NAT` emission.

**Step 4.4 — Series context**

Record: Single-patch series (v1 only). Not part of a multi-patch
dependency chain.

**Step 4.5 — Stable list**

Record: Not searched (lore blocked). Similar Westphal leak fix already
accepted into this stable tree.

---

## Phase 5: Code Semantic Analysis

**Step 5.1 — Key functions**

Record: `nf_ct_expect_alloc()`, `nf_ct_expect_init()`,
`ctnetlink_alloc_expect()`, `ctnetlink_exp_dump_expect()`.

**Step 5.2 — Callers**

Record: `nf_ct_expect_alloc()` called from ~15 sites: protocol helpers
(FTP, SIP, H.323, PPTP, TFTP, IRC, etc.), `nf_conntrack_broadcast.c`,
`ctnetlink_alloc_expect()`, `nft_ct.c`, IPVS. Most call
`nf_ct_expect_init()` afterward; broadcast manually sets fields without
`nf_ct_expect_init()`.

**Step 5.3 — Callees**

Record: `kmem_cache_zalloc`/`kmem_cache_alloc`, `refcount_set`, slab
free via RCU. Dump path reads struct fields into netlink skb.

**Step 5.4 — Reachability**

Record: Leak is reachable when a privileged user dumps expectations via
ctnetlink (`ctnetlink_exp_dump_expect()`). Creating expectations via
broadcast helper (no NAT field init) and then dumping can expose stale
NAT data — path exists in this tree.

**Step 5.5 — Similar patterns**

Record: `929f7a9a7aad9` fixed the same class of bug narrowly in
ctnetlink. `nf_ct_expect_init()` already zeroes most fields on the
packet path but omitted `dir`. Centralized zalloc is the comprehensive
fix.

---

## Phase 6: Cross-Reference Against Local Tree (v6.18.44)

**Step 6.1 — Buggy code present?**

Record: Yes. HEAD is `v6.18.44` on `stable/linux-6.18.y`. Current code
still uses `kmem_cache_alloc` at line 307 of `nf_conntrack_expect.c`.
Commit `241ccd2fed905` is **not** in this tree.

**Step 6.2 — Backport complications**

Record: Clean apply verified. Removes code added by in-tree
`929f7a9a7aad9`; no structural conflicts.

**Step 6.3 — Related fixes already present**

Record: `929f7a9a7aad9` partially fixes ctnetlink NAT-field leak only.
Does **not** cover `nf_conntrack_broadcast.c` and other paths that
allocate without fully initializing NAT fields. This commit still adds
value.

---

## Phase 7: Subsystem Context

**Step 7.1 — Subsystem**

Record: netfilter / nf_conntrack / ctnetlink. Criticality: **IMPORTANT**
(networking core subsystem, widely deployed).

**Step 7.2 — Activity**

Record: Actively maintained; multiple recent expectation/ctnetlink fixes
in this tree’s history.

---

## Phase 8: Impact and Risk Assessment

**Step 8.1 — Who is affected**

Record: Systems with `CONFIG_NF_CONNTRACK` and ctnetlink users (firewall
managers, `conntrack` tools). Affects administrators/privileged tooling,
not unprivileged users directly.

**Step 8.2 — Trigger conditions**

Record: Allocate expectation without full field initialization (slab
reuse), then dump via ctnetlink. Moderately rare but reproducible
(demonstrated for ctnetlink path in `929f7a9a7aad9`). Requires
`CAP_NET_ADMIN` for dump.

**Step 8.3 — Failure mode**

Record: Kernel heap memory leaked to userspace via netlink attributes.
Severity: **MEDIUM** (security information disclosure, not
crash/corruption).

**Step 8.4 — Risk/benefit**

Record:
- Benefit: Closes remaining leak paths beyond the partial ctnetlink fix;
  defense-in-depth at the central allocator.
- Risk: Very low — 14-line change, standard zalloc pattern, infrequent
  code path.
- Ratio: Favorable for stable inclusion.

---

## Phase 9: Final Synthesis

**Step 9.1 — Evidence summary**

FOR:
- Real kernel memory info leak via ctnetlink
- Partial fix (`929f7a9a7aad9`) already in tree leaves gaps (e.g.,
  `nf_conntrack_broadcast.c` never initializes NAT fields)
- Tiny, obviously correct, applies cleanly
- Same author’s similar leak fixes already in 6.18.y
- Adds missing `exp->dir` init in `nf_ct_expect_init()`

AGAINST:
- Requires privileged access to observe leak
- Expectations are uncommon
- Primary reported case partially addressed by existing stable commit
- No syzbot/formal CVE; “LLM hints” only in this commit message

UNRESOLVED:
- Full lore review thread (bot-blocked)
- No independent Tested-by on this specific commit

**Step 9.2 — Stable rules checklist**

1. Obviously correct and tested? **PASS** — zalloc is standard; related
   leak class already reproduced in-tree via `929f7a9a7aad9`.
2. Fixes a real bug affecting users? **PASS** — verified stale-data leak
   path; broadcast path still vulnerable without this fix.
3. Important issue? **PASS** — security information leak (medium
   severity).
4. Small and contained? **PASS** — 14 lines, 2 files.
5. No new features/APIs? **PASS**.
6. Can apply to local tree? **PASS** — `git apply --check` succeeded.

**Step 9.3 — Exception category**

Record: N/A (not device ID, quirk, DT, build, or docs fix — standard bug
fix).

**Step 9.4 — Decision rationale**

This tree (6.18.44) still has the underlying allocator bug. While
`929f7a9a7aad9` patched one ctnetlink-specific leak, `kmem_cache_zalloc`
in `nf_ct_expect_alloc()` fixes all allocation paths comprehensively,
including `nf_conntrack_broadcast.c` which never calls
`nf_ct_expect_init()` and does not initialize NAT-related fields. The
change is minimal, low-risk, and consistent with other netfilter leak
fixes already accepted into this stable series.

---

## Verification

- [Phase 1] Parsed commit `241ccd2fed905`: subject, body, only SOB from
  Florian Westphal
- [Phase 2] Diff analysis: 2 files, `kmem_cache_zalloc`, `exp->dir = 0`,
  removed ctnetlink else branches
- [Phase 3] `git describe HEAD`: v6.18.44; tree is stable/linux-6.18.y
- [Phase 3] `git blame`: `kmem_cache_alloc` since 2007
- [Phase 3] `929f7a9a7aad9` confirmed in tree via `git merge-base --is-
  ancestor`
- [Phase 3] `241ccd2fed905` confirmed NOT in tree
- [Phase 3] `git apply --check` on patch: clean apply
- [Phase 4] `b4 dig -c 241ccd2fed905`: found v1 at
  patch.msgid.link/[email protected]
- [Phase 4] `b4 dig -w`: netfilter-devel CC'd
- [Phase 4] `b4 dig -a`: v1 only
- [Phase 4] Lore thread fetch: blocked by Anubis (UNVERIFIED: reviewer
  comments)
- [Phase 5] `grep nf_ct_expect_alloc`: 15+ call sites; broadcast path
  does not call `nf_ct_expect_init()`
- [Phase 5] Read `ctnetlink_exp_dump_expect()`: dumps flags always; NAT
  block when `saved_addr`/`saved_proto` non-zero
- [Phase 5] Read `nf_conntrack_broadcast.c`: does not init
  `saved_addr`/`saved_proto`/`dir`
- [Phase 6] Current code at line 307: still `kmem_cache_alloc`
- [Phase 6] `7e23965d44f06` similar Westphal leak fix present in tree
- [Phase 8] Trigger requires CAP_NET_ADMIN for ctnetlink dump (standard
  nfnetlink permission model)

**YES**

 net/netfilter/nf_conntrack_expect.c  |  3 ++-
 net/netfilter/nf_conntrack_netlink.c | 11 +----------
 2 files changed, 3 insertions(+), 11 deletions(-)

diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c
index 8e943efbdf0a5..6266d4d2ffca4 100644
--- a/net/netfilter/nf_conntrack_expect.c
+++ b/net/netfilter/nf_conntrack_expect.c
@@ -304,7 +304,7 @@ struct nf_conntrack_expect *nf_ct_expect_alloc(struct nf_conn *me)
 {
 	struct nf_conntrack_expect *new;
 
-	new = kmem_cache_alloc(nf_ct_expect_cachep, GFP_ATOMIC);
+	new = kmem_cache_zalloc(nf_ct_expect_cachep, GFP_ATOMIC);
 	if (!new)
 		return NULL;
 
@@ -386,6 +386,7 @@ void nf_ct_expect_init(struct nf_conntrack_expect *exp, unsigned int class,
 #if IS_ENABLED(CONFIG_NF_NAT)
 	memset(&exp->saved_addr, 0, sizeof(exp->saved_addr));
 	memset(&exp->saved_proto, 0, sizeof(exp->saved_proto));
+	exp->dir = 0;
 #endif
 }
 EXPORT_SYMBOL_GPL(nf_ct_expect_init);
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index 3df7e5fc76c8b..e046281895743 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -3559,8 +3559,6 @@ ctnetlink_alloc_expect(const struct nlattr * const cda[], struct nf_conn *ct,
 	if (cda[CTA_EXPECT_FLAGS]) {
 		exp->flags = ntohl(nla_get_be32(cda[CTA_EXPECT_FLAGS]));
 		exp->flags &= ~NF_CT_EXPECT_USERSPACE;
-	} else {
-		exp->flags = 0;
 	}
 	if (cda[CTA_EXPECT_FN]) {
 		const char *name = nla_data(cda[CTA_EXPECT_FN]);
@@ -3572,8 +3570,7 @@ ctnetlink_alloc_expect(const struct nlattr * const cda[], struct nf_conn *ct,
 			goto err_out;
 		}
 		exp->expectfn = expfn->expectfn;
-	} else
-		exp->expectfn = NULL;
+	}
 
 	exp->class = class;
 	exp->master = ct;
@@ -3592,12 +3589,6 @@ ctnetlink_alloc_expect(const struct nlattr * const cda[], struct nf_conn *ct,
 						 exp, nf_ct_l3num(ct));
 		if (err < 0)
 			goto err_out;
-#if IS_ENABLED(CONFIG_NF_NAT)
-	} else {
-		memset(&exp->saved_addr, 0, sizeof(exp->saved_addr));
-		memset(&exp->saved_proto, 0, sizeof(exp->saved_proto));
-		exp->dir = 0;
-#endif
 	}
 	return exp;
 err_out:
-- 
2.53.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.