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
975975 * still freeing memory.
976976 */
977977 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);
978985 for_each_thread(p, t) {
979986 list_for_each_entry(child, &t->children, sibling) {
980987 unsigned int child_points;
@@ -994,6 +1001,7 @@ static void oom_kill_process(struct oom_control *oc, const char *message) · 13 unmodified lines
9941001 }
9951002 }
9961003 }
1004+ put_task_struct(p);
9971005 read_unlock(&tasklist_lock);
9981006
9991007 /*

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