"Maciej W. Rozycki" wrote:
> On Wed, 7 Aug 2002, Maciej W. Rozycki wrote:
>
> > 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 ?
>
> 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.
> */
|