History

mm, oom: fix use-after-free in oom_kill_process

Syzbot instance running on upstream kernel found a use-after-free bug in oom_kill_process. On further inspection it seems like the process selected to be oom-killed has exited even before reaching read_lock(&tasklist_lock) in oom_kill_process(). More specifically the tsk->usage is 1 which is due to get_task_struct() in oom_evaluate_task() and the put_task_struct within for_each_thread() frees the tsk and for_each_thread() tries to access the tsk. The easiest fix is to do get/put across the for_each_thread() on the selected task. Now the next question is should we continue with the oom-kill as the previously selected task has exited? However before adding more complexity and heuristics, let's answer why we even look at the children of oom-kill selected task? The select_bad_process() has already selected the worst process in the system/memcg. Due to race, the selected process might not be the worst at the kill time but does that matter? The userspace can use the oom_score_adj interface to prefer children to be killed before the parent. I looked at the history but it seems like this is there before git history.

Shakeel Butt committed 7 years ago

Commit cefc7ef1 parent b13bc351 file · +8 −0Browse files

Unified · Split

mm/oom_kill.c+8−0
@@ -975,6 +975,13 @@ static void oom_kill_process(struct oom_control *oc, const char *message) · 974 unmodified lines
975 * still freeing memory.975 * still freeing memory.
976 */976 */
977 read_lock(&tasklist_lock);977 read_lock(&tasklist_lock);
978
979 /*
980 * The task 'p' might have already exited before reaching here. The
981 * put_task_struct() will free task_struct 'p' while the loop still try
982 * to access the field of 'p', so, get an extra reference.
983 */
984 get_task_struct(p);
978 for_each_thread(p, t) {985 for_each_thread(p, t) {
979 list_for_each_entry(child, &t->children, sibling) {986 list_for_each_entry(child, &t->children, sibling) {
980 unsigned int child_points;987 unsigned int child_points;
@@ -994,6 +1001,7 @@ static void oom_kill_process(struct oom_control *oc, const char *message) · 13 unmodified lines
994 }1001 }
995 }1002 }
996 }1003 }
1004 put_task_struct(p);
997 read_unlock(&tasklist_lock);1005 read_unlock(&tasklist_lock);
998 1006
999 /*1007 /*

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t