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 /kernel | |
| 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>
Diffstat (limited to 'kernel')
| -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, |
