upgrade to fedora-2.6.12-1.1398.FC4 + vserver 2.0.rc7
[linux-2.6.git] / arch / ppc64 / kernel / signal32.c
index bdc0d62..3c2fa5c 100644 (file)
@@ -31,6 +31,7 @@
 #include <asm/ppcdebug.h>
 #include <asm/unistd.h>
 #include <asm/cacheflush.h>
+#include <asm/vdso.h>
 
 #define DEBUG_SIG 0
 
@@ -72,7 +73,7 @@ struct sigregs32 {
  *
  */
 struct rt_sigframe32 {
-       struct compat_siginfo   info;
+       compat_siginfo_t        info;
        struct ucontext32       uc;
        /*
         * Programs using the rs6000/xcoff abi can save up to 19 gp
@@ -341,7 +342,6 @@ long sys32_sigaction(int sig, struct old_sigaction32 __user *act,
  *       sigpending               sys32_rt_sigpending
  *       sigprocmask              sys32_rt_sigprocmask
  *       sigreturn                sys32_rt_sigreturn
- *       sigtimedwait             sys32_rt_sigtimedwait
  *       sigqueueinfo             sys32_rt_sigqueueinfo
  *       sigsuspend               sys32_rt_sigsuspend
  *
@@ -445,9 +445,9 @@ long sys32_rt_sigpending(compat_sigset_t __user *set, compat_size_t sigsetsize)
 }
 
 
-static long copy_siginfo_to_user32(compat_siginfo_t __user *d, siginfo_t *s)
+int copy_siginfo_to_user32(struct compat_siginfo __user *d, siginfo_t *s)
 {
-       long err;
+       int err;
 
        if (!access_ok (VERIFY_WRITE, d, sizeof(*d)))
                return -EFAULT;
@@ -500,35 +500,6 @@ static long copy_siginfo_to_user32(compat_siginfo_t __user *d, siginfo_t *s)
        return err;
 }
 
-long sys32_rt_sigtimedwait(compat_sigset_t __user *uthese, compat_siginfo_t __user *uinfo,
-               struct compat_timespec __user *uts, compat_size_t sigsetsize)
-{
-       sigset_t s;
-       compat_sigset_t s32;
-       struct timespec t;
-       int ret;
-       mm_segment_t old_fs = get_fs();
-       siginfo_t info;
-
-       if (copy_from_user(&s32, uthese, sizeof(compat_sigset_t)))
-               return -EFAULT;
-       sigset_from_compat(&s, &s32);
-       if (uts && get_compat_timespec(&t, uts))
-               return -EFAULT;
-       set_fs(KERNEL_DS);
-       /* The __user pointer casts are valid because of the set_fs() */
-       ret = sys_rt_sigtimedwait((sigset_t __user *) &s,
-                       uinfo ? (siginfo_t __user *) &info : NULL,
-                       uts ? (struct timespec __user *) &t : NULL,
-                       sigsetsize);
-       set_fs(old_fs);
-       if (ret >= 0 && uinfo) {
-               if (copy_siginfo_to_user32(uinfo, &info))
-                       return -EFAULT;
-       }
-       return ret;
-}
-
 /*
  * 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
@@ -667,7 +638,7 @@ static int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka,
        /* create a stack frame for the caller of the handler */
        newsp -= __SIGNAL_FRAMESIZE32 + 16;
 
-       if (verify_area(VERIFY_WRITE, (void __user *)newsp, origsp - newsp))
+       if (!access_ok(VERIFY_WRITE, (void __user *)newsp, origsp - newsp))
                goto badframe;
 
        compat_from_sigset(&c_oldset, oldset);
@@ -686,18 +657,24 @@ static int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka,
 
        /* Save user registers on the stack */
        frame = &rt_sf->uc.uc_mcontext;
-       if (save_user_regs(regs, frame, __NR_rt_sigreturn))
+       if (put_user(regs->gpr[1], (u32 __user *)newsp))
                goto badframe;
 
-       if (put_user(regs->gpr[1], (unsigned long __user *)newsp))
-               goto badframe;
+       if (vdso32_rt_sigtramp && current->thread.vdso_base) {
+               if (save_user_regs(regs, frame, 0))
+                       goto badframe;
+               regs->link = current->thread.vdso_base + vdso32_rt_sigtramp;
+       } else {
+               if (save_user_regs(regs, frame, __NR_rt_sigreturn))
+                       goto badframe;
+               regs->link = (unsigned long) frame->tramp;
+       }
        regs->gpr[1] = (unsigned long) newsp;
        regs->gpr[3] = sig;
        regs->gpr[4] = (unsigned long) &rt_sf->info;
        regs->gpr[5] = (unsigned long) &rt_sf->uc;
        regs->gpr[6] = (unsigned long) rt_sf;
        regs->nip = (unsigned long) ka->sa.sa_handler;
-       regs->link = (unsigned long) frame->tramp;
        regs->trap = 0;
        regs->result = 0;
 
@@ -751,7 +728,7 @@ long sys32_swapcontext(struct ucontext32 __user *old_ctx,
 
        if (old_ctx != NULL) {
                compat_from_sigset(&c_set, &current->blocked);
-               if (verify_area(VERIFY_WRITE, old_ctx, sizeof(*old_ctx))
+               if (!access_ok(VERIFY_WRITE, old_ctx, sizeof(*old_ctx))
                    || save_user_regs(regs, &old_ctx->uc_mcontext, 0)
                    || __copy_to_user(&old_ctx->uc_sigmask, &c_set, sizeof(c_set))
                    || __put_user((u32)(u64)&old_ctx->uc_mcontext, &old_ctx->uc_regs))
@@ -759,7 +736,7 @@ long sys32_swapcontext(struct ucontext32 __user *old_ctx,
        }
        if (new_ctx == NULL)
                return 0;
-       if (verify_area(VERIFY_READ, new_ctx, sizeof(*new_ctx))
+       if (!access_ok(VERIFY_READ, new_ctx, sizeof(*new_ctx))
            || __get_user(tmp, (u8 __user *) new_ctx)
            || __get_user(tmp, (u8 __user *) (new_ctx + 1) - 1))
                return -EFAULT;
@@ -769,7 +746,7 @@ long sys32_swapcontext(struct ucontext32 __user *old_ctx,
         * image of the user's registers, we can't just return -EFAULT
         * because the user's registers will be corrupted.  For instance
         * the NIP value may have been updated but not some of the
-        * other registers.  Given that we have done the verify_area
+        * other registers.  Given that we have done the access_ok
         * and successfully read the first and last bytes of the region
         * above, this should only happen in an out-of-memory situation
         * or if another thread unmaps the region containing the context.
@@ -793,7 +770,7 @@ long sys32_rt_sigreturn(int r3, int r4, int r5, int r6, int r7, int r8,
 
        rt_sf = (struct rt_sigframe32 __user *)
                (regs->gpr[1] + __SIGNAL_FRAMESIZE32 + 16);
-       if (verify_area(VERIFY_READ, rt_sf, sizeof(*rt_sf)))
+       if (!access_ok(VERIFY_READ, rt_sf, sizeof(*rt_sf)))
                goto bad;
        if (do_setcontext32(&rt_sf->uc, regs, 1))
                goto bad;
@@ -842,7 +819,7 @@ static int handle_signal32(unsigned long sig, struct k_sigaction *ka,
        /* create a stack frame for the caller of the handler */
        newsp -= __SIGNAL_FRAMESIZE32;
 
-       if (verify_area(VERIFY_WRITE, (void __user *) newsp, origsp - newsp))
+       if (!access_ok(VERIFY_WRITE, (void __user *) newsp, origsp - newsp))
                goto badframe;
 
 #if _NSIG != 64
@@ -855,16 +832,22 @@ static int handle_signal32(unsigned long sig, struct k_sigaction *ka,
            || __put_user(sig, &sc->signal))
                goto badframe;
 
-       if (save_user_regs(regs, &frame->mctx, __NR_sigreturn))
-               goto badframe;
+       if (vdso32_sigtramp && current->thread.vdso_base) {
+               if (save_user_regs(regs, &frame->mctx, 0))
+                       goto badframe;
+               regs->link = current->thread.vdso_base + vdso32_sigtramp;
+       } else {
+               if (save_user_regs(regs, &frame->mctx, __NR_sigreturn))
+                       goto badframe;
+               regs->link = (unsigned long) frame->mctx.tramp;
+       }
 
-       if (put_user(regs->gpr[1], (unsigned long __user *)newsp))
+       if (put_user(regs->gpr[1], (u32 __user *)newsp))
                goto badframe;
        regs->gpr[1] = (unsigned long) newsp;
        regs->gpr[3] = sig;
        regs->gpr[4] = (unsigned long) sc;
        regs->nip = (unsigned long) ka->sa.sa_handler;
-       regs->link = (unsigned long) frame->mctx.tramp;
        regs->trap = 0;
        regs->result = 0;
 
@@ -909,7 +892,7 @@ long sys32_sigreturn(int r3, int r4, int r5, int r6, int r7, int r8,
        restore_sigmask(&set);
 
        sr = (struct mcontext32 __user *)(u64)sigctx.regs;
-       if (verify_area(VERIFY_READ, sr, sizeof(*sr))
+       if (!access_ok(VERIFY_READ, sr, sizeof(*sr))
            || restore_user_regs(regs, sr, 1))
                goto badframe;