aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/ptrace.c61
1 files changed, 61 insertions, 0 deletions
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index c719bb9d79ab..fad5f1e8511f 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -366,6 +366,50 @@ static int ptrace_setsiginfo(struct task_struct *child, siginfo_t __user * data)
366 return error; 366 return error;
367} 367}
368 368
369
370#ifdef PTRACE_SINGLESTEP
371#define is_singlestep(request) ((request) == PTRACE_SINGLESTEP)
372#else
373#define is_singlestep(request) 0
374#endif
375
376#ifdef PTRACE_SYSEMU
377#define is_sysemu_singlestep(request) ((request) == PTRACE_SYSEMU_SINGLESTEP)
378#else
379#define is_sysemu_singlestep(request) 0
380#endif
381
382static int ptrace_resume(struct task_struct *child, long request, long data)
383{
384 if (!valid_signal(data))
385 return -EIO;
386
387 if (request == PTRACE_SYSCALL)
388 set_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
389 else
390 clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
391
392#ifdef TIF_SYSCALL_EMU
393 if (request == PTRACE_SYSEMU || request == PTRACE_SYSEMU_SINGLESTEP)
394 set_tsk_thread_flag(child, TIF_SYSCALL_EMU);
395 else
396 clear_tsk_thread_flag(child, TIF_SYSCALL_EMU);
397#endif
398
399 if (is_singlestep(request) || is_sysemu_singlestep(request)) {
400 if (unlikely(!arch_has_single_step()))
401 return -EIO;
402 user_enable_single_step(child);
403 }
404 else
405 user_disable_single_step(child);
406
407 child->exit_code = data;
408 wake_up_process(child);
409
410 return 0;
411}
412
369int ptrace_request(struct task_struct *child, long request, 413int ptrace_request(struct task_struct *child, long request,
370 long addr, long data) 414 long addr, long data)
371{ 415{
@@ -390,6 +434,23 @@ int ptrace_request(struct task_struct *child, long request,
390 case PTRACE_DETACH: /* detach a process that was attached. */ 434 case PTRACE_DETACH: /* detach a process that was attached. */
391 ret = ptrace_detach(child, data); 435 ret = ptrace_detach(child, data);
392 break; 436 break;
437
438#ifdef PTRACE_SINGLESTEP
439 case PTRACE_SINGLESTEP:
440#endif
441#ifdef PTRACE_SYSEMU
442 case PTRACE_SYSEMU:
443 case PTRACE_SYSEMU_SINGLESTEP:
444#endif
445 case PTRACE_SYSCALL:
446 case PTRACE_CONT:
447 return ptrace_resume(child, request, data);
448
449 case PTRACE_KILL:
450 if (child->exit_state) /* already dead */
451 return 0;
452 return ptrace_resume(child, request, SIGKILL);
453
393 default: 454 default:
394 break; 455 break;
395 } 456 }