* [PATCH] i386: fix stack alignment for signal handlers
@ 2005-09-13 20:55 Markus F.X.J. Oberhumer
2005-09-13 22:53 ` Linus Torvalds
0 siblings, 1 reply; 14+ messages in thread
From: Markus F.X.J. Oberhumer @ 2005-09-13 20:55 UTC (permalink / raw)
To: linux-kernel; +Cc: Linus Torvalds, Andi Kleen
[-- Attachment #1: Type: text/plain, Size: 772 bytes --]
[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 <markus@oberhumer.com>
Please try the small attached user-space test program and please also
carefully review the patch below - I don't do much kernel hacking...
~Markus
--
Markus Oberhumer, <markus@oberhumer.com>, http://www.oberhumer.com/
[-- Attachment #2: test_sigframe_alignment.c --]
[-- Type: text/plain, Size: 1220 bytes --]
/* test signal stack alignment (sigframe) */
/* Markus F.X.J. Oberhumer <markus@oberhumer.com> */
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
volatile unsigned long signal_sp = 0;
#if defined(__x86_64__)
/* amd64: signal stack is properly aligned */
asm(
".text\n .align 16\n"
"my_sighandler:\n"
"lea 8(%rsp),%rax\n"
"movq %rax,(signal_sp)\n"
"retq\n"
);
#elif defined(__i386__)
/* i386: signal stack is always mis-aligned to 4-bytes */
asm(
".text\n .align 16\n"
"my_sighandler:\n"
"lea 4(%esp),%eax\n"
"movl %eax,(signal_sp)\n"
"ret\n"
);
#else
#error "arch not supported - please insert your code here"
#endif
#if defined(__cplusplus)
extern "C"
#endif
void my_sighandler(int);
int main()
{
int signo = SIGUSR1;
#if 1
/* randomize stack */
void * volatile dummy = NULL;
srand((unsigned)clock() % RAND_MAX);
dummy = __builtin_alloca(rand() % 2048ul);
#endif
signal_sp = 0;
signal(signo, my_sighandler);
raise(signo);
printf("sp = 0x%lx alignment = %lu\n", signal_sp, signal_sp & 15);
if (signal_sp & 15)
printf(" error: signal stack not aligned\n");
return 0;
}
/* vim:set ts=4 et: */
[-- Attachment #3: i386-align_sigframe.patch --]
[-- Type: text/x-patch, Size: 2447 bytes --]
[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 <markus@oberhumer.com>
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;
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] i386: fix stack alignment for signal handlers
2005-09-13 20:55 [PATCH] i386: fix stack alignment for signal handlers Markus F.X.J. Oberhumer
@ 2005-09-13 22:53 ` Linus Torvalds
2005-09-13 23:30 ` Markus F.X.J. Oberhumer
0 siblings, 1 reply; 14+ messages in thread
From: Linus Torvalds @ 2005-09-13 22:53 UTC (permalink / raw)
To: Markus F.X.J. Oberhumer; +Cc: linux-kernel, Andi Kleen
On Tue, 13 Sep 2005, Markus F.X.J. Oberhumer wrote:
>
> 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).
Actually, not really.
They get entered with the stack pointer aligned, at least in my tests.
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
extern void handler(int);
void *saved_esp;
asm("handler: movl %esp,saved_esp; ret");
int main(int argc, char **argv)
{
signal(SIGALRM, handler);
alarm(1);
pause();
printf("%p\n", saved_esp);
return 0;
}
always prints out an aligned address for me.
You seem to be expecting that the address be aligned "before the return
address push", which is a totally different thing. Quite frankly, I don't
know which one gcc prefers or whether there's an ABI specifying any
preferences.
Linus
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] i386: fix stack alignment for signal handlers
2005-09-13 22:53 ` Linus Torvalds
@ 2005-09-13 23:30 ` Markus F.X.J. Oberhumer
2005-09-13 23:52 ` Linus Torvalds
2005-09-14 20:11 ` J.A. Magallon
0 siblings, 2 replies; 14+ messages in thread
From: Markus F.X.J. Oberhumer @ 2005-09-13 23:30 UTC (permalink / raw)
To: Linus Torvalds; +Cc: linux-kernel, Andi Kleen
Linus Torvalds wrote:
>
> On Tue, 13 Sep 2005, Markus F.X.J. Oberhumer wrote:
>
>>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).
>
> Actually, not really.
>
> They get entered with the stack pointer aligned, at least in my tests.
>
> #include <stdio.h>
> #include <signal.h>
> #include <unistd.h>
>
> extern void handler(int);
> void *saved_esp;
>
> asm("handler: movl %esp,saved_esp; ret");
>
> int main(int argc, char **argv)
> {
> signal(SIGALRM, handler);
> alarm(1);
> pause();
> printf("%p\n", saved_esp);
> return 0;
> }
>
> always prints out an aligned address for me.
>
> You seem to be expecting that the address be aligned "before the return
> address push", which is a totally different thing. Quite frankly, I don't
> know which one gcc prefers or whether there's an ABI specifying any
> preferences.
I'm pretty sure that on both amd64 and i386 the alignment has to be
_before_ the address push from the call, though I cannot find any exact ABI
specs at the moment. Experts please advise.
What do you get when running this slightly modified version of your test
program? My patch would fix the alignment of Aligned16 here.
And for amd64, please also see arch/x86_64/kernel/signal.c where 8 is
subtracted from the get_stack() result. Actually I wonder if other archs
might be affected as well...
~Markus
#include <stdio.h>
#include <signal.h>
#include <unistd.h>
#include <assert.h>
typedef struct { double x,y; } Aligned16 __attribute__((__aligned__(16)));
void *saved_esp;
void handler(int unused) {
Aligned16 a;
assert(__alignof(a) >= 16),
saved_esp = (void *) &a;
}
int main()
{
Aligned16 a;
assert(__alignof(a) >= 16),
printf("%p\n", &a);
signal(SIGALRM, handler);
alarm(1);
pause();
printf("%p\n", saved_esp);
return 0;
}
--
Markus Oberhumer, <markus@oberhumer.com>, http://www.oberhumer.com/
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] i386: fix stack alignment for signal handlers
2005-09-13 23:30 ` Markus F.X.J. Oberhumer
@ 2005-09-13 23:52 ` Linus Torvalds
2005-09-14 1:39 ` Markus F.X.J. Oberhumer
` (2 more replies)
2005-09-14 20:11 ` J.A. Magallon
1 sibling, 3 replies; 14+ messages in thread
From: Linus Torvalds @ 2005-09-13 23:52 UTC (permalink / raw)
To: Markus F.X.J. Oberhumer; +Cc: linux-kernel, Andi Kleen
On Wed, 14 Sep 2005, Markus F.X.J. Oberhumer wrote:
>
> > You seem to be expecting that the address be aligned "before the return
> > address push", which is a totally different thing. Quite frankly, I don't
> > know which one gcc prefers or whether there's an ABI specifying any
> > preferences.
>
> I'm pretty sure that on both amd64 and i386 the alignment has to be
> _before_ the address push from the call, though I cannot find any exact ABI
> specs at the moment. Experts please advise.
>
> What do you get when running this slightly modified version of your test
> program? My patch would fix the alignment of Aligned16 here.
Your test program does seems to imply that gcc wants the alignment before
the return address (ie it prints out an address that is 4 bytes offset),
but on the other hand I'm not even sure how careful gcc is about this
alignment thing at all.
In the "main()" function, gcc will actually generate a "andl $-16,%esp" to
force the alignment, but ot in the handler function. Just a gcc special
case? Random luck?
Andi - you know the gcc people, is there some documented rules somewhere?
How does gcc itself try to align the stack when it generates the calls?
Linus
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] i386: fix stack alignment for signal handlers
2005-09-13 23:52 ` Linus Torvalds
@ 2005-09-14 1:39 ` Markus F.X.J. Oberhumer
2005-09-14 4:54 ` Andi Kleen
2005-09-14 14:22 ` Daniel Jacobowitz
2 siblings, 0 replies; 14+ messages in thread
From: Markus F.X.J. Oberhumer @ 2005-09-14 1:39 UTC (permalink / raw)
To: Linus Torvalds; +Cc: linux-kernel, Andi Kleen, John Reiser
Linus Torvalds wrote:
>
> On Wed, 14 Sep 2005, Markus F.X.J. Oberhumer wrote:
>
>>>You seem to be expecting that the address be aligned "before the return
>>>address push", which is a totally different thing. Quite frankly, I don't
>>>know which one gcc prefers or whether there's an ABI specifying any
>>>preferences.
>>
>>I'm pretty sure that on both amd64 and i386 the alignment has to be
>>_before_ the address push from the call, though I cannot find any exact ABI
>>specs at the moment. Experts please advise.
>>
>>What do you get when running this slightly modified version of your test
>>program? My patch would fix the alignment of Aligned16 here.
>
>
> Your test program does seems to imply that gcc wants the alignment before
> the return address (ie it prints out an address that is 4 bytes offset),
> but on the other hand I'm not even sure how careful gcc is about this
> alignment thing at all.
>
> In the "main()" function, gcc will actually generate a "andl $-16,%esp" to
> force the alignment, but ot in the handler function. Just a gcc special
> case? Random luck?
I think that main() is a known name and therefore gets a special treatment
- if you rename main() to foo() and then compare the disassembly you will
see that the "andl $-16,%esp" has vanished.
OTOS the "andl" in main() exactly does show how gcc wants the stack to be
aligned, i.e. _before_ the call-address push.
Another argument would be the 16-byte aligned stack-setup of glibc - please
try runing this tiny program under gdb and look at "info reg":
asm(".globl main\n main:\n int $3\n");
All of this would indicate that the kernel should get fixed.
~Markus
>
> Andi - you know the gcc people, is there some documented rules somewhere?
> How does gcc itself try to align the stack when it generates the calls?
>
> Linus
>
--
Markus Oberhumer, <markus@oberhumer.com>, http://www.oberhumer.com/
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] i386: fix stack alignment for signal handlers
2005-09-13 23:52 ` Linus Torvalds
2005-09-14 1:39 ` Markus F.X.J. Oberhumer
@ 2005-09-14 4:54 ` Andi Kleen
2005-09-14 14:22 ` Daniel Jacobowitz
2 siblings, 0 replies; 14+ messages in thread
From: Andi Kleen @ 2005-09-14 4:54 UTC (permalink / raw)
To: Linus Torvalds; +Cc: Markus F.X.J. Oberhumer, linux-kernel, Andi Kleen, jh
> Andi - you know the gcc people, is there some documented rules somewhere?
> How does gcc itself try to align the stack when it generates the calls?
The x86-64 ABI says
>>
The end of the input argument area shall be aligned on a 16 byte boundary.
In other words, the value (%rsp - 8) is always a multiple of 16 when control is
transferred to the function entry point. The stack pointer, %rsp, always points to
the end of the latest allocated stack frame. 7
<<
I presume acts i386 (it's likely undocumented because the ABI documents
predate this), but Jan surely can confirm?
It makes sense because when long double is passed on the stack
you really want them to be aligned there.
This would mean Markus' patch is correct for x86-64 and likely for i386
too.
-Andi
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] i386: fix stack alignment for signal handlers
2005-09-13 23:52 ` Linus Torvalds
2005-09-14 1:39 ` Markus F.X.J. Oberhumer
2005-09-14 4:54 ` Andi Kleen
@ 2005-09-14 14:22 ` Daniel Jacobowitz
2005-09-14 14:55 ` Linus Torvalds
2 siblings, 1 reply; 14+ messages in thread
From: Daniel Jacobowitz @ 2005-09-14 14:22 UTC (permalink / raw)
To: Linus Torvalds; +Cc: Markus F.X.J. Oberhumer, linux-kernel, Andi Kleen
On Tue, Sep 13, 2005 at 04:52:30PM -0700, Linus Torvalds wrote:
> Your test program does seems to imply that gcc wants the alignment before
> the return address (ie it prints out an address that is 4 bytes offset),
> but on the other hand I'm not even sure how careful gcc is about this
> alignment thing at all.
Very, on architectures where the ABI requires alignment. E.G. for
vector register loads that require 16-byte alignment to avoid a trap.
The comment for the relevant bits of the GCC configuration says it
won't assume this for x86, but I believe that comment is out of date.
I think it'll assume 16-byte alignment on entrance to non-main()
functions.
> In the "main()" function, gcc will actually generate a "andl $-16,%esp" to
> force the alignment, but ot in the handler function. Just a gcc special
> case? Random luck?
Special case. This is only done for main().
--
Daniel Jacobowitz
CodeSourcery, LLC
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] i386: fix stack alignment for signal handlers
2005-09-14 14:22 ` Daniel Jacobowitz
@ 2005-09-14 14:55 ` Linus Torvalds
2005-09-14 15:44 ` Andi Kleen
0 siblings, 1 reply; 14+ messages in thread
From: Linus Torvalds @ 2005-09-14 14:55 UTC (permalink / raw)
To: Daniel Jacobowitz; +Cc: Markus F.X.J. Oberhumer, linux-kernel, Andi Kleen
On Wed, 14 Sep 2005, Daniel Jacobowitz wrote:
>
> The comment for the relevant bits of the GCC configuration says it won't
> assume this for x86, but I believe that comment is out of date. I think
> it'll assume 16-byte alignment on entrance to non-main() functions.
Well, that's kind of the point. We _do_ have the stack aligned on
entrance, but it looks like gcc wants it _non-aligned_. It seems to want
it offset by the "return address push" - ie it seems to expect that it was
aligned before the "call", but entry into the next function will thus
_never_ be aligned.
So the kernel actually seems to have it _too_ aligned right now.
Linus
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] i386: fix stack alignment for signal handlers
2005-09-14 14:55 ` Linus Torvalds
@ 2005-09-14 15:44 ` Andi Kleen
2005-10-09 16:54 ` Markus F.X.J. Oberhumer
0 siblings, 1 reply; 14+ messages in thread
From: Andi Kleen @ 2005-09-14 15:44 UTC (permalink / raw)
To: Linus Torvalds
Cc: Daniel Jacobowitz, Markus F.X.J. Oberhumer, linux-kernel,
Andi Kleen
On Wed, Sep 14, 2005 at 07:55:53AM -0700, Linus Torvalds wrote:
>
>
> On Wed, 14 Sep 2005, Daniel Jacobowitz wrote:
> >
> > The comment for the relevant bits of the GCC configuration says it won't
> > assume this for x86, but I believe that comment is out of date. I think
> > it'll assume 16-byte alignment on entrance to non-main() functions.
>
> Well, that's kind of the point. We _do_ have the stack aligned on
> entrance, but it looks like gcc wants it _non-aligned_. It seems to want
> it offset by the "return address push" - ie it seems to expect that it was
> aligned before the "call", but entry into the next function will thus
> _never_ be aligned.
>
> So the kernel actually seems to have it _too_ aligned right now.
Yes it's wrong. I would recommend to apply Markus' patch for i386
and x86-64.
-Andi
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] i386: fix stack alignment for signal handlers
2005-09-13 23:30 ` Markus F.X.J. Oberhumer
2005-09-13 23:52 ` Linus Torvalds
@ 2005-09-14 20:11 ` J.A. Magallon
1 sibling, 0 replies; 14+ messages in thread
From: J.A. Magallon @ 2005-09-14 20:11 UTC (permalink / raw)
To: Markus F.X.J. Oberhumer; +Cc: Linus Torvalds, linux-kernel, Andi Kleen
On 09.14, Markus F.X.J. Oberhumer wrote:
...
>
> #include <stdio.h>
> #include <signal.h>
> #include <unistd.h>
> #include <assert.h>
>
> typedef struct { double x,y; } Aligned16 __attribute__((__aligned__(16)));
>
> void *saved_esp;
> void handler(int unused) {
> Aligned16 a;
> assert(__alignof(a) >= 16),
errr... assert(__alignof(a) < 16), ???
--
J.A. Magallon <jamagallon()able!es> \ Software is like sex:
werewolf!able!es \ It's better when it's free
Mandriva Linux release 2006.0 (Cooker) for i586
Linux 2.6.13-jam4 (gcc 4.0.1 (4.0.1-5mdk for Mandriva Linux release 2006.0))
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] i386: fix stack alignment for signal handlers
2005-09-14 15:44 ` Andi Kleen
@ 2005-10-09 16:54 ` Markus F.X.J. Oberhumer
2005-10-09 16:57 ` Andi Kleen
0 siblings, 1 reply; 14+ messages in thread
From: Markus F.X.J. Oberhumer @ 2005-10-09 16:54 UTC (permalink / raw)
To: Andi Kleen; +Cc: Linus Torvalds, Daniel Jacobowitz, linux-kernel
[-- Attachment #1: Type: text/plain, Size: 1343 bytes --]
Andi Kleen wrote:
> On Wed, Sep 14, 2005 at 07:55:53AM -0700, Linus Torvalds wrote:
>>
>>On Wed, 14 Sep 2005, Daniel Jacobowitz wrote:
>>
>>>The comment for the relevant bits of the GCC configuration says it won't
>>>assume this for x86, but I believe that comment is out of date. I think
>>>it'll assume 16-byte alignment on entrance to non-main() functions.
>>
>>Well, that's kind of the point. We _do_ have the stack aligned on
>>entrance, but it looks like gcc wants it _non-aligned_. It seems to want
>>it offset by the "return address push" - ie it seems to expect that it was
>>aligned before the "call", but entry into the next function will thus
>>_never_ be aligned.
>>
>>So the kernel actually seems to have it _too_ aligned right now.
>
>
> Yes it's wrong. I would recommend to apply Markus' patch for i386
> and x86-64.
>
> -Andi
Here is a somewhat simplified version of my previous patch with
updated comments.
Attached is also a new small user-space test program which does not
depend on any special gcc features and should trigger the problem on all
machines.
~Markus
P.S. I have not been involved in lkml back since 1999, so I currently don't
know whom to bug to get this patch applied, esp. as there seems to be no
official i386 maintainer.
--
Markus Oberhumer, <markus@oberhumer.com>, http://www.oberhumer.com/
[-- Attachment #2: i386-align_sigframe.patch --]
[-- Type: text/x-patch, Size: 1816 bytes --]
[PATCH] i386: fix stack alignment for signal handlers
This patches fixes the setup of the alignment of the signal frame, so
that all signal handlers are run with a properly aligned stack frame.
The current code "over-aligns" the stack pointer so that the stack
frame is effectively always mis-aligned by 4 bytes. But what we really
want is that on function entry ((sp + 4) & 15) == 0.
Signed-off-by: Markus F.X.J. Oberhumer <markus@oberhumer.com>
arch/i386/kernel/signal.c | 6 +++++-
arch/x86_64/ia32/ia32_signal.c | 6 +++++-
2 files changed, 10 insertions(+), 2 deletions(-)
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,11 @@
esp = (unsigned long) ka->sa.sa_restorer;
}
- return (void __user *)((esp - frame_size) & -8ul);
+ esp -= frame_size;
+ /* Align the stack pointer according to the i386 ABI,
+ * i.e. so that on function entry ((sp + 4) & 15) == 0. */
+ esp = ((esp + 4) & -16ul) - 4;
+ return (void __user *) esp;
}
/* These symbols are defined with the addresses in the vsyscall page.
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,11 @@
rsp = (unsigned long) ka->sa.sa_restorer;
}
- return (void __user *)((rsp - frame_size) & -8UL);
+ rsp -= frame_size;
+ /* Align the stack pointer according to the i386 ABI,
+ * i.e. so that on function entry ((sp + 4) & 15) == 0. */
+ rsp = ((rsp + 4) & -16ul) - 4;
+ return (void __user *) rsp;
}
int ia32_setup_frame(int sig, struct k_sigaction *ka,
[-- Attachment #3: test_sigframe_alignment.c --]
[-- Type: text/plain, Size: 1561 bytes --]
/* test signal stack alignment (sigframe)
*
* a small user-space demo program to show that the signal stack
* is currently mis-aligned on i386-linux
*
* Markus F.X.J. Oberhumer <markus@oberhumer.com>
*/
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
void sighandler(int);
void test(void);
volatile unsigned long sp = 0;
/* assembler prologue code that stores the stack pointer into 'sp'
* and then jumps to the real function */
#if defined(__i386__)
asm(
".text\n"
"sighandler:\n"
"lea 4(%esp), %eax\n"
"mov %eax, (sp)\n"
"jmp do_sighandler\n"
"test:\n"
"lea 4(%esp), %eax\n"
"mov %eax, (sp)\n"
"jmp do_test\n"
".globl main\n"
"main:\n"
"lea 4(%esp), %eax\n"
"mov %eax, (sp)\n"
"jmp do_main\n"
);
#elif defined(__x86_64__)
asm(
".text\n"
"sighandler:\n"
"lea 8(%rsp), %rax\n"
"mov %rax, sp(%rip)\n"
"jmp do_sighandler\n"
"test:\n"
"lea 8(%rsp), %rax\n"
"mov %rax, sp(%rip)\n"
"jmp do_test\n"
".globl main\n"
"main:\n"
"lea 8(%rsp), %rax\n"
"mov %rax, sp(%rip)\n"
"jmp do_main\n"
);
#else
#error "arch not supported - please insert your code here"
#endif
void do_sighandler(void)
{
printf("in sighandler: sp = 0x%lx\n", sp);
}
void do_test(void)
{
printf("in test : sp = 0x%lx\n", sp);
signal(SIGUSR1, sighandler);
raise(SIGUSR1);
}
int do_main(void)
{
printf("in main : sp = 0x%lx\n", sp);
test();
printf("All done.\n");
return 0;
}
/* vim:set ts=4 et: */
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] i386: fix stack alignment for signal handlers
2005-10-09 16:54 ` Markus F.X.J. Oberhumer
@ 2005-10-09 16:57 ` Andi Kleen
2005-10-09 17:06 ` Markus F.X.J. Oberhumer
2005-10-11 0:23 ` Markus F.X.J. Oberhumer
0 siblings, 2 replies; 14+ messages in thread
From: Andi Kleen @ 2005-10-09 16:57 UTC (permalink / raw)
To: Markus F.X.J. Oberhumer; +Cc: Linus Torvalds, Daniel Jacobowitz, linux-kernel
On Sunday 09 October 2005 18:54, Markus F.X.J. Oberhumer wrote:
> Here is a somewhat simplified version of my previous patch with
> updated comments.
>
> Attached is also a new small user-space test program which does not
> depend on any special gcc features and should trigger the problem on all
> machines.
I already have a version of the patch in my queue, but it's not a strict
bugfix so it's only for after 2.6.14.
-Andi
ftp://ftp.firstfloor.org/pub/ak/x86_64/quilt-current/patches/sigframe-alignment
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] i386: fix stack alignment for signal handlers
2005-10-09 16:57 ` Andi Kleen
@ 2005-10-09 17:06 ` Markus F.X.J. Oberhumer
2005-10-11 0:23 ` Markus F.X.J. Oberhumer
1 sibling, 0 replies; 14+ messages in thread
From: Markus F.X.J. Oberhumer @ 2005-10-09 17:06 UTC (permalink / raw)
To: Andi Kleen; +Cc: Linus Torvalds, Daniel Jacobowitz, linux-kernel
Andi Kleen wrote:
> On Sunday 09 October 2005 18:54, Markus F.X.J. Oberhumer wrote:
>
>
>>Here is a somewhat simplified version of my previous patch with
>>updated comments.
>>
>>Attached is also a new small user-space test program which does not
>>depend on any special gcc features and should trigger the problem on all
>>machines.
>
>
> I already have a version of the patch in my queue, but it's not a strict
> bugfix so it's only for after 2.6.14.
I see, many thanks.
Please note that your current version could waste 16-bytes for unneeded
alignment, while my new version does not. Not a real problem, but still
things like these should be done right.
~Markus
>
> -Andi
>
> ftp://ftp.firstfloor.org/pub/ak/x86_64/quilt-current/patches/sigframe-alignment
>
>
--
Markus Oberhumer, <markus@oberhumer.com>, http://www.oberhumer.com/
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH] i386: fix stack alignment for signal handlers
2005-10-09 16:57 ` Andi Kleen
2005-10-09 17:06 ` Markus F.X.J. Oberhumer
@ 2005-10-11 0:23 ` Markus F.X.J. Oberhumer
1 sibling, 0 replies; 14+ messages in thread
From: Markus F.X.J. Oberhumer @ 2005-10-11 0:23 UTC (permalink / raw)
To: Linus Torvalds; +Cc: Andi Kleen, linux-kernel
[-- Attachment #1: Type: text/plain, Size: 833 bytes --]
I've just seen that Linus has merged my second patch, so here is one more
missing piece to fix ia64 in ia32 emulation as well.
~Markus
p.s. this patch has not been tested due to lack of hardware
Andi Kleen wrote:
> On Sunday 09 October 2005 18:54, Markus F.X.J. Oberhumer wrote:
>
>
>>Here is a somewhat simplified version of my previous patch with
>>updated comments.
>>
>>Attached is also a new small user-space test program which does not
>>depend on any special gcc features and should trigger the problem on all
>>machines.
>
>
> I already have a version of the patch in my queue, but it's not a strict
> bugfix so it's only for after 2.6.14.
>
> -Andi
>
> ftp://ftp.firstfloor.org/pub/ak/x86_64/quilt-current/patches/sigframe-alignment
>
>
--
Markus Oberhumer, <markus@oberhumer.com>, http://www.oberhumer.com/
[-- Attachment #2: i386-align_sigframe-ia64.patch --]
[-- Type: text/x-patch, Size: 1219 bytes --]
[PATCH] i386: fix stack alignment for signal handlers (ia64)
This fixes the setup of the alignment of the signal frame, so that all
signal handlers are run with a properly aligned stack frame.
The current code "over-aligns" the stack pointer so that the stack frame
is effectively always mis-aligned by 4 bytes. But what we really want
is that on function entry ((sp + 4) & 15) == 0, which matches what would
happen if the stack were aligned before a "call" instruction.
[ This patch fixes ia64. i386 and x86_64 are already fixed by
git commit d347f372273c2b3d86a66e2e1c94c790c208e166 ]
Signed-off-by: Markus F.X.J. Oberhumer <markus@oberhumer.com>
Index: linux-2.6.git/arch/ia64/ia32/ia32_signal.c
===================================================================
--- linux-2.6.git.orig/arch/ia64/ia32/ia32_signal.c
+++ linux-2.6.git/arch/ia64/ia32/ia32_signal.c
@@ -810,7 +810,11 @@
}
/* Legacy stack switching not supported */
- return (void __user *)((esp - frame_size) & -8ul);
+ esp -= frame_size;
+ /* Align the stack pointer according to the i386 ABI,
+ * i.e. so that on function entry ((sp + 4) & 15) == 0. */
+ esp = ((esp + 4) & -16ul) - 4;
+ return (void __user *) esp;
}
static int
^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2005-10-11 0:22 UTC | newest]
Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-09-13 20:55 [PATCH] i386: fix stack alignment for signal handlers Markus F.X.J. Oberhumer
2005-09-13 22:53 ` Linus Torvalds
2005-09-13 23:30 ` Markus F.X.J. Oberhumer
2005-09-13 23:52 ` Linus Torvalds
2005-09-14 1:39 ` Markus F.X.J. Oberhumer
2005-09-14 4:54 ` Andi Kleen
2005-09-14 14:22 ` Daniel Jacobowitz
2005-09-14 14:55 ` Linus Torvalds
2005-09-14 15:44 ` Andi Kleen
2005-10-09 16:54 ` Markus F.X.J. Oberhumer
2005-10-09 16:57 ` Andi Kleen
2005-10-09 17:06 ` Markus F.X.J. Oberhumer
2005-10-11 0:23 ` Markus F.X.J. Oberhumer
2005-09-14 20:11 ` J.A. Magallon
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox