diff options
author | David Howells <dhowells@redhat.com> | 2008-11-13 18:39:19 -0500 |
---|---|---|
committer | James Morris <jmorris@namei.org> | 2008-11-13 18:39:19 -0500 |
commit | c69e8d9c01db2adc503464993c358901c9af9de4 (patch) | |
tree | bed94aaa9aeb7a7834d1c880f72b62a11a752c78 /kernel/exit.c | |
parent | 86a264abe542cfececb4df129bc45a0338d8cdb9 (diff) |
CRED: Use RCU to access another task's creds and to release a task's own creds
Use RCU to access another task's creds and to release a task's own creds.
This means that it will be possible for the credentials of a task to be
replaced without another task (a) requiring a full lock to read them, and (b)
seeing deallocated memory.
Signed-off-by: David Howells <dhowells@redhat.com>
Acked-by: James Morris <jmorris@namei.org>
Acked-by: Serge Hallyn <serue@us.ibm.com>
Signed-off-by: James Morris <jmorris@namei.org>
Diffstat (limited to 'kernel/exit.c')
-rw-r--r-- | kernel/exit.c | 14 |
1 files changed, 9 insertions, 5 deletions
diff --git a/kernel/exit.c b/kernel/exit.c index e0f6e1892fb9..bbc22530f2c1 100644 --- a/kernel/exit.c +++ b/kernel/exit.c | |||
@@ -160,7 +160,10 @@ void release_task(struct task_struct * p) | |||
160 | int zap_leader; | 160 | int zap_leader; |
161 | repeat: | 161 | repeat: |
162 | tracehook_prepare_release_task(p); | 162 | tracehook_prepare_release_task(p); |
163 | atomic_dec(&p->cred->user->processes); | 163 | /* don't need to get the RCU readlock here - the process is dead and |
164 | * can't be modifying its own credentials */ | ||
165 | atomic_dec(&__task_cred(p)->user->processes); | ||
166 | |||
164 | proc_flush_task(p); | 167 | proc_flush_task(p); |
165 | write_lock_irq(&tasklist_lock); | 168 | write_lock_irq(&tasklist_lock); |
166 | tracehook_finish_release_task(p); | 169 | tracehook_finish_release_task(p); |
@@ -1267,12 +1270,12 @@ static int wait_task_zombie(struct task_struct *p, int options, | |||
1267 | unsigned long state; | 1270 | unsigned long state; |
1268 | int retval, status, traced; | 1271 | int retval, status, traced; |
1269 | pid_t pid = task_pid_vnr(p); | 1272 | pid_t pid = task_pid_vnr(p); |
1273 | uid_t uid = __task_cred(p)->uid; | ||
1270 | 1274 | ||
1271 | if (!likely(options & WEXITED)) | 1275 | if (!likely(options & WEXITED)) |
1272 | return 0; | 1276 | return 0; |
1273 | 1277 | ||
1274 | if (unlikely(options & WNOWAIT)) { | 1278 | if (unlikely(options & WNOWAIT)) { |
1275 | uid_t uid = p->cred->uid; | ||
1276 | int exit_code = p->exit_code; | 1279 | int exit_code = p->exit_code; |
1277 | int why, status; | 1280 | int why, status; |
1278 | 1281 | ||
@@ -1393,7 +1396,7 @@ static int wait_task_zombie(struct task_struct *p, int options, | |||
1393 | if (!retval && infop) | 1396 | if (!retval && infop) |
1394 | retval = put_user(pid, &infop->si_pid); | 1397 | retval = put_user(pid, &infop->si_pid); |
1395 | if (!retval && infop) | 1398 | if (!retval && infop) |
1396 | retval = put_user(p->cred->uid, &infop->si_uid); | 1399 | retval = put_user(uid, &infop->si_uid); |
1397 | if (!retval) | 1400 | if (!retval) |
1398 | retval = pid; | 1401 | retval = pid; |
1399 | 1402 | ||
@@ -1458,7 +1461,8 @@ static int wait_task_stopped(int ptrace, struct task_struct *p, | |||
1458 | if (!unlikely(options & WNOWAIT)) | 1461 | if (!unlikely(options & WNOWAIT)) |
1459 | p->exit_code = 0; | 1462 | p->exit_code = 0; |
1460 | 1463 | ||
1461 | uid = p->cred->uid; | 1464 | /* don't need the RCU readlock here as we're holding a spinlock */ |
1465 | uid = __task_cred(p)->uid; | ||
1462 | unlock_sig: | 1466 | unlock_sig: |
1463 | spin_unlock_irq(&p->sighand->siglock); | 1467 | spin_unlock_irq(&p->sighand->siglock); |
1464 | if (!exit_code) | 1468 | if (!exit_code) |
@@ -1532,10 +1536,10 @@ static int wait_task_continued(struct task_struct *p, int options, | |||
1532 | } | 1536 | } |
1533 | if (!unlikely(options & WNOWAIT)) | 1537 | if (!unlikely(options & WNOWAIT)) |
1534 | p->signal->flags &= ~SIGNAL_STOP_CONTINUED; | 1538 | p->signal->flags &= ~SIGNAL_STOP_CONTINUED; |
1539 | uid = __task_cred(p)->uid; | ||
1535 | spin_unlock_irq(&p->sighand->siglock); | 1540 | spin_unlock_irq(&p->sighand->siglock); |
1536 | 1541 | ||
1537 | pid = task_pid_vnr(p); | 1542 | pid = task_pid_vnr(p); |
1538 | uid = p->cred->uid; | ||
1539 | get_task_struct(p); | 1543 | get_task_struct(p); |
1540 | read_unlock(&tasklist_lock); | 1544 | read_unlock(&tasklist_lock); |
1541 | 1545 | ||