diff options
author | Jeff Dike <jdike@addtoit.com> | 2005-11-22 00:32:04 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2005-11-22 12:13:41 -0500 |
commit | 39d730ab87f07592e3a3794353f097d5184cae7a (patch) | |
tree | 36cb363e0815cb7508227a5063a677fe95e0fa4b | |
parent | 18317ab0ca5ac0c654be3eac31ebb781b4a5e9b2 (diff) |
[PATCH] uml: eliminate use of local in clone stub
We have a bug in the i386 stub_syscall6 which pushes ebp before the system
call and pops it afterwards. Because we use syscall6 to remap the stack, the
old contents of the stack (and the former value of ebp) are no longer
available. Some versions of gcc make from a real local, accessed through ebp,
despite my efforts to make it obvious that references to from are really
constants. This patch attempts to make it even more obvious by eliminating
from and using a macro to access the stub's data explicitly with constants.
My original thinking on this was to replace syscall6 with a remap_stack
interface which saved ebp someplace and restored it afterwards. The problem
is that there are no registers to put it in, except for esp. That could work,
since we can store a constant in esp after the mmap because we just replaced
the stack. However, this approach seems a tad cleaner.
Signed-off-by: Jeff Dike <jdike@addtoit.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | arch/um/kernel/skas/clone.c | 10 |
1 files changed, 6 insertions, 4 deletions
diff --git a/arch/um/kernel/skas/clone.c b/arch/um/kernel/skas/clone.c index 4dc55f10cd18..39c0d7145d31 100644 --- a/arch/um/kernel/skas/clone.c +++ b/arch/um/kernel/skas/clone.c | |||
@@ -13,11 +13,13 @@ | |||
13 | /* This is in a separate file because it needs to be compiled with any | 13 | /* This is in a separate file because it needs to be compiled with any |
14 | * extraneous gcc flags (-pg, -fprofile-arcs, -ftest-coverage) disabled | 14 | * extraneous gcc flags (-pg, -fprofile-arcs, -ftest-coverage) disabled |
15 | */ | 15 | */ |
16 | |||
17 | #define STUB_DATA(field) (((struct stub_data *) UML_CONFIG_STUB_DATA)->field) | ||
18 | |||
16 | void __attribute__ ((__section__ (".__syscall_stub"))) | 19 | void __attribute__ ((__section__ (".__syscall_stub"))) |
17 | stub_clone_handler(void) | 20 | stub_clone_handler(void) |
18 | { | 21 | { |
19 | long err; | 22 | long err; |
20 | struct stub_data *from = (struct stub_data *) UML_CONFIG_STUB_DATA; | ||
21 | 23 | ||
22 | err = stub_syscall2(__NR_clone, CLONE_PARENT | CLONE_FILES | SIGCHLD, | 24 | err = stub_syscall2(__NR_clone, CLONE_PARENT | CLONE_FILES | SIGCHLD, |
23 | UML_CONFIG_STUB_DATA + PAGE_SIZE / 2 - | 25 | UML_CONFIG_STUB_DATA + PAGE_SIZE / 2 - |
@@ -30,15 +32,15 @@ stub_clone_handler(void) | |||
30 | goto out; | 32 | goto out; |
31 | 33 | ||
32 | err = stub_syscall3(__NR_setitimer, ITIMER_VIRTUAL, | 34 | err = stub_syscall3(__NR_setitimer, ITIMER_VIRTUAL, |
33 | (long) &from->timer, 0); | 35 | (long) &STUB_DATA(timer), 0); |
34 | if(err) | 36 | if(err) |
35 | goto out; | 37 | goto out; |
36 | 38 | ||
37 | err = stub_syscall6(STUB_MMAP_NR, UML_CONFIG_STUB_DATA, PAGE_SIZE, | 39 | err = stub_syscall6(STUB_MMAP_NR, UML_CONFIG_STUB_DATA, PAGE_SIZE, |
38 | PROT_READ | PROT_WRITE, MAP_FIXED | MAP_SHARED, | 40 | PROT_READ | PROT_WRITE, MAP_FIXED | MAP_SHARED, |
39 | from->fd, from->offset); | 41 | STUB_DATA(fd), STUB_DATA(offset)); |
40 | out: | 42 | out: |
41 | /* save current result. Parent: pid; child: retcode of mmap */ | 43 | /* save current result. Parent: pid; child: retcode of mmap */ |
42 | from->err = err; | 44 | STUB_DATA(err) = err; |
43 | trap_myself(); | 45 | trap_myself(); |
44 | } | 46 | } |