* Re: [PATCH]: Fix N32 sigsuspend syscall that causes non-fatal oopses
@ 2006-01-24 19:17 Kumba
2006-01-24 19:34 ` Daniel Jacobowitz
0 siblings, 1 reply; 4+ messages in thread
From: Kumba @ 2006-01-24 19:17 UTC (permalink / raw)
To: linux-mips
[-- Attachment #1: Type: text/plain, Size: 587 bytes --]
Fix to the sigsuspend syscall so N32 userlands work without triggering
non-fatal oopses. Patch was originally drafted by Daniel Jacobwitz.
Problem was originally discovered via a configure test in the glib
package. When run, the test triggered a segmentation fault and an
oops, as well as causing the test, and ultimately, configure, to fail.
Signed-off-by: Joshua Kinard <kumba@gentoo.org>
---
linux32.c | 19 -------------------
scall64-n32.S | 4 ++--
signal.c | 42 ++++++++++++++++++++++++++++++++++++++++++
3 files changed, 44 insertions(+), 21 deletions(-)
[-- Attachment #2: n32-fix-sigsuspend.patch --]
[-- Type: text/plain, Size: 3548 bytes --]
diff -Naurp mipslinux/arch/mips/kernel/linux32.c mipslinux-sigsuspend/arch/mips/kernel/linux32.c
--- mipslinux/arch/mips/kernel/linux32.c 2006-01-22 21:14:11.000000000 -0500
+++ mipslinux-sigsuspend/arch/mips/kernel/linux32.c 2006-01-24 13:39:37.000000000 -0500
@@ -1450,25 +1450,6 @@ sys32_timer_create(u32 clock, struct sig
return sys_timer_create(clock, p, timer_id);
}
-asmlinkage long
-sysn32_rt_sigtimedwait(const sigset_t __user *uthese,
- siginfo_t __user *uinfo,
- const struct compat_timespec __user *uts32,
- size_t sigsetsize)
-{
- struct timespec __user *uts = NULL;
-
- if (uts32) {
- struct timespec ts;
- uts = compat_alloc_user_space(sizeof(struct timespec));
- if (get_user(ts.tv_sec, &uts32->tv_sec) ||
- get_user(ts.tv_nsec, &uts32->tv_nsec) ||
- copy_to_user (uts, &ts, sizeof (ts)))
- return -EFAULT;
- }
- return sys_rt_sigtimedwait(uthese, uinfo, uts, sigsetsize);
-}
-
save_static_function(sys32_clone);
__attribute_used__ noinline static int
_sys32_clone(nabi_no_regargs struct pt_regs regs)
diff -Naurp mipslinux/arch/mips/kernel/scall64-n32.S mipslinux-sigsuspend/arch/mips/kernel/scall64-n32.S
--- mipslinux/arch/mips/kernel/scall64-n32.S 2006-01-22 21:14:11.000000000 -0500
+++ mipslinux-sigsuspend/arch/mips/kernel/scall64-n32.S 2006-01-24 13:39:37.000000000 -0500
@@ -245,9 +245,9 @@ EXPORT(sysn32_call_table)
PTR sys_capget
PTR sys_capset
PTR sys32_rt_sigpending /* 6125 */
- PTR sysn32_rt_sigtimedwait
+ PTR compat_sys_rt_sigtimedwait
PTR sys_rt_sigqueueinfo
- PTR sys32_rt_sigsuspend
+ PTR sysn32_rt_sigsuspend
PTR sys32_sigaltstack
PTR compat_sys_utime /* 6130 */
PTR sys_mknod
diff -Naurp mipslinux/arch/mips/kernel/signal.c mipslinux-sigsuspend/arch/mips/kernel/signal.c
--- mipslinux/arch/mips/kernel/signal.c 2006-01-22 21:14:11.000000000 -0500
+++ mipslinux-sigsuspend/arch/mips/kernel/signal.c 2006-01-24 13:39:37.000000000 -0500
@@ -21,6 +21,7 @@
#include <linux/ptrace.h>
#include <linux/unistd.h>
#include <linux/compiler.h>
+#include <linux/compat.h>
#include <asm/abi.h>
#include <asm/asm.h>
@@ -39,6 +40,10 @@
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
+#ifdef CONFIG_MIPS32_N32
+extern void sigset_from_compat (sigset_t *set, compat_sigset_t *compat);
+#endif
+
int do_signal(sigset_t *oldset, struct pt_regs *regs);
/*
@@ -109,6 +114,43 @@ _sys_rt_sigsuspend(nabi_no_regargs struc
}
}
+#ifdef CONFIG_MIPS32_N32
+save_static_function(sysn32_rt_sigsuspend);
+__attribute_used__ noinline static int
+_sysn32_rt_sigsuspend(nabi_no_regargs struct pt_regs regs)
+{
+ sigset_t saveset, newset;
+ compat_sigset_t __user *unewset, uset;
+ size_t sigsetsize;
+
+ /* XXX Don't preclude handling different sized sigset_t's. */
+ sigsetsize = regs.regs[5];
+ if (sigsetsize != sizeof(sigset_t))
+ return -EINVAL;
+
+ unewset = (compat_sigset_t __user *) regs.regs[4];
+ if (copy_from_user(&uset, unewset, sizeof(uset)))
+ return -EFAULT;
+ sigset_from_compat (&newset, &uset);
+ sigdelsetmask(&newset, ~_BLOCKABLE);
+
+ spin_lock_irq(¤t->sighand->siglock);
+ saveset = current->blocked;
+ current->blocked = newset;
+ recalc_sigpending();
+ spin_unlock_irq(¤t->sighand->siglock);
+
+ regs.regs[2] = EINTR;
+ regs.regs[7] = 1;
+ while (1) {
+ current->state = TASK_INTERRUPTIBLE;
+ schedule();
+ if (do_signal(&saveset, ®s))
+ return -EINTR;
+ }
+}
+#endif
+
#ifdef CONFIG_TRAD_SIGNALS
asmlinkage int sys_sigaction(int sig, const struct sigaction *act,
struct sigaction *oact)
^ permalink raw reply [flat|nested] 4+ messages in thread* Re: [PATCH]: Fix N32 sigsuspend syscall that causes non-fatal oopses
2006-01-24 19:17 [PATCH]: Fix N32 sigsuspend syscall that causes non-fatal oopses Kumba
@ 2006-01-24 19:34 ` Daniel Jacobowitz
2006-02-18 22:43 ` Ralf Baechle
0 siblings, 1 reply; 4+ messages in thread
From: Daniel Jacobowitz @ 2006-01-24 19:34 UTC (permalink / raw)
To: Kumba; +Cc: linux-mips
On Tue, Jan 24, 2006 at 07:17:41PM +0000, Kumba wrote:
> Fix to the sigsuspend syscall so N32 userlands work without triggering
> non-fatal oopses. Patch was originally drafted by Daniel Jacobwitz.
>
> Problem was originally discovered via a configure test in the glib
> package. When run, the test triggered a segmentation fault and an
> oops, as well as causing the test, and ultimately, configure, to fail.
>
> Signed-off-by: Joshua Kinard <kumba@gentoo.org>
> ---
>
> linux32.c | 19 -------------------
> scall64-n32.S | 4 ++--
> signal.c | 42 ++++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 44 insertions(+), 21 deletions(-)
If you're going to mess around with sigsuspend, there's a better option
now: take a look at the recently added TIF_RESTORE_SIGMASK (committed
last week).
Everyone really should migrate over to that approach; it fixes (among
other things) a nasty debugging corner case and some code duplication.
--
Daniel Jacobowitz
CodeSourcery
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH]: Fix N32 sigsuspend syscall that causes non-fatal oopses
2006-01-24 19:34 ` Daniel Jacobowitz
@ 2006-02-18 22:43 ` Ralf Baechle
0 siblings, 0 replies; 4+ messages in thread
From: Ralf Baechle @ 2006-02-18 22:43 UTC (permalink / raw)
To: Daniel Jacobowitz; +Cc: Kumba, linux-mips
On Tue, Jan 24, 2006 at 02:34:59PM -0500, Daniel Jacobowitz wrote:
> If you're going to mess around with sigsuspend, there's a better option
> now: take a look at the recently added TIF_RESTORE_SIGMASK (committed
> last week).
>
> Everyone really should migrate over to that approach; it fixes (among
> other things) a nasty debugging corner case and some code duplication.
The patch as posted doesn't even compile anymore. It was adding some
N32-specific stuff into signal.c where it has no business - there is
signal_n32.c after all. So if fixed those things also. New patch below.
Kumba, I'm going to check this patch in, can you test this asap please?
Thanks,
Ralf
diff --git a/arch/mips/kernel/linux32.c b/arch/mips/kernel/linux32.c
index 60353f5..9996b6e 100644
--- a/arch/mips/kernel/linux32.c
+++ b/arch/mips/kernel/linux32.c
@@ -1450,25 +1450,6 @@ sys32_timer_create(u32 clock, struct sig
return sys_timer_create(clock, p, timer_id);
}
-asmlinkage long
-sysn32_rt_sigtimedwait(const sigset_t __user *uthese,
- siginfo_t __user *uinfo,
- const struct compat_timespec __user *uts32,
- size_t sigsetsize)
-{
- struct timespec __user *uts = NULL;
-
- if (uts32) {
- struct timespec ts;
- uts = compat_alloc_user_space(sizeof(struct timespec));
- if (get_user(ts.tv_sec, &uts32->tv_sec) ||
- get_user(ts.tv_nsec, &uts32->tv_nsec) ||
- copy_to_user (uts, &ts, sizeof (ts)))
- return -EFAULT;
- }
- return sys_rt_sigtimedwait(uthese, uinfo, uts, sigsetsize);
-}
-
save_static_function(sys32_clone);
__attribute_used__ noinline static int
_sys32_clone(nabi_no_regargs struct pt_regs regs)
diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S
index bc4980c..d87b544 100644
--- a/arch/mips/kernel/scall64-n32.S
+++ b/arch/mips/kernel/scall64-n32.S
@@ -245,9 +245,9 @@ EXPORT(sysn32_call_table)
PTR sys_capget
PTR sys_capset
PTR sys32_rt_sigpending /* 6125 */
- PTR sysn32_rt_sigtimedwait
+ PTR compat_sys_rt_sigtimedwait
PTR sys_rt_sigqueueinfo
- PTR sys32_rt_sigsuspend
+ PTR sysn32_rt_sigsuspend
PTR sys32_sigaltstack
PTR compat_sys_utime /* 6130 */
PTR sys_mknod
diff --git a/arch/mips/kernel/signal_n32.c b/arch/mips/kernel/signal_n32.c
index 5a37760..3e168c0 100644
--- a/arch/mips/kernel/signal_n32.c
+++ b/arch/mips/kernel/signal_n32.c
@@ -81,6 +81,39 @@ struct rt_sigframe_n32 {
#endif
};
+extern void sigset_from_compat (sigset_t *set, compat_sigset_t *compat);
+
+save_static_function(sysn32_rt_sigsuspend);
+__attribute_used__ noinline static int
+_sysn32_rt_sigsuspend(nabi_no_regargs struct pt_regs regs)
+{
+ compat_sigset_t __user *unewset, uset;
+ size_t sigsetsize;
+ sigset_t newset;
+
+ /* XXX Don't preclude handling different sized sigset_t's. */
+ sigsetsize = regs.regs[5];
+ if (sigsetsize != sizeof(sigset_t))
+ return -EINVAL;
+
+ unewset = (compat_sigset_t __user *) regs.regs[4];
+ if (copy_from_user(&uset, unewset, sizeof(uset)))
+ return -EFAULT;
+ sigset_from_compat (&newset, &uset);
+ sigdelsetmask(&newset, ~_BLOCKABLE);
+
+ spin_lock_irq(¤t->sighand->siglock);
+ current->saved_sigmask = current->blocked;
+ current->blocked = newset;
+ recalc_sigpending();
+ spin_unlock_irq(¤t->sighand->siglock);
+
+ current->state = TASK_INTERRUPTIBLE;
+ schedule();
+ set_thread_flag(TIF_RESTORE_SIGMASK);
+ return -ERESTARTNOHAND;
+}
+
save_static_function(sysn32_rt_sigreturn);
__attribute_used__ noinline static void
_sysn32_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
diff --git a/kernel/compat.c b/kernel/compat.c
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH]: Fix N32 sigsuspend syscall that causes non-fatal oopses
@ 2006-01-23 20:45 Kumba
0 siblings, 0 replies; 4+ messages in thread
From: Kumba @ 2006-01-23 20:45 UTC (permalink / raw)
To: linux-mips
[-- Attachment #1: Type: text/plain, Size: 711 bytes --]
When using an N32 userland, it was discovered that a specific configure test in glib triggered a non-fatal oops, as
well as killing the build. Daniel Jacobwitz just happened to have the patch that fixed this issue, and with a small
#ifdef tweak to make it build for 32bit systems, it fixed the problem and allowed glib to build properly.
The patch is attached for comment, however we've been using it in our kernel patchset for sometime now with no
observable ill effect.
--Kumba
--
Gentoo/MIPS Team Lead
Gentoo Foundation Board of Trustees
"Such is oft the course of deeds that move the wheels of the world: small hands do them because they must, while the
eyes of the great are elsewhere." --Elrond
[-- Attachment #2: misc-2.6.13-n32-fix-sigsuspend.patch --]
[-- Type: text/plain, Size: 3572 bytes --]
diff -Naurp linux-2.6.13.3.orig/arch/mips/kernel/linux32.c linux-2.6.13.3/arch/mips/kernel/linux32.c
--- linux-2.6.13.3.orig/arch/mips/kernel/linux32.c 2005-10-05 22:46:31.000000000 -0400
+++ linux-2.6.13.3/arch/mips/kernel/linux32.c 2005-10-05 22:34:45.000000000 -0400
@@ -1453,25 +1453,6 @@ sys32_timer_create(u32 clock, struct sig
return sys_timer_create(clock, p, timer_id);
}
-asmlinkage long
-sysn32_rt_sigtimedwait(const sigset_t __user *uthese,
- siginfo_t __user *uinfo,
- const struct compat_timespec __user *uts32,
- size_t sigsetsize)
-{
- struct timespec __user *uts = NULL;
-
- if (uts32) {
- struct timespec ts;
- uts = compat_alloc_user_space(sizeof(struct timespec));
- if (get_user(ts.tv_sec, &uts32->tv_sec) ||
- get_user(ts.tv_nsec, &uts32->tv_nsec) ||
- copy_to_user (uts, &ts, sizeof (ts)))
- return -EFAULT;
- }
- return sys_rt_sigtimedwait(uthese, uinfo, uts, sigsetsize);
-}
-
save_static_function(sys32_clone);
__attribute_used__ noinline static int
_sys32_clone(nabi_no_regargs struct pt_regs regs)
diff -Naurp linux-2.6.13.3.orig/arch/mips/kernel/scall64-n32.S linux-2.6.13.3/arch/mips/kernel/scall64-n32.S
--- linux-2.6.13.3.orig/arch/mips/kernel/scall64-n32.S 2005-10-05 22:46:31.000000000 -0400
+++ linux-2.6.13.3/arch/mips/kernel/scall64-n32.S 2005-10-05 22:34:45.000000000 -0400
@@ -243,9 +243,9 @@ EXPORT(sysn32_call_table)
PTR sys_capget
PTR sys_capset
PTR sys32_rt_sigpending /* 6125 */
- PTR sysn32_rt_sigtimedwait
+ PTR compat_sys_rt_sigtimedwait
PTR sys_rt_sigqueueinfo
- PTR sys32_rt_sigsuspend
+ PTR sysn32_rt_sigsuspend
PTR sys32_sigaltstack
PTR compat_sys_utime /* 6130 */
PTR sys_mknod
diff -Naurp linux-2.6.13.3.orig/arch/mips/kernel/signal.c linux-2.6.13.3/arch/mips/kernel/signal.c
--- linux-2.6.13.3.orig/arch/mips/kernel/signal.c 2005-10-05 22:46:31.000000000 -0400
+++ linux-2.6.13.3/arch/mips/kernel/signal.c 2005-10-05 22:47:07.000000000 -0400
@@ -21,6 +21,7 @@
#include <linux/ptrace.h>
#include <linux/unistd.h>
#include <linux/compiler.h>
+#include <linux/compat.h>
#include <asm/abi.h>
#include <asm/asm.h>
@@ -39,6 +40,10 @@
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
+#ifdef CONFIG_MIPS32_N32
+extern void sigset_from_compat (sigset_t *set, compat_sigset_t *compat);
+#endif
+
int do_signal(sigset_t *oldset, struct pt_regs *regs);
/*
@@ -109,6 +114,43 @@ _sys_rt_sigsuspend(nabi_no_regargs struc
}
}
+#ifdef CONFIG_MIPS32_N32
+save_static_function(sysn32_rt_sigsuspend);
+__attribute_used__ noinline static int
+_sysn32_rt_sigsuspend(nabi_no_regargs struct pt_regs regs)
+{
+ sigset_t saveset, newset;
+ compat_sigset_t __user *unewset, uset;
+ size_t sigsetsize;
+
+ /* XXX Don't preclude handling different sized sigset_t's. */
+ sigsetsize = regs.regs[5];
+ if (sigsetsize != sizeof(sigset_t))
+ return -EINVAL;
+
+ unewset = (compat_sigset_t __user *) regs.regs[4];
+ if (copy_from_user(&uset, unewset, sizeof(uset)))
+ return -EFAULT;
+ sigset_from_compat (&newset, &uset);
+ sigdelsetmask(&newset, ~_BLOCKABLE);
+
+ spin_lock_irq(¤t->sighand->siglock);
+ saveset = current->blocked;
+ current->blocked = newset;
+ recalc_sigpending();
+ spin_unlock_irq(¤t->sighand->siglock);
+
+ regs.regs[2] = EINTR;
+ regs.regs[7] = 1;
+ while (1) {
+ current->state = TASK_INTERRUPTIBLE;
+ schedule();
+ if (do_signal(&saveset, ®s))
+ return -EINTR;
+ }
+}
+#endif
+
#ifdef CONFIG_TRAD_SIGNALS
asmlinkage int sys_sigaction(int sig, const struct sigaction *act,
struct sigaction *oact)
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2006-02-20 10:58 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-01-24 19:17 [PATCH]: Fix N32 sigsuspend syscall that causes non-fatal oopses Kumba
2006-01-24 19:34 ` Daniel Jacobowitz
2006-02-18 22:43 ` Ralf Baechle
-- strict thread matches above, loose matches on Subject: below --
2006-01-23 20:45 Kumba
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.