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>
diff --git a/kernel/futex.c b/kernel/futex.c
index 28421d8..4fe790e 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -439,15 +439,20 @@
static struct task_struct * futex_find_get_task(pid_t pid)
{
struct task_struct *p;
- uid_t euid = current_euid();
+ const struct cred *cred = current_cred(), *pcred;
rcu_read_lock();
p = find_task_by_vpid(pid);
- if (!p || (euid != p->cred->euid &&
- euid != p->cred->uid))
+ if (!p) {
p = ERR_PTR(-ESRCH);
- else
- get_task_struct(p);
+ } else {
+ pcred = __task_cred(p);
+ if (cred->euid != pcred->euid &&
+ cred->euid != pcred->uid)
+ p = ERR_PTR(-ESRCH);
+ else
+ get_task_struct(p);
+ }
rcu_read_unlock();
@@ -1831,7 +1836,7 @@
{
struct robust_list_head __user *head;
unsigned long ret;
- uid_t euid = current_euid();
+ const struct cred *cred = current_cred(), *pcred;
if (!futex_cmpxchg_enabled)
return -ENOSYS;
@@ -1847,8 +1852,9 @@
if (!p)
goto err_unlock;
ret = -EPERM;
- if (euid != p->cred->euid &&
- euid != p->cred->uid &&
+ pcred = __task_cred(p);
+ if (cred->euid != pcred->euid &&
+ cred->euid != pcred->uid &&
!capable(CAP_SYS_PTRACE))
goto err_unlock;
head = p->robust_list;