|
@@ -844,6 +844,47 @@ int ptrace_request(struct task_struct *child, long request,
|
|
|
ret = ptrace_setsiginfo(child, &siginfo);
|
|
|
break;
|
|
|
|
|
|
+ case PTRACE_GETSIGMASK:
|
|
|
+ if (addr != sizeof(sigset_t)) {
|
|
|
+ ret = -EINVAL;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (copy_to_user(datavp, &child->blocked, sizeof(sigset_t)))
|
|
|
+ ret = -EFAULT;
|
|
|
+ else
|
|
|
+ ret = 0;
|
|
|
+
|
|
|
+ break;
|
|
|
+
|
|
|
+ case PTRACE_SETSIGMASK: {
|
|
|
+ sigset_t new_set;
|
|
|
+
|
|
|
+ if (addr != sizeof(sigset_t)) {
|
|
|
+ ret = -EINVAL;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (copy_from_user(&new_set, datavp, sizeof(sigset_t))) {
|
|
|
+ ret = -EFAULT;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ sigdelsetmask(&new_set, sigmask(SIGKILL)|sigmask(SIGSTOP));
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Every thread does recalc_sigpending() after resume, so
|
|
|
+ * retarget_shared_pending() and recalc_sigpending() are not
|
|
|
+ * called here.
|
|
|
+ */
|
|
|
+ spin_lock_irq(&child->sighand->siglock);
|
|
|
+ child->blocked = new_set;
|
|
|
+ spin_unlock_irq(&child->sighand->siglock);
|
|
|
+
|
|
|
+ ret = 0;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
case PTRACE_INTERRUPT:
|
|
|
/*
|
|
|
* Stop tracee without any side-effect on signal or job
|
|
@@ -948,8 +989,7 @@ int ptrace_request(struct task_struct *child, long request,
|
|
|
|
|
|
#ifdef CONFIG_HAVE_ARCH_TRACEHOOK
|
|
|
case PTRACE_GETREGSET:
|
|
|
- case PTRACE_SETREGSET:
|
|
|
- {
|
|
|
+ case PTRACE_SETREGSET: {
|
|
|
struct iovec kiov;
|
|
|
struct iovec __user *uiov = datavp;
|
|
|
|