hulk inclusion category: bugfix bugzilla: 189183, https://gitee.com/openeuler/kernel/issues/I7Z1ZU CVE: NA
----------------------------------------
It is found that the last bugfix patch for this problem is not enough for higher version like 4.19, since drain_all_stock() now has nothing to do with css's offline process, and so a memcg could still be on the stock after it's been freed.
Fix this problem by adding (and decreasing) css's refcnt when the css is put onto (and removed from) stock. After all, "being on the stock" is a kind of reference with regards to memcg. As such, it's guaranteed that a css on stock would not be freed.
Signed-off-by: GONG, Ruiqi gongruiqi1@huawei.com --- mm/memcontrol.c | 6 ++++++ 1 file changed, 6 insertions(+)
diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 032bb52cd2ed..29d430885b1a 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -2149,6 +2149,9 @@ static void drain_stock(struct memcg_stock_pcp *stock) { struct mem_cgroup *old = stock->cached;
+ if (!old) + return; + if (stock->nr_pages) { page_counter_uncharge(&old->memory, stock->nr_pages); if (do_memsw_account()) @@ -2156,6 +2159,8 @@ static void drain_stock(struct memcg_stock_pcp *stock) css_put_many(&old->css, stock->nr_pages); stock->nr_pages = 0; } + + css_put(&old->css); stock->cached = NULL; }
@@ -2191,6 +2196,7 @@ static void refill_stock(struct mem_cgroup *memcg, unsigned int nr_pages) stock = this_cpu_ptr(&memcg_stock); if (stock->cached != memcg) { /* reset if necessary */ drain_stock(stock); + css_get(&memcg->css); stock->cached = memcg; } stock->nr_pages += nr_pages;