aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorJeff Dike <jdike@addtoit.com>2005-12-18 11:50:39 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2005-12-18 14:19:44 -0500
commit5b7b15afee89d6940482259b54d0864b7b2302b0 (patch)
treea3294a2c1f14ff4ebc9d645189ad12070529a639 /arch
parent76c842d8f8096e2c98ff9ebe1db861363ff254e5 (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')
-rw-r--r--arch/um/include/sysdep-i386/stub.h29
-rw-r--r--arch/um/include/sysdep-x86_64/stub.h30
-rw-r--r--arch/um/kernel/skas/clone.c23
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
12extern void stub_segv_handler(int sig); 16extern void stub_segv_handler(int sig);
13extern void stub_clone_handler(void); 17extern 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
79static inline long stub_syscall6(long syscall, long arg1, long arg2, long arg3, 83static 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
93static inline void trap_myself(void) 88static 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
12extern void stub_segv_handler(int sig); 16extern void stub_segv_handler(int sig);
13extern void stub_clone_handler(void); 17extern 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
84static inline long stub_syscall6(long syscall, long arg1, long arg2, long arg3, 88static 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
98static inline void trap_myself(void) 93static 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
23void __attribute__ ((__section__ (".__syscall_stub"))) 21void __attribute__ ((__section__ (".__syscall_stub")))
24stub_clone_handler(void) 22stub_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}