Re: sigaltstack fun

From: Al Viro
Date: Sun Nov 18 2012 - 16:03:03 EST


On Sun, Nov 18, 2012 at 07:59:21PM +0000, Al Viro wrote:
> On Sun, Nov 18, 2012 at 02:03:32PM -0500, David Miller wrote:
> > > I have absolutely no objections. sigaltstack has always been kind of
> > > messy, and made worse by the fact that it gets effectively no testing
> > > (because it's generally not used by normal code and even code that
> > > uses it tends to use it only for very uncommon events). So forcing all
> > > the sigaltstack code into generic code and at least avoiding the
> > > "different architectures can get things subtly - or not so subtly -
> > > wrong in different ways" sounds like a good thing.
> >
> > FWIW, if folks are looking for testcases there are a small number in
> > glibc, a quick grep shows:
> >
> > nptl/tst-cancel20.c
> > nptl/tst-cancel21.c
> > nptl/tst-signal6.c
> > debug/tst-longjmp_chk2.c
> >
> > LTP probably has a bunch too.
>
> Might be a good idea to start adding tests/* in the kernel tree, perhaps?
> Ones in glibc had been present prior to the LGPLv3 clusterfuck, by the
> look of it...

Incidentally, sparc64 is also broken the same way:
sparc64:~# gcc sigreturn-test.c
sparc64:~# ./a.out
entering SIGUSR1 on altstack
entering SIGUSR2 on altstack
SIGUSR2 done
SIGUSR1 done
sparc64:~# gcc -m64 sigreturn-test.c
sparc64:~# ./a.out
entering SIGUSR1 on altstack
entering SIGUSR2 on altstack
SIGUSR2 done
Segmentation fault
sparc64:~#

32bit rt_sigreturn (in signal32.c) simply ignores all errors. One in
signal_64.c fails on *any* error from do_sigaltstack(), with the results
above...

sigreturn-test.c is what I've posted upthread. I think this one is
-stable fodder. It's not hard to deal with, fortunately. Are you
OK with the patch below? Should be the minimal fix, getting rid of
those segfaults and converting to usual semantics here...

Signed-off-by: Al Viro <viro@xxxxxxxxxxxxxxxxxx>
---
diff --git a/arch/sparc/kernel/signal_64.c b/arch/sparc/kernel/signal_64.c
index 867de2f..689e1ba 100644
--- a/arch/sparc/kernel/signal_64.c
+++ b/arch/sparc/kernel/signal_64.c
@@ -295,9 +295,7 @@ void do_rt_sigreturn(struct pt_regs *regs)
err |= restore_fpu_state(regs, fpu_save);

err |= __copy_from_user(&set, &sf->mask, sizeof(sigset_t));
- err |= do_sigaltstack(&sf->stack, NULL, (unsigned long)sf);
-
- if (err)
+ if (err || do_sigaltstack(&sf->stack, NULL, (unsigned long)sf) == -EFAULT)
goto segv;

err |= __get_user(rwin_save, &sf->rwin_save);
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/