提交 36d09fa1 编写于 作者: L Liu Shixin 提交者: openeuler-sync-bot

mm/memcg_memfs_info: fix potential oom_lock recursion deadlock

hulk inclusion
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/I6ADCF
CVE: NA

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

syzbot is reporting GFP_KERNEL allocation with oom_lock held when
reporting memcg OOM [1]. If this allocation triggers the global OOM
situation then the system can livelock because the GFP_KERNEL
allocation with oom_lock held cannot trigger the global OOM killer
because __alloc_pages_may_oom() fails to hold oom_lock.

The problem mentioned above has been fixed by patch[2]. The is the same
problem in memcg_memfs_info feature too. Refer to the patch[2], fix it by
removing the allocation from mem_cgroup_print_memfs_info() completely,
and pass static buffer when calling from memcg OOM path.

Link: https://syzkaller.appspot.com/bug?extid=2d2aeadc6ce1e1f11d45 [1]
Link: https://lkml.kernel.org/r/86afb39f-8c65-bec2-6cfc-c5e3cd600c0b@I-love.SAKURA.ne.jp [2]
Fixes: 6b1d4d3a ("mm/memcg_memfs_info: show files that having pages charged in mem_cgroup")
Signed-off-by: NLiu Shixin <liushixin2@huawei.com>
Reviewed-by: NKefeng Wang <wangkefeng.wang@huawei.com>
Reviewed-by: NCai Xinchen <caixinchen1@huawei.com>
Signed-off-by: NJialin Zhang <zhangjialin11@huawei.com>
(cherry picked from commit d2218535)
上级 3f533ee3
...@@ -6,11 +6,13 @@ ...@@ -6,11 +6,13 @@
#include <linux/seq_file.h> #include <linux/seq_file.h>
#ifdef CONFIG_MEMCG_MEMFS_INFO #ifdef CONFIG_MEMCG_MEMFS_INFO
void mem_cgroup_print_memfs_info(struct mem_cgroup *memcg, struct seq_file *m); void mem_cgroup_print_memfs_info(struct mem_cgroup *memcg, char *pathbuf,
struct seq_file *m);
int mem_cgroup_memfs_files_show(struct seq_file *m, void *v); int mem_cgroup_memfs_files_show(struct seq_file *m, void *v);
void mem_cgroup_memfs_info_init(void); void mem_cgroup_memfs_info_init(void);
#else #else
static inline void mem_cgroup_print_memfs_info(struct mem_cgroup *memcg, static inline void mem_cgroup_print_memfs_info(struct mem_cgroup *memcg,
char *pathbuf,
struct seq_file *m) struct seq_file *m)
{ {
} }
......
...@@ -157,7 +157,8 @@ static void memfs_show_files_in_mem_cgroup(struct super_block *sb, void *data) ...@@ -157,7 +157,8 @@ static void memfs_show_files_in_mem_cgroup(struct super_block *sb, void *data)
mntput(pfc->vfsmnt); mntput(pfc->vfsmnt);
} }
void mem_cgroup_print_memfs_info(struct mem_cgroup *memcg, struct seq_file *m) void mem_cgroup_print_memfs_info(struct mem_cgroup *memcg, char *pathbuf,
struct seq_file *m)
{ {
struct print_files_control pfc = { struct print_files_control pfc = {
.memcg = memcg, .memcg = memcg,
...@@ -165,17 +166,11 @@ void mem_cgroup_print_memfs_info(struct mem_cgroup *memcg, struct seq_file *m) ...@@ -165,17 +166,11 @@ void mem_cgroup_print_memfs_info(struct mem_cgroup *memcg, struct seq_file *m)
.max_print_files = memfs_max_print_files, .max_print_files = memfs_max_print_files,
.size_threshold = memfs_size_threshold, .size_threshold = memfs_size_threshold,
}; };
char *pathbuf;
int i; int i;
if (!memfs_enable || !memcg) if (!memfs_enable || !memcg)
return; return;
pathbuf = kmalloc(PATH_MAX, GFP_KERNEL);
if (!pathbuf) {
SEQ_printf(m, "Show memfs failed due to OOM\n");
return;
}
pfc.pathbuf = pathbuf; pfc.pathbuf = pathbuf;
pfc.pathbuf_size = PATH_MAX; pfc.pathbuf_size = PATH_MAX;
...@@ -192,15 +187,20 @@ void mem_cgroup_print_memfs_info(struct mem_cgroup *memcg, struct seq_file *m) ...@@ -192,15 +187,20 @@ void mem_cgroup_print_memfs_info(struct mem_cgroup *memcg, struct seq_file *m)
SEQ_printf(m, "total files: %lu, total memory-size: %lukB\n", SEQ_printf(m, "total files: %lu, total memory-size: %lukB\n",
pfc.total_print_files, pfc.total_files_size >> 10); pfc.total_print_files, pfc.total_files_size >> 10);
} }
kfree(pfc.pathbuf);
} }
int mem_cgroup_memfs_files_show(struct seq_file *m, void *v) int mem_cgroup_memfs_files_show(struct seq_file *m, void *v)
{ {
struct mem_cgroup *memcg = mem_cgroup_from_css(seq_css(m)); struct mem_cgroup *memcg = mem_cgroup_from_css(seq_css(m));
char *pathbuf;
mem_cgroup_print_memfs_info(memcg, m); pathbuf = kmalloc(PATH_MAX, GFP_KERNEL);
if (!pathbuf) {
SEQ_printf(m, "Show memfs abort: failed to allocate memory\n");
return 0;
}
mem_cgroup_print_memfs_info(memcg, pathbuf, m);
kfree(pathbuf);
return 0; return 0;
} }
......
...@@ -1611,6 +1611,7 @@ void mem_cgroup_print_oom_meminfo(struct mem_cgroup *memcg) ...@@ -1611,6 +1611,7 @@ void mem_cgroup_print_oom_meminfo(struct mem_cgroup *memcg)
{ {
/* Use static buffer, for the caller is holding oom_lock. */ /* Use static buffer, for the caller is holding oom_lock. */
static char buf[PAGE_SIZE]; static char buf[PAGE_SIZE];
static char pathbuf[PATH_MAX];
lockdep_assert_held(&oom_lock); lockdep_assert_held(&oom_lock);
...@@ -1636,7 +1637,7 @@ void mem_cgroup_print_oom_meminfo(struct mem_cgroup *memcg) ...@@ -1636,7 +1637,7 @@ void mem_cgroup_print_oom_meminfo(struct mem_cgroup *memcg)
memory_stat_format(memcg, buf, sizeof(buf)); memory_stat_format(memcg, buf, sizeof(buf));
pr_info("%s", buf); pr_info("%s", buf);
mem_cgroup_print_memfs_info(memcg, NULL); mem_cgroup_print_memfs_info(memcg, pathbuf, NULL);
} }
/* /*
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册