diff options
author | Jeff Dike <jdike@addtoit.com> | 2005-12-18 11:50:39 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-12-18 14:19:44 -0500 |
commit | 5b7b15afee89d6940482259b54d0864b7b2302b0 (patch) | |
tree | a3294a2c1f14ff4ebc9d645189ad12070529a639 /arch/um | |
parent | 76c842d8f8096e2c98ff9ebe1db861363ff254e5 (diff) |
[PATCH] uml skas0: stop gcc's insanity
With Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
UML skas0 stub has been miscompiling for many people (incidentally not
the authors), depending on the used GCC versions.
I think (and testing on some GCC versions shows) this patch avoids the
fundamental issue which is behind this, namely gcc using the stack when
we have just replaced it, behind gcc's back. The remapping and storage
of the return value is hidden in a blob of asm, hopefully giving gcc no
room for creativity.
Signed-off-by: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch/um')
-rw-r--r-- | arch/um/include/sysdep-i386/stub.h | 29 | ||||
-rw-r--r-- | arch/um/include/sysdep-x86_64/stub.h | 30 | ||||
-rw-r--r-- | arch/um/kernel/skas/clone.c | 23 |
3 files changed, 46 insertions, 36 deletions
diff --git a/arch/um/include/sysdep-i386/stub.h b/arch/um/include/sysdep-i386/stub.h index 6ba8cbbe0d36..b492b12b4a10 100644 --- a/arch/um/include/sysdep-i386/stub.h +++ b/arch/um/include/sysdep-i386/stub.h | |||
@@ -6,8 +6,12 @@ | |||
6 | #ifndef __SYSDEP_STUB_H | 6 | #ifndef __SYSDEP_STUB_H |
7 | #define __SYSDEP_STUB_H | 7 | #define __SYSDEP_STUB_H |
8 | 8 | ||
9 | #include <sys/mman.h> | ||
9 | #include <asm/ptrace.h> | 10 | #include <asm/ptrace.h> |
10 | #include <asm/unistd.h> | 11 | #include <asm/unistd.h> |
12 | #include "stub-data.h" | ||
13 | #include "kern_constants.h" | ||
14 | #include "uml-config.h" | ||
11 | 15 | ||
12 | extern void stub_segv_handler(int sig); | 16 | extern void stub_segv_handler(int sig); |
13 | extern void stub_clone_handler(void); | 17 | extern void stub_clone_handler(void); |
@@ -76,23 +80,22 @@ static inline long stub_syscall5(long syscall, long arg1, long arg2, long arg3, | |||
76 | return ret; | 80 | return ret; |
77 | } | 81 | } |
78 | 82 | ||
79 | static inline long stub_syscall6(long syscall, long arg1, long arg2, long arg3, | 83 | static inline void trap_myself(void) |
80 | long arg4, long arg5, long arg6) | ||
81 | { | 84 | { |
82 | long ret; | 85 | __asm("int3"); |
83 | |||
84 | __asm__ volatile ("push %%ebp ; movl %%eax,%%ebp ; movl %1,%%eax ; " | ||
85 | "int $0x80 ; pop %%ebp" | ||
86 | : "=a" (ret) | ||
87 | : "g" (syscall), "b" (arg1), "c" (arg2), "d" (arg3), | ||
88 | "S" (arg4), "D" (arg5), "0" (arg6)); | ||
89 | |||
90 | return ret; | ||
91 | } | 86 | } |
92 | 87 | ||
93 | static inline void trap_myself(void) | 88 | static inline void remap_stack(int fd, unsigned long offset) |
94 | { | 89 | { |
95 | __asm("int3"); | 90 | __asm__ volatile ("movl %%eax,%%ebp ; movl %0,%%eax ; int $0x80 ;" |
91 | "movl %7, %%ebx ; movl %%eax, (%%ebx)" | ||
92 | : : "g" (STUB_MMAP_NR), "b" (UML_CONFIG_STUB_DATA), | ||
93 | "c" (UM_KERN_PAGE_SIZE), | ||
94 | "d" (PROT_READ | PROT_WRITE), | ||
95 | "S" (MAP_FIXED | MAP_SHARED), "D" (fd), | ||
96 | "a" (offset), | ||
97 | "i" (&((struct stub_data *) UML_CONFIG_STUB_DATA)->err) | ||
98 | : "memory"); | ||
96 | } | 99 | } |
97 | 100 | ||
98 | #endif | 101 | #endif |
diff --git a/arch/um/include/sysdep-x86_64/stub.h b/arch/um/include/sysdep-x86_64/stub.h index c41689c13dc9..92e989f81761 100644 --- a/arch/um/include/sysdep-x86_64/stub.h +++ b/arch/um/include/sysdep-x86_64/stub.h | |||
@@ -6,8 +6,12 @@ | |||
6 | #ifndef __SYSDEP_STUB_H | 6 | #ifndef __SYSDEP_STUB_H |
7 | #define __SYSDEP_STUB_H | 7 | #define __SYSDEP_STUB_H |
8 | 8 | ||
9 | #include <sys/mman.h> | ||
9 | #include <asm/unistd.h> | 10 | #include <asm/unistd.h> |
10 | #include <sysdep/ptrace_user.h> | 11 | #include <sysdep/ptrace_user.h> |
12 | #include "stub-data.h" | ||
13 | #include "kern_constants.h" | ||
14 | #include "uml-config.h" | ||
11 | 15 | ||
12 | extern void stub_segv_handler(int sig); | 16 | extern void stub_segv_handler(int sig); |
13 | extern void stub_clone_handler(void); | 17 | extern void stub_clone_handler(void); |
@@ -81,23 +85,23 @@ static inline long stub_syscall5(long syscall, long arg1, long arg2, long arg3, | |||
81 | return ret; | 85 | return ret; |
82 | } | 86 | } |
83 | 87 | ||
84 | static inline long stub_syscall6(long syscall, long arg1, long arg2, long arg3, | 88 | static inline void trap_myself(void) |
85 | long arg4, long arg5, long arg6) | ||
86 | { | 89 | { |
87 | long ret; | 90 | __asm("int3"); |
88 | |||
89 | __asm__ volatile ("movq %5,%%r10 ; movq %6,%%r8 ; " | ||
90 | "movq %7, %%r9; " __syscall : "=a" (ret) | ||
91 | : "0" (syscall), "D" (arg1), "S" (arg2), "d" (arg3), | ||
92 | "g" (arg4), "g" (arg5), "g" (arg6) | ||
93 | : __syscall_clobber, "r10", "r8", "r9" ); | ||
94 | |||
95 | return ret; | ||
96 | } | 91 | } |
97 | 92 | ||
98 | static inline void trap_myself(void) | 93 | static inline void remap_stack(long fd, unsigned long offset) |
99 | { | 94 | { |
100 | __asm("int3"); | 95 | __asm__ volatile ("movq %4,%%r10 ; movq %5,%%r8 ; " |
96 | "movq %6, %%r9; " __syscall "; movq %7, %%rbx ; " | ||
97 | "movq %%rax, (%%rbx)": | ||
98 | : "a" (STUB_MMAP_NR), "D" (UML_CONFIG_STUB_DATA), | ||
99 | "S" (UM_KERN_PAGE_SIZE), | ||
100 | "d" (PROT_READ | PROT_WRITE), | ||
101 | "g" (MAP_FIXED | MAP_SHARED), "g" (fd), | ||
102 | "g" (offset), | ||
103 | "i" (&((struct stub_data *) UML_CONFIG_STUB_DATA)->err) | ||
104 | : __syscall_clobber, "r10", "r8", "r9" ); | ||
101 | } | 105 | } |
102 | 106 | ||
103 | #endif | 107 | #endif |
diff --git a/arch/um/kernel/skas/clone.c b/arch/um/kernel/skas/clone.c index cb37ce9124a6..47b812b3bca8 100644 --- a/arch/um/kernel/skas/clone.c +++ b/arch/um/kernel/skas/clone.c | |||
@@ -18,11 +18,10 @@ | |||
18 | * on some systems. | 18 | * on some systems. |
19 | */ | 19 | */ |
20 | 20 | ||
21 | #define STUB_DATA(field) (((struct stub_data *) UML_CONFIG_STUB_DATA)->field) | ||
22 | |||
23 | void __attribute__ ((__section__ (".__syscall_stub"))) | 21 | void __attribute__ ((__section__ (".__syscall_stub"))) |
24 | stub_clone_handler(void) | 22 | stub_clone_handler(void) |
25 | { | 23 | { |
24 | struct stub_data *data = (struct stub_data *) UML_CONFIG_STUB_DATA; | ||
26 | long err; | 25 | long err; |
27 | 26 | ||
28 | err = stub_syscall2(__NR_clone, CLONE_PARENT | CLONE_FILES | SIGCHLD, | 27 | err = stub_syscall2(__NR_clone, CLONE_PARENT | CLONE_FILES | SIGCHLD, |
@@ -35,17 +34,21 @@ stub_clone_handler(void) | |||
35 | if(err) | 34 | if(err) |
36 | goto out; | 35 | goto out; |
37 | 36 | ||
38 | err = stub_syscall3(__NR_setitimer, ITIMER_VIRTUAL, | 37 | err = stub_syscall3(__NR_setitimer, ITIMER_VIRTUAL, |
39 | (long) &STUB_DATA(timer), 0); | 38 | (long) &data->timer, 0); |
40 | if(err) | 39 | if(err) |
41 | goto out; | 40 | goto out; |
42 | 41 | ||
43 | err = stub_syscall6(STUB_MMAP_NR, UML_CONFIG_STUB_DATA, | 42 | remap_stack(data->fd, data->offset); |
44 | UM_KERN_PAGE_SIZE, PROT_READ | PROT_WRITE, | 43 | goto done; |
45 | MAP_FIXED | MAP_SHARED, STUB_DATA(fd), | 44 | |
46 | STUB_DATA(offset)); | ||
47 | out: | 45 | out: |
48 | /* save current result. Parent: pid; child: retcode of mmap */ | 46 | /* save current result. |
49 | STUB_DATA(err) = err; | 47 | * Parent: pid; |
48 | * child: retcode of mmap already saved and it jumps around this | ||
49 | * assignment | ||
50 | */ | ||
51 | data->err = err; | ||
52 | done: | ||
50 | trap_myself(); | 53 | trap_myself(); |
51 | } | 54 | } |