]> err.no Git - linux-2.6/blobdiff - arch/powerpc/kernel/signal_32.c
[RAPIDIO] Add serial RapidIO controller support, which includes MPC8548, MPC8641
[linux-2.6] / arch / powerpc / kernel / signal_32.c
index 590057e9e98779e227c52d967b776d4b1900214c..ad6943468ee9f25aee853a3ded8f99271f1c3d72 100644 (file)
 #include <linux/signal.h>
 #include <linux/errno.h>
 #include <linux/elf.h>
+#include <linux/ptrace.h>
 #ifdef CONFIG_PPC64
 #include <linux/syscalls.h>
 #include <linux/compat.h>
-#include <linux/ptrace.h>
 #else
 #include <linux/wait.h>
-#include <linux/ptrace.h>
 #include <linux/unistd.h>
 #include <linux/stddef.h>
 #include <linux/tty.h>
@@ -622,6 +621,18 @@ int copy_siginfo_to_user32(struct compat_siginfo __user *d, siginfo_t *s)
 
 #define copy_siginfo_to_user   copy_siginfo_to_user32
 
+int copy_siginfo_from_user32(siginfo_t *to, struct compat_siginfo __user *from)
+{
+       memset(to, 0, sizeof *to);
+
+       if (copy_from_user(to, from, 3*sizeof(int)) ||
+           copy_from_user(to->_sifields._pad,
+                          from->_sifields._pad, SI_PAD_SIZE32))
+               return -EFAULT;
+
+       return 0;
+}
+
 /*
  * Note: it is necessary to treat pid and sig as unsigned ints, with the
  * corresponding cast to a signed int to insure that the proper conversion
@@ -635,9 +646,10 @@ long compat_sys_rt_sigqueueinfo(u32 pid, u32 sig, compat_siginfo_t __user *uinfo
        int ret;
        mm_segment_t old_fs = get_fs();
 
-       if (copy_from_user (&info, uinfo, 3*sizeof(int)) ||
-           copy_from_user (info._sifields._pad, uinfo->_sifields._pad, SI_PAD_SIZE32))
-               return -EFAULT;
+       ret = copy_siginfo_from_user32(&info, uinfo);
+       if (unlikely(ret))
+               return ret;
+
        set_fs (KERNEL_DS);
        /* The __user pointer cast is valid becasuse of the set_fs() */
        ret = sys_rt_sigqueueinfo((int)pid, (int)sig, (siginfo_t __user *) &info);
@@ -705,11 +717,13 @@ int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka,
 {
        struct rt_sigframe __user *rt_sf;
        struct mcontext __user *frame;
+       void __user *addr;
        unsigned long newsp = 0;
 
        /* Set up Signal Frame */
        /* Put a Real Time Context onto stack */
        rt_sf = get_sigframe(ka, regs, sizeof(*rt_sf));
+       addr = rt_sf;
        if (unlikely(rt_sf == NULL))
                goto badframe;
 
@@ -728,6 +742,7 @@ int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka,
 
        /* Save user registers on the stack */
        frame = &rt_sf->uc.uc_mcontext;
+       addr = frame;
        if (vdso32_rt_sigtramp && current->mm->context.vdso_base) {
                if (save_user_regs(regs, frame, 0))
                        goto badframe;
@@ -742,6 +757,7 @@ int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka,
 
        /* create a stack frame for the caller of the handler */
        newsp = ((unsigned long)rt_sf) - (__SIGNAL_FRAMESIZE + 16);
+       addr = (void __user *)regs->gpr[1];
        if (put_user(regs->gpr[1], (u32 __user *)newsp))
                goto badframe;
 
@@ -762,6 +778,12 @@ badframe:
        printk("badframe in handle_rt_signal, regs=%p frame=%p newsp=%lx\n",
               regs, frame, newsp);
 #endif
+       if (show_unhandled_signals && printk_ratelimit())
+               printk(KERN_INFO "%s[%d]: bad frame in handle_rt_signal32: "
+                       "%p nip %08lx lr %08lx\n",
+                       current->comm, current->pid,
+                       addr, regs->nip, regs->link);
+
        force_sigsegv(sig, current);
        return 0;
 }
@@ -886,6 +908,12 @@ long sys_rt_sigreturn(int r3, int r4, int r5, int r6, int r7, int r8,
        return 0;
 
  bad:
+       if (show_unhandled_signals && printk_ratelimit())
+               printk(KERN_INFO "%s[%d]: bad frame in sys_rt_sigreturn: "
+                       "%p nip %08lx lr %08lx\n",
+                       current->comm, current->pid,
+                       rt_sf, regs->nip, regs->link);
+
        force_sig(SIGSEGV, current);
        return 0;
 }
@@ -967,6 +995,13 @@ int sys_debug_setcontext(struct ucontext __user *ctx,
         * We kill the task with a SIGSEGV in this situation.
         */
        if (do_setcontext(ctx, regs, 1)) {
+               if (show_unhandled_signals && printk_ratelimit())
+                       printk(KERN_INFO "%s[%d]: bad frame in "
+                               "sys_debug_setcontext: %p nip %08lx "
+                               "lr %08lx\n",
+                               current->comm, current->pid,
+                               ctx, regs->nip, regs->link);
+
                force_sig(SIGSEGV, current);
                goto out;
        }
@@ -1048,6 +1083,12 @@ badframe:
        printk("badframe in handle_signal, regs=%p frame=%p newsp=%lx\n",
               regs, frame, newsp);
 #endif
+       if (show_unhandled_signals && printk_ratelimit())
+               printk(KERN_INFO "%s[%d]: bad frame in handle_signal32: "
+                       "%p nip %08lx lr %08lx\n",
+                       current->comm, current->pid,
+                       frame, regs->nip, regs->link);
+
        force_sigsegv(sig, current);
        return 0;
 }
@@ -1061,12 +1102,14 @@ long sys_sigreturn(int r3, int r4, int r5, int r6, int r7, int r8,
        struct sigcontext __user *sc;
        struct sigcontext sigctx;
        struct mcontext __user *sr;
+       void __user *addr;
        sigset_t set;
 
        /* Always make any pending restarted system calls return -EINTR */
        current_thread_info()->restart_block.fn = do_no_restart_syscall;
 
        sc = (struct sigcontext __user *)(regs->gpr[1] + __SIGNAL_FRAMESIZE);
+       addr = sc;
        if (copy_from_user(&sigctx, sc, sizeof(sigctx)))
                goto badframe;
 
@@ -1083,6 +1126,7 @@ long sys_sigreturn(int r3, int r4, int r5, int r6, int r7, int r8,
        restore_sigmask(&set);
 
        sr = (struct mcontext __user *)from_user_ptr(sigctx.regs);
+       addr = sr;
        if (!access_ok(VERIFY_READ, sr, sizeof(*sr))
            || restore_user_regs(regs, sr, 1))
                goto badframe;
@@ -1091,6 +1135,12 @@ long sys_sigreturn(int r3, int r4, int r5, int r6, int r7, int r8,
        return 0;
 
 badframe:
+       if (show_unhandled_signals && printk_ratelimit())
+               printk(KERN_INFO "%s[%d]: bad frame in sys_sigreturn: "
+                       "%p nip %08lx lr %08lx\n",
+                       current->comm, current->pid,
+                       addr, regs->nip, regs->link);
+
        force_sig(SIGSEGV, current);
        return 0;
 }