]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - kernel/signal.c
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/livep...
[linux.git] / kernel / signal.c
index f14492ff976f688cdde6a0be7a6c4cf9a2b70920..c6e4c83dc090ab1361ee9c229f8ff185295c2f46 100644 (file)
@@ -40,6 +40,7 @@
 #include <linux/cn_proc.h>
 #include <linux/compiler.h>
 #include <linux/posix-timers.h>
+#include <linux/livepatch.h>
 
 #define CREATE_TRACE_POINTS
 #include <trace/events/signal.h>
@@ -165,7 +166,8 @@ void recalc_sigpending_and_wake(struct task_struct *t)
 
 void recalc_sigpending(void)
 {
-       if (!recalc_sigpending_tsk(current) && !freezing(current))
+       if (!recalc_sigpending_tsk(current) && !freezing(current) &&
+           !klp_patch_pending(current))
                clear_thread_flag(TIF_SIGPENDING);
 
 }
@@ -1491,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;