Also stupid. People use a segfault handler on a signal stack,
*because* the previous stack may be broken.
Since any trick we try appears to (possibly) break some existing
software, the next idea is to add yet another flag to signal.h. With
this, the user can decide whether he want to get extra safety or not.
Comments?
Jörn
-- The only real mistake is the one from which we learn nothing. -- John Powell--- linux-2.5.74/arch/i386/kernel/signal.c~ss_i386 2003-07-07 10:30:30.000000000 +0200 +++ linux-2.5.74/arch/i386/kernel/signal.c 2003-07-07 10:31:09.000000000 +0200 @@ -181,6 +181,9 @@ } } + if (sas_ss_flags(regs->esp) == 0) + current->flags &= ~PF_SS_ACTIVE; + err |= __get_user(*peax, &sc->eax); return err; @@ -317,9 +320,23 @@ esp = regs->esp; /* This is the X/Open sanctioned signal stack switching. */ - if (ka->sa.sa_flags & SA_ONSTACK) { - if (sas_ss_flags(esp) == 0) - esp = current->sas_ss_sp + current->sas_ss_size; + if ((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags(esp) == 0)) { + /* If we have switches to the signal stack before, + * something bad has happened to it, asking for a + * segmentation fault. + * If not, remember it for the next time + */ + if ((ka->sa.sa_flags & SA_KERNEL_RET) && + (current->flags & PF_SS_ACTIVE)) { + ka->sa.sa_handler = SIG_DFL; + force_sig(SIGSEGV, current); + /* XXX would it be simpler to return some broken + * value like NULL and have the calling function + * signal the segv? + */ + } + current->flags |= PF_SS_ACTIVE; + esp = current->sas_ss_sp + current->sas_ss_size; } /* This is the legacy signal stack switching. */ --- linux-2.5.74/include/asm-i386/signal.h~ss_i386 2003-07-07 10:30:30.000000000 +0200 +++ linux-2.5.74/include/asm-i386/signal.h 2003-07-07 11:29:42.000000000 +0200 @@ -76,6 +76,8 @@ * SA_FLAGS values: * * SA_ONSTACK indicates that a registered stack_t will be used. + * SA_KERNEL_RET indices that the handler returns through the kernel, not + * with longjmp or similar. * SA_INTERRUPT is a no-op, but left due to historical reasons. Use the * SA_RESTART flag to get restarting signals (which were the default long ago) * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop. @@ -89,6 +91,7 @@ #define SA_NOCLDSTOP 0x00000001u #define SA_NOCLDWAIT 0x00000002u #define SA_SIGINFO 0x00000004u +#define SA_KERNEL_RET 0x01000000u #define SA_ONSTACK 0x08000000u #define SA_RESTART 0x10000000u #define SA_NODEFER 0x40000000u - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/