[PATCH] fix incorrect SA_ONSTACK behaviour for 64-bit processes
authorLaurent MEYER <meyerlau@fr.ibm.com>
Fri, 23 Jun 2006 09:05:36 +0000 (02:05 -0700)
committerLinus Torvalds <torvalds@g5.osdl.org>
Fri, 23 Jun 2006 14:43:05 +0000 (07:43 -0700)
- When setting a sighandler using sigaction() call, if the flag
  SA_ONSTACK is set and no alternate stack is provided via sigaltstack(),
  the kernel still try to install the alternate stack.  This behavior is
  the opposite of the one which is documented in Single Unix Specifications
  V3.

- Also when setting an alternate stack using sigaltstack() with the flag
  SS_DISABLE, the kernel try to install the alternate stack on signal
  delivery.

These two use cases makes the process crash at signal delivery.

Signed-off-by: Laurent Meyer <meyerlau@fr.ibm.com>
Cc: Richard Henderson <rth@twiddle.net>
Cc: Ivan Kokshaysky <ink@jurassic.park.msu.ru>
Cc: David Howells <dhowells@redhat.com>
Cc: Yoshinori Sato <ysato@users.sourceforge.jp>
Cc: Geert Uytterhoeven <geert@linux-m68k.org>
Cc: Roman Zippel <zippel@linux-m68k.org>
Cc: Kyle McMartin <kyle@mcmartin.ca>
Cc: Paul Mundt <lethal@linux-sh.org>
Cc: Kazumoto Kojima <kkojima@rr.iij4u.or.jp>
Cc: Chris Zankel <chris@zankel.net>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
arch/alpha/kernel/signal.c
arch/frv/kernel/signal.c
arch/h8300/kernel/signal.c
arch/m68k/kernel/signal.c
arch/m68knommu/kernel/signal.c
arch/parisc/kernel/signal.c
arch/sh64/kernel/signal.c
arch/v850/kernel/signal.c
arch/xtensa/kernel/signal.c

index 2e45e8604e325454e87681321c862e57b19b1355..741da0945dc4c801c0e97ca2ae2f35aaea5c8bc0 100644 (file)
@@ -375,7 +375,7 @@ give_sigsegv:
 static inline void __user *
 get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size)
 {
-       if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! on_sig_stack(sp))
+       if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! sas_ss_flags(sp))
                sp = current->sas_ss_sp + current->sas_ss_size;
 
        return (void __user *)((sp - frame_size) & -32ul);
index dd5e6fdd85fdd6ae88076b9ac57ee8d5bd1797d6..b8a5882b862562332ee0833a0f75cf5aedc2f419 100644 (file)
@@ -233,7 +233,7 @@ static inline void __user *get_sigframe(struct k_sigaction *ka,
 
        /* This is the X/Open sanctioned signal stack switching.  */
        if (ka->sa.sa_flags & SA_ONSTACK) {
-               if (! on_sig_stack(sp))
+               if (! sas_ss_flags(sp))
                        sp = current->sas_ss_sp + current->sas_ss_size;
        }
 
index f13d5e82d4b977065727d88ce45be4f0904c7dbb..7787f70a05bbaeee9e15188fc21f5cfe2d5f14bb 100644 (file)
@@ -307,7 +307,7 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
 
        /* This is the X/Open sanctioned signal stack switching.  */
        if (ka->sa.sa_flags & SA_ONSTACK) {
-               if (!on_sig_stack(usp))
+               if (!sas_ss_flags(usp))
                        usp = current->sas_ss_sp + current->sas_ss_size;
        }
        return (void *)((usp - frame_size) & -8UL);
index 866917bfa0280f16898df65c5d7cc632cc63b957..f9af893cd2892dde83b6e089d370d093f6db2ac0 100644 (file)
@@ -763,7 +763,7 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
 
        /* This is the X/Open sanctioned signal stack switching.  */
        if (ka->sa.sa_flags & SA_ONSTACK) {
-               if (!on_sig_stack(usp))
+               if (!sas_ss_flags(usp))
                        usp = current->sas_ss_sp + current->sas_ss_size;
        }
        return (void __user *)((usp - frame_size) & -8UL);
index e1b3aa39e2708f8d0dd1b1200591c2a918790548..8e2c5a88efa7599aa59e8bdd60fc719556741c9a 100644 (file)
@@ -553,7 +553,7 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
 
        /* This is the X/Open sanctioned signal stack switching.  */
        if (ka->sa.sa_flags & SA_ONSTACK) {
-               if (!on_sig_stack(usp))
+               if (!sas_ss_flags(usp))
                        usp = current->sas_ss_sp + current->sas_ss_size;
        }
        return (void *)((usp - frame_size) & -8UL);
index 05767e83cf2dd38f3aaacebd9e61e56349d0088c..cc38edfd90c5bcac048647d5dacb298254314c8b 100644 (file)
@@ -248,7 +248,7 @@ get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size)
        DBG(1,"get_sigframe: ka = %#lx, sp = %#lx, frame_size = %#lx\n",
                        (unsigned long)ka, sp, frame_size);
        
-       if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! on_sig_stack(sp))
+       if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! sas_ss_flags(sp))
                sp = current->sas_ss_sp; /* Stacks grow up! */
 
        DBG(1,"get_sigframe: Returning sp = %#lx\n", (unsigned long)sp);
index 3ea8929e483b5fea4f99fc6b6ebe2144ed61eb77..9e2ffc45c0e0ffe480c614da00edee056903fec3 100644 (file)
@@ -407,7 +407,7 @@ setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
 static inline void __user *
 get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size)
 {
-       if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! on_sig_stack(sp))
+       if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! sas_ss_flags(sp))
                sp = current->sas_ss_sp + current->sas_ss_size;
 
        return (void __user *)((sp - frame_size) & -8ul);
index 633e4e1b825f875daa32f2759ab3f6b94d555209..17c2d4359b048be7927410674074b623aed702f0 100644 (file)
@@ -274,7 +274,7 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
        /* Default to using normal stack */
        unsigned long sp = regs->gpr[GPR_SP];
 
-       if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! on_sig_stack(sp))
+       if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! sas_ss_flags(sp))
                sp = current->sas_ss_sp + current->sas_ss_size;
 
        return (void *)((sp - frame_size) & -8UL);
index beba497e78df1c065eaadc05735d11581782c513..c494f0826fc560f52258fd0a663d442b3d393ebd 100644 (file)
@@ -433,7 +433,7 @@ badframe:
 static inline void *
 get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size)
 {
-       if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! on_sig_stack(sp))
+       if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! sas_ss_flags(sp))
                sp = current->sas_ss_sp + current->sas_ss_size;
 
        return (void *)((sp - frame_size) & -16ul);