summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Mosberger-Tang <davidm@mostang.com>2005-11-03 07:40:19 +0100
committerTony Luck <tony.luck@intel.com>2005-11-08 18:58:06 +0100
commitcf20d1eafb648bf395b153cbcd0cde40f88c220a (patch)
treeb8ffb8bd95fb62738f891ace618b3727bd8dbeca
parentMerge git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc-merge (diff)
downloadlinux-cf20d1eafb648bf395b153cbcd0cde40f88c220a.tar.xz
linux-cf20d1eafb648bf395b153cbcd0cde40f88c220a.zip
[IA64] align signal-frame even when not using alternate signal-stack
At the moment, attempting to invoke a signal-handler on the normal stack is guaranteed to fail if the stack-pointer happens not to be 16-byte aligned. This is because the signal-trampoline will attempt to store fp-regs with stf.spill instructions, which will trap for misaligned addresses. This isn't terribly useful behavior. It's better to just always align the signal frame to the next lower 16-byte boundary. Signed-off-by: David Mosberger-Tang <David.Mosberger@acm.org> Signed-off-by: Tony Luck <tony.luck@intel.com>
-rw-r--r--arch/ia64/kernel/signal.c11
1 files changed, 5 insertions, 6 deletions
diff --git a/arch/ia64/kernel/signal.c b/arch/ia64/kernel/signal.c
index 774f34b675cf..58ce07efc56e 100644
--- a/arch/ia64/kernel/signal.c
+++ b/arch/ia64/kernel/signal.c
@@ -387,15 +387,14 @@ setup_frame (int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set,
struct sigscratch *scr)
{
extern char __kernel_sigtramp[];
- unsigned long tramp_addr, new_rbs = 0;
+ unsigned long tramp_addr, new_rbs = 0, new_sp;
struct sigframe __user *frame;
long err;
- frame = (void __user *) scr->pt.r12;
+ new_sp = scr->pt.r12;
tramp_addr = (unsigned long) __kernel_sigtramp;
- if ((ka->sa.sa_flags & SA_ONSTACK) && sas_ss_flags((unsigned long) frame) == 0) {
- frame = (void __user *) ((current->sas_ss_sp + current->sas_ss_size)
- & ~(STACK_ALIGN - 1));
+ if ((ka->sa.sa_flags & SA_ONSTACK) && sas_ss_flags(new_sp) == 0) {
+ new_sp = current->sas_ss_sp + current->sas_ss_size;
/*
* We need to check for the register stack being on the signal stack
* separately, because it's switched separately (memory stack is switched
@@ -404,7 +403,7 @@ setup_frame (int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set,
if (!rbs_on_sig_stack(scr->pt.ar_bspstore))
new_rbs = (current->sas_ss_sp + sizeof(long) - 1) & ~(sizeof(long) - 1);
}
- frame = (void __user *) frame - ((sizeof(*frame) + STACK_ALIGN - 1) & ~(STACK_ALIGN - 1));
+ frame = (void __user *) ((new_sp - sizeof(*frame)) & -STACK_ALIGN);
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
return force_sigsegv_info(sig, frame);