diff options
Diffstat (limited to 'kernel/ptrace.c')
-rw-r--r-- | kernel/ptrace.c | 61 |
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 | ||
1186 | int 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 | |||
1194 | void 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 */ | ||