aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/ptrace.c
diff options
context:
space:
mode:
authorJames Morris <jmorris@namei.org>2009-05-08 03:56:47 -0400
committerJames Morris <jmorris@namei.org>2009-05-08 03:56:47 -0400
commitd254117099d711f215e62427f55dfb8ebd5ad011 (patch)
tree0848ff8dd74314fec14a86497f8d288c86ba7c65 /kernel/ptrace.c
parent07ff7a0b187f3951788f64ae1f30e8109bc8e9eb (diff)
parent8c9ed899b44c19e81859fbb0e9d659fe2f8630fc (diff)
Merge branch 'master' into next
Diffstat (limited to 'kernel/ptrace.c')
-rw-r--r--kernel/ptrace.c130
1 files changed, 101 insertions, 29 deletions
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index c9cf48b21f05..0692ab5a0d67 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -21,9 +21,7 @@
21#include <linux/audit.h> 21#include <linux/audit.h>
22#include <linux/pid_namespace.h> 22#include <linux/pid_namespace.h>
23#include <linux/syscalls.h> 23#include <linux/syscalls.h>
24 24#include <linux/uaccess.h>
25#include <asm/pgtable.h>
26#include <asm/uaccess.h>
27 25
28 26
29/* 27/*
@@ -48,7 +46,7 @@ void __ptrace_link(struct task_struct *child, struct task_struct *new_parent)
48 list_add(&child->ptrace_entry, &new_parent->ptraced); 46 list_add(&child->ptrace_entry, &new_parent->ptraced);
49 child->parent = new_parent; 47 child->parent = new_parent;
50} 48}
51 49
52/* 50/*
53 * Turn a tracing stop into a normal stop now, since with no tracer there 51 * Turn a tracing stop into a normal stop now, since with no tracer there
54 * would be no way to wake it up with SIGCONT or SIGKILL. If there was a 52 * would be no way to wake it up with SIGCONT or SIGKILL. If there was a
@@ -60,11 +58,15 @@ static void ptrace_untrace(struct task_struct *child)
60{ 58{
61 spin_lock(&child->sighand->siglock); 59 spin_lock(&child->sighand->siglock);
62 if (task_is_traced(child)) { 60 if (task_is_traced(child)) {
63 if (child->signal->flags & SIGNAL_STOP_STOPPED) { 61 /*
62 * If the group stop is completed or in progress,
63 * this thread was already counted as stopped.
64 */
65 if (child->signal->flags & SIGNAL_STOP_STOPPED ||
66 child->signal->group_stop_count)
64 __set_task_state(child, TASK_STOPPED); 67 __set_task_state(child, TASK_STOPPED);
65 } else { 68 else
66 signal_wake_up(child, 1); 69 signal_wake_up(child, 1);
67 }
68 } 70 }
69 spin_unlock(&child->sighand->siglock); 71 spin_unlock(&child->sighand->siglock);
70} 72}
@@ -169,7 +171,7 @@ bool ptrace_may_access(struct task_struct *task, unsigned int mode)
169 task_lock(task); 171 task_lock(task);
170 err = __ptrace_may_access(task, mode); 172 err = __ptrace_may_access(task, mode);
171 task_unlock(task); 173 task_unlock(task);
172 return (!err ? true : false); 174 return !err;
173} 175}
174 176
175int ptrace_attach(struct task_struct *task) 177int ptrace_attach(struct task_struct *task)
@@ -186,7 +188,7 @@ int ptrace_attach(struct task_struct *task)
186 /* Protect exec's credential calculations against our interference; 188 /* Protect exec's credential calculations against our interference;
187 * SUID, SGID and LSM creds get determined differently under ptrace. 189 * SUID, SGID and LSM creds get determined differently under ptrace.
188 */ 190 */
189 retval = mutex_lock_interruptible(&current->cred_exec_mutex); 191 retval = mutex_lock_interruptible(&task->cred_exec_mutex);
190 if (retval < 0) 192 if (retval < 0)
191 goto out; 193 goto out;
192 194
@@ -230,23 +232,63 @@ repeat:
230bad: 232bad:
231 write_unlock_irqrestore(&tasklist_lock, flags); 233 write_unlock_irqrestore(&tasklist_lock, flags);
232 task_unlock(task); 234 task_unlock(task);
233 mutex_unlock(&current->cred_exec_mutex); 235 mutex_unlock(&task->cred_exec_mutex);
234out: 236out:
235 return retval; 237 return retval;
236} 238}
237 239
238static inline void __ptrace_detach(struct task_struct *child, unsigned int data) 240/*
241 * Called with irqs disabled, returns true if childs should reap themselves.
242 */
243static int ignoring_children(struct sighand_struct *sigh)
239{ 244{
240 child->exit_code = data; 245 int ret;
241 /* .. re-parent .. */ 246 spin_lock(&sigh->siglock);
242 __ptrace_unlink(child); 247 ret = (sigh->action[SIGCHLD-1].sa.sa_handler == SIG_IGN) ||
243 /* .. and wake it up. */ 248 (sigh->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDWAIT);
244 if (child->exit_state != EXIT_ZOMBIE) 249 spin_unlock(&sigh->siglock);
245 wake_up_process(child); 250 return ret;
251}
252
253/*
254 * Called with tasklist_lock held for writing.
255 * Unlink a traced task, and clean it up if it was a traced zombie.
256 * Return true if it needs to be reaped with release_task().
257 * (We can't call release_task() here because we already hold tasklist_lock.)
258 *
259 * If it's a zombie, our attachedness prevented normal parent notification
260 * or self-reaping. Do notification now if it would have happened earlier.
261 * If it should reap itself, return true.
262 *
263 * If it's our own child, there is no notification to do.
264 * But if our normal children self-reap, then this child
265 * was prevented by ptrace and we must reap it now.
266 */
267static bool __ptrace_detach(struct task_struct *tracer, struct task_struct *p)
268{
269 __ptrace_unlink(p);
270
271 if (p->exit_state == EXIT_ZOMBIE) {
272 if (!task_detached(p) && thread_group_empty(p)) {
273 if (!same_thread_group(p->real_parent, tracer))
274 do_notify_parent(p, p->exit_signal);
275 else if (ignoring_children(tracer->sighand))
276 p->exit_signal = -1;
277 }
278 if (task_detached(p)) {
279 /* Mark it as in the process of being reaped. */
280 p->exit_state = EXIT_DEAD;
281 return true;
282 }
283 }
284
285 return false;
246} 286}
247 287
248int ptrace_detach(struct task_struct *child, unsigned int data) 288int ptrace_detach(struct task_struct *child, unsigned int data)
249{ 289{
290 bool dead = false;
291
250 if (!valid_signal(data)) 292 if (!valid_signal(data))
251 return -EIO; 293 return -EIO;
252 294
@@ -255,14 +297,45 @@ int ptrace_detach(struct task_struct *child, unsigned int data)
255 clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); 297 clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
256 298
257 write_lock_irq(&tasklist_lock); 299 write_lock_irq(&tasklist_lock);
258 /* protect against de_thread()->release_task() */ 300 /*
259 if (child->ptrace) 301 * This child can be already killed. Make sure de_thread() or
260 __ptrace_detach(child, data); 302 * our sub-thread doing do_wait() didn't do release_task() yet.
303 */
304 if (child->ptrace) {
305 child->exit_code = data;
306 dead = __ptrace_detach(current, child);
307 }
261 write_unlock_irq(&tasklist_lock); 308 write_unlock_irq(&tasklist_lock);
262 309
310 if (unlikely(dead))
311 release_task(child);
312
263 return 0; 313 return 0;
264} 314}
265 315
316/*
317 * Detach all tasks we were using ptrace on.
318 */
319void exit_ptrace(struct task_struct *tracer)
320{
321 struct task_struct *p, *n;
322 LIST_HEAD(ptrace_dead);
323
324 write_lock_irq(&tasklist_lock);
325 list_for_each_entry_safe(p, n, &tracer->ptraced, ptrace_entry) {
326 if (__ptrace_detach(tracer, p))
327 list_add(&p->ptrace_entry, &ptrace_dead);
328 }
329 write_unlock_irq(&tasklist_lock);
330
331 BUG_ON(!list_empty(&tracer->ptraced));
332
333 list_for_each_entry_safe(p, n, &ptrace_dead, ptrace_entry) {
334 list_del_init(&p->ptrace_entry);
335 release_task(p);
336 }
337}
338
266int ptrace_readdata(struct task_struct *tsk, unsigned long src, char __user *dst, int len) 339int ptrace_readdata(struct task_struct *tsk, unsigned long src, char __user *dst, int len)
267{ 340{
268 int copied = 0; 341 int copied = 0;
@@ -283,7 +356,7 @@ int ptrace_readdata(struct task_struct *tsk, unsigned long src, char __user *dst
283 copied += retval; 356 copied += retval;
284 src += retval; 357 src += retval;
285 dst += retval; 358 dst += retval;
286 len -= retval; 359 len -= retval;
287 } 360 }
288 return copied; 361 return copied;
289} 362}
@@ -308,7 +381,7 @@ int ptrace_writedata(struct task_struct *tsk, char __user *src, unsigned long ds
308 copied += retval; 381 copied += retval;
309 src += retval; 382 src += retval;
310 dst += retval; 383 dst += retval;
311 len -= retval; 384 len -= retval;
312 } 385 }
313 return copied; 386 return copied;
314} 387}
@@ -421,9 +494,9 @@ static int ptrace_resume(struct task_struct *child, long request, long data)
421 if (unlikely(!arch_has_single_step())) 494 if (unlikely(!arch_has_single_step()))
422 return -EIO; 495 return -EIO;
423 user_enable_single_step(child); 496 user_enable_single_step(child);
424 } 497 } else {
425 else
426 user_disable_single_step(child); 498 user_disable_single_step(child);
499 }
427 500
428 child->exit_code = data; 501 child->exit_code = data;
429 wake_up_process(child); 502 wake_up_process(child);
@@ -531,10 +604,11 @@ repeat:
531 ret = security_ptrace_traceme(current->parent); 604 ret = security_ptrace_traceme(current->parent);
532 605
533 /* 606 /*
534 * Set the ptrace bit in the process ptrace flags. 607 * Check PF_EXITING to ensure ->real_parent has not passed
535 * Then link us on our parent's ptraced list. 608 * exit_ptrace(). Otherwise we don't report the error but
609 * pretend ->real_parent untraces us right after return.
536 */ 610 */
537 if (!ret) { 611 if (!ret && !(current->real_parent->flags & PF_EXITING)) {
538 current->ptrace |= PT_PTRACED; 612 current->ptrace |= PT_PTRACED;
539 __ptrace_link(current, current->real_parent); 613 __ptrace_link(current, current->real_parent);
540 } 614 }
@@ -612,8 +686,6 @@ SYSCALL_DEFINE4(ptrace, long, request, long, pid, long, addr, long, data)
612 goto out_put_task_struct; 686 goto out_put_task_struct;
613 687
614 ret = arch_ptrace(child, request, addr, data); 688 ret = arch_ptrace(child, request, addr, data);
615 if (ret < 0)
616 goto out_put_task_struct;
617 689
618 out_put_task_struct: 690 out_put_task_struct:
619 put_task_struct(child); 691 put_task_struct(child);