]> git.hungrycats.org Git - linux/commitdiff
[PATCH] ppc64: siginfo conversion fix
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>
Mon, 19 Apr 2004 11:39:52 +0000 (04:39 -0700)
committerLinus Torvalds <torvalds@ppc970.osdl.org>
Mon, 19 Apr 2004 11:39:52 +0000 (04:39 -0700)
My message queue patch fixes the 64 bits -> 32 bits conversion of
siginfo, but didn't change the 32 -> 64 bits conversion done in
sys32_rt_sigqueueinfo() which was apparently bogus as well.

After much discussion & debate on the right way of converting that
structure, I decided to go the sparc64 / s390 way, and not the x86_64
way, that is to copy the various unions data "as is". This guarantees
that whatever a 32 bist app passes there, another 32 bits app will
understand it. Crossover between 32 and 64 bits apps on such things
as home-made userland siginfo isn't something we can help with anyway.

The x86_64 choice of converting as if it was an RT signal, thus
converting the sigval, cannot easily be applied to big endian archs
since the sigval is a union of a ptr and an int, on BE, the int
happens to be on the wrong half of the 64 bits ptr, thus  we can't
do a simple conversion.

arch/ppc64/kernel/signal32.c

index 395ce86b99ff8e81ee1f4812ae401e3c5607f842..fb2042711def17f269f6c12927be3700ab8ae17e 100644 (file)
@@ -507,45 +507,6 @@ long sys32_rt_sigtimedwait(compat_sigset_t *uthese, compat_siginfo_t *uinfo,
        return ret;
 }
 
-
-
-static siginfo_t * siginfo32to64(siginfo_t *d, compat_siginfo_t *s)
-{
-       d->si_signo = s->si_signo;
-       d->si_errno = s->si_errno;
-       d->si_code = s->si_code;
-       if (s->si_signo >= SIGRTMIN) {
-               d->si_pid = s->si_pid;
-               d->si_uid = s->si_uid;
-               d->si_int = s->si_int;
-       } else {
-               switch (s->si_signo) {
-               /* XXX: What about POSIX1.b timers */
-               case SIGCHLD:
-                       d->si_pid = s->si_pid;
-                       d->si_status = s->si_status;
-                       d->si_utime = s->si_utime;
-                       d->si_stime = s->si_stime;
-                       break;
-               case SIGSEGV:
-               case SIGBUS:
-               case SIGFPE:
-               case SIGILL:
-                       d->si_addr = (void *)A(s->si_addr);
-                       break;
-               case SIGPOLL:
-                       d->si_band = s->si_band;
-                       d->si_fd = s->si_fd;
-                       break;
-               default:
-                       d->si_pid = s->si_pid;
-                       d->si_uid = s->si_uid;
-                       break;
-               }
-       }
-       return d;
-}
-
 /*
  * 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
@@ -556,15 +517,12 @@ static siginfo_t * siginfo32to64(siginfo_t *d, compat_siginfo_t *s)
 long sys32_rt_sigqueueinfo(u32 pid, u32 sig, compat_siginfo_t *uinfo)
 {
        siginfo_t info;
-       compat_siginfo_t info32;
        int ret;
        mm_segment_t old_fs = get_fs();
        
-       if (copy_from_user (&info32, uinfo, sizeof(compat_siginfo_t)))
+       if (copy_from_user (&info, uinfo, 3*sizeof(int)) ||
+           copy_from_user (info._sifields._pad, uinfo->_sifields._pad, SI_PAD_SIZE32))
                return -EFAULT;
-       /* XXX: Is this correct? */
-       siginfo32to64(&info, &info32);
-
        set_fs (KERNEL_DS);
        ret = sys_rt_sigqueueinfo((int)pid, (int)sig, &info);
        set_fs (old_fs);