public inbox for linux-arch@vger.kernel.org
 help / color / mirror / Atom feed
* Generic compat_sys_rt_sigqueueinfo
@ 2006-10-28 22:37 Kyle McMartin
  2006-10-28 22:47 ` Matthew Wilcox
                   ` (2 more replies)
  0 siblings, 3 replies; 11+ messages in thread
From: Kyle McMartin @ 2006-10-28 22:37 UTC (permalink / raw)
  To: akpm; +Cc: linux-arch

Every 32-on-64 arch (except parisc) was implementing effectively the
same sys32_rt_sigqueueinfo. Add a generic implementation taken from
x86_64 and add it to kernel/compat.c, which required the addition of
copy_siginfo_from_user32 on mips and powerpc. sparc64 had a sufficient
implementation for this purpose, so crib it for both those platforms.

This yields a nice clean up and is one step towards cleaning up some
of the compat signals mess parisc has been carrying out of tree for a few
years.

Signed-off-by: Kyle McMartin <kyle@parisc-linux.org>
--
[N.B. the modification to powerpc is probably wrong, since it seems
 to require a wrapper for handling the signed ints like sparc64 and s390
 have. -- Kyle]

 arch/ia64/ia32/ia32_entry.S        |    2 +-
 arch/ia64/ia32/ia32_signal.c       |   15 ---------------
 arch/mips/kernel/scall64-n32.S     |    2 +-
 arch/mips/kernel/scall64-o32.S     |    2 +-
 arch/mips/kernel/signal32.c        |   31 ++++++++++++++++---------------
 arch/parisc/kernel/syscall_table.S |    2 +-
 arch/powerpc/kernel/signal_32.c    |   33 +++++++++++++--------------------
 arch/s390/kernel/compat_linux.c    |   15 ---------------
 arch/s390/kernel/compat_wrapper.S  |    2 +-
 arch/sparc64/kernel/sys_sparc32.c  |   16 ----------------
 arch/x86_64/ia32/ia32entry.S       |    2 +-
 arch/x86_64/ia32/sys_ia32.c        |   15 ---------------
 kernel/compat.c                    |   17 +++++++++++++++++
 13 files changed, 52 insertions(+), 102 deletions(-)

diff --git a/arch/ia64/ia32/ia32_entry.S b/arch/ia64/ia32/ia32_entry.S
index a32cd59..8d41c2c 100644
--- a/arch/ia64/ia32/ia32_entry.S
+++ b/arch/ia64/ia32/ia32_entry.S
@@ -388,7 +388,7 @@ ia32_syscall_table:
 	data8 sys32_rt_sigprocmask /* 175 */
 	data8 sys_rt_sigpending
 	data8 compat_sys_rt_sigtimedwait
-	data8 sys32_rt_sigqueueinfo
+	data8 compat_sys_rt_sigqueueinfo
 	data8 sys32_rt_sigsuspend
 	data8 sys32_pread	  /* 180 */
 	data8 sys32_pwrite
diff --git a/arch/ia64/ia32/ia32_signal.c b/arch/ia64/ia32/ia32_signal.c
index b3355a9..00341ff 100644
--- a/arch/ia64/ia32/ia32_signal.c
+++ b/arch/ia64/ia32/ia32_signal.c
@@ -588,21 +588,6 @@ sys32_rt_sigprocmask (int how, compat_si
 }
 
 asmlinkage long
-sys32_rt_sigqueueinfo (int pid, int sig, compat_siginfo_t __user *uinfo)
-{
-	mm_segment_t old_fs = get_fs();
-	siginfo_t info;
-	int ret;
-
-	if (copy_siginfo_from_user32(&info, uinfo))
-		return -EFAULT;
-	set_fs(KERNEL_DS);
-	ret = sys_rt_sigqueueinfo(pid, sig, (siginfo_t __user *) &info);
-	set_fs(old_fs);
-	return ret;
-}
-
-asmlinkage long
 sys32_sigaction (int sig, struct old_sigaction32 __user *act, struct old_sigaction32 __user *oact)
 {
 	struct k_sigaction new_ka, old_ka;
diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S
index 67b92a1..013efe9 100644
--- a/arch/mips/kernel/scall64-n32.S
+++ b/arch/mips/kernel/scall64-n32.S
@@ -247,7 +247,7 @@ EXPORT(sysn32_call_table)
 	PTR	sys_capset
 	PTR	sys32_rt_sigpending		/* 6125 */
 	PTR	compat_sys_rt_sigtimedwait
-	PTR	sys32_rt_sigqueueinfo
+	PTR	compat_sys_rt_sigqueueinfo
 	PTR	sysn32_rt_sigsuspend
 	PTR	sys32_sigaltstack
 	PTR	compat_sys_utime		/* 6130 */
diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S
index 2875c4a..e9bc5a6 100644
--- a/arch/mips/kernel/scall64-o32.S
+++ b/arch/mips/kernel/scall64-o32.S
@@ -403,7 +403,7 @@ sys_call_table:
 	PTR	sys32_rt_sigprocmask 		/* 4195 */
 	PTR	sys32_rt_sigpending
 	PTR	compat_sys_rt_sigtimedwait
-	PTR	sys32_rt_sigqueueinfo
+	PTR	compat_sys_rt_sigqueueinfo
 	PTR	sys32_rt_sigsuspend
 	PTR	sys32_pread			/* 4200 */
 	PTR	sys32_pwrite
diff --git a/arch/mips/kernel/signal32.c b/arch/mips/kernel/signal32.c
index c86a5dd..b680e7d 100644
--- a/arch/mips/kernel/signal32.c
+++ b/arch/mips/kernel/signal32.c
@@ -463,6 +463,22 @@ int copy_siginfo_to_user32(compat_siginf
 	return err;
 }
 
+/* CAUTION: This is just a very minimalist implementation for the
+ *	    sake of compat_sys_rt_sigqueueinfo(), cribbed from sparc64.
+ */
+int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
+{
+	if (!access_ok(VERIFY_WRITE, from, sizeof(compat_siginfo_t)))
+		return -EFAULT;
+
+	if (copy_from_user(to, from, 3*sizeof(int)) ||
+	    copy_from_user(to->_sifields._pad, from->_sifields._pad,
+			   SI_PAD_SIZE))
+		return -EFAULT;
+
+	return 0;
+}
+
 save_static_function(sys32_sigreturn);
 __attribute_used__ noinline static void
 _sys32_sigreturn(nabi_no_regargs struct pt_regs regs)
@@ -950,21 +966,6 @@ asmlinkage int sys32_rt_sigpending(compa
 	return ret;
 }
 
-asmlinkage int sys32_rt_sigqueueinfo(int pid, int sig, compat_siginfo_t __user *uinfo)
-{
-	siginfo_t info;
-	int ret;
-	mm_segment_t old_fs = get_fs();
-
-	if (copy_from_user (&info, uinfo, 3*sizeof(int)) ||
-	    copy_from_user (info._sifields._pad, uinfo->_sifields._pad, SI_PAD_SIZE))
-		return -EFAULT;
-	set_fs (KERNEL_DS);
-	ret = sys_rt_sigqueueinfo(pid, sig, (siginfo_t __user *)&info);
-	set_fs (old_fs);
-	return ret;
-}
-
 asmlinkage long
 sys32_waitid(int which, compat_pid_t pid,
 	     compat_siginfo_t __user *uinfo, int options,
diff --git a/arch/parisc/kernel/syscall_table.S b/arch/parisc/kernel/syscall_table.S
index 701d66a..c91605b 100644
--- a/arch/parisc/kernel/syscall_table.S
+++ b/arch/parisc/kernel/syscall_table.S
@@ -282,7 +282,7 @@ #endif
 	 * to worry about faulting trying to copy in a larger 64-bit
 	 * struct from a 32-bit user-space app.
 	 */
-	ENTRY_SAME(rt_sigqueueinfo)
+	ENTRY_COMP(rt_sigqueueinfo)
 	ENTRY_SAME(rt_sigsuspend_wrapper) /* not really SAME -- see the code */
 	ENTRY_SAME(chown)		/* 180 */
 	/* setsockopt() used by iptables: SO_SET_REPLACE/SO_SET_ADD_COUNTERS */
diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c
index 320353f..6bdc1a4 100644
--- a/arch/powerpc/kernel/signal_32.c
+++ b/arch/powerpc/kernel/signal_32.c
@@ -573,7 +573,6 @@ long compat_sys_rt_sigpending(compat_sig
 	return ret;
 }
 
-
 int copy_siginfo_to_user32(struct compat_siginfo __user *d, siginfo_t *s)
 {
 	int err;
@@ -629,30 +628,24 @@ int copy_siginfo_to_user32(struct compat
 	return err;
 }
 
-#define copy_siginfo_to_user	copy_siginfo_to_user32
-
-/*
- * Note: it is necessary to treat pid and sig as unsigned ints, with the
- * corresponding cast to a signed int to insure that the proper conversion
- * (sign extension) between the register representation of a signed int
- * (msr in 32-bit mode) and the register representation of a signed int
- * (msr in 64-bit mode) is performed.
+/* CAUTION: This is just a very minimalist implementation for the
+ *	    sake of compat_sys_rt_sigqueueinfo(), cribbed from sparc64.
  */
-long compat_sys_rt_sigqueueinfo(u32 pid, u32 sig, compat_siginfo_t __user *uinfo)
+int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
 {
-	siginfo_t info;
-	int ret;
-	mm_segment_t old_fs = get_fs();
+	if (!access_ok(VERIFY_WRITE, from, sizeof(compat_siginfo_t)))
+		return -EFAULT;
 
-	if (copy_from_user (&info, uinfo, 3*sizeof(int)) ||
-	    copy_from_user (info._sifields._pad, uinfo->_sifields._pad, SI_PAD_SIZE32))
+	if (copy_from_user(to, from, 3*sizeof(int)) ||
+	    copy_from_user(to->_sifields._pad, from->_sifields._pad,
+			   SI_PAD_SIZE))
 		return -EFAULT;
-	set_fs (KERNEL_DS);
-	/* The __user pointer cast is valid becasuse of the set_fs() */
-	ret = sys_rt_sigqueueinfo((int)pid, (int)sig, (siginfo_t __user *) &info);
-	set_fs (old_fs);
-	return ret;
+
+	return 0;
 }
+
+#define copy_siginfo_to_user	copy_siginfo_to_user32
+
 /*
  *  Start Alternate signal stack support
  *
diff --git a/arch/s390/kernel/compat_linux.c b/arch/s390/kernel/compat_linux.c
index 2001767..7566d07 100644
--- a/arch/s390/kernel/compat_linux.c
+++ b/arch/s390/kernel/compat_linux.c
@@ -514,21 +514,6 @@ asmlinkage long sys32_rt_sigpending(comp
 	return ret;
 }
 
-asmlinkage long
-sys32_rt_sigqueueinfo(int pid, int sig, compat_siginfo_t __user *uinfo)
-{
-	siginfo_t info;
-	int ret;
-	mm_segment_t old_fs = get_fs();
-	
-	if (copy_siginfo_from_user32(&info, uinfo))
-		return -EFAULT;
-	set_fs (KERNEL_DS);
-	ret = sys_rt_sigqueueinfo(pid, sig, (siginfo_t __user *) &info);
-	set_fs (old_fs);
-	return ret;
-}
-
 /*
  * sys32_execve() executes a new program after the asm stub has set
  * things up for us.  This should basically do what I want it to.
diff --git a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S
index cb0efae..251844c 100644
--- a/arch/s390/kernel/compat_wrapper.S
+++ b/arch/s390/kernel/compat_wrapper.S
@@ -857,7 +857,7 @@ sys32_rt_sigqueueinfo_wrapper:
 	lgfr	%r2,%r2			# int
 	lgfr	%r3,%r3			# int
 	llgtr	%r4,%r4			# siginfo_emu31_t *
-	jg	sys32_rt_sigqueueinfo	# branch to system call
+	jg	compat_sys_rt_sigqueueinfo	# branch to system call
 
 	.globl compat_sys_rt_sigsuspend_wrapper
 compat_sys_rt_sigsuspend_wrapper:
diff --git a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c
index e27cb71..16ff6ff 100644
--- a/arch/sparc64/kernel/sys_sparc32.c
+++ b/arch/sparc64/kernel/sys_sparc32.c
@@ -601,22 +601,6 @@ asmlinkage long sys32_rt_sigpending(comp
 	return ret;
 }
 
-asmlinkage long compat_sys_rt_sigqueueinfo(int pid, int sig,
-					   struct compat_siginfo __user *uinfo)
-{
-	siginfo_t info;
-	int ret;
-	mm_segment_t old_fs = get_fs();
-	
-	if (copy_siginfo_from_user32(&info, uinfo))
-		return -EFAULT;
-
-	set_fs (KERNEL_DS);
-	ret = sys_rt_sigqueueinfo(pid, sig, (siginfo_t __user *) &info);
-	set_fs (old_fs);
-	return ret;
-}
-
 asmlinkage long compat_sys_sigaction(int sig, struct old_sigaction32 __user *act,
 				     struct old_sigaction32 __user *oact)
 {
diff --git a/arch/x86_64/ia32/ia32entry.S b/arch/x86_64/ia32/ia32entry.S
index b4aa875..9fa991a 100644
--- a/arch/x86_64/ia32/ia32entry.S
+++ b/arch/x86_64/ia32/ia32entry.S
@@ -577,7 +577,7 @@ #endif
 	.quad sys32_rt_sigprocmask	/* 175 */
 	.quad sys32_rt_sigpending
 	.quad compat_sys_rt_sigtimedwait
-	.quad sys32_rt_sigqueueinfo
+	.quad compat_sys_rt_sigqueueinfo
 	.quad stub32_rt_sigsuspend
 	.quad sys32_pread		/* 180 */
 	.quad sys32_pwrite
diff --git a/arch/x86_64/ia32/sys_ia32.c b/arch/x86_64/ia32/sys_ia32.c
index c9bac3a..db10734 100644
--- a/arch/x86_64/ia32/sys_ia32.c
+++ b/arch/x86_64/ia32/sys_ia32.c
@@ -628,21 +628,6 @@ sys32_rt_sigpending(compat_sigset_t __us
 	return ret;
 }
 
-asmlinkage long
-sys32_rt_sigqueueinfo(int pid, int sig, compat_siginfo_t __user *uinfo)
-{
-	siginfo_t info;
-	int ret;
-	mm_segment_t old_fs = get_fs();
-	
-	if (copy_siginfo_from_user32(&info, uinfo))
-		return -EFAULT;
-	set_fs (KERNEL_DS);
-	ret = sys_rt_sigqueueinfo(pid, sig, (siginfo_t __user *)&info);
-	set_fs (old_fs);
-	return ret;
-}
-
 /* These are here just in case some old ia32 binary calls it. */
 asmlinkage long
 sys32_pause(void)
diff --git a/kernel/compat.c b/kernel/compat.c
index 75573e5..cc77247 100644
--- a/kernel/compat.c
+++ b/kernel/compat.c
@@ -837,6 +837,23 @@ compat_sys_rt_sigtimedwait (compat_sigse
 
 }
 
+asmlinkage long compat_sys_rt_sigqueueinfo(int pid, int sig,
+	struct compat_siginfo __user *uinfo)
+{
+	mm_segment_t old_fs = get_fs();
+	siginfo_t info;
+	int ret;
+
+	if (copy_siginfo_from_user32(&info, uinfo))
+		return -EFAULT;
+
+	set_fs(KERNEL_DS);
+	ret = sys_rt_sigqueueinfo(pid, sig, (siginfo_t __user *)&info);
+	set_fs(old_fs);
+
+	return ret;
+}
+
 #ifdef __ARCH_WANT_COMPAT_SYS_TIME
 
 /* compat_time_t is a 32 bit "long" and needs to get converted. */

^ permalink raw reply related	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2006-11-01 14:24 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-10-28 22:37 Generic compat_sys_rt_sigqueueinfo Kyle McMartin
2006-10-28 22:47 ` Matthew Wilcox
2006-10-28 22:53   ` Kyle McMartin
2006-10-28 23:09     ` Matthew Wilcox
2006-10-28 23:09 ` Arnd Bergmann
2006-10-28 23:12   ` Arnd Bergmann
2006-10-30 15:46   ` Kyle McMartin
2006-10-30 15:59 ` Kyle McMartin
2006-10-31  7:02   ` Andrew Morton
2006-11-01  7:23     ` Stephen Rothwell
2006-11-01 14:24       ` Kyle McMartin

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox