Skip to content

blk-cgroup: fix blkg list and policy data races#1029

Open
blktests-ci[bot] wants to merge 4 commits into
linus-master_basefrom
series/1116232=>linus-master
Open

blk-cgroup: fix blkg list and policy data races#1029
blktests-ci[bot] wants to merge 4 commits into
linus-master_basefrom
series/1116232=>linus-master

Conversation

@blktests-ci

@blktests-ci blktests-ci Bot commented Jul 3, 2026

Copy link
Copy Markdown

Pull request for series with
subject: blk-cgroup: fix blkg list and policy data races
version: 3
url: https://patchwork.kernel.org/project/linux-block/list/?series=1116232

@blktests-ci

blktests-ci Bot commented Jul 3, 2026

Copy link
Copy Markdown
Author

Upstream branch: 87320be
series: https://patchwork.kernel.org/project/linux-block/list/?series=1116232
version: 3

@blktests-ci

blktests-ci Bot commented Jul 6, 2026

Copy link
Copy Markdown
Author

Upstream branch: 8cdeaa5
series: https://patchwork.kernel.org/project/linux-block/list/?series=1116232
version: 3

@blktests-ci blktests-ci Bot force-pushed the series/1116232=>linus-master branch from c78a875 to c83dbe4 Compare July 6, 2026 09:16
@blktests-ci blktests-ci Bot force-pushed the linus-master_base branch from a644c13 to a2204c3 Compare July 7, 2026 08:33
Yu Kuai and others added 4 commits July 7, 2026 08:56
… blkcg_mutex

blkg_destroy_all() iterates q->blkg_list without holding blkcg_mutex,
which can race with blkg_free_workfn() that removes blkgs from the list
while holding blkcg_mutex.

Add blkcg_mutex protection around the q->blkg_list iteration to prevent
potential list corruption or use-after-free issues.

Reviewed-by: Tang Yizhou <yizhou.tang@shopee.com>
Signed-off-by: Yu Kuai <yukuai@fygo.io>
When switching an IO scheduler on a block device, blkcg_activate_policy()
allocates blkg_policy_data (pd) for all blkgs attached to the queue.
However, blkcg_activate_policy() may race with concurrent blkcg deletion,
leading to use-after-free and memory leak issues.

The use-after-free occurs in the following race:

T1 (blkcg_activate_policy):
  - Successfully allocates pd for blkg1 (loop0->queue, blkcgA)
  - Fails to allocate pd for blkg2 (loop0->queue, blkcgB)
  - Enters the enomem rollback path to release blkg1 resources

T2 (blkcg deletion):
  - blkcgA is deleted concurrently
  - blkg1 is freed via blkg_free_workfn()
  - blkg1->pd is freed

T1 (continued):
  - Rollback path accesses blkg1->pd->online after pd is freed
  - Triggers use-after-free

In addition, blkg_free_workfn() frees pd before removing the blkg from
q->blkg_list. This allows blkcg_activate_policy() to allocate a new pd
for a blkg that is being destroyed, leaving the newly allocated pd
unreachable when the blkg is finally freed.

Fix these races by extending blkcg_mutex coverage to serialize
blkcg_activate_policy() rollback and blkg destruction, ensuring pd
lifecycle is synchronized with blkg list visibility.

Fixes: f1c006f ("blk-cgroup: synchronize pd_free_fn() from blkg_free_workfn() and blkcg_deactivate_policy()")
Signed-off-by: Zheng Qixing <zhengqixing@huawei.com>
Reviewed-by: Tang Yizhou <yizhou.tang@shopee.com>
Signed-off-by: Yu Kuai <yukuai@fygo.io>
When switching IO schedulers on a block device, blkcg_activate_policy()
can race with concurrent blkcg deletion, leading to a use-after-free in
rcu_accelerate_cbs.

T1:                               T2:
                                  blkg_destroy
                                  kill(&blkg->refcnt) // blkg->refcnt=1->0
                                  blkg_release // call_rcu(__blkg_release)
                                  ...
                                  blkg_free_workfn
                                  ->pd_free_fn(pd)
elv_iosched_store
elevator_switch
...
iterate blkg list
blkg_get(blkg) // blkg->refcnt=0->1
                                  list_del_init(&blkg->q_node)
blkg_put(pinned_blkg) // blkg->refcnt=1->0
blkg_release // call_rcu again
rcu_accelerate_cbs // uaf

Fix this by checking hlist_unhashed(&blkg->blkcg_node) before getting
a reference to the blkg. This is the same check used in blkg_destroy()
to detect if a blkg has already been destroyed. If the blkg is already
unhashed, skip processing it since it's being destroyed.

Fixes: f1c006f ("blk-cgroup: synchronize pd_free_fn() from blkg_free_workfn() and blkcg_deactivate_policy()")
Signed-off-by: Zheng Qixing <zhengqixing@huawei.com>
Reviewed-by: Tang Yizhou <yizhou.tang@shopee.com>
Signed-off-by: Yu Kuai <yukuai@fygo.io>
Move the teardown sequence which offlines and frees per-policy
blkg_policy_data (pd) into a helper for readability.

No functional change intended.

Signed-off-by: Zheng Qixing <zhengqixing@huawei.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Tang Yizhou <yizhou.tang@shopee.com>
Signed-off-by: Yu Kuai <yukuai@fygo.io>
@blktests-ci

blktests-ci Bot commented Jul 7, 2026

Copy link
Copy Markdown
Author

Upstream branch: 0e35b9b
series: https://patchwork.kernel.org/project/linux-block/list/?series=1116232
version: 3

@blktests-ci blktests-ci Bot force-pushed the series/1116232=>linus-master branch from c83dbe4 to e2a0569 Compare July 7, 2026 08:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant