hulk inclusion category: bugfix bugzilla: 46904, https://gitee.com/openeuler/kernel/issues/IA5JXN
--------------------------------
In freeing process, set memcg->hpool or dpool_global_hpool to NULL and then freeing it. To avoid UAF problem of hpool, we have to make sure the users that already hold pointer to hpool don't use the pointer after freeing hpool. The freeing of hpool should block until make sure all such users don't use hpool. Since anyone who want to use hpool have to increase its refcount at first. Use rcu_read_lock() and synchronize_rcu() to guarantee all such users failed to get hpool before freeing hpool.
Fixes: 0bc0d0d57eda ("dhugetlb: backport dynamic hugetlb feature") Signed-off-by: Liu Shixin liushixin2@huawei.com --- mm/hugetlb.c | 1 + mm/memcontrol.c | 11 ++++++++--- 2 files changed, 9 insertions(+), 3 deletions(-)
diff --git a/mm/hugetlb.c b/mm/hugetlb.c index 4be708677ce6..07b961d0a5ff 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -3360,6 +3360,7 @@ void dhugetlb_pool_put(struct dhugetlb_pool *hpool)
if (atomic_dec_and_test(&hpool->refcnt)) { css_put(&hpool->attach_memcg->css); + synchronize_rcu(); kfree(hpool); } } diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 7dc68b1792ef..4ecb6f09b68b 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -4701,14 +4701,19 @@ static ssize_t memcg_write_event_control(struct kernfs_open_file *of, struct dhugetlb_pool *get_dhugetlb_pool_from_memcg(struct mem_cgroup *memcg) { struct mem_cgroup_extension *memcg_ext; + struct dhugetlb_pool *hpool;
if (!memcg) return NULL;
+ rcu_read_lock(); memcg_ext = container_of(memcg, struct mem_cgroup_extension, memcg); - if (dhugetlb_pool_get(memcg_ext->hpool)) - return memcg_ext->hpool; - return NULL; + hpool = memcg_ext->hpool; + if (!dhugetlb_pool_get(hpool)) + hpool = NULL; + rcu_read_unlock(); + + return hpool; }
static void set_dhugetlb_pool_to_memcg(struct mem_cgroup *memcg,