diff options
| author | Andrey Vagin <avagin@openvz.org> | 2013-07-03 18:08:12 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-07-03 19:08:01 -0400 |
| commit | 29000caecbe87b6b66f144f72111f0d02fbbf0c1 (patch) | |
| tree | 91d178abd9543a49c087af857a3cfabececfd71e | |
| parent | 37f07655522042399db7a4b54aee830bdb52ce2c (diff) | |
ptrace: add ability to get/set signal-blocked mask
crtools uses a parasite code for dumping processes. The parasite code is
injected into a process with help PTRACE_SEIZE.
Currently crtools blocks signals from a parasite code. If a process has
pending signals, crtools wait while a process handles these signals.
This method is not suitable for stopped tasks. A stopped task can have a
few pending signals, when we will try to execute a parasite code, we will
need to drop SIGSTOP, but all other signals must remain pending, because a
state of processes must not be changed during checkpointing.
This patch adds two ptrace commands to set/get signal-blocked mask.
I think gdb can use this commands too.
[akpm@linux-foundation.org: be consistent with brace layout]
Signed-off-by: Andrey Vagin <avagin@openvz.org>
Reviewed-by: Oleg Nesterov <oleg@redhat.com>
Cc: Roland McGrath <roland@redhat.com>
Cc: Michael Kerrisk <mtk.manpages@gmail.com>
Cc: Pavel Emelyanov <xemul@parallels.com>
Cc: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
| -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 | ||
