[glsdk/meta-ti-glsdk.git] / recipes-kernel / linux / linux-ti33x-psp-3.2 / 3.2.16 / 0064-futex-Do-not-leak-robust-list-to-unprivileged-proces.patch
1 From 7480d9953ded1b970bb05c7585e2a08001ae8565 Mon Sep 17 00:00:00 2001
2 From: Kees Cook <keescook@chromium.org>
3 Date: Mon, 19 Mar 2012 16:12:53 -0700
4 Subject: [PATCH 64/68] futex: Do not leak robust list to unprivileged process
6 commit bdbb776f882f5ad431aa1e694c69c1c3d6a4a5b8 upstream.
8 It was possible to extract the robust list head address from a setuid
9 process if it had used set_robust_list(), allowing an ASLR info leak. This
10 changes the permission checks to be the same as those used for similar
11 info that comes out of /proc.
13 Running a setuid program that uses robust futexes would have had:
14 cred->euid != pcred->euid
15 cred->euid == pcred->uid
16 so the old permissions check would allow it. I'm not aware of any setuid
17 programs that use robust futexes, so this is just a preventative measure.
19 (This patch is based on changes from grsecurity.)
21 Signed-off-by: Kees Cook <keescook@chromium.org>
22 Cc: Darren Hart <dvhart@linux.intel.com>
23 Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
24 Cc: Jiri Kosina <jkosina@suse.cz>
25 Cc: Eric W. Biederman <ebiederm@xmission.com>
26 Cc: David Howells <dhowells@redhat.com>
27 Cc: Serge E. Hallyn <serge.hallyn@canonical.com>
28 Cc: kernel-hardening@lists.openwall.com
29 Cc: spender@grsecurity.net
30 Link: http://lkml.kernel.org/r/20120319231253.GA20893@www.outflux.net
31 Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
32 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
33 ---
34 kernel/futex.c | 36 +++++++++++++-----------------------
35 kernel/futex_compat.c | 36 +++++++++++++-----------------------
36 2 files changed, 26 insertions(+), 46 deletions(-)
38 diff --git a/kernel/futex.c b/kernel/futex.c
39 index 0677023..866c9d5 100644
40 --- a/kernel/futex.c
41 +++ b/kernel/futex.c
42 @@ -59,6 +59,7 @@
43 #include <linux/magic.h>
44 #include <linux/pid.h>
45 #include <linux/nsproxy.h>
46 +#include <linux/ptrace.h>
48 #include <asm/futex.h>
50 @@ -2443,40 +2444,29 @@ SYSCALL_DEFINE3(get_robust_list, int, pid,
51 {
52 struct robust_list_head __user *head;
53 unsigned long ret;
54 - const struct cred *cred = current_cred(), *pcred;
55 + struct task_struct *p;
57 if (!futex_cmpxchg_enabled)
58 return -ENOSYS;
60 + rcu_read_lock();
61 +
62 + ret = -ESRCH;
63 if (!pid)
64 - head = current->robust_list;
65 + p = current;
66 else {
67 - struct task_struct *p;
68 -
69 - ret = -ESRCH;
70 - rcu_read_lock();
71 p = find_task_by_vpid(pid);
72 if (!p)
73 goto err_unlock;
74 - ret = -EPERM;
75 - pcred = __task_cred(p);
76 - /* If victim is in different user_ns, then uids are not
77 - comparable, so we must have CAP_SYS_PTRACE */
78 - if (cred->user->user_ns != pcred->user->user_ns) {
79 - if (!ns_capable(pcred->user->user_ns, CAP_SYS_PTRACE))
80 - goto err_unlock;
81 - goto ok;
82 - }
83 - /* If victim is in same user_ns, then uids are comparable */
84 - if (cred->euid != pcred->euid &&
85 - cred->euid != pcred->uid &&
86 - !ns_capable(pcred->user->user_ns, CAP_SYS_PTRACE))
87 - goto err_unlock;
88 -ok:
89 - head = p->robust_list;
90 - rcu_read_unlock();
91 }
93 + ret = -EPERM;
94 + if (!ptrace_may_access(p, PTRACE_MODE_READ))
95 + goto err_unlock;
96 +
97 + head = p->robust_list;
98 + rcu_read_unlock();
99 +
100 if (put_user(sizeof(*head), len_ptr))
101 return -EFAULT;
102 return put_user(head, head_ptr);
103 diff --git a/kernel/futex_compat.c b/kernel/futex_compat.c
104 index 5f9e689..a9642d5 100644
105 --- a/kernel/futex_compat.c
106 +++ b/kernel/futex_compat.c
107 @@ -10,6 +10,7 @@
108 #include <linux/compat.h>
109 #include <linux/nsproxy.h>
110 #include <linux/futex.h>
111 +#include <linux/ptrace.h>
113 #include <asm/uaccess.h>
115 @@ -136,40 +137,29 @@ compat_sys_get_robust_list(int pid, compat_uptr_t __user *head_ptr,
116 {
117 struct compat_robust_list_head __user *head;
118 unsigned long ret;
119 - const struct cred *cred = current_cred(), *pcred;
120 + struct task_struct *p;
122 if (!futex_cmpxchg_enabled)
123 return -ENOSYS;
125 + rcu_read_lock();
126 +
127 + ret = -ESRCH;
128 if (!pid)
129 - head = current->compat_robust_list;
130 + p = current;
131 else {
132 - struct task_struct *p;
133 -
134 - ret = -ESRCH;
135 - rcu_read_lock();
136 p = find_task_by_vpid(pid);
137 if (!p)
138 goto err_unlock;
139 - ret = -EPERM;
140 - pcred = __task_cred(p);
141 - /* If victim is in different user_ns, then uids are not
142 - comparable, so we must have CAP_SYS_PTRACE */
143 - if (cred->user->user_ns != pcred->user->user_ns) {
144 - if (!ns_capable(pcred->user->user_ns, CAP_SYS_PTRACE))
145 - goto err_unlock;
146 - goto ok;
147 - }
148 - /* If victim is in same user_ns, then uids are comparable */
149 - if (cred->euid != pcred->euid &&
150 - cred->euid != pcred->uid &&
151 - !ns_capable(pcred->user->user_ns, CAP_SYS_PTRACE))
152 - goto err_unlock;
153 -ok:
154 - head = p->compat_robust_list;
155 - rcu_read_unlock();
156 }
158 + ret = -EPERM;
159 + if (!ptrace_may_access(p, PTRACE_MODE_READ))
160 + goto err_unlock;
161 +
162 + head = p->compat_robust_list;
163 + rcu_read_unlock();
164 +
165 if (put_user(sizeof(*head), len_ptr))
166 return -EFAULT;
167 return put_user(ptr_to_compat(head), head_ptr);
168 --
169 1.7.10