diff options
author | Oleg Nesterov <oleg@tv-sign.ru> | 2008-02-08 07:19:07 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2008-02-08 12:22:26 -0500 |
commit | 3a515e4a62dbf7e4c213740268a5267faa69e5b2 (patch) | |
tree | 51f98e662c80ca5de628f09c5eb24d18f1794f6c | |
parent | f2cc3eb133baa2e9dc8efd40f417106b2ee520f3 (diff) |
wait_task_continued/zombie: don't use task_pid_nr_ns() lockless
Surprise, the other two wait_task_*() functions also abuse the
task_pid_nr_ns() function, and may cause read-after-free or report nr == 0
in wait_task_continued(). wait_task_zombie() doesn't have this problem,
but it is still better to cache pid_t rather than call task_pid_nr_ns()
three times on the saved pid_namespace.
Signed-off-by: Oleg Nesterov <oleg@tv-sign.ru>
Cc: Roland McGrath <roland@redhat.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | kernel/exit.c | 15 |
1 files changed, 5 insertions, 10 deletions
diff --git a/kernel/exit.c b/kernel/exit.c index ee607720ae58..dee8b4d63403 100644 --- a/kernel/exit.c +++ b/kernel/exit.c | |||
@@ -1189,12 +1189,9 @@ static int wait_task_zombie(struct task_struct *p, int noreap, | |||
1189 | { | 1189 | { |
1190 | unsigned long state; | 1190 | unsigned long state; |
1191 | int retval, status, traced; | 1191 | int retval, status, traced; |
1192 | struct pid_namespace *ns; | 1192 | pid_t pid = task_pid_nr_ns(p, current->nsproxy->pid_ns); |
1193 | |||
1194 | ns = current->nsproxy->pid_ns; | ||
1195 | 1193 | ||
1196 | if (unlikely(noreap)) { | 1194 | if (unlikely(noreap)) { |
1197 | pid_t pid = task_pid_nr_ns(p, ns); | ||
1198 | uid_t uid = p->uid; | 1195 | uid_t uid = p->uid; |
1199 | int exit_code = p->exit_code; | 1196 | int exit_code = p->exit_code; |
1200 | int why, status; | 1197 | int why, status; |
@@ -1313,11 +1310,11 @@ static int wait_task_zombie(struct task_struct *p, int noreap, | |||
1313 | retval = put_user(status, &infop->si_status); | 1310 | retval = put_user(status, &infop->si_status); |
1314 | } | 1311 | } |
1315 | if (!retval && infop) | 1312 | if (!retval && infop) |
1316 | retval = put_user(task_pid_nr_ns(p, ns), &infop->si_pid); | 1313 | retval = put_user(pid, &infop->si_pid); |
1317 | if (!retval && infop) | 1314 | if (!retval && infop) |
1318 | retval = put_user(p->uid, &infop->si_uid); | 1315 | retval = put_user(p->uid, &infop->si_uid); |
1319 | if (!retval) | 1316 | if (!retval) |
1320 | retval = task_pid_nr_ns(p, ns); | 1317 | retval = pid; |
1321 | 1318 | ||
1322 | if (traced) { | 1319 | if (traced) { |
1323 | write_lock_irq(&tasklist_lock); | 1320 | write_lock_irq(&tasklist_lock); |
@@ -1436,7 +1433,6 @@ static int wait_task_continued(struct task_struct *p, int noreap, | |||
1436 | int retval; | 1433 | int retval; |
1437 | pid_t pid; | 1434 | pid_t pid; |
1438 | uid_t uid; | 1435 | uid_t uid; |
1439 | struct pid_namespace *ns; | ||
1440 | 1436 | ||
1441 | if (!(p->signal->flags & SIGNAL_STOP_CONTINUED)) | 1437 | if (!(p->signal->flags & SIGNAL_STOP_CONTINUED)) |
1442 | return 0; | 1438 | return 0; |
@@ -1451,8 +1447,7 @@ static int wait_task_continued(struct task_struct *p, int noreap, | |||
1451 | p->signal->flags &= ~SIGNAL_STOP_CONTINUED; | 1447 | p->signal->flags &= ~SIGNAL_STOP_CONTINUED; |
1452 | spin_unlock_irq(&p->sighand->siglock); | 1448 | spin_unlock_irq(&p->sighand->siglock); |
1453 | 1449 | ||
1454 | ns = current->nsproxy->pid_ns; | 1450 | pid = task_pid_nr_ns(p, current->nsproxy->pid_ns); |
1455 | pid = task_pid_nr_ns(p, ns); | ||
1456 | uid = p->uid; | 1451 | uid = p->uid; |
1457 | get_task_struct(p); | 1452 | get_task_struct(p); |
1458 | read_unlock(&tasklist_lock); | 1453 | read_unlock(&tasklist_lock); |
@@ -1463,7 +1458,7 @@ static int wait_task_continued(struct task_struct *p, int noreap, | |||
1463 | if (!retval && stat_addr) | 1458 | if (!retval && stat_addr) |
1464 | retval = put_user(0xffff, stat_addr); | 1459 | retval = put_user(0xffff, stat_addr); |
1465 | if (!retval) | 1460 | if (!retval) |
1466 | retval = task_pid_nr_ns(p, ns); | 1461 | retval = pid; |
1467 | } else { | 1462 | } else { |
1468 | retval = wait_noreap_copyout(p, pid, uid, | 1463 | retval = wait_noreap_copyout(p, pid, uid, |
1469 | CLD_CONTINUED, SIGCONT, | 1464 | CLD_CONTINUED, SIGCONT, |