aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/ptrace.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/ptrace.c')
-rw-r--r--kernel/ptrace.c29
1 files changed, 23 insertions, 6 deletions
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index 4c8bcd7dd8e0..ca2df68faf76 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -115,6 +115,8 @@ int ptrace_check_attach(struct task_struct *child, int kill)
115 115
116int __ptrace_may_access(struct task_struct *task, unsigned int mode) 116int __ptrace_may_access(struct task_struct *task, unsigned int mode)
117{ 117{
118 const struct cred *cred = current_cred(), *tcred;
119
118 /* May we inspect the given task? 120 /* May we inspect the given task?
119 * This check is used both for attaching with ptrace 121 * This check is used both for attaching with ptrace
120 * and for allowing access to sensitive information in /proc. 122 * and for allowing access to sensitive information in /proc.
@@ -127,13 +129,19 @@ int __ptrace_may_access(struct task_struct *task, unsigned int mode)
127 /* Don't let security modules deny introspection */ 129 /* Don't let security modules deny introspection */
128 if (task == current) 130 if (task == current)
129 return 0; 131 return 0;
130 if (((current->uid != task->euid) || 132 rcu_read_lock();
131 (current->uid != task->suid) || 133 tcred = __task_cred(task);
132 (current->uid != task->uid) || 134 if ((cred->uid != tcred->euid ||
133 (current->gid != task->egid) || 135 cred->uid != tcred->suid ||
134 (current->gid != task->sgid) || 136 cred->uid != tcred->uid ||
135 (current->gid != task->gid)) && !capable(CAP_SYS_PTRACE)) 137 cred->gid != tcred->egid ||
138 cred->gid != tcred->sgid ||
139 cred->gid != tcred->gid) &&
140 !capable(CAP_SYS_PTRACE)) {
141 rcu_read_unlock();
136 return -EPERM; 142 return -EPERM;
143 }
144 rcu_read_unlock();
137 smp_rmb(); 145 smp_rmb();
138 if (task->mm) 146 if (task->mm)
139 dumpable = get_dumpable(task->mm); 147 dumpable = get_dumpable(task->mm);
@@ -163,6 +171,14 @@ int ptrace_attach(struct task_struct *task)
163 if (same_thread_group(task, current)) 171 if (same_thread_group(task, current))
164 goto out; 172 goto out;
165 173
174 /* Protect exec's credential calculations against our interference;
175 * SUID, SGID and LSM creds get determined differently under ptrace.
176 */
177 retval = mutex_lock_interruptible(&current->cred_exec_mutex);
178 if (retval < 0)
179 goto out;
180
181 retval = -EPERM;
166repeat: 182repeat:
167 /* 183 /*
168 * Nasty, nasty. 184 * Nasty, nasty.
@@ -202,6 +218,7 @@ repeat:
202bad: 218bad:
203 write_unlock_irqrestore(&tasklist_lock, flags); 219 write_unlock_irqrestore(&tasklist_lock, flags);
204 task_unlock(task); 220 task_unlock(task);
221 mutex_unlock(&current->cred_exec_mutex);
205out: 222out:
206 return retval; 223 return retval;
207} 224}