hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/IAFWQH ---------------------------------------- mem_cgroup_show() reads pool_memcg[] without any lock, while writers (zspool_bind_memcg, reset_memcg) hold init_lock write and css_put the old memcg before assigning a new value or NULL. A reader can obtain a pointer to an already-freed memcg and dereference it via cgroup_path(), causing use-after-free. The race is as follows. CPU0 (mem_cgroup_show) CPU1 (zspool_bind_memcg) memcg = zram->pool_memcg[pool_index]; down_write(&zram->init_lock); css_put(&old_memcg->css); // freed zram->pool_memcg[pool_index] = new_memcg; up_write(&zram->init_lock); cgroup_path(memcg->css.cgroup, ...); // UAF Fix by reading pool_memcg[] under init_lock read lock, which serializes with all writers that hold init_lock write lock. Fixes: 0f9e909b4624 ("[Huawei] multi_pool_zram: add sysfs file to support binding memcg for zpool") Signed-off-by: Jinjiang Tu <tujinjiang@huawei.com> --- .../block/multi_pool_zram/multi_pool_zram_drv.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/drivers/block/multi_pool_zram/multi_pool_zram_drv.c b/drivers/block/multi_pool_zram/multi_pool_zram_drv.c index 5af9ee71f8c1..ffec4d3baa26 100644 --- a/drivers/block/multi_pool_zram/multi_pool_zram_drv.c +++ b/drivers/block/multi_pool_zram/multi_pool_zram_drv.c @@ -1110,18 +1110,22 @@ static ssize_t mem_cgroup_show(struct device *dev, struct mem_cgroup *memcg; struct zram *zram; int pool_index; + int ret; zram = dev_to_zram(kobj_to_dev(kobj->parent->parent)); pool_index = kobj_to_pool_index(zram, kobj); + down_read(&zram->init_lock); memcg = zram->pool_memcg[pool_index]; if (!memcg) - return scnprintf(buf, PAGE_SIZE, "none\n"); - - if (!cgroup_path(memcg->css.cgroup, buf, PATH_MAX)) - return scnprintf(buf, PAGE_SIZE, "none\n"); + ret = scnprintf(buf, PAGE_SIZE, "none\n"); + else if (!cgroup_path(memcg->css.cgroup, buf, PATH_MAX)) + ret = scnprintf(buf, PAGE_SIZE, "none\n"); + else + ret = scnprintf(buf, PAGE_SIZE, "%s\n", buf); - return scnprintf(buf, PAGE_SIZE, "%s\n", buf); + up_read(&zram->init_lock); + return ret; } static ssize_t mem_cgroup_store(struct device *dev, -- 2.43.0