Use compat code to translate siginfo_t for N32
PATCH 1/1 Use compat code to translate siginfo_t for N32
This patch fixes incorrect data returned from waitid() for mips64el N32. It uses compat code to translate siginfo_t for N32, and factors out common O32 and N32 compat code for siginfo_t, to compat32.c. Tested on glibc suite and LTP.
From: Peter Watkins <[email protected]>
Date: Thu, 27 Jul 2006 19:13:09 -0400
Subject: Use compat code to translate siginfo_t for N32.
Use compat code to translate siginfo_t for N32.
Factor out common O32 and N32 compat code for siginfo_t, to compat32.c.
--- arch/mips/kernel/Makefile | 4 +- arch/mips/kernel/compat32.c | 88 +++++++++++++++++++++++++++++++++++++++++ arch/mips/kernel/compat32.h | 76 +++++++++++++++++++++++++++++++++++ arch/mips/kernel/linux32.c | 28 ------------- arch/mips/kernel/signal32.c | 52 ------------------------ arch/mips/kernel/signal_n32.c | 37 ++++++++++++++++- 6 files changed, 200 insertions(+), 85 deletions(-)
arch/mips/kernel/Makefile +2 -2
@@ -56,8 +56,8 @@ obj-$(CONFIG_32BIT) += scall32-o32.o obj-$(CONFIG_64BIT) += scall64-64.o obj-$(CONFIG_BINFMT_IRIX) += binfmt_irix.o obj-$(CONFIG_MIPS32_COMPAT) += linux32.o signal32.o -obj-$(CONFIG_MIPS32_N32) += binfmt_elfn32.o scall64-n32.o signal_n32.o -obj-$(CONFIG_MIPS32_O32) += binfmt_elfo32.o scall64-o32.o ptrace32.o +obj-$(CONFIG_MIPS32_N32) += binfmt_elfn32.o scall64-n32.o signal_n32.o compat32.o +obj-$(CONFIG_MIPS32_O32) += binfmt_elfo32.o scall64-o32.o ptrace32.o compat32.o obj-$(CONFIG_KGDB) += gdb-low.o gdb-stub.o obj-$(CONFIG_PROC_FS) += proc.o
arch/mips/kernel/compat32.c new file +88 -0
88 lines not on this page · raw message
arch/mips/kernel/compat32.h new file +76 -0
76 lines not on this page · raw message
arch/mips/kernel/linux32.c +0 -28
@@ -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 ];
arch/mips/kernel/signal32.c +0 -52
58 lines not on this page · raw message
arch/mips/kernel/signal_n32.c +34 -3
@@ -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>
@@ -41,6 +42,7 @@ #include <asm/cpu-features.h>#include <asm/war.h> #include "signal-common.h" +#include "compat32.h" /* * Including <asm/unistd.h> would give use the 64-bit syscall numbers ...
@@ -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;struct ucontextn32 rs_uc;#if ICACHE_REFILLS_WORKAROUND_WAR u32 rs_code[8 ]____cacheline_aligned ;/* signal trampoline */
@@ -180,7 +182,7 @@ int setup_rt_frame_n32(struct k_sigactioinstall_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 +217,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 +228,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); +}
Signature · 1 line
1.4.1
Hi,
arch/mips/kernel/Makefile obj-$(CONFIG_32BIT) += scall32-o32.o · line 60
Quoted 12 lines
arch/mips/kernel/Makefile +2
-2@@ -56,8 +56,8 @@ obj-$(CONFIG_32BIT) += scall32-o32.o obj-$(CONFIG_64BIT) += scall64-64.o obj-$(CONFIG_BINFMT_IRIX) += binfmt_irix.o obj-$(CONFIG_MIPS32_COMPAT) += linux32.o signal32.o -obj-$(CONFIG_MIPS32_N32) += binfmt_elfn32.o scall64-n32.o signal_n32.o -obj-$(CONFIG_MIPS32_O32) += binfmt_elfo32.o scall64-o32.o ptrace32.o +obj-$(CONFIG_MIPS32_N32) += binfmt_elfn32.o scall64-n32.o signal_n32.o compat32.o +obj-$(CONFIG_MIPS32_O32) += binfmt_elfo32.o scall64-o32.o ptrace32.o compat32.o
Why do you separate comapt32.o ?
Quoted 5 lines
arch/mips/kernel/compat32.c new file +0
-0
<snip>
Quoted 1 line
+int
copy_siginfo_to_user32(compat_siginfo_t *to, siginfo_t *from)
see include/linux/compat.h .
int copy_siginfo_to_user32(struct compat_siginfo __user *to, siginfo_t *from);
Quoted 6 lines
arch/mips/kernel/compat32.h new file +0
-0@@ -0,0 +1,76 @@
<snip>
Quoted 1 line
+int
copy_siginfo_to_user32(compat_siginfo_t *to, siginfo_t *from);
It's already defined in include/linux/compat.h .
Quoted 4 lines
arch/mips/kernel/signal_n32.c +0
-0
<snip>
arch/mips/kernel/signal_n32.c #if ICACHE_REFILLS_WORKAROUND_WAR · line 79
Quoted 6 lines
arch/mips/kernel/signal_n32.c +1
-1@@ -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 .
Yoichi
Hello Yoichi,
The attached patch addresses your points, and ends up cleaner and simpler. Except:
Quoted 7 lines
Quoted 4 lines
arch/mips/kernel/signal_n32.c +0
-0<snip>
Quoted 9 lines
arch/mips/kernel/signal_n32.c #if ICACHE_REFILLS_WORKAROUND_WAR · line 79
Quoted 6 lines
arch/mips/kernel/signal_n32.c +1
-1@@ -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 <[email protected]>
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(-)
arch/mips/kernel/linux32.c +0 -28
@@ -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 ];
arch/mips/kernel/signal-common.h +65 -0
74 lines not on this page · raw message
arch/mips/kernel/signal_n32.c +33 -3
@@ -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_sigactioinstall_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); +}
Signature · 1 line
1.4.1