linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 2.5.73] Fix broken signal optimization for i386
@ 2003-07-03 20:24 Jörn Engel
  2003-07-04 17:43 ` Jörn Engel
  0 siblings, 1 reply; 30+ messages in thread
From: Jörn Engel @ 2003-07-03 20:24 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: paulus, anton, benh, engebret, linux-kernel, linuxppc-dev,
	linuxppc64-dev

Hi!

I guess it is an optimizasion that there is no flag to indicate
whether a process is operating on the signal stack or not.  That
information is instead generated by checking whether the stack pointer
is inside the signal stack or not.

But the stack pointer is under the control of the userspace.  Thus, a
broken program can cause the kernel to have utterly unexpected
behaviour.  You can recreate this by running the program below, which
I would expect to cause a segmentation fault and dump a core in the
process.

This patch fixes the problem for i386.  It could still some work, but
at least, it is better than the current behaviour.  One possible
improvement may be to cause the final SIGSEGV a bit sooner, another to
fold the flag into an unused bit somewhere in struct task_struct,
possibly in the low bits of the two sas_ss_* fields.

Two more patches for ppc are in the queue, ppc64 should be quite
similar.  I guess those should go to Paul and Anton, right?

[ My fscking email is still broken for some, including kernel.org.
  The admin that thought DNS entries should be cached for a full week
  to save some network bandwidth ought to be shot after some very
  cruel torture.  Sorry, folks. ]

---<snip>---
#define __USE_BSD
#include <signal.h>


#if defined(i386)
# define killstack() asm("mov %ebx,0")
#elif defined(PPC)
# define killstack() asm("lis 1,0")
#else
# define killstack() fprintf(stderr, "cannot kill stack on this arch\n")
#endif


char stack[8192];

struct sigaltstack ss = {
	.ss_sp = stack,
	.ss_flags = 0,
	.ss_size = sizeof(stack),
};

void null_handler(int signal)
{
	printf("SIGNAL .... %d\n", signal);
	killstack();
}

int main(int argc, char** argv)
{
	struct sigaction sa = {
		.sa_handler     = null_handler,
		.sa_flags       = SA_ONSTACK,
	};

	sigaltstack(&ss, 0);
	sigaction(SIGSEGV, &sa, 0);
	killstack();
	return 0; /* yeah, right! */
}
---<snap>---

Jörn

-- 
"Error protection by error detection and correction."
-- from a university class

--- linux-2.5.73/arch/i386/kernel/signal.c~signal_i386	2003-07-03 19:17:21.000000000 +0200
+++ linux-2.5.73/arch/i386/kernel/signal.c	2003-07-03 22:04:30.000000000 +0200
@@ -181,6 +181,9 @@
 		}
 	}
 
+	if (sas_ss_flags(regs->esp) == 0)
+		current->sas_ss_inuse = 0;
+
 	err |= __get_user(*peax, &sc->eax);
 	return err;
 
@@ -317,9 +320,22 @@
 	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 (current->sas_ss_inuse) {
+			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->sas_ss_inuse = 1;
+		esp = current->sas_ss_sp + current->sas_ss_size;
 	}
 
 	/* This is the legacy signal stack switching. */
--- linux-2.5.73/include/linux/sched.h~signal_i386	2003-07-03 19:17:21.000000000 +0200
+++ linux-2.5.73/include/linux/sched.h	2003-07-03 19:17:58.000000000 +0200
@@ -425,6 +425,7 @@
 
 	unsigned long sas_ss_sp;
 	size_t sas_ss_size;
+	int sas_ss_inuse;
 	int (*notifier)(void *priv);
 	void *notifier_data;
 	sigset_t *notifier_mask;

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

end of thread, other threads:[~2003-07-07 11:45 UTC | newest]

Thread overview: 30+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-07-03 20:24 [PATCH 2.5.73] Fix broken signal optimization for i386 Jörn Engel
2003-07-04 17:43 ` Jörn Engel
2003-07-04 17:45   ` [PATCH 2.5.73] Signal stack fixes #1 introduce PF_SS_ACTIVE Jörn Engel
2003-07-04 17:51     ` [PATCH 2.5.73] Signal stack fixes #2 i386-specific Jörn Engel
2003-07-04 17:54     ` [PATCH 2.5.73] Signal stack fixes #1 introduce PF_SS_ACTIVE Jörn Engel
2003-07-04 17:58       ` [PATCH 2.5.73] Signal handling fix for ppc Jörn Engel
2003-07-04 23:26         ` Paul Mackerras
2003-07-05  7:33           ` Jörn Engel
2003-07-04 23:18       ` [PATCH 2.5.73] Signal stack fixes #1 introduce PF_SS_ACTIVE Paul Mackerras
2003-07-05  7:39         ` Jörn Engel
2003-07-06  8:47           ` Paul Mackerras
2003-07-06 10:17             ` Jörn Engel
2003-07-07 11:29               ` Paul Mackerras
2003-07-07 11:58                 ` Jörn Engel
2003-07-07 11:33               ` Paul Mackerras
2003-07-07 11:46                 ` Jörn Engel
2003-07-04 19:21     ` Linus Torvalds
2003-07-04 19:38       ` Jörn Engel
2003-07-04 20:06         ` Linus Torvalds
2003-07-04 20:18           ` Jörn Engel
2003-07-05  0:39             ` Linus Torvalds
2003-07-05  7:30               ` Jörn Engel
2003-07-05 10:44                 ` Jörn Engel
2003-07-05 17:16                   ` Linus Torvalds
2003-07-06 12:51                     ` Jörn Engel
2003-07-07  9:30                       ` [PATCH 2.5.74] Signal stack safety #2 i386 specific Jörn Engel
2003-07-05 17:06             ` [PATCH 2.5.73] Signal stack fixes #1 introduce PF_SS_ACTIVE Jamie Lokier
2003-07-06  1:27           ` Eric W. Biederman
2003-07-04 19:39       ` Davide Libenzi
2003-07-04 20:24         ` Jörn Engel

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).