Merge branch 'x86-pti-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[linux-2.6-block.git] / kernel / signal.c
index 8dcd8825b2dedf3f16c108808192f8751aa19c96..9558664bd9ecd21d5cee8a504084b2ee4a2d0a50 100644 (file)
@@ -78,7 +78,7 @@ static int sig_task_ignored(struct task_struct *t, int sig, bool force)
        handler = sig_handler(t, sig);
 
        if (unlikely(t->signal->flags & SIGNAL_UNKILLABLE) &&
-                       handler == SIG_DFL && !force)
+           handler == SIG_DFL && !(force && sig_kernel_only(sig)))
                return 1;
 
        return sig_handler_ignored(handler, sig);
@@ -94,13 +94,15 @@ static int sig_ignored(struct task_struct *t, int sig, bool force)
        if (sigismember(&t->blocked, sig) || sigismember(&t->real_blocked, sig))
                return 0;
 
-       if (!sig_task_ignored(t, sig, force))
-               return 0;
-
        /*
-        * Tracers may want to know about even ignored signals.
+        * Tracers may want to know about even ignored signal unless it
+        * is SIGKILL which can't be reported anyway but can be ignored
+        * by SIGNAL_UNKILLABLE task.
         */
-       return !t->ptrace;
+       if (t->ptrace && sig != SIGKILL)
+               return 0;
+
+       return sig_task_ignored(t, sig, force);
 }
 
 /*
@@ -929,9 +931,9 @@ static void complete_signal(int sig, struct task_struct *p, int group)
         * then start taking the whole group down immediately.
         */
        if (sig_fatal(p, sig) &&
-           !(signal->flags & (SIGNAL_UNKILLABLE | SIGNAL_GROUP_EXIT)) &&
+           !(signal->flags & SIGNAL_GROUP_EXIT) &&
            !sigismember(&t->real_blocked, sig) &&
-           (sig == SIGKILL || !t->ptrace)) {
+           (sig == SIGKILL || !p->ptrace)) {
                /*
                 * This signal will be fatal to the whole group.
                 */
@@ -1036,8 +1038,7 @@ static int __send_signal(int sig, struct siginfo *info, struct task_struct *t,
        else
                override_rlimit = 0;
 
-       q = __sigqueue_alloc(sig, t, GFP_ATOMIC | __GFP_NOTRACK_FALSE_POSITIVE,
-               override_rlimit);
+       q = __sigqueue_alloc(sig, t, GFP_ATOMIC, override_rlimit);
        if (q) {
                list_add_tail(&q->list, &pending->list);
                switch ((unsigned long) info) {
@@ -2600,7 +2601,6 @@ SYSCALL_DEFINE4(rt_sigprocmask, int, how, sigset_t __user *, nset,
 COMPAT_SYSCALL_DEFINE4(rt_sigprocmask, int, how, compat_sigset_t __user *, nset,
                compat_sigset_t __user *, oset, compat_size_t, sigsetsize)
 {
-#ifdef __BIG_ENDIAN
        sigset_t old_set = current->blocked;
 
        /* XXX: Don't preclude handling different sized sigset_t's.  */
@@ -2608,38 +2608,22 @@ COMPAT_SYSCALL_DEFINE4(rt_sigprocmask, int, how, compat_sigset_t __user *, nset,
                return -EINVAL;
 
        if (nset) {
-               compat_sigset_t new32;
                sigset_t new_set;
                int error;
-               if (copy_from_user(&new32, nset, sizeof(compat_sigset_t)))
+               if (get_compat_sigset(&new_set, nset))
                        return -EFAULT;
-
-               sigset_from_compat(&new_set, &new32);
                sigdelsetmask(&new_set, sigmask(SIGKILL)|sigmask(SIGSTOP));
 
                error = sigprocmask(how, &new_set, NULL);
                if (error)
                        return error;
        }
-       if (oset) {
-               compat_sigset_t old32;
-               sigset_to_compat(&old32, &old_set);
-               if (copy_to_user(oset, &old32, sizeof(compat_sigset_t)))
-                       return -EFAULT;
-       }
-       return 0;
-#else
-       return sys_rt_sigprocmask(how, (sigset_t __user *)nset,
-                                 (sigset_t __user *)oset, sigsetsize);
-#endif
+       return oset ? put_compat_sigset(oset, &old_set, sizeof(*oset)) : 0;
 }
 #endif
 
-static int do_sigpending(void *set, unsigned long sigsetsize)
+static int do_sigpending(sigset_t *set)
 {
-       if (sigsetsize > sizeof(sigset_t))
-               return -EINVAL;
-
        spin_lock_irq(&current->sighand->siglock);
        sigorsets(set, &current->pending.signal,
                  &current->signal->shared_pending.signal);
@@ -2659,7 +2643,12 @@ static int do_sigpending(void *set, unsigned long sigsetsize)
 SYSCALL_DEFINE2(rt_sigpending, sigset_t __user *, uset, size_t, sigsetsize)
 {
        sigset_t set;
-       int err = do_sigpending(&set, sigsetsize);
+       int err;
+
+       if (sigsetsize > sizeof(*uset))
+               return -EINVAL;
+
+       err = do_sigpending(&set);
        if (!err && copy_to_user(uset, &set, sigsetsize))
                err = -EFAULT;
        return err;
@@ -2669,20 +2658,16 @@ SYSCALL_DEFINE2(rt_sigpending, sigset_t __user *, uset, size_t, sigsetsize)
 COMPAT_SYSCALL_DEFINE2(rt_sigpending, compat_sigset_t __user *, uset,
                compat_size_t, sigsetsize)
 {
-#ifdef __BIG_ENDIAN
        sigset_t set;
-       int err = do_sigpending(&set, sigsetsize);
-       if (!err) {
-               compat_sigset_t set32;
-               sigset_to_compat(&set32, &set);
-               /* we can get here only if sigsetsize <= sizeof(set) */
-               if (copy_to_user(uset, &set32, sigsetsize))
-                       err = -EFAULT;
-       }
+       int err;
+
+       if (sigsetsize > sizeof(*uset))
+               return -EINVAL;
+
+       err = do_sigpending(&set);
+       if (!err)
+               err = put_compat_sigset(uset, &set, sigsetsize);
        return err;
-#else
-       return sys_rt_sigpending((sigset_t __user *)uset, sigsetsize);
-#endif
 }
 #endif
 
@@ -2916,7 +2901,6 @@ COMPAT_SYSCALL_DEFINE4(rt_sigtimedwait, compat_sigset_t __user *, uthese,
                struct compat_siginfo __user *, uinfo,
                struct compat_timespec __user *, uts, compat_size_t, sigsetsize)
 {
-       compat_sigset_t s32;
        sigset_t s;
        struct timespec t;
        siginfo_t info;
@@ -2925,9 +2909,8 @@ COMPAT_SYSCALL_DEFINE4(rt_sigtimedwait, compat_sigset_t __user *, uthese,
        if (sigsetsize != sizeof(sigset_t))
                return -EINVAL;
 
-       if (copy_from_user(&s32, uthese, sizeof(compat_sigset_t)))
+       if (get_compat_sigset(&s, uthese))
                return -EFAULT;
-       sigset_from_compat(&s, &s32);
 
        if (uts) {
                if (compat_get_timespec(&t, uts))
@@ -3345,15 +3328,11 @@ SYSCALL_DEFINE1(sigpending, old_sigset_t __user *, set)
 #ifdef CONFIG_COMPAT
 COMPAT_SYSCALL_DEFINE1(sigpending, compat_old_sigset_t __user *, set32)
 {
-#ifdef __BIG_ENDIAN
        sigset_t set;
-       int err = do_sigpending(&set, sizeof(set.sig[0]));
+       int err = do_sigpending(&set);
        if (!err)
                err = put_user(set.sig[0], set32);
        return err;
-#else
-       return sys_rt_sigpending((sigset_t __user *)set32, sizeof(*set32));
-#endif
 }
 #endif
 
@@ -3451,7 +3430,6 @@ COMPAT_SYSCALL_DEFINE4(rt_sigaction, int, sig,
                compat_size_t, sigsetsize)
 {
        struct k_sigaction new_ka, old_ka;
-       compat_sigset_t mask;
 #ifdef __ARCH_HAS_SA_RESTORER
        compat_uptr_t restorer;
 #endif
@@ -3469,19 +3447,18 @@ COMPAT_SYSCALL_DEFINE4(rt_sigaction, int, sig,
                ret |= get_user(restorer, &act->sa_restorer);
                new_ka.sa.sa_restorer = compat_ptr(restorer);
 #endif
-               ret |= copy_from_user(&mask, &act->sa_mask, sizeof(mask));
+               ret |= get_compat_sigset(&new_ka.sa.sa_mask, &act->sa_mask);
                ret |= get_user(new_ka.sa.sa_flags, &act->sa_flags);
                if (ret)
                        return -EFAULT;
-               sigset_from_compat(&new_ka.sa.sa_mask, &mask);
        }
 
        ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
        if (!ret && oact) {
-               sigset_to_compat(&mask, &old_ka.sa.sa_mask);
                ret = put_user(ptr_to_compat(old_ka.sa.sa_handler), 
                               &oact->sa_handler);
-               ret |= copy_to_user(&oact->sa_mask, &mask, sizeof(mask));
+               ret |= put_compat_sigset(&oact->sa_mask, &old_ka.sa.sa_mask,
+                                        sizeof(oact->sa_mask));
                ret |= put_user(old_ka.sa.sa_flags, &oact->sa_flags);
 #ifdef __ARCH_HAS_SA_RESTORER
                ret |= put_user(ptr_to_compat(old_ka.sa.sa_restorer),
@@ -3661,22 +3638,15 @@ SYSCALL_DEFINE2(rt_sigsuspend, sigset_t __user *, unewset, size_t, sigsetsize)
 #ifdef CONFIG_COMPAT
 COMPAT_SYSCALL_DEFINE2(rt_sigsuspend, compat_sigset_t __user *, unewset, compat_size_t, sigsetsize)
 {
-#ifdef __BIG_ENDIAN
        sigset_t newset;
-       compat_sigset_t newset32;
 
        /* XXX: Don't preclude handling different sized sigset_t's.  */
        if (sigsetsize != sizeof(sigset_t))
                return -EINVAL;
 
-       if (copy_from_user(&newset32, unewset, sizeof(compat_sigset_t)))
+       if (get_compat_sigset(&newset, unewset))
                return -EFAULT;
-       sigset_from_compat(&newset, &newset32);
        return sigsuspend(&newset);
-#else
-       /* on little-endian bitmaps don't care about granularity */
-       return sys_rt_sigsuspend((sigset_t __user *)unewset, sigsetsize);
-#endif
 }
 #endif