Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/livep...
[muen/linux.git] / kernel / signal.c
index 186143b06d0015aa9bb5b1c69759127fafa7b268..c6e4c83dc090ab1361ee9c229f8ff185295c2f46 100644 (file)
@@ -79,7 +79,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);
@@ -95,13 +95,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);
 }
 
 /*
@@ -549,6 +551,7 @@ still_pending:
                 * a fast-pathed signal or we must have been
                 * out of queue space.  So zero out the info.
                 */
+               clear_siginfo(info);
                info->si_signo = sig;
                info->si_errno = 0;
                info->si_code = SI_USER;
@@ -642,6 +645,9 @@ int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info)
                spin_unlock(&tsk->sighand->siglock);
                posixtimer_rearm(info);
                spin_lock(&tsk->sighand->siglock);
+
+               /* Don't expose the si_sys_private value to userspace */
+               info->si_sys_private = 0;
        }
 #endif
        return signr;
@@ -931,9 +937,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.
                 */
@@ -1038,12 +1044,12 @@ 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) {
                case (unsigned long) SEND_SIG_NOINFO:
+                       clear_siginfo(&q->info);
                        q->info.si_signo = sig;
                        q->info.si_errno = 0;
                        q->info.si_code = SI_USER;
@@ -1052,6 +1058,7 @@ static int __send_signal(int sig, struct siginfo *info, struct task_struct *t,
                        q->info.si_uid = from_kuid_munged(current_user_ns(), current_uid());
                        break;
                case (unsigned long) SEND_SIG_PRIV:
+                       clear_siginfo(&q->info);
                        q->info.si_signo = sig;
                        q->info.si_errno = 0;
                        q->info.si_code = SI_KERNEL;
@@ -1486,6 +1493,129 @@ force_sigsegv(int sig, struct task_struct *p)
        return 0;
 }
 
+int force_sig_fault(int sig, int code, void __user *addr
+       ___ARCH_SI_TRAPNO(int trapno)
+       ___ARCH_SI_IA64(int imm, unsigned int flags, unsigned long isr)
+       , struct task_struct *t)
+{
+       struct siginfo info;
+
+       clear_siginfo(&info);
+       info.si_signo = sig;
+       info.si_errno = 0;
+       info.si_code  = code;
+       info.si_addr  = addr;
+#ifdef __ARCH_SI_TRAPNO
+       info.si_trapno = trapno;
+#endif
+#ifdef __ia64__
+       info.si_imm = imm;
+       info.si_flags = flags;
+       info.si_isr = isr;
+#endif
+       return force_sig_info(info.si_signo, &info, t);
+}
+
+int send_sig_fault(int sig, int code, void __user *addr
+       ___ARCH_SI_TRAPNO(int trapno)
+       ___ARCH_SI_IA64(int imm, unsigned int flags, unsigned long isr)
+       , struct task_struct *t)
+{
+       struct siginfo info;
+
+       clear_siginfo(&info);
+       info.si_signo = sig;
+       info.si_errno = 0;
+       info.si_code  = code;
+       info.si_addr  = addr;
+#ifdef __ARCH_SI_TRAPNO
+       info.si_trapno = trapno;
+#endif
+#ifdef __ia64__
+       info.si_imm = imm;
+       info.si_flags = flags;
+       info.si_isr = isr;
+#endif
+       return send_sig_info(info.si_signo, &info, t);
+}
+
+#if defined(BUS_MCEERR_AO) && defined(BUS_MCEERR_AR)
+int force_sig_mceerr(int code, void __user *addr, short lsb, struct task_struct *t)
+{
+       struct siginfo info;
+
+       WARN_ON((code != BUS_MCEERR_AO) && (code != BUS_MCEERR_AR));
+       clear_siginfo(&info);
+       info.si_signo = SIGBUS;
+       info.si_errno = 0;
+       info.si_code = code;
+       info.si_addr = addr;
+       info.si_addr_lsb = lsb;
+       return force_sig_info(info.si_signo, &info, t);
+}
+
+int send_sig_mceerr(int code, void __user *addr, short lsb, struct task_struct *t)
+{
+       struct siginfo info;
+
+       WARN_ON((code != BUS_MCEERR_AO) && (code != BUS_MCEERR_AR));
+       clear_siginfo(&info);
+       info.si_signo = SIGBUS;
+       info.si_errno = 0;
+       info.si_code = code;
+       info.si_addr = addr;
+       info.si_addr_lsb = lsb;
+       return send_sig_info(info.si_signo, &info, t);
+}
+EXPORT_SYMBOL(send_sig_mceerr);
+#endif
+
+#ifdef SEGV_BNDERR
+int force_sig_bnderr(void __user *addr, void __user *lower, void __user *upper)
+{
+       struct siginfo info;
+
+       clear_siginfo(&info);
+       info.si_signo = SIGSEGV;
+       info.si_errno = 0;
+       info.si_code  = SEGV_BNDERR;
+       info.si_addr  = addr;
+       info.si_lower = lower;
+       info.si_upper = upper;
+       return force_sig_info(info.si_signo, &info, current);
+}
+#endif
+
+#ifdef SEGV_PKUERR
+int force_sig_pkuerr(void __user *addr, u32 pkey)
+{
+       struct siginfo info;
+
+       clear_siginfo(&info);
+       info.si_signo = SIGSEGV;
+       info.si_errno = 0;
+       info.si_code  = SEGV_PKUERR;
+       info.si_addr  = addr;
+       info.si_pkey  = pkey;
+       return force_sig_info(info.si_signo, &info, current);
+}
+#endif
+
+/* For the crazy architectures that include trap information in
+ * the errno field, instead of an actual errno value.
+ */
+int force_sig_ptrace_errno_trap(int errno, void __user *addr)
+{
+       struct siginfo info;
+
+       clear_siginfo(&info);
+       info.si_signo = SIGTRAP;
+       info.si_errno = errno;
+       info.si_code  = TRAP_HWBKPT;
+       info.si_addr  = addr;
+       return force_sig_info(info.si_signo, &info, current);
+}
+
 int kill_pgrp(struct pid *pid, int sig, int priv)
 {
        int ret;
@@ -1624,6 +1754,7 @@ bool do_notify_parent(struct task_struct *tsk, int sig)
                        sig = SIGCHLD;
        }
 
+       clear_siginfo(&info);
        info.si_signo = sig;
        info.si_errno = 0;
        /*
@@ -1718,6 +1849,7 @@ static void do_notify_parent_cldstop(struct task_struct *tsk,
                parent = tsk->real_parent;
        }
 
+       clear_siginfo(&info);
        info.si_signo = SIGCHLD;
        info.si_errno = 0;
        /*
@@ -1930,7 +2062,7 @@ static void ptrace_do_notify(int signr, int exit_code, int why)
 {
        siginfo_t info;
 
-       memset(&info, 0, sizeof info);
+       clear_siginfo(&info);
        info.si_signo = signr;
        info.si_code = exit_code;
        info.si_pid = task_pid_vnr(current);
@@ -2137,6 +2269,7 @@ static int ptrace_signal(int signr, siginfo_t *info)
         * have updated *info via PTRACE_SETSIGINFO.
         */
        if (signr != info->si_signo) {
+               clear_siginfo(info);
                info->si_signo = signr;
                info->si_errno = 0;
                info->si_code = SI_USER;
@@ -2602,7 +2735,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.  */
@@ -2610,38 +2742,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);
@@ -2661,7 +2777,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;
@@ -2671,20 +2792,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
 
@@ -2705,9 +2822,7 @@ enum siginfo_layout siginfo_layout(int sig, int si_code)
 #endif
                        [SIGCHLD] = { NSIGCHLD, SIL_CHLD },
                        [SIGPOLL] = { NSIGPOLL, SIL_POLL },
-#ifdef __ARCH_SIGSYS
                        [SIGSYS]  = { NSIGSYS,  SIL_SYS },
-#endif
                };
                if ((sig < ARRAY_SIZE(filter)) && (si_code <= filter[sig].limit))
                        layout = filter[sig].layout;
@@ -2728,13 +2843,15 @@ enum siginfo_layout siginfo_layout(int sig, int si_code)
 #ifdef FPE_FIXME
                if ((sig == SIGFPE) && (si_code == FPE_FIXME))
                        layout = SIL_FAULT;
+#endif
+#ifdef BUS_FIXME
+               if ((sig == SIGBUS) && (si_code == BUS_FIXME))
+                       layout = SIL_FAULT;
 #endif
        }
        return layout;
 }
 
-#ifndef HAVE_ARCH_COPY_SIGINFO_TO_USER
-
 int copy_siginfo_to_user(siginfo_t __user *to, const siginfo_t *from)
 {
        int err;
@@ -2773,13 +2890,21 @@ int copy_siginfo_to_user(siginfo_t __user *to, const siginfo_t *from)
 #ifdef __ARCH_SI_TRAPNO
                err |= __put_user(from->si_trapno, &to->si_trapno);
 #endif
-#ifdef BUS_MCEERR_AO
+#ifdef __ia64__
+               err |= __put_user(from->si_imm, &to->si_imm);
+               err |= __put_user(from->si_flags, &to->si_flags);
+               err |= __put_user(from->si_isr, &to->si_isr);
+#endif
                /*
                 * Other callers might not initialize the si_lsb field,
                 * so check explicitly for the right codes here.
                 */
-               if (from->si_signo == SIGBUS &&
-                   (from->si_code == BUS_MCEERR_AR || from->si_code == BUS_MCEERR_AO))
+#ifdef BUS_MCEERR_AR
+               if (from->si_signo == SIGBUS && from->si_code == BUS_MCEERR_AR)
+                       err |= __put_user(from->si_addr_lsb, &to->si_addr_lsb);
+#endif
+#ifdef BUS_MCEERR_AO
+               if (from->si_signo == SIGBUS && from->si_code == BUS_MCEERR_AO)
                        err |= __put_user(from->si_addr_lsb, &to->si_addr_lsb);
 #endif
 #ifdef SEGV_BNDERR
@@ -2805,18 +2930,185 @@ int copy_siginfo_to_user(siginfo_t __user *to, const siginfo_t *from)
                err |= __put_user(from->si_uid, &to->si_uid);
                err |= __put_user(from->si_ptr, &to->si_ptr);
                break;
-#ifdef __ARCH_SIGSYS
        case SIL_SYS:
                err |= __put_user(from->si_call_addr, &to->si_call_addr);
                err |= __put_user(from->si_syscall, &to->si_syscall);
                err |= __put_user(from->si_arch, &to->si_arch);
                break;
-#endif
        }
        return err;
 }
 
+#ifdef CONFIG_COMPAT
+int copy_siginfo_to_user32(struct compat_siginfo __user *to,
+                          const struct siginfo *from)
+#if defined(CONFIG_X86_X32_ABI) || defined(CONFIG_IA32_EMULATION)
+{
+       return __copy_siginfo_to_user32(to, from, in_x32_syscall());
+}
+int __copy_siginfo_to_user32(struct compat_siginfo __user *to,
+                            const struct siginfo *from, bool x32_ABI)
+#endif
+{
+       struct compat_siginfo new;
+       memset(&new, 0, sizeof(new));
+
+       new.si_signo = from->si_signo;
+       new.si_errno = from->si_errno;
+       new.si_code  = from->si_code;
+       switch(siginfo_layout(from->si_signo, from->si_code)) {
+       case SIL_KILL:
+               new.si_pid = from->si_pid;
+               new.si_uid = from->si_uid;
+               break;
+       case SIL_TIMER:
+               new.si_tid     = from->si_tid;
+               new.si_overrun = from->si_overrun;
+               new.si_int     = from->si_int;
+               break;
+       case SIL_POLL:
+               new.si_band = from->si_band;
+               new.si_fd   = from->si_fd;
+               break;
+       case SIL_FAULT:
+               new.si_addr = ptr_to_compat(from->si_addr);
+#ifdef __ARCH_SI_TRAPNO
+               new.si_trapno = from->si_trapno;
+#endif
+#ifdef BUS_MCEERR_AR
+               if ((from->si_signo == SIGBUS) && (from->si_code == BUS_MCEERR_AR))
+                       new.si_addr_lsb = from->si_addr_lsb;
+#endif
+#ifdef BUS_MCEERR_AO
+               if ((from->si_signo == SIGBUS) && (from->si_code == BUS_MCEERR_AO))
+                       new.si_addr_lsb = from->si_addr_lsb;
+#endif
+#ifdef SEGV_BNDERR
+               if ((from->si_signo == SIGSEGV) &&
+                   (from->si_code == SEGV_BNDERR)) {
+                       new.si_lower = ptr_to_compat(from->si_lower);
+                       new.si_upper = ptr_to_compat(from->si_upper);
+               }
+#endif
+#ifdef SEGV_PKUERR
+               if ((from->si_signo == SIGSEGV) &&
+                   (from->si_code == SEGV_PKUERR))
+                       new.si_pkey = from->si_pkey;
+#endif
+
+               break;
+       case SIL_CHLD:
+               new.si_pid    = from->si_pid;
+               new.si_uid    = from->si_uid;
+               new.si_status = from->si_status;
+#ifdef CONFIG_X86_X32_ABI
+               if (x32_ABI) {
+                       new._sifields._sigchld_x32._utime = from->si_utime;
+                       new._sifields._sigchld_x32._stime = from->si_stime;
+               } else
 #endif
+               {
+                       new.si_utime = from->si_utime;
+                       new.si_stime = from->si_stime;
+               }
+               break;
+       case SIL_RT:
+               new.si_pid = from->si_pid;
+               new.si_uid = from->si_uid;
+               new.si_int = from->si_int;
+               break;
+       case SIL_SYS:
+               new.si_call_addr = ptr_to_compat(from->si_call_addr);
+               new.si_syscall   = from->si_syscall;
+               new.si_arch      = from->si_arch;
+               break;
+       }
+
+       if (copy_to_user(to, &new, sizeof(struct compat_siginfo)))
+               return -EFAULT;
+
+       return 0;
+}
+
+int copy_siginfo_from_user32(struct siginfo *to,
+                            const struct compat_siginfo __user *ufrom)
+{
+       struct compat_siginfo from;
+
+       if (copy_from_user(&from, ufrom, sizeof(struct compat_siginfo)))
+               return -EFAULT;
+
+       clear_siginfo(to);
+       to->si_signo = from.si_signo;
+       to->si_errno = from.si_errno;
+       to->si_code  = from.si_code;
+       switch(siginfo_layout(from.si_signo, from.si_code)) {
+       case SIL_KILL:
+               to->si_pid = from.si_pid;
+               to->si_uid = from.si_uid;
+               break;
+       case SIL_TIMER:
+               to->si_tid     = from.si_tid;
+               to->si_overrun = from.si_overrun;
+               to->si_int     = from.si_int;
+               break;
+       case SIL_POLL:
+               to->si_band = from.si_band;
+               to->si_fd   = from.si_fd;
+               break;
+       case SIL_FAULT:
+               to->si_addr = compat_ptr(from.si_addr);
+#ifdef __ARCH_SI_TRAPNO
+               to->si_trapno = from.si_trapno;
+#endif
+#ifdef BUS_MCEERR_AR
+               if ((from.si_signo == SIGBUS) && (from.si_code == BUS_MCEERR_AR))
+                       to->si_addr_lsb = from.si_addr_lsb;
+#endif
+#ifdef BUS_MCEER_AO
+               if ((from.si_signo == SIGBUS) && (from.si_code == BUS_MCEERR_AO))
+                       to->si_addr_lsb = from.si_addr_lsb;
+#endif
+#ifdef SEGV_BNDERR
+               if ((from.si_signo == SIGSEGV) && (from.si_code == SEGV_BNDERR)) {
+                       to->si_lower = compat_ptr(from.si_lower);
+                       to->si_upper = compat_ptr(from.si_upper);
+               }
+#endif
+#ifdef SEGV_PKUERR
+               if ((from.si_signo == SIGSEGV) && (from.si_code == SEGV_PKUERR))
+                       to->si_pkey = from.si_pkey;
+#endif
+               break;
+       case SIL_CHLD:
+               to->si_pid    = from.si_pid;
+               to->si_uid    = from.si_uid;
+               to->si_status = from.si_status;
+#ifdef CONFIG_X86_X32_ABI
+               if (in_x32_syscall()) {
+                       to->si_utime = from._sifields._sigchld_x32._utime;
+                       to->si_stime = from._sifields._sigchld_x32._stime;
+               } else
+#endif
+               {
+                       to->si_utime = from.si_utime;
+                       to->si_stime = from.si_stime;
+               }
+               break;
+       case SIL_RT:
+               to->si_pid = from.si_pid;
+               to->si_uid = from.si_uid;
+               to->si_int = from.si_int;
+               break;
+       case SIL_SYS:
+               to->si_call_addr = compat_ptr(from.si_call_addr);
+               to->si_syscall   = from.si_syscall;
+               to->si_arch      = from.si_arch;
+               break;
+       }
+       return 0;
+}
+#endif /* CONFIG_COMPAT */
 
 /**
  *  do_sigtimedwait - wait for queued signals specified in @which
@@ -2918,7 +3210,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;
@@ -2927,9 +3218,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))
@@ -2956,6 +3246,7 @@ SYSCALL_DEFINE2(kill, pid_t, pid, int, sig)
 {
        struct siginfo info;
 
+       clear_siginfo(&info);
        info.si_signo = sig;
        info.si_errno = 0;
        info.si_code = SI_USER;
@@ -2997,8 +3288,9 @@ do_send_specific(pid_t tgid, pid_t pid, int sig, struct siginfo *info)
 
 static int do_tkill(pid_t tgid, pid_t pid, int sig)
 {
-       struct siginfo info = {};
+       struct siginfo info;
 
+       clear_siginfo(&info);
        info.si_signo = sig;
        info.si_errno = 0;
        info.si_code = SI_TKILL;
@@ -3079,7 +3371,7 @@ COMPAT_SYSCALL_DEFINE3(rt_sigqueueinfo,
                        int, sig,
                        struct compat_siginfo __user *, uinfo)
 {
-       siginfo_t info = {};
+       siginfo_t info;
        int ret = copy_siginfo_from_user32(&info, uinfo);
        if (unlikely(ret))
                return ret;
@@ -3123,7 +3415,7 @@ COMPAT_SYSCALL_DEFINE4(rt_tgsigqueueinfo,
                        int, sig,
                        struct compat_siginfo __user *, uinfo)
 {
-       siginfo_t info = {};
+       siginfo_t info;
 
        if (copy_siginfo_from_user32(&info, uinfo))
                return -EFAULT;
@@ -3347,15 +3639,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
 
@@ -3453,7 +3741,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
@@ -3471,19 +3758,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),
@@ -3663,22 +3949,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
 
@@ -3709,6 +3988,7 @@ void __init signals_init(void)
        /* If this check fails, the __ARCH_SI_PREAMBLE_SIZE value is wrong! */
        BUILD_BUG_ON(__ARCH_SI_PREAMBLE_SIZE
                != offsetof(struct siginfo, _sifields._pad));
+       BUILD_BUG_ON(sizeof(struct siginfo) != SI_MAX_SIZE);
 
        sigqueue_cachep = KMEM_CACHE(sigqueue, SLAB_PANIC);
 }
@@ -3716,26 +3996,25 @@ void __init signals_init(void)
 #ifdef CONFIG_KGDB_KDB
 #include <linux/kdb.h>
 /*
- * kdb_send_sig_info - Allows kdb to send signals without exposing
+ * kdb_send_sig - Allows kdb to send signals without exposing
  * signal internals.  This function checks if the required locks are
  * available before calling the main signal code, to avoid kdb
  * deadlocks.
  */
-void
-kdb_send_sig_info(struct task_struct *t, struct siginfo *info)
+void kdb_send_sig(struct task_struct *t, int sig)
 {
        static struct task_struct *kdb_prev_t;
-       int sig, new_t;
+       int new_t, ret;
        if (!spin_trylock(&t->sighand->siglock)) {
                kdb_printf("Can't do kill command now.\n"
                           "The sigmask lock is held somewhere else in "
                           "kernel, try again later\n");
                return;
        }
-       spin_unlock(&t->sighand->siglock);
        new_t = kdb_prev_t != t;
        kdb_prev_t = t;
        if (t->state != TASK_RUNNING && new_t) {
+               spin_unlock(&t->sighand->siglock);
                kdb_printf("Process is not RUNNING, sending a signal from "
                           "kdb risks deadlock\n"
                           "on the run queue locks. "
@@ -3744,8 +4023,9 @@ kdb_send_sig_info(struct task_struct *t, struct siginfo *info)
                           "the deadlock.\n");
                return;
        }
-       sig = info->si_signo;
-       if (send_sig_info(sig, info, t))
+       ret = send_signal(sig, SEND_SIG_PRIV, t, false);
+       spin_unlock(&t->sighand->siglock);
+       if (ret)
                kdb_printf("Fail to deliver Signal %d to process %d.\n",
                           sig, t->pid);
        else