Skip to contentSkip to conversation

Use compat code to translate siginfo_t for N32

PATCH In review Peter Watkins 2 participants 3 messages Jul 27, 2006 – Jul 28, 2006 MIPS

lore
Share & tools
lore
#0 lore raw

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
index 881c467..108171a 100644
@@ -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
index 450ac59..dd71096 100644
@@ -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
index 477c533..f805bea 100644
@@ -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);
+}
Signature · 1 line
1.4.1
#1 lore raw

Hi,

arch/mips/kernel/Makefile obj-$(CONFIG_32BIT) += scall32-o32.o · line 60

Quoted 12 lines
arch/mips/kernel/Makefile +2 -2
index 881c467..108171a 100644
@@ -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
new file mode 100644
index 0000000..858f7db

<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
new file mode 100644
index 0000000..e2bb23b
@@ -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
index 477c533..f805bea 100644

<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

#2 lore raw

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
index 477c533..f805bea 100644

<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
index 450ac59..dd71096 100644
@@ -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
index 477c533..394d4c6 100644
@@ -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);
+}
Signature · 1 line
1.4.1