From: "Albert Cahalan" <acahalan@gmail.com>
To: linux-kernel@vger.kernel.org, "Andrew Morton" <akpm@osdl.org>,
"Andi Kleen" <ak@suse.de>, "Linus Torvalds" <torvalds@osdl.org>,
hpa@zytor.com
Subject: [PATCH] i386/x86_64 signal handler arg fixes
Date: Thu, 14 Sep 2006 04:34:00 -0400 [thread overview]
Message-ID: <787b0d920609140134j5935c743kae4af8d51eea2a90@mail.gmail.com> (raw)
[-- Attachment #1: Type: text/plain, Size: 4294 bytes --]
Some time ago, the i386 kernel was patched to support user code that
has signal handlers marked with __attribute__((regparm(3))) or compiled
with the -mregparm=3 gcc option. This is useful for klibc at least.
The code wasn't quite right, and it never got ported to x86_64.
For i386, the non-RT frame is wrong. It was using the raw sig value
instead of the translated value, and did not pass the semi-documented
extra parameters.
For x86-64, the regparm 3 calling convention was simply missing.
This patch should do the job, provided I'm right in guessing that a
struct passed by value is really passed as a pointer in this case.
(the non-RT signal handler's second arg is a pass-by-value struct)
Signed-off-by: Albert Cahalan <acahalan@gmail.com>
---
I'm sending this inline for review, and attached because
the whitespace will surely be mangled.
diff -Naurd old/arch/i386/kernel/signal.c new/arch/i386/kernel/signal.c
--- old/arch/i386/kernel/signal.c 2006-09-14 03:49:30.000000000 -0400
+++ new/arch/i386/kernel/signal.c 2006-09-14 03:52:54.000000000 -0400
@@ -375,9 +375,9 @@
/* 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->edx = (unsigned long) 0;
- regs->ecx = (unsigned long) 0;
+ regs->eax = (unsigned long) usig;
+ regs->edx = (unsigned long) &frame->sc;
+ regs->ecx = (unsigned long) &frame->fpstate;
set_fs(USER_DS);
regs->xds = __USER_DS;
diff -Naurd old/arch/x86_64/ia32/ia32_signal.c
new/arch/x86_64/ia32/ia32_signal.c
--- old/arch/x86_64/ia32/ia32_signal.c 2006-09-14 03:21:21.000000000 -0400
+++ new/arch/x86_64/ia32/ia32_signal.c 2006-09-14 03:47:32.000000000 -0400
@@ -433,6 +433,7 @@
{
struct sigframe __user *frame;
int err = 0;
+ int usig;
frame = get_sigframe(ka, regs, sizeof(*frame));
@@ -441,12 +442,10 @@
{
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);
+ usig = ed && ed->signal_invmap && sig < 32
+ ? ed->signal_invmap[sig]
+ : sig;
+ err |= __put_user(usig,&frame->sig);
}
if (err)
goto give_sigsegv;
@@ -493,6 +492,9 @@
/* Set up registers for signal handler */
regs->rsp = (unsigned long) frame;
regs->rip = (unsigned long) ka->sa.sa_handler;
+ regs->rax = (unsigned long) usig;
+ regs->rdx = (unsigned long) &frame->sc;
+ regs->rcx = (unsigned long) &frame->fpstate;
asm volatile("movl %0,%%ds" :: "r" (__USER32_DS));
asm volatile("movl %0,%%es" :: "r" (__USER32_DS));
@@ -522,6 +524,7 @@
{
struct rt_sigframe __user *frame;
int err = 0;
+ int usig;
frame = get_sigframe(ka, regs, sizeof(*frame));
@@ -530,12 +533,10 @@
{
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);
+ usig = ed && ed->signal_invmap && sig < 32
+ ? ed->signal_invmap[sig]
+ : 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);
@@ -589,6 +590,9 @@
/* Set up registers for signal handler */
regs->rsp = (unsigned long) frame;
regs->rip = (unsigned long) ka->sa.sa_handler;
+ regs->rax = (unsigned long) usig;
+ regs->rdx = (unsigned long) &frame->info;
+ regs->rcx = (unsigned long) &frame->uc;
asm volatile("movl %0,%%ds" :: "r" (__USER32_DS));
asm volatile("movl %0,%%es" :: "r" (__USER32_DS));
[-- Attachment #2: regparm3.patch --]
[-- Type: text/x-patch, Size: 2838 bytes --]
diff -Naurd old/arch/i386/kernel/signal.c new/arch/i386/kernel/signal.c
--- old/arch/i386/kernel/signal.c 2006-09-14 03:49:30.000000000 -0400
+++ new/arch/i386/kernel/signal.c 2006-09-14 03:52:54.000000000 -0400
@@ -375,9 +375,9 @@
/* 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->edx = (unsigned long) 0;
- regs->ecx = (unsigned long) 0;
+ regs->eax = (unsigned long) usig;
+ regs->edx = (unsigned long) &frame->sc;
+ regs->ecx = (unsigned long) &frame->fpstate;
set_fs(USER_DS);
regs->xds = __USER_DS;
diff -Naurd old/arch/x86_64/ia32/ia32_signal.c new/arch/x86_64/ia32/ia32_signal.c
--- old/arch/x86_64/ia32/ia32_signal.c 2006-09-14 03:21:21.000000000 -0400
+++ new/arch/x86_64/ia32/ia32_signal.c 2006-09-14 03:47:32.000000000 -0400
@@ -433,6 +433,7 @@
{
struct sigframe __user *frame;
int err = 0;
+ int usig;
frame = get_sigframe(ka, regs, sizeof(*frame));
@@ -441,12 +442,10 @@
{
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);
+ usig = ed && ed->signal_invmap && sig < 32
+ ? ed->signal_invmap[sig]
+ : sig;
+ err |= __put_user(usig,&frame->sig);
}
if (err)
goto give_sigsegv;
@@ -493,6 +492,9 @@
/* Set up registers for signal handler */
regs->rsp = (unsigned long) frame;
regs->rip = (unsigned long) ka->sa.sa_handler;
+ regs->rax = (unsigned long) usig;
+ regs->rdx = (unsigned long) &frame->sc;
+ regs->rcx = (unsigned long) &frame->fpstate;
asm volatile("movl %0,%%ds" :: "r" (__USER32_DS));
asm volatile("movl %0,%%es" :: "r" (__USER32_DS));
@@ -522,6 +524,7 @@
{
struct rt_sigframe __user *frame;
int err = 0;
+ int usig;
frame = get_sigframe(ka, regs, sizeof(*frame));
@@ -530,12 +533,10 @@
{
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);
+ usig = ed && ed->signal_invmap && sig < 32
+ ? ed->signal_invmap[sig]
+ : 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);
@@ -589,6 +590,9 @@
/* Set up registers for signal handler */
regs->rsp = (unsigned long) frame;
regs->rip = (unsigned long) ka->sa.sa_handler;
+ regs->rax = (unsigned long) usig;
+ regs->rdx = (unsigned long) &frame->info;
+ regs->rcx = (unsigned long) &frame->uc;
asm volatile("movl %0,%%ds" :: "r" (__USER32_DS));
asm volatile("movl %0,%%es" :: "r" (__USER32_DS));
next reply other threads:[~2006-09-14 8:34 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2006-09-14 8:34 Albert Cahalan [this message]
2006-09-14 10:11 ` Andi Kleen
2006-09-14 15:01 ` Albert Cahalan
2006-09-14 13:40 ` Andi Kleen
2006-09-14 16:01 ` Albert Cahalan
2006-09-14 16:23 ` H. Peter Anvin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=787b0d920609140134j5935c743kae4af8d51eea2a90@mail.gmail.com \
--to=acahalan@gmail.com \
--cc=ak@suse.de \
--cc=akpm@osdl.org \
--cc=hpa@zytor.com \
--cc=linux-kernel@vger.kernel.org \
--cc=torvalds@osdl.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®