Thread (5 messages) 5 messages, 2 authors, 2002-08-09

Re: siginfo structure in 64-bit kernel

From: Carsten Langgaard <hidden>
Date: 2002-08-08 19:56:22


"Maciej W. Rozycki" wrote:
On Wed, 7 Aug 2002, Maciej W. Rozycki wrote:
quoted
I'll check the patch at run-time later.
 I checked the patch and discovered you somehow made the order of struct
members wrong.
Good spotted, that's what happens when MIPS is the only one that put 'si_code' before 'si_errno' in the structure.

 Here is an updated version that works for me.  It includes
both the ordering fix and unsigned type changes I suggested before.
With your sign changes we are doing things a little bit different than others, I know that's not really an argument, but does the unsigned types not work for you ?


quoted hunk ↗ jump to hunk
 This version should be OK to apply.

--
+  Maciej W. Rozycki, Technical University of Gdansk, Poland   +
+--------------------------------------------------------------+
+        e-mail: macro@ds2.pg.gda.pl, PGP key available        +

patch-mips-2.4.19-rc1-20020807-carsten-signal32-3
diff -up --recursive --new-file linux-mips-2.4.19-rc1-20020807.macro/arch/mips64/kernel/signal32.c linux-mips-2.4.19-rc1-20020807/arch/mips64/kernel/signal32.c
--- linux-mips-2.4.19-rc1-20020807.macro/arch/mips64/kernel/signal32.c  2002-08-06 02:57:36.000000000 +0000
+++ linux-mips-2.4.19-rc1-20020807/arch/mips64/kernel/signal32.c        2002-08-08 00:20:04.000000000 +0000
@@ -360,13 +360,55 @@ struct sigframe {
        sigset_t sf_mask;
 };

-struct rt_sigframe {
+struct rt_sigframe32 {
        u32 rs_ass[4];                  /* argument save space for o32 */
        u32 rs_code[2];                 /* signal trampoline */
-       struct siginfo rs_info;
+       struct siginfo32 rs_info;
        struct ucontext rs_uc;
 };

+static int copy_siginfo_to_user32(siginfo_t32 *to, siginfo_t *from)
+{
+       int err;
+
+       if (!access_ok (VERIFY_WRITE, to, sizeof(siginfo_t32)))
+               return -EFAULT;
+
+       /* If you change siginfo_t structure, please be sure
+          this code is fixed accordingly.
+          It should never copy any pad contained in the structure
+          to avoid security leaks, but must copy the generic
+          3 ints plus the relevant union member.
+          This routine must convert siginfo from 64bit to 32bit as well
+          at the same time.  */
+       err = __put_user(from->si_signo, &to->si_signo);
+       err |= __put_user(from->si_errno, &to->si_errno);
+       err |= __put_user((short)from->si_code, &to->si_code);
+       if (from->si_code < 0)
+               err |= __copy_to_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE);
+       else {
+               switch (from->si_code >> 16) {
+               case __SI_CHLD >> 16:
+                       err |= __put_user(from->si_utime, &to->si_utime);
+                       err |= __put_user(from->si_stime, &to->si_stime);
+                       err |= __put_user(from->si_status, &to->si_status);
+               default:
+                       err |= __put_user(from->si_pid, &to->si_pid);
+                       err |= __put_user(from->si_uid, &to->si_uid);
+                       break;
+               case __SI_FAULT >> 16:
+                       err |= __put_user((long)from->si_addr, &to->si_addr);
+                       break;
+               case __SI_POLL >> 16:
+                       err |= __put_user(from->si_band, &to->si_band);
+                       err |= __put_user(from->si_fd, &to->si_fd);
+                       break;
+               /* case __SI_RT: This is not generated by the kernel as of now.  */
+               }
+       }
+       return err;
+}
+
 asmlinkage void sys32_sigreturn(abi64_no_regargs, struct pt_regs regs)
 {
        struct sigframe *frame;
@@ -405,11 +447,11 @@ badframe:

 asmlinkage void sys32_rt_sigreturn(abi64_no_regargs, struct pt_regs regs)
 {
-       struct rt_sigframe *frame;
+       struct rt_sigframe32 *frame;
        sigset_t set;
        stack_t st;

-       frame = (struct rt_sigframe *) regs.regs[29];
+       frame = (struct rt_sigframe32 *) regs.regs[29];
        if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
                goto badframe;
        if (__copy_from_user(&set, &frame->rs_uc.uc_sigmask, sizeof(set)))
@@ -588,7 +630,7 @@ static void inline setup_rt_frame(struct
                                  struct pt_regs *regs, int signr,
                                  sigset_t *set, siginfo_t *info)
 {
-       struct rt_sigframe *frame;
+       struct rt_sigframe32 *frame;
        int err = 0;

        frame = get_sigframe(ka, regs, sizeof(*frame));
@@ -613,8 +655,8 @@ static void inline setup_rt_frame(struct
                flush_cache_sigtramp((unsigned long) frame->rs_code);
        }

-       /* Create siginfo.  */
-       err |= __copy_to_user(&frame->rs_info, info, sizeof(*info));
+       /* Convert (siginfo_t -> siginfo_t32) and copy to user. */
+       err |= copy_siginfo_to_user32(&frame->rs_info, info);

        /* Create the ucontext.  */
        err |= __put_user(0, &frame->rs_uc.uc_flags);
@@ -639,7 +681,7 @@ static void inline setup_rt_frame(struct
         *   a2 = pointer to ucontext
         *
         * $25 and c0_epc point to the signal handler, $29 points to
-        * the struct rt_sigframe.
+        * the struct rt_sigframe32.
         */
        regs->regs[ 4] = signr;
        regs->regs[ 5] = (unsigned long) &frame->rs_info;
diff -up --recursive --new-file linux-mips-2.4.19-rc1-20020807.macro/include/asm-mips64/siginfo.h linux-mips-2.4.19-rc1-20020807/include/asm-mips64/siginfo.h
--- linux-mips-2.4.19-rc1-20020807.macro/include/asm-mips64/siginfo.h   2002-08-06 02:58:32.000000000 +0000
+++ linux-mips-2.4.19-rc1-20020807/include/asm-mips64/siginfo.h 2002-08-08 07:14:29.000000000 +0000
@@ -18,11 +18,21 @@ typedef union sigval {
        void *sival_ptr;
 } sigval_t;

+#ifdef __KERNEL__
+
+typedef union sigval32 {
+       int sival_int;
+       s32 sival_ptr;
+} sigval_t32;
+
+#endif /* __KERNEL__ */
+
 /* This structure matches IRIX 32/n32 ABIs for binary compatibility but
    has Linux extensions.  */

 #define SI_MAX_SIZE    128
-#define SI_PAD_SIZE    ((SI_MAX_SIZE/sizeof(int)) - 3)
+#define SI_PAD_SIZE    ((SI_MAX_SIZE/sizeof(int)) - 4)
+#define SI_PAD_SIZE32  ((SI_MAX_SIZE/sizeof(int)) - 3)

 typedef struct siginfo {
        int si_signo;
@@ -82,6 +92,68 @@ typedef struct siginfo {
        } _sifields;
 } siginfo_t;

+#ifdef __KERNEL__
+
+typedef struct siginfo32 {
+       int si_signo;
+       int si_code;
+       int si_errno;
+
+       union {
+               int _pad[SI_PAD_SIZE32];
+
+               /* kill() */
+               struct {
+                       __kernel_pid_t32 _pid;  /* sender's pid */
+                       __kernel_uid_t32 _uid;  /* sender's uid */
+               } _kill;
+
+               /* SIGCHLD */
+               struct {
+                       __kernel_pid_t32 _pid;  /* which child */
+                       __kernel_uid_t32 _uid;  /* sender's uid */
+                       __kernel_clock_t32 _utime;
+                       int _status;            /* exit code */
+                       __kernel_clock_t32 _stime;
+               } _sigchld;
+
+               /* IRIX SIGCHLD */
+               struct {
+                       __kernel_pid_t32 _pid;  /* which child */
+                       __kernel_clock_t32 _utime;
+                       int _status;            /* exit code */
+                       __kernel_clock_t32 _stime;
+               } _irix_sigchld;
+
+               /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
+               struct {
+                       s32 _addr; /* faulting insn/memory ref. */
+               } _sigfault;
+
+               /* SIGPOLL, SIGXFSZ (To do ...)  */
+               struct {
+                       int _band;      /* POLL_IN, POLL_OUT, POLL_MSG */
+                       int _fd;
+               } _sigpoll;
+
+               /* POSIX.1b timers */
+               struct {
+                       unsigned int _timer1;
+                       unsigned int _timer2;
+               } _timer;
+
+               /* POSIX.1b signals */
+               struct {
+                       __kernel_pid_t32 _pid;  /* sender's pid */
+                       __kernel_uid_t32 _uid;  /* sender's uid */
+                       sigval_t32 _sigval;
+               } _rt;
+
+       } _sifields;
+} siginfo_t32;
+
+#endif /* __KERNEL__ */
+
 /*
  * How these fields are to be accessed.
  */
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help