LKML Archive on lore.kernel.org
help / color / mirror / Atom feed
* [PATCH 2.6.21-rc1] x86 signal number delivery fixes
@ 2007-02-25 11:47 Mikael Pettersson
  2007-02-25 22:39 ` Andi Kleen
  0 siblings, 1 reply; 3+ messages in thread
From: Mikael Pettersson @ 2007-02-25 11:47 UTC (permalink / raw)
  To: torvalds; +Cc: ak, linux-kernel

The invokation of signal handlers on x86 has several bugs
in its treatment of the signal number parameter:

- the i386 kernel passes the raw not the translated signal number
  in EAX to non-SA_SIGINFO handlers compiled with -mregparm=3;
  the value passed on the stack is correct, and SA_SIGINFO handlers
  are also invoked correctly
- the x86-64 kernel's ia32 emulation for SA_SIGINFO handlers also
  passes the wrong (untranslated) signal number in EAX; the value
  on the stack is correct
- the x86-64 kernel's ia32 emulation for non-SA_SIGINFO handlers
  passes the wrong (untranslated) signal number both on the stack
  and in EAX

Also, the x86-64 kernel's ia32_setup_rt_frame() has duplicated code
for setting up -mregparm=3 parameters: it looks like the same patch
hunk was merged twice at some point.

Fixed by the following patch.

Signed-off-by: Mikael Pettersson <mikpe@it.uu.se>

---

The fix in ia32_setup_frame() is ugly, but follows the coding style
of ia32_setup_rt_frame().

 arch/i386/kernel/signal.c      |    2 +-
 arch/x86_64/ia32/ia32_signal.c |   31 +++++++++++++++++--------------
 2 files changed, 18 insertions(+), 15 deletions(-)

diff -rupN linux-2.6.21-rc1/arch/i386/kernel/signal.c linux-2.6.21-rc1.x86-signals-usig-fixes/arch/i386/kernel/signal.c
--- linux-2.6.21-rc1/arch/i386/kernel/signal.c	2007-02-24 22:32:42.000000000 +0100
+++ linux-2.6.21-rc1.x86-signals-usig-fixes/arch/i386/kernel/signal.c	2007-02-25 11:09:24.000000000 +0100
@@ -377,7 +377,7 @@ static int setup_frame(int sig, struct k
 	/* Set up registers for signal handler */
 	regs->esp = (unsigned long) frame;
 	regs->eip = (unsigned long) ka->sa.sa_handler;
-	regs->eax = (unsigned long) sig;
+	regs->eax = (unsigned long) usig;
 	regs->edx = (unsigned long) 0;
 	regs->ecx = (unsigned long) 0;
 
diff -rupN linux-2.6.21-rc1/arch/x86_64/ia32/ia32_signal.c linux-2.6.21-rc1.x86-signals-usig-fixes/arch/x86_64/ia32/ia32_signal.c
--- linux-2.6.21-rc1/arch/x86_64/ia32/ia32_signal.c	2007-02-24 22:32:42.000000000 +0100
+++ linux-2.6.21-rc1.x86-signals-usig-fixes/arch/x86_64/ia32/ia32_signal.c	2007-02-25 11:09:24.000000000 +0100
@@ -426,13 +426,21 @@ int ia32_setup_frame(int sig, struct k_s
 {
 	struct sigframe __user *frame;
 	int err = 0;
+	int usig;
 
 	frame = get_sigframe(ka, regs, sizeof(*frame));
 
 	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
 		goto give_sigsegv;
 
-	err |= __put_user(sig, &frame->sig);
+	{
+		struct exec_domain *ed = current_thread_info()->exec_domain;
+		if (ed && ed->signal_invmap && sig < 32)
+			usig = ed->signal_invmap[sig];
+		else
+			usig = sig;
+		err |= __put_user(usig, &frame->sig);
+	}
 	if (err)
 		goto give_sigsegv;
 
@@ -484,7 +492,7 @@ int ia32_setup_frame(int sig, struct k_s
 	regs->rip = (unsigned long) ka->sa.sa_handler;
 
 	/* Make -mregparm=3 work */
-	regs->rax = sig;
+	regs->rax = usig;
 	regs->rdx = 0;
 	regs->rcx = 0;
 
@@ -516,6 +524,7 @@ int ia32_setup_rt_frame(int sig, struct 
 {
 	struct rt_sigframe __user *frame;
 	int err = 0;
+	int usig;
 
 	frame = get_sigframe(ka, regs, sizeof(*frame));
 
@@ -524,12 +533,11 @@ int ia32_setup_rt_frame(int sig, struct 
 
 	{
 		struct exec_domain *ed = current_thread_info()->exec_domain;
-		err |= __put_user((ed
-		    	   && ed->signal_invmap
-		    	   && sig < 32
-		    	   ? ed->signal_invmap[sig]
-			   : sig),
-			  &frame->sig);
+		if (ed && ed->signal_invmap && sig < 32)
+			usig = ed->signal_invmap[sig];
+		else
+			usig = sig;
+		err |= __put_user(usig, &frame->sig);
 	}
 	err |= __put_user(ptr_to_compat(&frame->info), &frame->pinfo);
 	err |= __put_user(ptr_to_compat(&frame->uc), &frame->puc);
@@ -585,12 +593,7 @@ int ia32_setup_rt_frame(int sig, struct 
 	regs->rip = (unsigned long) ka->sa.sa_handler;
 
 	/* Make -mregparm=3 work */
-	regs->rax = sig;
-	regs->rdx = (unsigned long) &frame->info;
-	regs->rcx = (unsigned long) &frame->uc;
-
-	/* Make -mregparm=3 work */
-	regs->rax = sig;
+	regs->rax = usig;
 	regs->rdx = (unsigned long) &frame->info;
 	regs->rcx = (unsigned long) &frame->uc;
 

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

* Re: [PATCH 2.6.21-rc1] x86 signal number delivery fixes
  2007-02-25 11:47 [PATCH 2.6.21-rc1] x86 signal number delivery fixes Mikael Pettersson
@ 2007-02-25 22:39 ` Andi Kleen
  0 siblings, 0 replies; 3+ messages in thread
From: Andi Kleen @ 2007-02-25 22:39 UTC (permalink / raw)
  To: Mikael Pettersson; +Cc: torvalds, linux-kernel

On Sunday 25 February 2007 12:47, Mikael Pettersson wrote:
> The invokation of signal handlers on x86 has several bugs
> in its treatment of the signal number parameter:
> 
> - the i386 kernel passes the raw not the translated signal number
>   in EAX to non-SA_SIGINFO handlers compiled with -mregparm=3;
>   the value passed on the stack is correct, and SA_SIGINFO handlers
>   are also invoked correctly
> - the x86-64 kernel's ia32 emulation for SA_SIGINFO handlers also
>   passes the wrong (untranslated) signal number in EAX; the value
>   on the stack is correct
> - the x86-64 kernel's ia32 emulation for non-SA_SIGINFO handlers
>   passes the wrong (untranslated) signal number both on the stack 
>   and in EAX


Nobody should be using that signal translation code anymore. Certainly
nothing in tree. Perhaps it would be better to just rip it out.

If you have a user you should submit it.

-Andi

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

* Re: [PATCH 2.6.21-rc1] x86 signal number delivery fixes
@ 2007-02-25 23:03 Mikael Pettersson
  0 siblings, 0 replies; 3+ messages in thread
From: Mikael Pettersson @ 2007-02-25 23:03 UTC (permalink / raw)
  To: ak; +Cc: linux-kernel, torvalds

On Sun, 25 Feb 2007 23:39:48 +0100, Andi Kleen wrote:
> On Sunday 25 February 2007 12:47, Mikael Pettersson wrote:
> > The invokation of signal handlers on x86 has several bugs
> > in its treatment of the signal number parameter:
> > 
> > - the i386 kernel passes the raw not the translated signal number
> >   in EAX to non-SA_SIGINFO handlers compiled with -mregparm=3;
> >   the value passed on the stack is correct, and SA_SIGINFO handlers
> >   are also invoked correctly
> > - the x86-64 kernel's ia32 emulation for SA_SIGINFO handlers also
> >   passes the wrong (untranslated) signal number in EAX; the value
> >   on the stack is correct
> > - the x86-64 kernel's ia32 emulation for non-SA_SIGINFO handlers
> >   passes the wrong (untranslated) signal number both on the stack 
> >   and in EAX
> 
> 
> Nobody should be using that signal translation code anymore. Certainly
> nothing in tree. Perhaps it would be better to just rip it out.
> 
> If you have a user you should submit it.

The reason I noticed these issues was that I was studying the signal
delivery code for a virtualisation project, and these discrepancies
were immediately obvious just from reading the code.

I'm definitely not using that signal number translation feature; heck
I didn't even know it existed until a few days ago.

If it's dead as you say then it really ought to be removed. It currently
seems to make a mess in every arch's signal delivery code.

/Mikael

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

end of thread, other threads:[~2007-02-25 23:04 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-02-25 11:47 [PATCH 2.6.21-rc1] x86 signal number delivery fixes Mikael Pettersson
2007-02-25 22:39 ` Andi Kleen
2007-02-25 23:03 Mikael Pettersson

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).