summaryrefslogtreecommitdiffstats
path: root/kernel/ptrace.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/ptrace.c')
-rw-r--r--kernel/ptrace.c61
1 files changed, 43 insertions, 18 deletions
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index 335a7ae697f5..4041f5747e73 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -469,6 +469,7 @@ static int ptrace_detach(struct task_struct *child, unsigned int data)
469 /* Architecture-specific hardware disable .. */ 469 /* Architecture-specific hardware disable .. */
470 ptrace_disable(child); 470 ptrace_disable(child);
471 clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); 471 clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE);
472 flush_ptrace_hw_breakpoint(child);
472 473
473 write_lock_irq(&tasklist_lock); 474 write_lock_irq(&tasklist_lock);
474 /* 475 /*
@@ -844,6 +845,47 @@ int ptrace_request(struct task_struct *child, long request,
844 ret = ptrace_setsiginfo(child, &siginfo); 845 ret = ptrace_setsiginfo(child, &siginfo);
845 break; 846 break;
846 847
848 case PTRACE_GETSIGMASK:
849 if (addr != sizeof(sigset_t)) {
850 ret = -EINVAL;
851 break;
852 }
853
854 if (copy_to_user(datavp, &child->blocked, sizeof(sigset_t)))
855 ret = -EFAULT;
856 else
857 ret = 0;
858
859 break;
860
861 case PTRACE_SETSIGMASK: {
862 sigset_t new_set;
863
864 if (addr != sizeof(sigset_t)) {
865 ret = -EINVAL;
866 break;
867 }
868
869 if (copy_from_user(&new_set, datavp, sizeof(sigset_t))) {
870 ret = -EFAULT;
871 break;
872 }
873
874 sigdelsetmask(&new_set, sigmask(SIGKILL)|sigmask(SIGSTOP));
875
876 /*
877 * Every thread does recalc_sigpending() after resume, so
878 * retarget_shared_pending() and recalc_sigpending() are not
879 * called here.
880 */
881 spin_lock_irq(&child->sighand->siglock);
882 child->blocked = new_set;
883 spin_unlock_irq(&child->sighand->siglock);
884
885 ret = 0;
886 break;
887 }
888
847 case PTRACE_INTERRUPT: 889 case PTRACE_INTERRUPT:
848 /* 890 /*
849 * Stop tracee without any side-effect on signal or job 891 * Stop tracee without any side-effect on signal or job
@@ -948,8 +990,7 @@ int ptrace_request(struct task_struct *child, long request,
948 990
949#ifdef CONFIG_HAVE_ARCH_TRACEHOOK 991#ifdef CONFIG_HAVE_ARCH_TRACEHOOK
950 case PTRACE_GETREGSET: 992 case PTRACE_GETREGSET:
951 case PTRACE_SETREGSET: 993 case PTRACE_SETREGSET: {
952 {
953 struct iovec kiov; 994 struct iovec kiov;
954 struct iovec __user *uiov = datavp; 995 struct iovec __user *uiov = datavp;
955 996
@@ -1181,19 +1222,3 @@ asmlinkage long compat_sys_ptrace(compat_long_t request, compat_long_t pid,
1181 return ret; 1222 return ret;
1182} 1223}
1183#endif /* CONFIG_COMPAT */ 1224#endif /* CONFIG_COMPAT */
1184
1185#ifdef CONFIG_HAVE_HW_BREAKPOINT
1186int ptrace_get_breakpoints(struct task_struct *tsk)
1187{
1188 if (atomic_inc_not_zero(&tsk->ptrace_bp_refcnt))
1189 return 0;
1190
1191 return -1;
1192}
1193
1194void ptrace_put_breakpoints(struct task_struct *tsk)
1195{
1196 if (atomic_dec_and_test(&tsk->ptrace_bp_refcnt))
1197 flush_ptrace_hw_breakpoint(tsk);
1198}
1199#endif /* CONFIG_HAVE_HW_BREAKPOINT */