Hello Yoichi, The attached patch addresses your points, and ends up cleaner and simpler. Except:
> diff --git a/arch/mips/kernel/signal_n32.c b/arch/mips/kernel/signal_n32.c > index 477c533..f805bea 100644 > --- a/arch/mips/kernel/signal_n32.c > +++ b/arch/mips/kernel/signal_n32.c <snip> > @@ -74,7 +76,7 @@ #if ICACHE_REFILLS_WORKAROUND_WAR > #else > u32 rs_code[2]; /* signal trampoline */ > #endif > - struct siginfo rs_info; > + compat_siginfo_t rs_info; use struct compat_siginfo .
I did not change this as it's currently consistent with the form used in signal32.c and signal_n32.c. If we want to change this, it seemed preferable to have another patch for just that purpose. - Peter
From 214005a395dd08a209f2ec2d9c03cd00038ec783 Mon Sep 17 00:00:00 2001 From: Peter Watkins <treestem@xxxxxxxxx> Date: Fri, 28 Jul 2006 12:15:52 -0400 Subject: [PATCH] Fix incorrect data returned from waitid() for mips64el N32. Use compat code to translate siginfo_t for N32. --- arch/mips/kernel/linux32.c | 28 ---------------- arch/mips/kernel/signal-common.h | 65 ++++++++++++++++++++++++++++++++++++++ arch/mips/kernel/signal_n32.c | 36 +++++++++++++++++++-- 3 files changed, 98 insertions(+), 31 deletions(-) diff --git a/arch/mips/kernel/linux32.c b/arch/mips/kernel/linux32.c index 450ac59..dd71096 100644 --- a/arch/mips/kernel/linux32.c +++ b/arch/mips/kernel/linux32.c @@ -163,34 +163,6 @@ out: return error; } -asmlinkage long -sysn32_waitid(int which, compat_pid_t pid, - siginfo_t __user *uinfo, int options, - struct compat_rusage __user *uru) -{ - struct rusage ru; - long ret; - mm_segment_t old_fs = get_fs(); - int si_signo; - - if (!access_ok(VERIFY_WRITE, uinfo, sizeof(*uinfo))) - return -EFAULT; - - set_fs (KERNEL_DS); - ret = sys_waitid(which, pid, uinfo, options, - uru ? (struct rusage __user *) &ru : NULL); - set_fs (old_fs); - - if (__get_user(si_signo, &uinfo->si_signo)) - return -EFAULT; - if (ret < 0 || si_signo == 0) - return ret; - - if (uru) - ret = put_compat_rusage(&ru, uru); - return ret; -} - struct sysinfo32 { s32 uptime; u32 loads[3]; diff --git a/arch/mips/kernel/signal-common.h b/arch/mips/kernel/signal-common.h index b1f09d5..d4a80e7 100644 --- a/arch/mips/kernel/signal-common.h +++ b/arch/mips/kernel/signal-common.h @@ -8,6 +8,7 @@ * Copyright (C) 1999, 2000 Silicon Graphics, Inc. */ +#include <linux/compat.h> static inline int setup_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc) @@ -174,3 +175,67 @@ static inline int install_sigtramp(unsig return err; } + + +#define SI_PAD_SIZE32 ((SI_MAX_SIZE/sizeof(int)) - 3) + +typedef struct compat_siginfo { + int si_signo; + int si_code; + int si_errno; + + union { + int _pad[SI_PAD_SIZE32]; + + /* kill() */ + struct { + compat_pid_t _pid; /* sender's pid */ + compat_uid_t _uid; /* sender's uid */ + } _kill; + + /* SIGCHLD */ + struct { + compat_pid_t _pid; /* which child */ + compat_uid_t _uid; /* sender's uid */ + int _status; /* exit code */ + compat_clock_t _utime; + compat_clock_t _stime; + } _sigchld; + + /* IRIX SIGCHLD */ + struct { + compat_pid_t _pid; /* which child */ + compat_clock_t _utime; + int _status; /* exit code */ + compat_clock_t _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 { + timer_t _tid; /* timer id */ + int _overrun; /* overrun count */ + compat_sigval_t _sigval;/* same as below */ + int _sys_private; /* not to be passed to user */ + } _timer; + + /* POSIX.1b signals */ + struct { + compat_pid_t _pid; /* sender's pid */ + compat_uid_t _uid; /* sender's uid */ + compat_sigval_t _sigval; + } _rt; + + } _sifields; +} compat_siginfo_t; + diff --git a/arch/mips/kernel/signal_n32.c b/arch/mips/kernel/signal_n32.c index 477c533..394d4c6 100644 --- a/arch/mips/kernel/signal_n32.c +++ b/arch/mips/kernel/signal_n32.c @@ -23,6 +23,7 @@ #include <linux/smp.h> #include <linux/smp_lock.h> #include <linux/kernel.h> #include <linux/signal.h> +#include <linux/syscalls.h> #include <linux/errno.h> #include <linux/wait.h> #include <linux/ptrace.h> @@ -74,7 +75,7 @@ #if ICACHE_REFILLS_WORKAROUND_WAR #else u32 rs_code[2]; /* signal trampoline */ #endif - struct siginfo rs_info; + compat_siginfo_t rs_info; struct ucontextn32 rs_uc; #if ICACHE_REFILLS_WORKAROUND_WAR u32 rs_code[8] ____cacheline_aligned; /* signal trampoline */ @@ -180,7 +181,7 @@ int setup_rt_frame_n32(struct k_sigactio install_sigtramp(frame->rs_code, __NR_N32_rt_sigreturn); /* Create siginfo. */ - err |= copy_siginfo_to_user(&frame->rs_info, info); + err |= copy_siginfo_to_user32(&frame->rs_info, info); /* Create the ucontext. */ err |= __put_user(0, &frame->rs_uc.uc_flags); @@ -215,7 +216,7 @@ int setup_rt_frame_n32(struct k_sigactio regs->regs[31] = (unsigned long) frame->rs_code; regs->cp0_epc = regs->regs[25] = (unsigned long) ka->sa.sa_handler; -#if DEBUG_SIG +#ifdef DEBUG_SIG printk("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%p\n", current->comm, current->pid, frame, regs->cp0_epc, regs->regs[31]); @@ -226,3 +227,32 @@ give_sigsegv: force_sigsegv(signr, current); return -EFAULT; } + + + +asmlinkage long +sysn32_waitid(int which, compat_pid_t pid, + compat_siginfo_t __user *uinfo, int options, + struct compat_rusage __user *uru) +{ + siginfo_t info; + struct rusage ru; + long ret; + mm_segment_t old_fs = get_fs(); + + info.si_signo = 0; + set_fs (KERNEL_DS); + ret = sys_waitid(which, pid, (siginfo_t __user *) &info, options, + uru ? (struct rusage __user *) &ru : NULL); + set_fs (old_fs); + + if (ret < 0 || info.si_signo == 0) + return ret; + + if (uru && (ret = put_compat_rusage(&ru, uru))) + return ret; + + BUG_ON(info.si_code & __SI_MASK); + info.si_code |= __SI_CHLD; + return copy_siginfo_to_user32(uinfo, &info); +} -- 1.4.1