From: Peter Watkins <treestem@gmail.com>
To: linux-mips@linux-mips.org
Subject: [PATCH] Use compat code to translate siginfo_t for N32
Date: Thu, 27 Jul 2006 19:44:42 -0400 [thread overview]
Message-ID: <44C94FEA.1010607@gmail.com> (raw)
[-- Attachment #1: Type: text/plain, Size: 242 bytes --]
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.
[-- Attachment #2: patch-siginfo-2.6.18-rc1 --]
[-- Type: text/plain, Size: 11904 bytes --]
From: Peter Watkins <treestem@gmail.com>
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(-)
diff --git a/arch/mips/kernel/Makefile b/arch/mips/kernel/Makefile
index 881c467..108171a 100644
--- a/arch/mips/kernel/Makefile
+++ b/arch/mips/kernel/Makefile
@@ -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
diff --git a/arch/mips/kernel/compat32.c b/arch/mips/kernel/compat32.c
new file mode 100644
index 0000000..858f7db
--- /dev/null
+++ b/arch/mips/kernel/compat32.c
@@ -0,0 +1,88 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ * Copyright (C) 1994 - 2000 Ralf Baechle
+ * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
+ */
+#include <linux/cache.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#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>
+#include <linux/compat.h>
+#include <linux/suspend.h>
+#include <linux/compiler.h>
+
+#include <asm/abi.h>
+#include <asm/asm.h>
+#include <linux/bitops.h>
+#include <asm/sim.h>
+#include <asm/uaccess.h>
+#include <asm/ucontext.h>
+#include <asm/system.h>
+#include <asm/fpu.h>
+#include <asm/war.h>
+
+#include "compat32.h"
+
+
+int copy_siginfo_to_user32(compat_siginfo_t *to, siginfo_t *from)
+{
+ int err;
+
+ if (!access_ok (VERIFY_WRITE, to, sizeof(compat_siginfo_t)))
+ 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_TIMER >> 16:
+ err |= __put_user(from->si_tid, &to->si_tid);
+ err |= __put_user(from->si_overrun, &to->si_overrun);
+ err |= __put_user(from->si_int, &to->si_int);
+ break;
+ 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 >> 16: /* This is not generated by the kernel as of now. */
+ case __SI_MESGQ >> 16:
+ err |= __put_user(from->si_pid, &to->si_pid);
+ err |= __put_user(from->si_uid, &to->si_uid);
+ err |= __put_user(from->si_int, &to->si_int);
+ break;
+ }
+ }
+ return err;
+}
diff --git a/arch/mips/kernel/compat32.h b/arch/mips/kernel/compat32.h
new file mode 100644
index 0000000..e2bb23b
--- /dev/null
+++ b/arch/mips/kernel/compat32.h
@@ -0,0 +1,76 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ * Copyright (C) 1994 - 2000 Ralf Baechle
+ * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
+ */
+
+#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;
+
+
+
+int copy_siginfo_to_user32(compat_siginfo_t *to, siginfo_t *from);
+
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/signal32.c b/arch/mips/kernel/signal32.c
index f32a229..2ba8c53 100644
--- a/arch/mips/kernel/signal32.c
+++ b/arch/mips/kernel/signal32.c
@@ -411,58 +411,6 @@ #if ICACHE_REFILLS_WORKAROUND_WAR
#endif
};
-int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from)
-{
- int err;
-
- if (!access_ok (VERIFY_WRITE, to, sizeof(compat_siginfo_t)))
- 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_TIMER >> 16:
- err |= __put_user(from->si_tid, &to->si_tid);
- err |= __put_user(from->si_overrun, &to->si_overrun);
- err |= __put_user(from->si_int, &to->si_int);
- break;
- 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((unsigned 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 >> 16: /* This is not generated by the kernel as of now. */
- case __SI_MESGQ >> 16:
- err |= __put_user(from->si_pid, &to->si_pid);
- err |= __put_user(from->si_uid, &to->si_uid);
- err |= __put_user(from->si_int, &to->si_int);
- break;
- }
- }
- return err;
-}
-
save_static_function(sys32_sigreturn);
__attribute_used__ noinline static void
_sys32_sigreturn(nabi_no_regargs struct pt_regs regs)
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
@@ -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_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 +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);
+}
--
1.4.1
next reply other threads:[~2006-07-27 23:44 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2006-07-27 23:44 Peter Watkins [this message]
2006-07-28 1:44 ` [PATCH] Use compat code to translate siginfo_t for N32 Yoichi Yuasa
2006-07-28 17:00 ` Peter Watkins
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=44C94FEA.1010607@gmail.com \
--to=treestem@gmail.com \
--cc=linux-mips@linux-mips.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.