aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOleg Nesterov <oleg@redhat.com>2012-05-31 19:26:16 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-05-31 20:49:28 -0400
commit43e13cc107cf6cd3c15fbe1cef849435c2223d50 (patch)
tree9a1b3aa79ec2e8374944c23cf57a73790a3fc6ce
parent9b3c98cd663750c33434572ff76ba306505eba5a (diff)
cred: remove task_is_dead() from __task_cred() validation
Commit 8f92054e7ca1 ("CRED: Fix __task_cred()'s lockdep check and banner comment"): add the following validation condition: task->exit_state >= 0 to permit the access if the target task is dead and therefore unable to change its own credentials. OK, but afaics currently this can only help wait_task_zombie() which calls __task_cred() without rcu lock. Remove this validation and change wait_task_zombie() to use task_uid() instead. This means we do rcu_read_lock() only to shut up the lockdep, but we already do the same in, say, wait_task_stopped(). task_is_dead() should die, task->exit_state != 0 means that this task has passed exit_notify(), only do_wait-like code paths should use this. Unfortunately, we can't kill task_is_dead() right now, it has already acquired buggy users in drivers/staging. The fix already exists. Signed-off-by: Oleg Nesterov <oleg@redhat.com> Reviewed-by: "Eric W. Biederman" <ebiederm@xmission.com> Acked-by: David Howells <dhowells@redhat.com> Cc: Jiri Olsa <jolsa@redhat.com> Cc: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Cc: James Morris <jmorris@namei.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--include/linux/cred.h10
-rw-r--r--kernel/exit.c2
2 files changed, 4 insertions, 8 deletions
diff --git a/include/linux/cred.h b/include/linux/cred.h
index 917dc5aeb1d4..ebbed2ce6637 100644
--- a/include/linux/cred.h
+++ b/include/linux/cred.h
@@ -277,17 +277,13 @@ static inline void put_cred(const struct cred *_cred)
277 * @task: The task to query 277 * @task: The task to query
278 * 278 *
279 * Access the objective credentials of a task. The caller must hold the RCU 279 * Access the objective credentials of a task. The caller must hold the RCU
280 * readlock or the task must be dead and unable to change its own credentials. 280 * readlock.
281 * 281 *
282 * The result of this function should not be passed directly to get_cred(); 282 * The result of this function should not be passed directly to get_cred();
283 * rather get_task_cred() should be used instead. 283 * rather get_task_cred() should be used instead.
284 */ 284 */
285#define __task_cred(task) \ 285#define __task_cred(task) \
286 ({ \ 286 rcu_dereference((task)->real_cred)
287 const struct task_struct *__t = (task); \
288 rcu_dereference_check(__t->real_cred, \
289 task_is_dead(__t)); \
290 })
291 287
292/** 288/**
293 * get_current_cred - Get the current task's subjective credentials 289 * get_current_cred - Get the current task's subjective credentials
diff --git a/kernel/exit.c b/kernel/exit.c
index 910a0716e17a..3281493ce7ad 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -1214,7 +1214,7 @@ static int wait_task_zombie(struct wait_opts *wo, struct task_struct *p)
1214 unsigned long state; 1214 unsigned long state;
1215 int retval, status, traced; 1215 int retval, status, traced;
1216 pid_t pid = task_pid_vnr(p); 1216 pid_t pid = task_pid_vnr(p);
1217 uid_t uid = from_kuid_munged(current_user_ns(), __task_cred(p)->uid); 1217 uid_t uid = from_kuid_munged(current_user_ns(), task_uid(p));
1218 struct siginfo __user *infop; 1218 struct siginfo __user *infop;
1219 1219
1220 if (!likely(wo->wo_flags & WEXITED)) 1220 if (!likely(wo->wo_flags & WEXITED))