[PATCH] i386: fix stack alignment for signal handlers It seems that the current signal code always sets up a stack frame so that signal handlers are run with a somewhat mis-aligned stack, i.e. (esp % 8 == 4). While this is not an i386 ABI requirement we really would like to have at least a 8-byte alignment (e.g. when using doubles or other floating point stuff). Furthermore, as recent gcc versions default to -mpreferred-stack-boundary=4, this patch assures a 16-byte alignment. Signed-off-by: Markus F.X.J. Oberhumer Index: linux-2.6.git/arch/i386/kernel/signal.c =================================================================== --- linux-2.6.git.orig/arch/i386/kernel/signal.c +++ linux-2.6.git/arch/i386/kernel/signal.c @@ -338,7 +338,7 @@ esp = (unsigned long) ka->sa.sa_restorer; } - return (void __user *)((esp - frame_size) & -8ul); + return (void __user *)((esp - frame_size) & -16ul); } /* These symbols are defined with the addresses in the vsyscall page. @@ -354,7 +354,7 @@ int err = 0; int usig; - frame = get_sigframe(ka, regs, sizeof(*frame)); + frame = get_sigframe(ka, regs, sizeof(*frame)) - 4; if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) goto give_sigsegv; @@ -444,7 +444,7 @@ int err = 0; int usig; - frame = get_sigframe(ka, regs, sizeof(*frame)); + frame = get_sigframe(ka, regs, sizeof(*frame)) - 4; if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) goto give_sigsegv; Index: linux-2.6.git/arch/x86_64/ia32/ia32_signal.c =================================================================== --- linux-2.6.git.orig/arch/x86_64/ia32/ia32_signal.c +++ linux-2.6.git/arch/x86_64/ia32/ia32_signal.c @@ -425,7 +425,7 @@ rsp = (unsigned long) ka->sa.sa_restorer; } - return (void __user *)((rsp - frame_size) & -8UL); + return (void __user *)((rsp - frame_size) & -16UL); } int ia32_setup_frame(int sig, struct k_sigaction *ka, @@ -434,7 +434,7 @@ struct sigframe __user *frame; int err = 0; - frame = get_sigframe(ka, regs, sizeof(*frame)); + frame = get_sigframe(ka, regs, sizeof(*frame)) - 4; if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) goto give_sigsegv; @@ -527,7 +527,7 @@ struct rt_sigframe __user *frame; int err = 0; - frame = get_sigframe(ka, regs, sizeof(*frame)); + frame = get_sigframe(ka, regs, sizeof(*frame)) - 4; if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) goto give_sigsegv;