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 100a71cfdaba..29dc700e198c 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -127,6 +127,8 @@ int ptrace_check_attach(struct task_struct *child, int kill)
127 127
128int __ptrace_may_access(struct task_struct *task, unsigned int mode) 128int __ptrace_may_access(struct task_struct *task, unsigned int mode)
129{ 129{
130 const struct cred *cred = current_cred(), *tcred;
131
130 /* May we inspect the given task? 132 /* May we inspect the given task?
131 * This check is used both for attaching with ptrace 133 * This check is used both for attaching with ptrace
132 * and for allowing access to sensitive information in /proc. 134 * and for allowing access to sensitive information in /proc.
@@ -139,13 +141,19 @@ int __ptrace_may_access(struct task_struct *task, unsigned int mode)
139 /* Don't let security modules deny introspection */ 141 /* Don't let security modules deny introspection */
140 if (task == current) 142 if (task == current)
141 return 0; 143 return 0;
142 if (((current->uid != task->euid) || 144 rcu_read_lock();
143 (current->uid != task->suid) || 145 tcred = __task_cred(task);
144 (current->uid != task->uid) || 146 if ((cred->uid != tcred->euid ||
145 (current->gid != task->egid) || 147 cred->uid != tcred->suid ||
146 (current->gid != task->sgid) || 148 cred->uid != tcred->uid ||
147 (current->gid != task->gid)) && !capable(CAP_SYS_PTRACE)) 149 cred->gid != tcred->egid ||
150 cred->gid != tcred->sgid ||
151 cred->gid != tcred->gid) &&
152 !capable(CAP_SYS_PTRACE)) {
153 rcu_read_unlock();
148 return -EPERM; 154 return -EPERM;
155 }
156 rcu_read_unlock();
149 smp_rmb(); 157 smp_rmb();
150 if (task->mm) 158 if (task->mm)
151 dumpable = get_dumpable(task->mm); 159 dumpable = get_dumpable(task->mm);
@@ -175,6 +183,14 @@ int ptrace_attach(struct task_struct *task)
175 if (same_thread_group(task, current)) 183 if (same_thread_group(task, current))
176 goto out; 184 goto out;
177 185
186 /* Protect exec's credential calculations against our interference;
187 * SUID, SGID and LSM creds get determined differently under ptrace.
188 */
189 retval = mutex_lock_interruptible(&current->cred_exec_mutex);
190 if (retval < 0)
191 goto out;
192
193 retval = -EPERM;
178repeat: 194repeat:
179 /* 195 /*
180 * Nasty, nasty. 196 * Nasty, nasty.
@@ -214,6 +230,7 @@ repeat:
214bad: 230bad:
215 write_unlock_irqrestore(&tasklist_lock, flags); 231 write_unlock_irqrestore(&tasklist_lock, flags);
216 task_unlock(task); 232 task_unlock(task);
233 mutex_unlock(&current->cred_exec_mutex);
217out: 234out:
218 return retval; 235 return retval;
219} 236}