Commit e32ab324 authored by Zheng Liang's avatar Zheng Liang Committed by Zheng Zengkai
Browse files

block, bfq: fix UAF problem in bfqg_stats_init()

mainline inclusion
from mainline
commit 2fc428f6
category: bugfix
bugzilla: 185657 https://gitee.com/openeuler/kernel/issues/I4DDEL

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=2fc428f6b7ca80794cb9928c90d4de524366659f



-------------------------------------------------

In bfq_pd_alloc(), the function bfqg_stats_init() init bfqg. If
blkg_rwstat_init() init bfqg_stats->bytes successful and init
bfqg_stats->ios failed, bfqg_stats_init() return failed, bfqg will
be freed. But blkg_rwstat->cpu_cnt is not deleted from the list of
percpu_counters. If we traverse the list of percpu_counters, It will
have UAF problem.

we should use blkg_rwstat_exit() to cleanup bfqg_stats bytes in the
above scenario.

Fixes: commit fd41e603 ("bfq-iosched: stop using blkg->stat_bytes and ->stat_ios")
Signed-off-by: default avatarZheng Liang <zhengliang6@huawei.com>
Acked-by: default avatarTejun Heo <tj@kernel.org>
Link: https://lore.kernel.org/r/20211018024225.1493938-1-zhengliang6@huawei.com


Signed-off-by: default avatarJens Axboe <axboe@kernel.dk>
Reviewed-by: default avatarJason Yan <yanaijie@huawei.com>

Signed-off-by: default avatarChen Jun <chenjun102@huawei.com>
Signed-off-by: default avatarZheng Zengkai <zhengzengkai@huawei.com>
parent 95663749
Loading
Loading
Loading
Loading
+7 −5
Original line number Diff line number Diff line
@@ -463,7 +463,7 @@ static int bfqg_stats_init(struct bfqg_stats *stats, gfp_t gfp)
{
	if (blkg_rwstat_init(&stats->bytes, gfp) ||
	    blkg_rwstat_init(&stats->ios, gfp))
		return -ENOMEM;
		goto error;

#ifdef CONFIG_BFQ_CGROUP_DEBUG
	if (blkg_rwstat_init(&stats->merged, gfp) ||
@@ -476,13 +476,15 @@ static int bfqg_stats_init(struct bfqg_stats *stats, gfp_t gfp)
	    bfq_stat_init(&stats->dequeue, gfp) ||
	    bfq_stat_init(&stats->group_wait_time, gfp) ||
	    bfq_stat_init(&stats->idle_time, gfp) ||
	    bfq_stat_init(&stats->empty_time, gfp)) {
		bfqg_stats_exit(stats);
		return -ENOMEM;
	}
	    bfq_stat_init(&stats->empty_time, gfp))
		goto error;
#endif

	return 0;

error:
	bfqg_stats_exit(stats);
	return -ENOMEM;
}

static struct bfq_group_data *cpd_to_bfqgd(struct blkcg_policy_data *cpd)