Merge tag 'driver-core-4.20-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git...
[linux-2.6-microblaze.git] / kernel / signal.c
index e4aad0e..1756524 100644 (file)
@@ -78,6 +78,10 @@ static bool sig_task_ignored(struct task_struct *t, int sig, bool force)
 
        handler = sig_handler(t, sig);
 
+       /* SIGKILL and SIGSTOP may not be sent to the global init */
+       if (unlikely(is_global_init(t) && sig_kernel_only(sig)))
+               return true;
+
        if (unlikely(t->signal->flags & SIGNAL_UNKILLABLE) &&
            handler == SIG_DFL && !(force && sig_kernel_only(sig)))
                return true;
@@ -172,6 +176,7 @@ void recalc_sigpending(void)
                clear_thread_flag(TIF_SIGPENDING);
 
 }
+EXPORT_SYMBOL(recalc_sigpending);
 
 void calculate_sigpending(void)
 {
@@ -462,6 +467,7 @@ void flush_signals(struct task_struct *t)
        flush_sigqueue(&t->signal->shared_pending);
        spin_unlock_irqrestore(&t->sighand->siglock, flags);
 }
+EXPORT_SYMBOL(flush_signals);
 
 #ifdef CONFIG_POSIX_TIMERS
 static void __flush_itimer_signals(struct sigpending *pending)
@@ -543,7 +549,7 @@ bool unhandled_signal(struct task_struct *tsk, int sig)
        return !tsk->ptrace;
 }
 
-static void collect_signal(int sig, struct sigpending *list, siginfo_t *info,
+static void collect_signal(int sig, struct sigpending *list, kernel_siginfo_t *info,
                           bool *resched_timer)
 {
        struct sigqueue *q, *first = NULL;
@@ -589,7 +595,7 @@ still_pending:
 }
 
 static int __dequeue_signal(struct sigpending *pending, sigset_t *mask,
-                       siginfo_t *info, bool *resched_timer)
+                       kernel_siginfo_t *info, bool *resched_timer)
 {
        int sig = next_signal(pending, mask);
 
@@ -604,7 +610,7 @@ static int __dequeue_signal(struct sigpending *pending, sigset_t *mask,
  *
  * All callers have to hold the siglock.
  */
-int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info)
+int dequeue_signal(struct task_struct *tsk, sigset_t *mask, kernel_siginfo_t *info)
 {
        bool resched_timer = false;
        int signr;
@@ -680,6 +686,7 @@ int dequeue_signal(struct task_struct *tsk, sigset_t *mask, siginfo_t *info)
 #endif
        return signr;
 }
+EXPORT_SYMBOL_GPL(dequeue_signal);
 
 /*
  * Tell a process that it has a new active signal..
@@ -730,12 +737,12 @@ static void flush_sigqueue_mask(sigset_t *mask, struct sigpending *s)
        }
 }
 
-static inline int is_si_special(const struct siginfo *info)
+static inline int is_si_special(const struct kernel_siginfo *info)
 {
-       return info <= SEND_SIG_FORCED;
+       return info <= SEND_SIG_PRIV;
 }
 
-static inline bool si_fromuser(const struct siginfo *info)
+static inline bool si_fromuser(const struct kernel_siginfo *info)
 {
        return info == SEND_SIG_NOINFO ||
                (!is_si_special(info) && SI_FROMUSER(info));
@@ -760,7 +767,7 @@ static bool kill_ok_by_cred(struct task_struct *t)
  * Bad permissions for sending the signal
  * - the caller must hold the RCU read lock
  */
-static int check_kill_permission(int sig, struct siginfo *info,
+static int check_kill_permission(int sig, struct kernel_siginfo *info,
                                 struct task_struct *t)
 {
        struct pid *sid;
@@ -1003,7 +1010,7 @@ static inline bool legacy_queue(struct sigpending *signals, int sig)
 }
 
 #ifdef CONFIG_USER_NS
-static inline void userns_fixup_signal_uid(struct siginfo *info, struct task_struct *t)
+static inline void userns_fixup_signal_uid(struct kernel_siginfo *info, struct task_struct *t)
 {
        if (current_user_ns() == task_cred_xxx(t, user_ns))
                return;
@@ -1017,13 +1024,13 @@ static inline void userns_fixup_signal_uid(struct siginfo *info, struct task_str
        rcu_read_unlock();
 }
 #else
-static inline void userns_fixup_signal_uid(struct siginfo *info, struct task_struct *t)
+static inline void userns_fixup_signal_uid(struct kernel_siginfo *info, struct task_struct *t)
 {
        return;
 }
 #endif
 
-static int __send_signal(int sig, struct siginfo *info, struct task_struct *t,
+static int __send_signal(int sig, struct kernel_siginfo *info, struct task_struct *t,
                        enum pid_type type, int from_ancestor_ns)
 {
        struct sigpending *pending;
@@ -1035,7 +1042,7 @@ static int __send_signal(int sig, struct siginfo *info, struct task_struct *t,
 
        result = TRACE_SIGNAL_IGNORED;
        if (!prepare_signal(sig, t,
-                       from_ancestor_ns || (info == SEND_SIG_FORCED)))
+                       from_ancestor_ns || (info == SEND_SIG_PRIV)))
                goto ret;
 
        pending = (type != PIDTYPE_PID) ? &t->signal->shared_pending : &t->pending;
@@ -1050,10 +1057,10 @@ static int __send_signal(int sig, struct siginfo *info, struct task_struct *t,
 
        result = TRACE_SIGNAL_DELIVERED;
        /*
-        * fast-pathed signals for kernel-internal things like SIGSTOP
-        * or SIGKILL.
+        * Skip useless siginfo allocation for SIGKILL SIGSTOP,
+        * and kernel threads.
         */
-       if (info == SEND_SIG_FORCED)
+       if (sig_kernel_only(sig) || (t->flags & PF_KTHREAD))
                goto out_set;
 
        /*
@@ -1143,7 +1150,7 @@ ret:
        return ret;
 }
 
-static int send_signal(int sig, struct siginfo *info, struct task_struct *t,
+static int send_signal(int sig, struct kernel_siginfo *info, struct task_struct *t,
                        enum pid_type type)
 {
        int from_ancestor_ns = 0;
@@ -1190,18 +1197,12 @@ static int __init setup_print_fatal_signals(char *str)
 __setup("print-fatal-signals=", setup_print_fatal_signals);
 
 int
-__group_send_sig_info(int sig, struct siginfo *info, struct task_struct *p)
+__group_send_sig_info(int sig, struct kernel_siginfo *info, struct task_struct *p)
 {
        return send_signal(sig, info, p, PIDTYPE_TGID);
 }
 
-static int
-specific_send_sig_info(int sig, struct siginfo *info, struct task_struct *t)
-{
-       return send_signal(sig, info, t, PIDTYPE_PID);
-}
-
-int do_send_sig_info(int sig, struct siginfo *info, struct task_struct *p,
+int do_send_sig_info(int sig, struct kernel_siginfo *info, struct task_struct *p,
                        enum pid_type type)
 {
        unsigned long flags;
@@ -1227,7 +1228,7 @@ int do_send_sig_info(int sig, struct siginfo *info, struct task_struct *p,
  * that is why we also clear SIGNAL_UNKILLABLE.
  */
 int
-force_sig_info(int sig, struct siginfo *info, struct task_struct *t)
+force_sig_info(int sig, struct kernel_siginfo *info, struct task_struct *t)
 {
        unsigned long int flags;
        int ret, blocked, ignored;
@@ -1250,7 +1251,7 @@ force_sig_info(int sig, struct siginfo *info, struct task_struct *t)
         */
        if (action->sa.sa_handler == SIG_DFL && !t->ptrace)
                t->signal->flags &= ~SIGNAL_UNKILLABLE;
-       ret = specific_send_sig_info(sig, info, t);
+       ret = send_signal(sig, info, t, PIDTYPE_PID);
        spin_unlock_irqrestore(&t->sighand->siglock, flags);
 
        return ret;
@@ -1315,8 +1316,8 @@ struct sighand_struct *__lock_task_sighand(struct task_struct *tsk,
 /*
  * send signal info to all the members of a group
  */
-int group_send_sig_info(int sig, struct siginfo *info, struct task_struct *p,
-                       enum pid_type type)
+int group_send_sig_info(int sig, struct kernel_siginfo *info,
+                       struct task_struct *p, enum pid_type type)
 {
        int ret;
 
@@ -1335,7 +1336,7 @@ int group_send_sig_info(int sig, struct siginfo *info, struct task_struct *p,
  * control characters do (^C, ^Z etc)
  * - the caller must hold at least a readlock on tasklist_lock
  */
-int __kill_pgrp_info(int sig, struct siginfo *info, struct pid *pgrp)
+int __kill_pgrp_info(int sig, struct kernel_siginfo *info, struct pid *pgrp)
 {
        struct task_struct *p = NULL;
        int retval, success;
@@ -1350,7 +1351,7 @@ int __kill_pgrp_info(int sig, struct siginfo *info, struct pid *pgrp)
        return success ? 0 : retval;
 }
 
-int kill_pid_info(int sig, struct siginfo *info, struct pid *pid)
+int kill_pid_info(int sig, struct kernel_siginfo *info, struct pid *pid)
 {
        int error = -ESRCH;
        struct task_struct *p;
@@ -1372,7 +1373,7 @@ int kill_pid_info(int sig, struct siginfo *info, struct pid *pid)
        }
 }
 
-static int kill_proc_info(int sig, struct siginfo *info, pid_t pid)
+static int kill_proc_info(int sig, struct kernel_siginfo *info, pid_t pid)
 {
        int error;
        rcu_read_lock();
@@ -1393,7 +1394,7 @@ static inline bool kill_as_cred_perm(const struct cred *cred,
 }
 
 /* like kill_pid_info(), but doesn't use uid/euid of "current" */
-int kill_pid_info_as_cred(int sig, struct siginfo *info, struct pid *pid,
+int kill_pid_info_as_cred(int sig, struct kernel_siginfo *info, struct pid *pid,
                         const struct cred *cred)
 {
        int ret = -EINVAL;
@@ -1437,7 +1438,7 @@ EXPORT_SYMBOL_GPL(kill_pid_info_as_cred);
  * is probably wrong.  Should make it like BSD or SYSV.
  */
 
-static int kill_something_info(int sig, struct siginfo *info, pid_t pid)
+static int kill_something_info(int sig, struct kernel_siginfo *info, pid_t pid)
 {
        int ret;
 
@@ -1481,7 +1482,7 @@ static int kill_something_info(int sig, struct siginfo *info, pid_t pid)
  * These are for backward compatibility with the rest of the kernel source.
  */
 
-int send_sig_info(int sig, struct siginfo *info, struct task_struct *p)
+int send_sig_info(int sig, struct kernel_siginfo *info, struct task_struct *p)
 {
        /*
         * Make sure legacy kernel users don't send in bad values
@@ -1492,6 +1493,7 @@ int send_sig_info(int sig, struct siginfo *info, struct task_struct *p)
 
        return do_send_sig_info(sig, info, p, PIDTYPE_PID);
 }
+EXPORT_SYMBOL(send_sig_info);
 
 #define __si_special(priv) \
        ((priv) ? SEND_SIG_PRIV : SEND_SIG_NOINFO)
@@ -1501,11 +1503,13 @@ send_sig(int sig, struct task_struct *p, int priv)
 {
        return send_sig_info(sig, __si_special(priv), p);
 }
+EXPORT_SYMBOL(send_sig);
 
 void force_sig(int sig, struct task_struct *p)
 {
        force_sig_info(sig, SEND_SIG_PRIV, p);
 }
+EXPORT_SYMBOL(force_sig);
 
 /*
  * When things go south during signal handling, we
@@ -1529,7 +1533,7 @@ int force_sig_fault(int sig, int code, void __user *addr
        ___ARCH_SI_IA64(int imm, unsigned int flags, unsigned long isr)
        , struct task_struct *t)
 {
-       struct siginfo info;
+       struct kernel_siginfo info;
 
        clear_siginfo(&info);
        info.si_signo = sig;
@@ -1552,7 +1556,7 @@ int send_sig_fault(int sig, int code, void __user *addr
        ___ARCH_SI_IA64(int imm, unsigned int flags, unsigned long isr)
        , struct task_struct *t)
 {
-       struct siginfo info;
+       struct kernel_siginfo info;
 
        clear_siginfo(&info);
        info.si_signo = sig;
@@ -1572,7 +1576,7 @@ int send_sig_fault(int sig, int code, void __user *addr
 
 int force_sig_mceerr(int code, void __user *addr, short lsb, struct task_struct *t)
 {
-       struct siginfo info;
+       struct kernel_siginfo info;
 
        WARN_ON((code != BUS_MCEERR_AO) && (code != BUS_MCEERR_AR));
        clear_siginfo(&info);
@@ -1586,7 +1590,7 @@ int force_sig_mceerr(int code, void __user *addr, short lsb, struct task_struct
 
 int send_sig_mceerr(int code, void __user *addr, short lsb, struct task_struct *t)
 {
-       struct siginfo info;
+       struct kernel_siginfo info;
 
        WARN_ON((code != BUS_MCEERR_AO) && (code != BUS_MCEERR_AR));
        clear_siginfo(&info);
@@ -1601,7 +1605,7 @@ EXPORT_SYMBOL(send_sig_mceerr);
 
 int force_sig_bnderr(void __user *addr, void __user *lower, void __user *upper)
 {
-       struct siginfo info;
+       struct kernel_siginfo info;
 
        clear_siginfo(&info);
        info.si_signo = SIGSEGV;
@@ -1616,7 +1620,7 @@ int force_sig_bnderr(void __user *addr, void __user *lower, void __user *upper)
 #ifdef SEGV_PKUERR
 int force_sig_pkuerr(void __user *addr, u32 pkey)
 {
-       struct siginfo info;
+       struct kernel_siginfo info;
 
        clear_siginfo(&info);
        info.si_signo = SIGSEGV;
@@ -1633,7 +1637,7 @@ int force_sig_pkuerr(void __user *addr, u32 pkey)
  */
 int force_sig_ptrace_errno_trap(int errno, void __user *addr)
 {
-       struct siginfo info;
+       struct kernel_siginfo info;
 
        clear_siginfo(&info);
        info.si_signo = SIGTRAP;
@@ -1762,7 +1766,7 @@ ret:
  */
 bool do_notify_parent(struct task_struct *tsk, int sig)
 {
-       struct siginfo info;
+       struct kernel_siginfo info;
        unsigned long flags;
        struct sighand_struct *psig;
        bool autoreap = false;
@@ -1867,7 +1871,7 @@ bool do_notify_parent(struct task_struct *tsk, int sig)
 static void do_notify_parent_cldstop(struct task_struct *tsk,
                                     bool for_ptracer, int why)
 {
-       struct siginfo info;
+       struct kernel_siginfo info;
        unsigned long flags;
        struct task_struct *parent;
        struct sighand_struct *sighand;
@@ -1967,7 +1971,7 @@ static bool sigkill_pending(struct task_struct *tsk)
  * If we actually decide not to stop at all because the tracer
  * is gone, we keep current->exit_code unless clear_code.
  */
-static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info)
+static void ptrace_stop(int exit_code, int why, int clear_code, kernel_siginfo_t *info)
        __releases(&current->sighand->siglock)
        __acquires(&current->sighand->siglock)
 {
@@ -2104,7 +2108,7 @@ static void ptrace_stop(int exit_code, int why, int clear_code, siginfo_t *info)
 
 static void ptrace_do_notify(int signr, int exit_code, int why)
 {
-       siginfo_t info;
+       kernel_siginfo_t info;
 
        clear_siginfo(&info);
        info.si_signo = signr;
@@ -2285,7 +2289,7 @@ static void do_jobctl_trap(void)
        }
 }
 
-static int ptrace_signal(int signr, siginfo_t *info)
+static int ptrace_signal(int signr, kernel_siginfo_t *info)
 {
        /*
         * We do not check sig_kernel_stop(signr) but set this marker
@@ -2326,7 +2330,7 @@ static int ptrace_signal(int signr, siginfo_t *info)
 
        /* If the (new) signal is now blocked, requeue it.  */
        if (sigismember(&current->blocked, signr)) {
-               specific_send_sig_info(signr, info, current);
+               send_signal(signr, info, current, PIDTYPE_PID);
                signr = 0;
        }
 
@@ -2636,14 +2640,6 @@ out:
        }
 }
 
-EXPORT_SYMBOL(recalc_sigpending);
-EXPORT_SYMBOL_GPL(dequeue_signal);
-EXPORT_SYMBOL(flush_signals);
-EXPORT_SYMBOL(force_sig);
-EXPORT_SYMBOL(send_sig);
-EXPORT_SYMBOL(send_sig_info);
-EXPORT_SYMBOL(sigprocmask);
-
 /*
  * System call entry points.
  */
@@ -2737,6 +2733,7 @@ int sigprocmask(int how, sigset_t *set, sigset_t *oldset)
        __set_current_blocked(&newset);
        return 0;
 }
+EXPORT_SYMBOL(sigprocmask);
 
 /**
  *  sys_rt_sigprocmask - change the list of currently blocked signals
@@ -2847,27 +2844,48 @@ COMPAT_SYSCALL_DEFINE2(rt_sigpending, compat_sigset_t __user *, uset,
 }
 #endif
 
-enum siginfo_layout siginfo_layout(int sig, int si_code)
+static const struct {
+       unsigned char limit, layout;
+} sig_sicodes[] = {
+       [SIGILL]  = { NSIGILL,  SIL_FAULT },
+       [SIGFPE]  = { NSIGFPE,  SIL_FAULT },
+       [SIGSEGV] = { NSIGSEGV, SIL_FAULT },
+       [SIGBUS]  = { NSIGBUS,  SIL_FAULT },
+       [SIGTRAP] = { NSIGTRAP, SIL_FAULT },
+#if defined(SIGEMT)
+       [SIGEMT]  = { NSIGEMT,  SIL_FAULT },
+#endif
+       [SIGCHLD] = { NSIGCHLD, SIL_CHLD },
+       [SIGPOLL] = { NSIGPOLL, SIL_POLL },
+       [SIGSYS]  = { NSIGSYS,  SIL_SYS },
+};
+
+static bool known_siginfo_layout(unsigned sig, int si_code)
+{
+       if (si_code == SI_KERNEL)
+               return true;
+       else if ((si_code > SI_USER)) {
+               if (sig_specific_sicodes(sig)) {
+                       if (si_code <= sig_sicodes[sig].limit)
+                               return true;
+               }
+               else if (si_code <= NSIGPOLL)
+                       return true;
+       }
+       else if (si_code >= SI_DETHREAD)
+               return true;
+       else if (si_code == SI_ASYNCNL)
+               return true;
+       return false;
+}
+
+enum siginfo_layout siginfo_layout(unsigned sig, int si_code)
 {
        enum siginfo_layout layout = SIL_KILL;
        if ((si_code > SI_USER) && (si_code < SI_KERNEL)) {
-               static const struct {
-                       unsigned char limit, layout;
-               } filter[] = {
-                       [SIGILL]  = { NSIGILL,  SIL_FAULT },
-                       [SIGFPE]  = { NSIGFPE,  SIL_FAULT },
-                       [SIGSEGV] = { NSIGSEGV, SIL_FAULT },
-                       [SIGBUS]  = { NSIGBUS,  SIL_FAULT },
-                       [SIGTRAP] = { NSIGTRAP, SIL_FAULT },
-#if defined(SIGEMT) && defined(NSIGEMT)
-                       [SIGEMT]  = { NSIGEMT,  SIL_FAULT },
-#endif
-                       [SIGCHLD] = { NSIGCHLD, SIL_CHLD },
-                       [SIGPOLL] = { NSIGPOLL, SIL_POLL },
-                       [SIGSYS]  = { NSIGSYS,  SIL_SYS },
-               };
-               if ((sig < ARRAY_SIZE(filter)) && (si_code <= filter[sig].limit)) {
-                       layout = filter[sig].layout;
+               if ((sig < ARRAY_SIZE(sig_sicodes)) &&
+                   (si_code <= sig_sicodes[sig].limit)) {
+                       layout = sig_sicodes[sig].layout;
                        /* Handle the exceptions */
                        if ((sig == SIGBUS) &&
                            (si_code >= BUS_MCEERR_AR) && (si_code <= BUS_MCEERR_AO))
@@ -2892,22 +2910,69 @@ enum siginfo_layout siginfo_layout(int sig, int si_code)
        return layout;
 }
 
-int copy_siginfo_to_user(siginfo_t __user *to, const siginfo_t *from)
+static inline char __user *si_expansion(const siginfo_t __user *info)
+{
+       return ((char __user *)info) + sizeof(struct kernel_siginfo);
+}
+
+int copy_siginfo_to_user(siginfo_t __user *to, const kernel_siginfo_t *from)
 {
-       if (copy_to_user(to, from , sizeof(struct siginfo)))
+       char __user *expansion = si_expansion(to);
+       if (copy_to_user(to, from , sizeof(struct kernel_siginfo)))
+               return -EFAULT;
+       if (clear_user(expansion, SI_EXPANSION_SIZE))
                return -EFAULT;
        return 0;
 }
 
+static int post_copy_siginfo_from_user(kernel_siginfo_t *info,
+                                      const siginfo_t __user *from)
+{
+       if (unlikely(!known_siginfo_layout(info->si_signo, info->si_code))) {
+               char __user *expansion = si_expansion(from);
+               char buf[SI_EXPANSION_SIZE];
+               int i;
+               /*
+                * An unknown si_code might need more than
+                * sizeof(struct kernel_siginfo) bytes.  Verify all of the
+                * extra bytes are 0.  This guarantees copy_siginfo_to_user
+                * will return this data to userspace exactly.
+                */
+               if (copy_from_user(&buf, expansion, SI_EXPANSION_SIZE))
+                       return -EFAULT;
+               for (i = 0; i < SI_EXPANSION_SIZE; i++) {
+                       if (buf[i] != 0)
+                               return -E2BIG;
+               }
+       }
+       return 0;
+}
+
+static int __copy_siginfo_from_user(int signo, kernel_siginfo_t *to,
+                                   const siginfo_t __user *from)
+{
+       if (copy_from_user(to, from, sizeof(struct kernel_siginfo)))
+               return -EFAULT;
+       to->si_signo = signo;
+       return post_copy_siginfo_from_user(to, from);
+}
+
+int copy_siginfo_from_user(kernel_siginfo_t *to, const siginfo_t __user *from)
+{
+       if (copy_from_user(to, from, sizeof(struct kernel_siginfo)))
+               return -EFAULT;
+       return post_copy_siginfo_from_user(to, from);
+}
+
 #ifdef CONFIG_COMPAT
 int copy_siginfo_to_user32(struct compat_siginfo __user *to,
-                          const struct siginfo *from)
+                          const struct kernel_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)
+                            const struct kernel_siginfo *from, bool x32_ABI)
 #endif
 {
        struct compat_siginfo new;
@@ -2991,88 +3056,106 @@ int __copy_siginfo_to_user32(struct compat_siginfo __user *to,
        return 0;
 }
 
-int copy_siginfo_from_user32(struct siginfo *to,
-                            const struct compat_siginfo __user *ufrom)
+static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
+                                        const struct compat_siginfo *from)
 {
-       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)) {
+       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;
+               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;
+               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;
+               to->si_band = from->si_band;
+               to->si_fd   = from->si_fd;
                break;
        case SIL_FAULT:
-               to->si_addr = compat_ptr(from.si_addr);
+               to->si_addr = compat_ptr(from->si_addr);
 #ifdef __ARCH_SI_TRAPNO
-               to->si_trapno = from.si_trapno;
+               to->si_trapno = from->si_trapno;
 #endif
                break;
        case SIL_FAULT_MCEERR:
-               to->si_addr = compat_ptr(from.si_addr);
+               to->si_addr = compat_ptr(from->si_addr);
 #ifdef __ARCH_SI_TRAPNO
-               to->si_trapno = from.si_trapno;
+               to->si_trapno = from->si_trapno;
 #endif
-               to->si_addr_lsb = from.si_addr_lsb;
+               to->si_addr_lsb = from->si_addr_lsb;
                break;
        case SIL_FAULT_BNDERR:
-               to->si_addr = compat_ptr(from.si_addr);
+               to->si_addr = compat_ptr(from->si_addr);
 #ifdef __ARCH_SI_TRAPNO
-               to->si_trapno = from.si_trapno;
+               to->si_trapno = from->si_trapno;
 #endif
-               to->si_lower = compat_ptr(from.si_lower);
-               to->si_upper = compat_ptr(from.si_upper);
+               to->si_lower = compat_ptr(from->si_lower);
+               to->si_upper = compat_ptr(from->si_upper);
                break;
        case SIL_FAULT_PKUERR:
-               to->si_addr = compat_ptr(from.si_addr);
+               to->si_addr = compat_ptr(from->si_addr);
 #ifdef __ARCH_SI_TRAPNO
-               to->si_trapno = from.si_trapno;
+               to->si_trapno = from->si_trapno;
 #endif
-               to->si_pkey = from.si_pkey;
+               to->si_pkey = from->si_pkey;
                break;
        case SIL_CHLD:
-               to->si_pid    = from.si_pid;
-               to->si_uid    = from.si_uid;
-               to->si_status = from.si_status;
+               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;
+                       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;
+                       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;
+               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;
+               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;
 }
+
+static int __copy_siginfo_from_user32(int signo, struct kernel_siginfo *to,
+                                     const struct compat_siginfo __user *ufrom)
+{
+       struct compat_siginfo from;
+
+       if (copy_from_user(&from, ufrom, sizeof(struct compat_siginfo)))
+               return -EFAULT;
+
+       from.si_signo = signo;
+       return post_copy_siginfo_from_user32(to, &from);
+}
+
+int copy_siginfo_from_user32(struct kernel_siginfo *to,
+                            const struct compat_siginfo __user *ufrom)
+{
+       struct compat_siginfo from;
+
+       if (copy_from_user(&from, ufrom, sizeof(struct compat_siginfo)))
+               return -EFAULT;
+
+       return post_copy_siginfo_from_user32(to, &from);
+}
 #endif /* CONFIG_COMPAT */
 
 /**
@@ -3081,8 +3164,8 @@ int copy_siginfo_from_user32(struct siginfo *to,
  *  @info: if non-null, the signal's siginfo is returned here
  *  @ts: upper bound on process time suspension
  */
-static int do_sigtimedwait(const sigset_t *which, siginfo_t *info,
-                   const struct timespec *ts)
+static int do_sigtimedwait(const sigset_t *which, kernel_siginfo_t *info,
+                   const struct timespec64 *ts)
 {
        ktime_t *to = NULL, timeout = KTIME_MAX;
        struct task_struct *tsk = current;
@@ -3090,9 +3173,9 @@ static int do_sigtimedwait(const sigset_t *which, siginfo_t *info,
        int sig, ret = 0;
 
        if (ts) {
-               if (!timespec_valid(ts))
+               if (!timespec64_valid(ts))
                        return -EINVAL;
-               timeout = timespec_to_ktime(*ts);
+               timeout = timespec64_to_ktime(*ts);
                to = &timeout;
        }
 
@@ -3140,12 +3223,13 @@ static int do_sigtimedwait(const sigset_t *which, siginfo_t *info,
  *  @sigsetsize: size of sigset_t type
  */
 SYSCALL_DEFINE4(rt_sigtimedwait, const sigset_t __user *, uthese,
-               siginfo_t __user *, uinfo, const struct timespec __user *, uts,
+               siginfo_t __user *, uinfo,
+               const struct __kernel_timespec __user *, uts,
                size_t, sigsetsize)
 {
        sigset_t these;
-       struct timespec ts;
-       siginfo_t info;
+       struct timespec64 ts;
+       kernel_siginfo_t info;
        int ret;
 
        /* XXX: Don't preclude handling different sized sigset_t's.  */
@@ -3156,7 +3240,7 @@ SYSCALL_DEFINE4(rt_sigtimedwait, const sigset_t __user *, uthese,
                return -EFAULT;
 
        if (uts) {
-               if (copy_from_user(&ts, uts, sizeof(ts)))
+               if (get_timespec64(&ts, uts))
                        return -EFAULT;
        }
 
@@ -3173,11 +3257,11 @@ SYSCALL_DEFINE4(rt_sigtimedwait, const sigset_t __user *, uthese,
 #ifdef CONFIG_COMPAT
 COMPAT_SYSCALL_DEFINE4(rt_sigtimedwait, compat_sigset_t __user *, uthese,
                struct compat_siginfo __user *, uinfo,
-               struct compat_timespec __user *, uts, compat_size_t, sigsetsize)
+               struct old_timespec32 __user *, uts, compat_size_t, sigsetsize)
 {
        sigset_t s;
-       struct timespec t;
-       siginfo_t info;
+       struct timespec64 t;
+       kernel_siginfo_t info;
        long ret;
 
        if (sigsetsize != sizeof(sigset_t))
@@ -3187,7 +3271,7 @@ COMPAT_SYSCALL_DEFINE4(rt_sigtimedwait, compat_sigset_t __user *, uthese,
                return -EFAULT;
 
        if (uts) {
-               if (compat_get_timespec(&t, uts))
+               if (get_old_timespec32(&t, uts))
                        return -EFAULT;
        }
 
@@ -3209,7 +3293,7 @@ COMPAT_SYSCALL_DEFINE4(rt_sigtimedwait, compat_sigset_t __user *, uthese,
  */
 SYSCALL_DEFINE2(kill, pid_t, pid, int, sig)
 {
-       struct siginfo info;
+       struct kernel_siginfo info;
 
        clear_siginfo(&info);
        info.si_signo = sig;
@@ -3222,7 +3306,7 @@ SYSCALL_DEFINE2(kill, pid_t, pid, int, sig)
 }
 
 static int
-do_send_specific(pid_t tgid, pid_t pid, int sig, struct siginfo *info)
+do_send_specific(pid_t tgid, pid_t pid, int sig, struct kernel_siginfo *info)
 {
        struct task_struct *p;
        int error = -ESRCH;
@@ -3253,7 +3337,7 @@ 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 kernel_siginfo info;
 
        clear_siginfo(&info);
        info.si_signo = sig;
@@ -3300,7 +3384,7 @@ SYSCALL_DEFINE2(tkill, pid_t, pid, int, sig)
        return do_tkill(0, pid, sig);
 }
 
-static int do_rt_sigqueueinfo(pid_t pid, int sig, siginfo_t *info)
+static int do_rt_sigqueueinfo(pid_t pid, int sig, kernel_siginfo_t *info)
 {
        /* Not even root can pretend to send signals from the kernel.
         * Nor can they impersonate a kill()/tgkill(), which adds source info.
@@ -3309,8 +3393,6 @@ static int do_rt_sigqueueinfo(pid_t pid, int sig, siginfo_t *info)
            (task_pid_vnr(current) != pid))
                return -EPERM;
 
-       info->si_signo = sig;
-
        /* POSIX.1b doesn't mention process groups.  */
        return kill_proc_info(sig, info, pid);
 }
@@ -3324,9 +3406,10 @@ static int do_rt_sigqueueinfo(pid_t pid, int sig, siginfo_t *info)
 SYSCALL_DEFINE3(rt_sigqueueinfo, pid_t, pid, int, sig,
                siginfo_t __user *, uinfo)
 {
-       siginfo_t info;
-       if (copy_from_user(&info, uinfo, sizeof(siginfo_t)))
-               return -EFAULT;
+       kernel_siginfo_t info;
+       int ret = __copy_siginfo_from_user(sig, &info, uinfo);
+       if (unlikely(ret))
+               return ret;
        return do_rt_sigqueueinfo(pid, sig, &info);
 }
 
@@ -3336,15 +3419,15 @@ COMPAT_SYSCALL_DEFINE3(rt_sigqueueinfo,
                        int, sig,
                        struct compat_siginfo __user *, uinfo)
 {
-       siginfo_t info;
-       int ret = copy_siginfo_from_user32(&info, uinfo);
+       kernel_siginfo_t info;
+       int ret = __copy_siginfo_from_user32(sig, &info, uinfo);
        if (unlikely(ret))
                return ret;
        return do_rt_sigqueueinfo(pid, sig, &info);
 }
 #endif
 
-static int do_rt_tgsigqueueinfo(pid_t tgid, pid_t pid, int sig, siginfo_t *info)
+static int do_rt_tgsigqueueinfo(pid_t tgid, pid_t pid, int sig, kernel_siginfo_t *info)
 {
        /* This is only valid for single tasks */
        if (pid <= 0 || tgid <= 0)
@@ -3357,19 +3440,16 @@ static int do_rt_tgsigqueueinfo(pid_t tgid, pid_t pid, int sig, siginfo_t *info)
            (task_pid_vnr(current) != pid))
                return -EPERM;
 
-       info->si_signo = sig;
-
        return do_send_specific(tgid, pid, sig, info);
 }
 
 SYSCALL_DEFINE4(rt_tgsigqueueinfo, pid_t, tgid, pid_t, pid, int, sig,
                siginfo_t __user *, uinfo)
 {
-       siginfo_t info;
-
-       if (copy_from_user(&info, uinfo, sizeof(siginfo_t)))
-               return -EFAULT;
-
+       kernel_siginfo_t info;
+       int ret = __copy_siginfo_from_user(sig, &info, uinfo);
+       if (unlikely(ret))
+               return ret;
        return do_rt_tgsigqueueinfo(tgid, pid, sig, &info);
 }
 
@@ -3380,10 +3460,10 @@ COMPAT_SYSCALL_DEFINE4(rt_tgsigqueueinfo,
                        int, sig,
                        struct compat_siginfo __user *, uinfo)
 {
-       siginfo_t info;
-
-       if (copy_siginfo_from_user32(&info, uinfo))
-               return -EFAULT;
+       kernel_siginfo_t info;
+       int ret = __copy_siginfo_from_user32(sig, &info, uinfo);
+       if (unlikely(ret))
+               return ret;
        return do_rt_tgsigqueueinfo(tgid, pid, sig, &info);
 }
 #endif
@@ -3966,13 +4046,57 @@ __weak const char *arch_vma_name(struct vm_area_struct *vma)
        return NULL;
 }
 
-void __init signals_init(void)
+static inline void siginfo_buildtime_checks(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);
 
+       /* Verify the offsets in the two siginfos match */
+#define CHECK_OFFSET(field) \
+       BUILD_BUG_ON(offsetof(siginfo_t, field) != offsetof(kernel_siginfo_t, field))
+
+       /* kill */
+       CHECK_OFFSET(si_pid);
+       CHECK_OFFSET(si_uid);
+
+       /* timer */
+       CHECK_OFFSET(si_tid);
+       CHECK_OFFSET(si_overrun);
+       CHECK_OFFSET(si_value);
+
+       /* rt */
+       CHECK_OFFSET(si_pid);
+       CHECK_OFFSET(si_uid);
+       CHECK_OFFSET(si_value);
+
+       /* sigchld */
+       CHECK_OFFSET(si_pid);
+       CHECK_OFFSET(si_uid);
+       CHECK_OFFSET(si_status);
+       CHECK_OFFSET(si_utime);
+       CHECK_OFFSET(si_stime);
+
+       /* sigfault */
+       CHECK_OFFSET(si_addr);
+       CHECK_OFFSET(si_addr_lsb);
+       CHECK_OFFSET(si_lower);
+       CHECK_OFFSET(si_upper);
+       CHECK_OFFSET(si_pkey);
+
+       /* sigpoll */
+       CHECK_OFFSET(si_band);
+       CHECK_OFFSET(si_fd);
+
+       /* sigsys */
+       CHECK_OFFSET(si_call_addr);
+       CHECK_OFFSET(si_syscall);
+       CHECK_OFFSET(si_arch);
+#undef CHECK_OFFSET
+}
+
+void __init signals_init(void)
+{
+       siginfo_buildtime_checks();
+
        sigqueue_cachep = KMEM_CACHE(sigqueue, SLAB_PANIC);
 }