diff options
-rw-r--r-- | include/uapi/linux/ptrace.h | 3 | ||||
-rw-r--r-- | kernel/ptrace.c | 44 |
2 files changed, 45 insertions, 2 deletions
diff --git a/include/uapi/linux/ptrace.h b/include/uapi/linux/ptrace.h index 52ebcc89f306..cf1019e15f5b 100644 --- a/include/uapi/linux/ptrace.h +++ b/include/uapi/linux/ptrace.h | |||
@@ -61,6 +61,9 @@ struct ptrace_peeksiginfo_args { | |||
61 | __s32 nr; /* how may siginfos to take */ | 61 | __s32 nr; /* how may siginfos to take */ |
62 | }; | 62 | }; |
63 | 63 | ||
64 | #define PTRACE_GETSIGMASK 0x420a | ||
65 | #define PTRACE_SETSIGMASK 0x420b | ||
66 | |||
64 | /* Read signals from a shared (process wide) queue */ | 67 | /* Read signals from a shared (process wide) queue */ |
65 | #define PTRACE_PEEKSIGINFO_SHARED (1 << 0) | 68 | #define PTRACE_PEEKSIGINFO_SHARED (1 << 0) |
66 | 69 | ||
diff --git a/kernel/ptrace.c b/kernel/ptrace.c index 335a7ae697f5..ba5e6cea181a 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c | |||
@@ -844,6 +844,47 @@ int ptrace_request(struct task_struct *child, long request, | |||
844 | ret = ptrace_setsiginfo(child, &siginfo); | 844 | ret = ptrace_setsiginfo(child, &siginfo); |
845 | break; | 845 | break; |
846 | 846 | ||
847 | case PTRACE_GETSIGMASK: | ||
848 | if (addr != sizeof(sigset_t)) { | ||
849 | ret = -EINVAL; | ||
850 | break; | ||
851 | } | ||
852 | |||
853 | if (copy_to_user(datavp, &child->blocked, sizeof(sigset_t))) | ||
854 | ret = -EFAULT; | ||
855 | else | ||
856 | ret = 0; | ||
857 | |||
858 | break; | ||
859 | |||
860 | case PTRACE_SETSIGMASK: { | ||
861 | sigset_t new_set; | ||
862 | |||
863 | if (addr != sizeof(sigset_t)) { | ||
864 | ret = -EINVAL; | ||
865 | break; | ||
866 | } | ||
867 | |||
868 | if (copy_from_user(&new_set, datavp, sizeof(sigset_t))) { | ||
869 | ret = -EFAULT; | ||
870 | break; | ||
871 | } | ||
872 | |||
873 | sigdelsetmask(&new_set, sigmask(SIGKILL)|sigmask(SIGSTOP)); | ||
874 | |||
875 | /* | ||
876 | * Every thread does recalc_sigpending() after resume, so | ||
877 | * retarget_shared_pending() and recalc_sigpending() are not | ||
878 | * called here. | ||
879 | */ | ||
880 | spin_lock_irq(&child->sighand->siglock); | ||
881 | child->blocked = new_set; | ||
882 | spin_unlock_irq(&child->sighand->siglock); | ||
883 | |||
884 | ret = 0; | ||
885 | break; | ||
886 | } | ||
887 | |||
847 | case PTRACE_INTERRUPT: | 888 | case PTRACE_INTERRUPT: |
848 | /* | 889 | /* |
849 | * Stop tracee without any side-effect on signal or job | 890 | * Stop tracee without any side-effect on signal or job |
@@ -948,8 +989,7 @@ int ptrace_request(struct task_struct *child, long request, | |||
948 | 989 | ||
949 | #ifdef CONFIG_HAVE_ARCH_TRACEHOOK | 990 | #ifdef CONFIG_HAVE_ARCH_TRACEHOOK |
950 | case PTRACE_GETREGSET: | 991 | case PTRACE_GETREGSET: |
951 | case PTRACE_SETREGSET: | 992 | case PTRACE_SETREGSET: { |
952 | { | ||
953 | struct iovec kiov; | 993 | struct iovec kiov; |
954 | struct iovec __user *uiov = datavp; | 994 | struct iovec __user *uiov = datavp; |
955 | 995 | ||