From nobody Sat Sep 26 17:08:52 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 71E3C508383; Mon, 31 Aug 2026 13:42:24 +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=1788183746; cv=none; b=lR2uQkvY6N5+R2EZ+aadLauu12zKGmOkSvKcPUmowt3RJhkujt5ZhNTWhbiXq3aUeEoZZM5c3dOG4ZSqFFnXVyNMeDempNf39rSJwmGs9L2khd6jJFw0tcAmWdIYGjy2IitjXrBcDJU1nV209G6qu/9oY/QjNvce0AIoQ+m0h28= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1788183746; c=relaxed/simple; bh=JoEP6Ipo6byrIOxydR9E/h7I219CBrDGqwfEdH+p5vA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=motusp1plkhpW9vGnybXNDg6x7fwcX+h8JC8Q75TD5zasjoAJHO4BxvTWhJdh7ggFT7ebVwkGDa8zyx07hR6axyDop401Ginn+9ffF5G4hAkjcU1HZ/oxT+vOhgX0BcJ+F4ZcGC8OwJ6ZV5Lqhre/uDcO2ZAF2rpy5JFoeHTHyM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=XYQx37Ic; 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="XYQx37Ic" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 45F5D1F00ACF; Mon, 31 Aug 2026 13:42:23 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1788183744; bh=nIglp5nNykqg/DFMdZW1G8RO3BXqE82KyiWcozCeWXU=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=XYQx37IcbrCggZJ2YBDULgVqlxxMI29dJ4Z/MYW6m+O7T37Nxsa/ag799g2AUeaIb oGjpKnVRVF8KczTmSUfOsmY7ImSaf5OTU4nzAcDOSbJJ9j4Exkddow/SXDempuMeMv B62bIHnJ0hjmndTL8psNA6//TLZvx0YvhufEzc7ZZYzD55DexWehdLiwM8htEk/zQR xNrM4ulsgToBpEgzRMwDFLBXX20up4g0ldiivxA1mgjvMJ9ELEBvxvjLp7MjRV9hnf bxIFzX1nVfKgF9wAub5SuXz9Cu1BzbMmwJ+Chp4q5Dzhvl+eleonFClbEG+VP4rm8W Bil0dmwX48XIA== From: Sasha Levin To: patches@lists.linux.dev, stable@vger.kernel.org Cc: Tao Cui , Tejun Heo , Jens Axboe , Sasha Levin , josef@toxicpanda.com, cgroups@vger.kernel.org, linux-block@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH AUTOSEL 6.18-5.10] blk-cgroup: fix leaks and online flag on radix_tree_insert failure Date: Mon, 31 Aug 2026 09:25:06 -0400 Message-ID: <20260831133314.4125787-278-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 Content-Type: text/plain; charset="utf-8" X-stable: review X-Patchwork-Hint: Ignore X-stable-base: Linux 6.18.48 Content-Transfer-Encoding: quoted-printable From: Tao Cui [ Upstream commit dbbca20764382b4d411ec2918f4e278ffe547acc ] When radix_tree_insert() fails in blkg_create(), the error path has two issues: 1. blkg->online is set to true unconditionally, even when the blkg was never fully inserted. Move the assignment inside the success block. 2. The error path calls blkg_put() without first calling percpu_ref_kill(). Because the refcount is still in percpu mode, percpu_ref_put() only does this_cpu_sub() without checking for zero, so blkg_release() is never triggered. This permanently leaks the blkg memory, its percpu iostat, policy data, the parent blkg reference, and the cgroup css reference =E2=80=94 the latter preventing = the cgroup from ever being destroyed. Fix by replacing blkg_put() with percpu_ref_kill(), matching the pattern used in blkg_destroy(). Acked-by: Tejun Heo Signed-off-by: Tao Cui Link: https://patch.msgid.link/20260715132407.1469777-1-cui.tao@linux.dev Signed-off-by: Jens Axboe Signed-off-by: Sasha Levin --- LLM Generated explanations, may be completely bogus: # Stable Backport Analysis: `blk-cgroup: fix leaks and online flag on radix_tree_insert failure` **Local tree:** `v6.18.44` (Linux 6.18.44 stable) --- ## PHASE 1: COMMIT MESSAGE FORENSICS **Step 1.1 =E2=80=94 Subject line** Record: `[blk-cgroup]` `[fix]` =E2=80=94 fixes resource leaks and incorrect `online` flag when `radix_tree_insert()` fails in `blkg_create()`. **Step 1.2 =E2=80=94 Tags** Record: - **Acked-by:** Tejun Heo `` (cgroup/block-cgroup maintainer) - **Signed-off-by:** Tao Cui `` (author) - **Signed-off-by:** Jens Axboe `` (block layer maintainer) - **Link:** https://patch.msgid.link/20260715132407.1469777-1-cui.tao@linux.dev - No Fixes:, Reported-by:, Tested-by:, Reviewed-by:, or Cc: stable tags - (Ignoring pipeline-added Signed-off-by: Sasha Levin per instructions) **Step 1.3 =E2=80=94 Body analysis** Record: - **Bug:** When `radix_tree_insert()` fails in `blkg_create()`, two errors occur: 1. `blkg->online =3D true` is set even though the blkg was never inserted into the tree. 2. Error path calls `blkg_put()` without `percpu_ref_kill()`. While the refcount is still in percpu mode, `percpu_ref_put()` only decrements a per-CPU counter and never checks for zero, so `blkg_release()` is never called. - **Symptom/failure mode:** Permanent leak of blkg memory, percpu iostat, policy data, parent blkg reference, and cgroup css reference =E2= =80=94 the css leak prevents the cgroup from ever being destroyed. - **Root cause:** Wrong teardown primitive on the error path; `blkg_destroy()` correctly uses `percpu_ref_kill()`. **Step 1.4 =E2=80=94 Hidden bug fix?** Record: No =E2=80=94 this is an explicit bug fix, not disguised cleanup. --- ## PHASE 2: DIFF ANALYSIS **Step 2.1 =E2=80=94 Inventory** Record: - **Files:** `block/blk-cgroup.c` only (+2 / =E2=88=922 lines, 4 lines touc= hed) - **Function:** `blkg_create()` - **Scope:** Single-file, surgical fix **Step 2.2 =E2=80=94 Code flow change** Record: - **Hunk 1:** `blkg->online =3D true` moved inside the `if (likely(!ret))` success block. - Before: online set unconditionally after insert attempt. - After: online only set when insert succeeds. - **Hunk 2:** Error path changed from `blkg_put(blkg)` to `percpu_ref_kill(&blkg->refcnt)`. - Before: percpu-mode put never triggers release callback. - After: switches to atomic mode and triggers `blkg_release()` =E2=86=92 `__blkg_release()` =E2=86=92 `css_put()` + `blkg_free()`. **Step 2.3 =E2=80=94 Bug mechanism** Record: **Reference counting / resource leak fix.** Category (a) error- path leak + (g) logic correctness (online flag). The percpu_ref lifecycle requires `percpu_ref_kill()` before the final drop can trigger the release function =E2=80=94 documented in `include/linux/percpu-refcount= .h` lines 19=E2=80=9324. **Step 2.4 =E2=80=94 Fix quality** Record: Obviously correct =E2=80=94 mirrors `blkg_destroy()` at line 568. Minimal change. Very low regression risk; only affects the rare `radix_tree_insert()` failure path. --- ## PHASE 3: GIT HISTORY INVESTIGATION **Step 3.1 =E2=80=94 Blame** Record: Buggy lines in this tree all from `5d324e5159d9e` (v6.18 merge, Nov 2025). Same pattern present in `v6.12` and `v6.17` per `git show`. **Step 3.2 =E2=80=94 Fixes: tag** Record: Not applicable =E2=80=94 no Fixes: tag in commit message. **Step 3.3 =E2=80=94 Related file history** Record: - `93383b6681074` =E2=80=94 "wait for blkcg cleanup before initializing new disk" =E2=80=94 reduces `-EEXIST` from `radix_tree_insert()` during disk rebind, but does not fix the broken error path when insert still fails. - `5e5b7f2ef8549` =E2=80=94 UAF fix in `__blkcg_rstat_flush()` (related subsystem, separate issue). - Fix commit on master: `dbbca20764382` (Jul 15, 2026); **not** an ancestor of current HEAD (`merge-base` exit 1). **Step 3.4 =E2=80=94 Author context** Record: Tao Cui; Acked-by Tejun Heo (blk-cgroup/cgroup maintainer). No other Tao Cui commits in this tree's `block/blk-cgroup.c` history. **Step 3.5 =E2=80=94 Dependencies** Record: Standalone =E2=80=94 no series dependencies, no prerequisite commits required. Self-contained 4-line change. --- ## PHASE 4: MAILING LIST AND EXTERNAL RESEARCH **Step 4.1 =E2=80=94 Original discussion** Record: - `b4 dig -c dbbca20764382`: https://patch.msgid.link/20260715132407.1469777-1-cui.tao@linux.dev - Series: v4 only (no v1=E2=80=93v3 in b4 results; v4 is the applied versio= n) - No NAKs found in saved mbox - No explicit Cc: stable nomination in thread headers **Step 4.2 =E2=80=94 Reviewers** Record: `b4 dig -w` CC'd: tj@kernel.org, axboe@kernel.dk, josef@toxicpanda.com, cgroups@vger.kernel.org, linux- block@vger.kernel.org. Tejun Heo Acked-by. **Step 4.3 =E2=80=94 Bug report** Record: No external bug report or syzbot link. Bug identified via code review of percpu_ref lifecycle. **Step 4.4 =E2=80=94 Related patches** Record: Complementary to `93383b6681074` (reduces trigger frequency) but independently needed for correct error handling. **Step 4.5 =E2=80=94 Stable list** Record: No stable@vger.kernel.org discussion found for this specific fix. --- ## PHASE 5: CODE SEMANTIC ANALYSIS **Step 5.1 =E2=80=94 Key functions** Record: `blkg_create()` modified; related: `blkg_destroy()`, `blkg_release()`, `__blkg_release()`, `blkg_free()`. **Step 5.2 =E2=80=94 Callers** Record: `blkg_create()` called from: - `blkg_lookup_create()` =E2=80=94 I/O hot path via `blkg_tryget_closest()`= =E2=86=92 `bio_assoc_blkcg()` (line 2113) - `blkg_conf_prep()` =E2=80=94 cgroup sysfs configuration (uses `radix_tree_preload`) - `blkcg_init_disk()` =E2=80=94 disk initialization (uses `radix_tree_prelo= ad`) `blkg_lookup_create()` does **not** call `radix_tree_preload()`, so `-ENOMEM` from `radix_tree_insert()` is reachable under memory pressure. **Step 5.3 =E2=80=94 Callees** Record: On failure path after fix: `percpu_ref_kill()` =E2=86=92 `blkg_release()` =E2=86=92 `__blkcg_rstat_flush()` + `call_rcu(__blkg_relea= se)` =E2=86=92 `css_put()` + `blkg_free()` =E2=86=92 `blkg_free_workfn()` releas= es parent ref, policy data, queue ref, percpu iostat. **Step 5.4 =E2=80=94 Reachability** Record: Reachable from block I/O path when `CONFIG_BLK_CGROUP` is enabled and a new blkg must be created for a cgroup/disk pair. Userspace cgroup management can also trigger via `blkg_conf_prep()`. Unprivileged users can trigger via I/O in their cgroup. **Step 5.5 =E2=80=94 Similar patterns** Record: `blkg_destroy()` at line 568 already uses `percpu_ref_kill(&blkg->refcnt)` =E2=80=94 fix aligns error path with established pattern. `include/linux/percpu-refcount.h` documents that `percpu_ref_put()` does not check for zero before `percpu_ref_kill()`. --- ## PHASE 6: CROSS-REFERENCE WITH LOCAL TREE **Step 6.1 =E2=80=94 Buggy code present?** Record: **YES.** Current tree at lines 436 and 443: ```436:444:block/blk-cgroup.c blkg->online =3D true; spin_unlock(&blkcg->lock); if (!ret) return blkg; /* @blkg failed fully initialized, use the usual release path */ blkg_put(blkg); return ERR_PTR(ret); ``` Bug present since at least v6.12 in this repository's history. **Step 6.2 =E2=80=94 Backport complications** Record: Trivial change; `git apply --check` on upstream patch fails only because stable has `err_put_css:` label that mainline parent lacks (context line difference below the hunk). The three actual changed lines apply without modification. Expected difficulty: **minor context adjustment, not rework**. **Step 6.3 =E2=80=94 Related fixes already present?** Record: `93383b6681074` is present (reduces `-EEXIST` trigger). This specific leak fix is **not** present. --- ## PHASE 7: SUBSYSTEM AND MAINTAINER CONTEXT **Step 7.1 =E2=80=94 Subsystem** Record: **block/blk-cgroup** =E2=80=94 CORE/IMPORTANT subsystem. Affects all systems using cgroup v1/v2 block controller (`CONFIG_BLK_CGROUP`). **Step 7.2 =E2=80=94 Activity** Record: Active maintenance in 6.18.y =E2=80=94 recent fixes include UAF (`5e5b7f2ef8549`), disk reference leak (`b3e005f16cd98`), blkcg cleanup wait (`93383b6681074`). --- ## PHASE 8: IMPACT AND RISK ASSESSMENT **Step 8.1 =E2=80=94 Who is affected** Record: Systems with `CONFIG_BLK_CGROUP` enabled =E2=80=94 container hosts (Kubernetes, Docker, systemd cgroups), cloud VMs, any workload using block I/O cgroup controller. **Step 8.2 =E2=80=94 Trigger conditions** Record: - `radix_tree_insert()` returns error (`-ENOMEM` most likely in `blkg_lookup_create()` without preload; `-EEXIST` possible in races despite `93383b6681074`) - Requires blkg creation for a new cgroup/disk pair - Unprivileged cgroup users can trigger via I/O; cgroup admin via sysfs - Not every boot =E2=80=94 requires memory pressure or specific race =E2=80= =94 but consequences are permanent **Step 8.3 =E2=80=94 Failure mode severity** Record: - **Permanent memory/resource leak** (blkg, iostat, policy data) - **Cgroup css reference leak =E2=86=92 cgroup cannot be destroyed** =E2=80= =94 functional breakage for container lifecycle - **Incorrect online flag** =E2=80=94 minor (e.g., `blkcg_print_one_stat()`= at line 1190 may process a non-inserted blkg) - Severity: **HIGH** (resource leak with cgroup destruction blocked; not a crash but serious operational impact) **Step 8.4 =E2=80=94 Risk-benefit** Record: - **Benefit:** HIGH =E2=80=94 prevents unrecoverable resource leaks and stu= ck cgroups - **Risk:** VERY LOW =E2=80=94 4-line change, matches existing `blkg_destro= y()` pattern, only affects error path - **Ratio:** Strongly favors backport --- ## PHASE 9: FINAL SYNTHESIS **Step 9.1 =E2=80=94 Evidence summary** **FOR:** - Real, verifiable resource leak on error path - Cgroup css leak prevents cgroup destruction =E2=80=94 serious for product= ion container workloads - Small, surgical, maintainer-acked fix - Buggy code confirmed present in v6.18.44 - Matches documented percpu_ref semantics and existing `blkg_destroy()` pattern - Reachable from common I/O and cgroup configuration paths **AGAINST:** - Rare trigger (radix_tree_insert failure) - No syzbot/user crash report - Upstream patch needs trivial context adjustment for `err_put_css:` label **UNRESOLVED:** - No quantitative data on how often `radix_tree_insert()` fails in production **Step 9.2 =E2=80=94 Stable rules checklist** 1. Obviously correct and tested? **PASS** =E2=80=94 mechanism verified agai= nst `percpu-refcount.h` and `blkg_destroy()`; Acked-by cgroup maintainer 2. Fixes real bug affecting users? **PASS** =E2=80=94 permanent leak + cgro= up destruction blocked 3. Important issue? **PASS** =E2=80=94 HIGH severity resource leak affecting cgroup lifecycle 4. Small and contained? **PASS** =E2=80=94 4 lines, one function, one file 5. No new features or APIs? **PASS** 6. Can apply to local tree? **PASS** =E2=80=94 trivial manual apply (minor context difference only) **Step 9.3 =E2=80=94 Exception categories** Record: Not applicable (standard bug fix, not device ID/quirk/build/doc exception). **Step 9.4 =E2=80=94 Decision rationale** This commit fixes a genuine error-path bug in `blkg_create()` where failed `radix_tree_insert()` leaves resources permanently leaked because `blkg_put()` cannot trigger `blkg_release()` while the percpu refcount is still in percpu mode. The css reference leak prevents cgroup destruction =E2=80=94 a significant operational issue for any system using = block cgroups. The fix is minimal, follows the established `blkg_destroy()` pattern, is acked by the cgroup maintainer, and the buggy code is present in this v6.18.44 tree without the fix. --- ## Verification - [Phase 1] `git show dbbca20764382`: parsed subject, tags, body; Acked- by Tejun Heo confirmed - [Phase 2] Read `block/blk-cgroup.c` lines 371=E2=80=93452, 524=E2=80=9356= 9, 1190; read `include/linux/percpu-refcount.h` lines 19=E2=80=9324, 147=E2=80=93150, 3= 26=E2=80=93352 - [Phase 2] Confirmed `blkg_put()` =E2=86=92 `percpu_ref_put()` in `block/b= lk- cgroup.h` line 336=E2=80=93338 - [Phase 3] `git describe HEAD`: v6.18.44; `git blame -L 419,452`: buggy code from 5d324e5159d9e - [Phase 3] `git merge-base --is-ancestor dbbca20764382 HEAD`: exit 1 =E2= =80=94 fix NOT in tree - [Phase 3] `git show v6.12/v6.17:v6.18:block/blk-cgroup.c`: same buggy pattern back to v6.12 - [Phase 3] `93383b6681074` present in tree; complementary, not substitute - [Phase 4] `b4 dig -c dbbca20764382`: lore URL found; v4 series - [Phase 4] `b4 dig -w`: maintainers CC'd; Tejun Heo Acked-by - [Phase 4] `b4 dig -m /tmp/blkcg_fix.mbox`: no Cc: stable in thread - [Phase 5] Grep callers: `blkg_create` at lines 510, 936, 1526; `blkg_lookup_create` at 2113 - [Phase 5] Confirmed `blkg_lookup_create` does not use `radix_tree_preload` (only `blkg_conf_prep` and `blkcg_init_disk` do) - [Phase 6] Buggy code at lines 436, 443 confirmed in working tree - [Phase 6] `git apply --check` fails on context below hunk (`err_put_css:` vs `err_free_blkg:`); actual 3 changed lines are identical =E2=80=94 trivial backport - [Phase 8] Failure mode: permanent leak + cgroup destruction blocked; severity HIGH **YES** block/blk-cgroup.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c index 812f60905a708..9aa3b6ae81ca8 100644 --- a/block/blk-cgroup.c +++ b/block/blk-cgroup.c @@ -432,15 +432,15 @@ static struct blkcg_gq *blkg_create(struct blkcg *blk= cg, struct gendisk *disk, blkg->pd[i]->online =3D true; } } + blkg->online =3D true; } - blkg->online =3D true; spin_unlock(&blkcg->lock); =20 if (!ret) return blkg; =20 /* @blkg failed fully initialized, use the usual release path */ - blkg_put(blkg); + percpu_ref_kill(&blkg->refcnt); return ERR_PTR(ret); =20 err_put_css: --=20 2.53.0