| From b95c35e76b29ba812e5dabdd91592e25ec640e93 Mon Sep 17 00:00:00 2001 |
| From: Oleg Nesterov <oleg@redhat.com> |
| Date: Thu, 1 Apr 2010 15:13:57 +0200 |
| Subject: oom: fix the unsafe usage of badness() in proc_oom_score() |
| |
| From: Oleg Nesterov <oleg@redhat.com> |
| |
| commit b95c35e76b29ba812e5dabdd91592e25ec640e93 upstream. |
| |
| proc_oom_score(task) has a reference to task_struct, but that is all. |
| If this task was already released before we take tasklist_lock |
| |
| - we can't use task->group_leader, it points to nowhere |
| |
| - it is not safe to call badness() even if this task is |
| ->group_leader, has_intersects_mems_allowed() assumes |
| it is safe to iterate over ->thread_group list. |
| |
| - even worse, badness() can hit ->signal == NULL |
| |
| Add the pid_alive() check to ensure __unhash_process() was not called. |
| |
| Also, use "task" instead of task->group_leader. badness() should return |
| the same result for any sub-thread. Currently this is not true, but |
| this should be changed anyway. |
| |
| Signed-off-by: Oleg Nesterov <oleg@redhat.com> |
| Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> |
| |
| --- |
| fs/proc/base.c | 5 +++-- |
| 1 file changed, 3 insertions(+), 2 deletions(-) |
| |
| --- a/fs/proc/base.c |
| +++ b/fs/proc/base.c |
| @@ -442,12 +442,13 @@ static const struct file_operations proc |
| unsigned long badness(struct task_struct *p, unsigned long uptime); |
| static int proc_oom_score(struct task_struct *task, char *buffer) |
| { |
| - unsigned long points; |
| + unsigned long points = 0; |
| struct timespec uptime; |
| |
| do_posix_clock_monotonic_gettime(&uptime); |
| read_lock(&tasklist_lock); |
| - points = badness(task->group_leader, uptime.tv_sec); |
| + if (pid_alive(task)) |
| + points = badness(task, uptime.tv_sec); |
| read_unlock(&tasklist_lock); |
| return sprintf(buffer, "%lu\n", points); |
| } |