From: Kang Chen void0red@hust.edu.cn
hulk inclusion category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/I6NYW4 CVE: NA
--------------------------------
raw call flow:
oom_kill_process -> mem_cgroup_scan_tasks(.., .., message) -> memcg_print_bad_task(message, ..)
message is "const char*" type, and incorrectly cast to "oom_control*" type in memcg_print_bad_task.
Fix it by moving memcg_print_bad_task out of mem_cgroup_scan_tasks and call it in select_bad_process and dump_tasks. Furthermore, use struct oom_control* directly and remove the useless parm `ret`.
Reviewed-by: Kefeng Wang wangkefeng.wang@huawei.com Signed-off-by: Kang Chen void0red@hust.edu.cn (cherry picked from commit 789038c7436e6dc0efb144114992134a52233dbd)
Conflicts: include/linux/memcontrol.h [Add declaration of memcg_print_bad_task()] mm/memcontrol.c mm/oom_kill.c
Signed-off-by: Liu Shixin liushixin2@huawei.com Reviewed-by: Kefeng Wang wangkefeng.wang@huawei.com Signed-off-by: Yongqiang Liu liuyongqiang13@huawei.com --- include/linux/memcontrol.h | 10 +++++++++- mm/memcontrol.c | 15 +++++++++------ mm/oom_kill.c | 14 ++++++++------ 3 files changed, 26 insertions(+), 13 deletions(-)
diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h index 23db8eec0755..1cb695fb83c7 100644 --- a/include/linux/memcontrol.h +++ b/include/linux/memcontrol.h @@ -35,6 +35,7 @@ struct mem_cgroup; struct page; struct mm_struct; struct kmem_cache; +struct oom_control;
/* Cgroup-specific page state, on top of universal node page state */ enum memcg_stat_item { @@ -354,9 +355,11 @@ DECLARE_STATIC_KEY_FALSE(memcg_qos_stat_key);
bool memcg_low_priority_scan_tasks(int (*)(struct task_struct *, void *), void *); -void memcg_print_bad_task(void *arg, int ret); +void memcg_print_bad_task(struct oom_control *oc); extern int sysctl_memcg_qos_handler(struct ctl_table *table, int write, void __user *buffer, size_t *length, loff_t *ppos); +#else +void memcg_print_bad_task(struct oom_control *oc); #endif
/* @@ -1132,6 +1135,11 @@ static inline void count_memcg_event_mm(struct mm_struct *mm, enum vm_event_item idx) { } + +static inline void memcg_print_bad_task(struct oom_control *oc) +{ +} + #endif /* CONFIG_MEMCG */
/* idx can be of type enum memcg_stat_item or node_stat_item */ diff --git a/mm/memcontrol.c b/mm/memcontrol.c index aff8c05b2c72..1b11bc13e1aa 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -1246,9 +1246,6 @@ int mem_cgroup_scan_tasks(struct mem_cgroup *memcg, break; } } -#ifdef CONFIG_MEMCG_QOS - memcg_print_bad_task(arg, ret); -#endif return ret; }
@@ -3747,16 +3744,15 @@ bool memcg_low_priority_scan_tasks(int (*fn)(struct task_struct *, void *), return oc->chosen ? true : false; }
-void memcg_print_bad_task(void *arg, int ret) +void memcg_print_bad_task(struct oom_control *oc) { - struct oom_control *oc = arg; struct mem_cgroup *memcg; struct mem_cgroup_extension *memcg_ext;
if (!static_branch_likely(&memcg_qos_stat_key)) return;
- if (!ret && oc->chosen) { + if (oc->chosen) { memcg = mem_cgroup_from_task(oc->chosen); memcg_ext = to_memcg_ext(memcg); if (memcg_ext->memcg_priority) @@ -3786,6 +3782,13 @@ int sysctl_memcg_qos_handler(struct ctl_table *table, int write,
return ret; } + +#else + +void memcg_print_bad_task(struct oom_control *oc) +{ +} + #endif
#ifdef CONFIG_NUMA diff --git a/mm/oom_kill.c b/mm/oom_kill.c index bcd08df6d577..4ad05a72bb8c 100644 --- a/mm/oom_kill.c +++ b/mm/oom_kill.c @@ -415,9 +415,10 @@ static int oom_evaluate_task(struct task_struct *task, void *arg) */ static void select_bad_process(struct oom_control *oc) { - if (is_memcg_oom(oc)) - mem_cgroup_scan_tasks(oc->memcg, oom_evaluate_task, oc); - else { + if (is_memcg_oom(oc)) { + if (!mem_cgroup_scan_tasks(oc->memcg, oom_evaluate_task, oc)) + memcg_print_bad_task(oc); + } else { struct task_struct *p;
#ifdef CONFIG_MEMCG_QOS @@ -512,9 +513,10 @@ static void dump_tasks(struct oom_control *oc) pr_info("[ pid ] uid tgid total_vm rss pgtables_bytes swapents oom_score_adj name\n"); }
- if (is_memcg_oom(oc)) - mem_cgroup_scan_tasks(oc->memcg, dump_task, oc); - else { + if (is_memcg_oom(oc)) { + if (!mem_cgroup_scan_tasks(oc->memcg, dump_task, oc)) + memcg_print_bad_task(oc); + } else { struct task_struct *p;
rcu_read_lock();