Commit 9691cc0d authored by H. Peter Anvin's avatar H. Peter Anvin Committed by Linus Torvalds

[PATCH] Make i386 signal delivery work with -mregparm

This patch allows i386 signal delivery to work correctly when userspace is
compiled with -mregparm.  This is somewhat hacky: it passes the arguments
*both* on the stack and in registers, but it works because there are only
one or three (depending on SA_SIGINFO) official arguments.  If you're
relying on the unofficial arguments then you're doing something nonportable
anyway and can put in the __attribute__((cdecl,regparm(0))) in the correct
place.
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 26fec91d
...@@ -345,18 +345,20 @@ static void setup_frame(int sig, struct k_sigaction *ka, ...@@ -345,18 +345,20 @@ static void setup_frame(int sig, struct k_sigaction *ka,
void __user *restorer; void __user *restorer;
struct sigframe __user *frame; struct sigframe __user *frame;
int err = 0; int err = 0;
int usig;
frame = get_sigframe(ka, regs, sizeof(*frame)); frame = get_sigframe(ka, regs, sizeof(*frame));
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
goto give_sigsegv; goto give_sigsegv;
err |= __put_user((current_thread_info()->exec_domain usig = current_thread_info()->exec_domain
&& current_thread_info()->exec_domain->signal_invmap && current_thread_info()->exec_domain->signal_invmap
&& sig < 32 && sig < 32
? current_thread_info()->exec_domain->signal_invmap[sig] ? current_thread_info()->exec_domain->signal_invmap[sig]
: sig), : sig;
&frame->sig);
err |= __put_user(usig, &frame->sig);
if (err) if (err)
goto give_sigsegv; goto give_sigsegv;
...@@ -395,6 +397,9 @@ static void setup_frame(int sig, struct k_sigaction *ka, ...@@ -395,6 +397,9 @@ static void setup_frame(int sig, struct k_sigaction *ka,
/* Set up registers for signal handler */ /* Set up registers for signal handler */
regs->esp = (unsigned long) frame; regs->esp = (unsigned long) frame;
regs->eip = (unsigned long) ka->sa.sa_handler; regs->eip = (unsigned long) ka->sa.sa_handler;
regs->eax = (unsigned long) sig;
regs->edx = (unsigned long) 0;
regs->ecx = (unsigned long) 0;
set_fs(USER_DS); set_fs(USER_DS);
regs->xds = __USER_DS; regs->xds = __USER_DS;
...@@ -420,18 +425,20 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -420,18 +425,20 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
void __user *restorer; void __user *restorer;
struct rt_sigframe __user *frame; struct rt_sigframe __user *frame;
int err = 0; int err = 0;
int usig;
frame = get_sigframe(ka, regs, sizeof(*frame)); frame = get_sigframe(ka, regs, sizeof(*frame));
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
goto give_sigsegv; goto give_sigsegv;
err |= __put_user((current_thread_info()->exec_domain usig = current_thread_info()->exec_domain
&& current_thread_info()->exec_domain->signal_invmap && current_thread_info()->exec_domain->signal_invmap
&& sig < 32 && sig < 32
? current_thread_info()->exec_domain->signal_invmap[sig] ? current_thread_info()->exec_domain->signal_invmap[sig]
: sig), : sig;
&frame->sig);
err |= __put_user(usig, &frame->sig);
err |= __put_user(&frame->info, &frame->pinfo); err |= __put_user(&frame->info, &frame->pinfo);
err |= __put_user(&frame->uc, &frame->puc); err |= __put_user(&frame->uc, &frame->puc);
err |= copy_siginfo_to_user(&frame->info, info); err |= copy_siginfo_to_user(&frame->info, info);
...@@ -474,6 +481,9 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, ...@@ -474,6 +481,9 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
/* Set up registers for signal handler */ /* Set up registers for signal handler */
regs->esp = (unsigned long) frame; regs->esp = (unsigned long) frame;
regs->eip = (unsigned long) ka->sa.sa_handler; regs->eip = (unsigned long) ka->sa.sa_handler;
regs->eax = (unsigned long) usig;
regs->edx = (unsigned long) &frame->info;
regs->ecx = (unsigned long) &frame->uc;
set_fs(USER_DS); set_fs(USER_DS);
regs->xds = __USER_DS; regs->xds = __USER_DS;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment