From nobody Sat Sep 26 18:53:53 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-alma10-1.taild15c8.ts.net [100.103.45.18]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AE9B44582EA; Mon, 31 Aug 2026 13:34:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=100.103.45.18 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788183279; cv=none; b=NHq6noe4iUjMyAJElSiVSd+i+5055KHOoWimyf27J6JT19zWfXFLno2AK1f7ykv/3b0ZSOzQowquNahxBJX63f0UFO1nIeVrUvB3AKBjalxLCEG8Su2Ztj/cpDNBr39MUqYKdZlz7NxIOzJk0WRLJXBuTnLPstl5JWJwRhhkokM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788183279; c=relaxed/simple; bh=YJizs2VqBuIyojrxVICumIbnQrmoxahOKx5orOk+J9s=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=lrGQA01f8gN1iWyFwLg9D6jnFBdM6CDWc1JnI5nc0qrWn5LGYJrHLFz6GN1qUWeC49qvqT3leBD6mrP04o5KS8kJANXTAAFj+4bpyC6MwNWbDDJmYJHxOcvkl9CRnXfnpkv84QkzYzjqhMLhYMTTcaK5GAj6ae8+G+/O77Fgrug= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=cet1VFYp; arc=none smtp.client-ip=100.103.45.18 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="cet1VFYp" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 5DED31F000E9; Mon, 31 Aug 2026 13:34:36 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1788183277; bh=Mv1Ml1dy034fuDULIdoxng0b3t1Uqj3HHmg1kDNJjak=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=cet1VFYppTYsj2vb7lK5LBN8tCRqms5OwvI7ENvEXnjwCFRsdSQTbVEpFtf9+E1od qhrTzL9uHKrIb3QGWSgV2HtzfeAsqGfJ1wQn+nE0BZsXjk7kJqk1D1h52uHke2EUL3 W3Dw+M5JvNK30DqksofIZOjha8/gJysW6mCPEQMKinpC2xGk8p4mBUW/Xu71pBGQxw UBoPPNGWC0Ep+SXW/bWdkuILNbxuG8VdZ9YBSRleq6bkE/gzjsNs612JxmGqFydf+i AZTI+art8WXxVHcPBHDp2YHh1nDCBATQ1MfqaWHvBxKHu2IY2GxBukTFWA35gs2OKY gzsk8CQawCh7Q== From: Sasha Levin To: patches@lists.linux.dev, stable@vger.kernel.org Cc: Emmanuel Grumbach , Miri Korenblit , Sasha Levin , linux-wireless@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH AUTOSEL 6.18-6.12] wifi: iwlwifi: pcie: null RX pointers after free Date: Mon, 31 Aug 2026 09:21:19 -0400 Message-ID: <20260831133314.4125787-51-sashal@kernel.org> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260831133314.4125787-1-sashal@kernel.org> References: <20260831133314.4125787-1-sashal@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-stable: review X-Patchwork-Hint: Ignore X-stable-base: Linux 6.18.48 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable From: Emmanuel Grumbach [ Upstream commit 2c79d7a7b583050c9f58041465cb46fe3483ab5d ] When iwl_pcie_tx_init() fails after RX init, nic init unwinds via iwl_pcie_rx_free(). The freed RX members stayed non-NULL on the live transport object, so later teardown or retry could touch stale RX state. Set rx_pool, global_table, rxq, and alloc_page to NULL after free to make repeated cleanup and retry paths safe. Assisted-by: GitHubCopilot:gpt-5.3-codex Signed-off-by: Emmanuel Grumbach Link: https://patch.msgid.link/20260714141909.33e8978d8b36.Ibaedd4b0ce01405= b940de7b90223b6d2c5136ffd@changeid Signed-off-by: Miri Korenblit Signed-off-by: Sasha Levin --- LLM Generated explanations, may be completely bogus: ## Phase 1: Commit Message Forensics **Step 1.1 =E2=80=94 Subject line** Record: `[wifi: iwlwifi: pcie]` `[null]` =E2=80=94 Null out RX pointers aft= er `iwl_pcie_rx_free()` so teardown/retry does not use stale state. **Step 1.2 =E2=80=94 Tags** Record: - Fixes: =E2=80=94 not present (expected for candidate review) - Reported-by: =E2=80=94 none - Tested-by: =E2=80=94 none - Reviewed-by: =E2=80=94 none - Acked-by: =E2=80=94 none - Link: https://patch.msgid.link/20260714141909.33e8978d8b36... - Cc: stable@vger.kernel.org =E2=80=94 not present (expected) - Assisted-by: GitHubCopilot:gpt-5.3-codex - Signed-off-by: Emmanuel Grumbach, Miri Korenblit (ignore pipeline- added SOBs) Notable: no syzbot/user reports; author is Intel iwlwifi maintainer. **Step 1.3 =E2=80=94 Body** Record: - Bug: After RX init succeeds and `iwl_pcie_tx_init()` fails, `iwl_pcie_nic_init()` unwinds via `iwl_pcie_rx_free()`, but `rx_pool`, `global_table`, `rxq`, and `alloc_page` remain non-NULL. - Symptom: Later teardown or retry can touch freed RX state. - Root cause: `iwl_pcie_rx_free()` frees resources without clearing pointers, unlike the error path in `iwl_pcie_rx_alloc()`. **Step 1.4 =E2=80=94 Hidden bug fix?** Record: Yes. Despite not using =E2=80=9Cfix=E2=80=9D in the subject, this i= s a real memory-safety bug (double-free / use-after-free) on an error path, not cosmetic cleanup. --- ## Phase 2: Diff Analysis **Step 2.1 =E2=80=94 Inventory** Record: - File: `drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/rx.c` (+5 lines, copyright year tweak) - Function: `iwl_pcie_rx_free()` - Scope: single-file, surgical (~5 functional lines) **Step 2.2 =E2=80=94 Code flow change** Record: - Hunk 1 (`rx_pool`, `global_table`, `rxq`): before `kfree()` only =E2=86= =92 after `kfree()` + `=3D NULL` - Hunk 2 (`alloc_page`): before `__free_pages()` without clearing =E2=86=92 after `__free_pages()` + `alloc_page =3D NULL` - Affected path: RX teardown in `iwl_pcie_rx_free()`, especially when called from `iwl_pcie_nic_init()` error unwind **Step 2.3 =E2=80=94 Bug mechanism** Record: **Memory safety / double-free / UAF** - `iwl_pcie_rx_alloc()` err path already NULLs pointers (lines 826=E2=80=93= 831). - `iwl_pcie_rx_free()` did not, breaking the `if (!trans_pcie->rxq)` guard and leaving dangling pointers. - On `iwl_trans_pcie_free()` after failed init: second `iwl_pcie_rx_free()` =E2=86=92 double `kfree()` and UAF in `iwl_pcie_free_rbs_pool()`. - On retry via `_iwl_pcie_rx_init()`: non-NULL `rxq` skips re-allocation and dereferences freed memory. **Step 2.4 =E2=80=94 Fix quality** Record: Obviously correct; mirrors existing pattern in `iwl_pcie_rx_alloc()` err path. Minimal, low regression risk. --- ## Phase 3: Git History Investigation **Step 3.1 =E2=80=94 Blame** Record: `kfree()` lines in `iwl_pcie_rx_free()` trace to `5d324e5159d9e` (v6.18-rc8 merge, Nov 2025). Bug present since this code landed in this tree. **Step 3.2 =E2=80=94 Fixes: tag** Record: N/A =E2=80=94 no Fixes: tag. **Step 3.3 =E2=80=94 Related file history** Record: Shallow history on `gen1_2/rx.c`; `iwl_pcie_nic_init()` tx- failure unwind at lines 508=E2=80=93510 present at merge commit `5d324e5159= d9e`. Standalone one-commit fix. **Step 3.4 =E2=80=94 Author context** Record: Emmanuel Grumbach is iwlwifi maintainer. Miri Korenblit has multiple iwlwifi stable fixes in this tree (mvm/mld validation, race fixes). **Step 3.5 =E2=80=94 Dependencies** Record: None. No series markers. Self-contained. --- ## Phase 4: Mailing List and External Research **Step 4.1 =E2=80=94 Original discussion** Record: `b4 dig` without commit hash failed (commit not in local repo). `b4 dig` by subject failed (wrong usage). patch.msgid.link and lore.kernel.org blocked by bot protection. **UNVERIFIED** for reviewer feedback and stable nominations. **Step 4.2 =E2=80=94 Reviewers** Record: **UNVERIFIED** =E2=80=94 could not fetch thread. **Step 4.3 =E2=80=94 Bug report** Record: No Reported-by or syzbot link. Bug identified by code-path analysis. **Step 4.4 =E2=80=94 Related patches** Record: **UNVERIFIED** for series context. **Step 4.5 =E2=80=94 Stable list** Record: **UNVERIFIED** =E2=80=94 lore blocked. --- ## Phase 5: Code Semantic Analysis **Step 5.1 =E2=80=94 Key functions** Record: `iwl_pcie_rx_free()` (modified); callers `iwl_pcie_nic_init()`, `iwl_trans_pcie_free()`. **Step 5.2 =E2=80=94 Callers** Record: - `iwl_pcie_nic_init()` (trans.c:508=E2=80=93510): calls `iwl_pcie_rx_free(= )` when `iwl_pcie_tx_init()` fails after RX init - `iwl_trans_pcie_free()` (trans.c:1981): final teardown always calls `iwl_pcie_rx_free()` **Step 5.3 =E2=80=94 Callees** Record: `cancel_work_sync()`, `iwl_pcie_free_rbs_pool()`, `dma_free_coherent()`, `iwl_pcie_free_rxq_dma()`, `napi_disable()`, `kfree()`, `__free_pages()`. **Step 5.4 =E2=80=94 Reachability** Record: 1. `iwl_trans_start_fw()` =E2=86=92 `iwl_pcie_nic_init()` =E2=86=92 RX init= OK, TX init fails =E2=86=92 `iwl_pcie_rx_free()` (pointers left dangling) 2. Driver remove =E2=86=92 `iwl_trans_pcie_free()` =E2=86=92 second `iwl_pc= ie_rx_free()` =E2=86=92 double-free/UAF 3. FW reload retry =E2=86=92 `_iwl_pcie_rx_init()` sees non-NULL `rxq` =E2= =86=92 UAF Triggered on probe/firmware-load failure (e.g. ENOMEM in TX path). Reachable from normal driver operation. **Step 5.5 =E2=80=94 Similar patterns** Record: `iwl_pcie_rx_alloc()` err path (lines 826=E2=80=93831) already NULL= s the same pointers. `base_rb_stts` was already NULLed in `iwl_pcie_rx_free()`; this fix completes the pattern. --- ## Phase 6: Cross-Reference Against Local Tree (6.18.44) **Step 6.1 =E2=80=94 Buggy code present?** Record: **YES.** Local tree is `v6.18.44` (`git describe HEAD`, `make kernelversion`). `iwl_pcie_rx_free()` at lines 1243=E2=80=931248 frees with= out NULLing. Fix not yet applied. **Step 6.2 =E2=80=94 Backport complications** Record: Clean apply expected =E2=80=94 target lines match the provided diff exactly. No conflicting changes found. **Step 6.3 =E2=80=94 Related fixes already present?** Record: No. `git log --grep=3D"RX pointers"` and `--grep=3D"rx_free"` found nothing. Only `rx_pool =3D NULL` in `iwl_pcie_rx_alloc()` err path, not in `iwl_pcie_rx_free()`. --- ## Phase 7: Subsystem Context **Step 7.1 =E2=80=94 Subsystem** Record: `drivers/net/wireless/intel/iwlwifi` PCIe transport =E2=80=94 **IMPORTANT** (Intel WiFi on many laptops/desktops; CONFIG_IWLWIFI). **Step 7.2 =E2=80=94 Activity** Record: Active in 6.18.y =E2=80=94 recent iwlwifi stable fixes (validation, races, PTP). `gen1_2/` path is the PCIe RX/TX implementation in this tree. --- ## Phase 8: Impact and Risk Assessment **Step 8.1 =E2=80=94 Who is affected** Record: Intel iwlwifi PCIe users (mvm/mld op-modes). Config-dependent on `CONFIG_IWLWIFI`. **Step 8.2 =E2=80=94 Trigger conditions** Record: `iwl_pcie_tx_init()` fails after successful RX init (e.g. ENOMEM in `iwl_pcie_tx_alloc()` or `iwl_txq_init()`). Uncommon but valid; no special privileges needed beyond loading the driver. **Step 8.3 =E2=80=94 Failure severity** Record: Double-free and UAF on remove or retry =E2=86=92 kernel oops/crash/memory corruption. **Severity: HIGH/CRITICAL**. **Step 8.4 =E2=80=94 Risk vs benefit** Record: - Benefit: **HIGH** =E2=80=94 prevents crash/corruption on init-failure + teardown/retry - Risk: **VERY LOW** =E2=80=94 5 NULL assignments, established pattern - Ratio: strongly favors backport --- ## Phase 9: Final Synthesis **Step 9.1 =E2=80=94 Evidence** FOR: - Real double-free/UAF on documented error path - High severity (crash/corruption) - Minimal, obviously correct fix matching existing err-path code - Buggy code confirmed in 6.18.44 - iwlwifi maintainer authorship AGAINST: - Rare trigger (TX init failure after RX init) - No fuzzer/user report (lower visibility, not lower severity) UNRESOLVED: - Mailing list review/stable nomination (lore blocked) - Exact upstream commit SHA not in local repo **Step 9.2 =E2=80=94 Stable rules checklist** 1. Obviously correct and tested? **PASS** =E2=80=94 mirrors `iwl_pcie_rx_alloc()` err path; no Tested-by 2. Fixes real bug affecting users? **PASS** =E2=80=94 double-free/UAF on remove/retry after init failure 3. Important issue? **PASS** =E2=80=94 crash/memory corruption (HIGH/CRITIC= AL) 4. Small and contained? **PASS** =E2=80=94 ~5 lines, one function 5. No new features/APIs? **PASS** 6. Can apply to local tree? **PASS** =E2=80=94 lines match; fix not present **Step 9.3 =E2=80=94 Exception category** Record: None (standard bug fix, not quirk/DT/build/doc). **Step 9.4 =E2=80=94 Problem summary** When `iwl_pcie_nic_init()` fails at TX init after RX init, it calls `iwl_pcie_rx_free()` but leaves `rxq`, `rx_pool`, `global_table`, and `alloc_page` as dangling non-NULL pointers. A subsequent `iwl_trans_pcie_free()` calls `iwl_pcie_rx_free()` again (double-free), and a firmware-load retry calls `_iwl_pcie_rx_init()` which skips allocation and uses freed memory (UAF). The fix NULLs those pointers after free, consistent with the allocation error path. --- ## Verification - [Phase 1] Parsed subject, tags, body from user-provided commit message - [Phase 2] Read `rx.c` lines 766=E2=80=93834, 1083=E2=80=931168, 1204=E2= =80=931249; confirmed diff target matches current file - [Phase 2] Traced failure: `trans.c:508=E2=80=93510` calls `iwl_pcie_rx_fr= ee()` on `iwl_pcie_tx_init()` failure - [Phase 2] Confirmed `iwl_pcie_rx_alloc()` err path NULLs pointers at lines 826=E2=80=93831 - [Phase 3] `git blame -L 1243,1248 rx.c`: lines from `5d324e5159d9e` - [Phase 3] `git show 5d324e5159d9e:trans.c` lines 508=E2=80=93510: unwind = path present at merge - [Phase 3] `git log --grep=3D"RX pointers"`: no existing fix in tree - [Phase 4] `b4 dig`: no match (commit not local); patch.msgid.link and lore.kernel.org blocked =E2=80=94 **UNVERIFIED** - [Phase 5] `grep iwl_pcie_rx_free`: callers at `trans.c:509`, `trans.c:1981` - [Phase 5] Read `tx.c:941=E2=80=931004`: `iwl_pcie_tx_init()` can return e= rror from alloc/init - [Phase 5] Read `_iwl_pcie_rx_init()` lines 1090=E2=80=931095: skips alloc= when `rxq` non-NULL - [Phase 6] `git describe HEAD`: `v6.18.44-1-g2736c32da98b9`; `make kernelversion`: `6.18.44` - [Phase 6] Current `iwl_pcie_rx_free()` lacks NULL assignments (lines 1243=E2=80=931248) - [Phase 6] `grep rx_pool =3D NULL` in pcie: only in alloc err path, not in `rx_free` - [Phase 7] `git log -20 -- drivers/net/wireless/intel/iwlwifi/`: active iwlwifi maintenance - [Phase 8] Failure mode: double-free/UAF on driver remove or FW retry after init failure =E2=80=94 HIGH/CRITICAL **YES** drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/rx.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/rx.c b/drivers/= net/wireless/intel/iwlwifi/pcie/gen1_2/rx.c index 619a9505e6d9d..c723839288f2e 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/rx.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* - * Copyright (C) 2003-2014, 2018-2024 Intel Corporation + * Copyright (C) 2003-2014, 2018-2024, 2026 Intel Corporation * Copyright (C) 2013-2015 Intel Mobile Communications GmbH * Copyright (C) 2016-2017 Intel Deutschland GmbH */ @@ -1241,11 +1241,16 @@ void iwl_pcie_rx_free(struct iwl_trans *trans) } } kfree(trans_pcie->rx_pool); + trans_pcie->rx_pool =3D NULL; kfree(trans_pcie->global_table); + trans_pcie->global_table =3D NULL; kfree(trans_pcie->rxq); + trans_pcie->rxq =3D NULL; =20 - if (trans_pcie->alloc_page) + if (trans_pcie->alloc_page) { __free_pages(trans_pcie->alloc_page, trans_pcie->rx_page_order); + trans_pcie->alloc_page =3D NULL; + } } =20 static void iwl_pcie_rx_move_to_allocator(struct iwl_rxq *rxq, --=20 2.53.0