diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-12-12 15:22:13 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-12-12 15:22:13 -0500 |
commit | 9977d9b379cb77e0f67bd6f4563618106e58e11d (patch) | |
tree | 0191accfddf578edb52c69c933d64521e3dce297 /arch/x86 | |
parent | cf4af01221579a4e895f43dbfc47598fbfc5a731 (diff) | |
parent | 541880d9a2c7871f6370071d55aa6662d329c51e (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/signal
Pull big execve/kernel_thread/fork unification series from Al Viro:
"All architectures are converted to new model. Quite a bit of that
stuff is actually shared with architecture trees; in such cases it's
literally shared branch pulled by both, not a cherry-pick.
A lot of ugliness and black magic is gone (-3KLoC total in this one):
- kernel_thread()/kernel_execve()/sys_execve() redesign.
We don't do syscalls from kernel anymore for either kernel_thread()
or kernel_execve():
kernel_thread() is essentially clone(2) with callback run before we
return to userland, the callbacks either never return or do
successful do_execve() before returning.
kernel_execve() is a wrapper for do_execve() - it doesn't need to
do transition to user mode anymore.
As a result kernel_thread() and kernel_execve() are
arch-independent now - they live in kernel/fork.c and fs/exec.c
resp. sys_execve() is also in fs/exec.c and it's completely
architecture-independent.
- daemonize() is gone, along with its parts in fs/*.c
- struct pt_regs * is no longer passed to do_fork/copy_process/
copy_thread/do_execve/search_binary_handler/->load_binary/do_coredump.
- sys_fork()/sys_vfork()/sys_clone() unified; some architectures
still need wrappers (ones with callee-saved registers not saved in
pt_regs on syscall entry), but the main part of those suckers is in
kernel/fork.c now."
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/signal: (113 commits)
do_coredump(): get rid of pt_regs argument
print_fatal_signal(): get rid of pt_regs argument
ptrace_signal(): get rid of unused arguments
get rid of ptrace_signal_deliver() arguments
new helper: signal_pt_regs()
unify default ptrace_signal_deliver
flagday: kill pt_regs argument of do_fork()
death to idle_regs()
don't pass regs to copy_process()
flagday: don't pass regs to copy_thread()
bfin: switch to generic vfork, get rid of pointless wrappers
xtensa: switch to generic clone()
openrisc: switch to use of generic fork and clone
unicore32: switch to generic clone(2)
score: switch to generic fork/vfork/clone
c6x: sanitize copy_thread(), get rid of clone(2) wrapper, switch to generic clone()
take sys_fork/sys_vfork/sys_clone prototypes to linux/syscalls.h
mn10300: switch to generic fork/vfork/clone
h8300: switch to generic fork/vfork/clone
tile: switch to generic clone()
...
Conflicts:
arch/microblaze/include/asm/Kbuild
Diffstat (limited to 'arch/x86')
-rw-r--r-- | arch/x86/Kconfig | 1 | ||||
-rw-r--r-- | arch/x86/ia32/ia32_aout.c | 5 | ||||
-rw-r--r-- | arch/x86/ia32/ia32entry.S | 7 | ||||
-rw-r--r-- | arch/x86/ia32/sys_ia32.c | 11 | ||||
-rw-r--r-- | arch/x86/include/asm/processor.h | 2 | ||||
-rw-r--r-- | arch/x86/include/asm/signal.h | 2 | ||||
-rw-r--r-- | arch/x86/include/asm/sys_ia32.h | 2 | ||||
-rw-r--r-- | arch/x86/include/asm/syscalls.h | 9 | ||||
-rw-r--r-- | arch/x86/include/asm/unistd.h | 3 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/common.c | 9 | ||||
-rw-r--r-- | arch/x86/kernel/entry_32.S | 18 | ||||
-rw-r--r-- | arch/x86/kernel/entry_64.S | 22 | ||||
-rw-r--r-- | arch/x86/kernel/process.c | 30 | ||||
-rw-r--r-- | arch/x86/kernel/process_32.c | 12 | ||||
-rw-r--r-- | arch/x86/kernel/process_64.c | 10 | ||||
-rw-r--r-- | arch/x86/syscalls/syscall_32.tbl | 6 | ||||
-rw-r--r-- | arch/x86/um/Kconfig | 1 | ||||
-rw-r--r-- | arch/x86/um/shared/sysdep/syscalls.h | 2 | ||||
-rw-r--r-- | arch/x86/um/sys_call_table_32.c | 3 | ||||
-rw-r--r-- | arch/x86/um/syscalls_32.c | 15 |
20 files changed, 47 insertions, 123 deletions
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 037c4e30c271..9195fd80e11e 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig | |||
@@ -112,6 +112,7 @@ config X86 | |||
112 | select GENERIC_KERNEL_EXECVE | 112 | select GENERIC_KERNEL_EXECVE |
113 | select MODULES_USE_ELF_REL if X86_32 | 113 | select MODULES_USE_ELF_REL if X86_32 |
114 | select MODULES_USE_ELF_RELA if X86_64 | 114 | select MODULES_USE_ELF_RELA if X86_64 |
115 | select CLONE_BACKWARDS if X86_32 | ||
115 | 116 | ||
116 | config INSTRUCTION_DECODER | 117 | config INSTRUCTION_DECODER |
117 | def_bool y | 118 | def_bool y |
diff --git a/arch/x86/ia32/ia32_aout.c b/arch/x86/ia32/ia32_aout.c index 07b3a68d2d29..a703af19c281 100644 --- a/arch/x86/ia32/ia32_aout.c +++ b/arch/x86/ia32/ia32_aout.c | |||
@@ -35,7 +35,7 @@ | |||
35 | #undef WARN_OLD | 35 | #undef WARN_OLD |
36 | #undef CORE_DUMP /* definitely broken */ | 36 | #undef CORE_DUMP /* definitely broken */ |
37 | 37 | ||
38 | static int load_aout_binary(struct linux_binprm *, struct pt_regs *regs); | 38 | static int load_aout_binary(struct linux_binprm *); |
39 | static int load_aout_library(struct file *); | 39 | static int load_aout_library(struct file *); |
40 | 40 | ||
41 | #ifdef CORE_DUMP | 41 | #ifdef CORE_DUMP |
@@ -260,9 +260,10 @@ static u32 __user *create_aout_tables(char __user *p, struct linux_binprm *bprm) | |||
260 | * These are the functions used to load a.out style executables and shared | 260 | * These are the functions used to load a.out style executables and shared |
261 | * libraries. There is no binary dependent code anywhere else. | 261 | * libraries. There is no binary dependent code anywhere else. |
262 | */ | 262 | */ |
263 | static int load_aout_binary(struct linux_binprm *bprm, struct pt_regs *regs) | 263 | static int load_aout_binary(struct linux_binprm *bprm) |
264 | { | 264 | { |
265 | unsigned long error, fd_offset, rlim; | 265 | unsigned long error, fd_offset, rlim; |
266 | struct pt_regs *regs = current_pt_regs(); | ||
266 | struct exec ex; | 267 | struct exec ex; |
267 | int retval; | 268 | int retval; |
268 | 269 | ||
diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S index 076745fc8045..32e6f05ddaaa 100644 --- a/arch/x86/ia32/ia32entry.S +++ b/arch/x86/ia32/ia32entry.S | |||
@@ -467,11 +467,16 @@ GLOBAL(\label) | |||
467 | PTREGSCALL stub32_sigaltstack, sys32_sigaltstack, %rdx | 467 | PTREGSCALL stub32_sigaltstack, sys32_sigaltstack, %rdx |
468 | PTREGSCALL stub32_execve, compat_sys_execve, %rcx | 468 | PTREGSCALL stub32_execve, compat_sys_execve, %rcx |
469 | PTREGSCALL stub32_fork, sys_fork, %rdi | 469 | PTREGSCALL stub32_fork, sys_fork, %rdi |
470 | PTREGSCALL stub32_clone, sys32_clone, %rdx | ||
471 | PTREGSCALL stub32_vfork, sys_vfork, %rdi | 470 | PTREGSCALL stub32_vfork, sys_vfork, %rdi |
472 | PTREGSCALL stub32_iopl, sys_iopl, %rsi | 471 | PTREGSCALL stub32_iopl, sys_iopl, %rsi |
473 | 472 | ||
474 | ALIGN | 473 | ALIGN |
474 | GLOBAL(stub32_clone) | ||
475 | leaq sys_clone(%rip),%rax | ||
476 | mov %r8, %rcx | ||
477 | jmp ia32_ptregs_common | ||
478 | |||
479 | ALIGN | ||
475 | ia32_ptregs_common: | 480 | ia32_ptregs_common: |
476 | popq %r11 | 481 | popq %r11 |
477 | CFI_ENDPROC | 482 | CFI_ENDPROC |
diff --git a/arch/x86/ia32/sys_ia32.c b/arch/x86/ia32/sys_ia32.c index 86d68d1c8806..d0b689ba7be2 100644 --- a/arch/x86/ia32/sys_ia32.c +++ b/arch/x86/ia32/sys_ia32.c | |||
@@ -385,17 +385,6 @@ asmlinkage long sys32_sendfile(int out_fd, int in_fd, | |||
385 | return ret; | 385 | return ret; |
386 | } | 386 | } |
387 | 387 | ||
388 | asmlinkage long sys32_clone(unsigned int clone_flags, unsigned int newsp, | ||
389 | struct pt_regs *regs) | ||
390 | { | ||
391 | void __user *parent_tid = (void __user *)regs->dx; | ||
392 | void __user *child_tid = (void __user *)regs->di; | ||
393 | |||
394 | if (!newsp) | ||
395 | newsp = regs->sp; | ||
396 | return do_fork(clone_flags, newsp, regs, 0, parent_tid, child_tid); | ||
397 | } | ||
398 | |||
399 | /* | 388 | /* |
400 | * Some system calls that need sign extended arguments. This could be | 389 | * Some system calls that need sign extended arguments. This could be |
401 | * done by a generic wrapper. | 390 | * done by a generic wrapper. |
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index e101b38912de..888184b2fc85 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h | |||
@@ -178,8 +178,6 @@ static inline int hlt_works(int cpu) | |||
178 | 178 | ||
179 | extern void cpu_detect(struct cpuinfo_x86 *c); | 179 | extern void cpu_detect(struct cpuinfo_x86 *c); |
180 | 180 | ||
181 | extern struct pt_regs *idle_regs(struct pt_regs *); | ||
182 | |||
183 | extern void early_cpu_init(void); | 181 | extern void early_cpu_init(void); |
184 | extern void identify_boot_cpu(void); | 182 | extern void identify_boot_cpu(void); |
185 | extern void identify_secondary_cpu(struct cpuinfo_x86 *); | 183 | extern void identify_secondary_cpu(struct cpuinfo_x86 *); |
diff --git a/arch/x86/include/asm/signal.h b/arch/x86/include/asm/signal.h index 323973f4abf1..0dba8b7a6ac7 100644 --- a/arch/x86/include/asm/signal.h +++ b/arch/x86/include/asm/signal.h | |||
@@ -260,8 +260,6 @@ struct pt_regs; | |||
260 | 260 | ||
261 | #endif /* !__i386__ */ | 261 | #endif /* !__i386__ */ |
262 | 262 | ||
263 | #define ptrace_signal_deliver(regs, cookie) do { } while (0) | ||
264 | |||
265 | #endif /* __KERNEL__ */ | 263 | #endif /* __KERNEL__ */ |
266 | #endif /* __ASSEMBLY__ */ | 264 | #endif /* __ASSEMBLY__ */ |
267 | 265 | ||
diff --git a/arch/x86/include/asm/sys_ia32.h b/arch/x86/include/asm/sys_ia32.h index a9a8cf3da49d..c76fae4d90be 100644 --- a/arch/x86/include/asm/sys_ia32.h +++ b/arch/x86/include/asm/sys_ia32.h | |||
@@ -54,8 +54,6 @@ asmlinkage long sys32_pwrite(unsigned int, const char __user *, u32, u32, u32); | |||
54 | asmlinkage long sys32_personality(unsigned long); | 54 | asmlinkage long sys32_personality(unsigned long); |
55 | asmlinkage long sys32_sendfile(int, int, compat_off_t __user *, s32); | 55 | asmlinkage long sys32_sendfile(int, int, compat_off_t __user *, s32); |
56 | 56 | ||
57 | asmlinkage long sys32_clone(unsigned int, unsigned int, struct pt_regs *); | ||
58 | |||
59 | long sys32_lseek(unsigned int, int, unsigned int); | 57 | long sys32_lseek(unsigned int, int, unsigned int); |
60 | long sys32_kill(int, int); | 58 | long sys32_kill(int, int); |
61 | long sys32_fadvise64_64(int, __u32, __u32, __u32, __u32, int); | 59 | long sys32_fadvise64_64(int, __u32, __u32, __u32, __u32, int); |
diff --git a/arch/x86/include/asm/syscalls.h b/arch/x86/include/asm/syscalls.h index 2be0b880417e..2f8374718aa3 100644 --- a/arch/x86/include/asm/syscalls.h +++ b/arch/x86/include/asm/syscalls.h | |||
@@ -20,15 +20,6 @@ | |||
20 | asmlinkage long sys_ioperm(unsigned long, unsigned long, int); | 20 | asmlinkage long sys_ioperm(unsigned long, unsigned long, int); |
21 | long sys_iopl(unsigned int, struct pt_regs *); | 21 | long sys_iopl(unsigned int, struct pt_regs *); |
22 | 22 | ||
23 | /* kernel/process.c */ | ||
24 | int sys_fork(struct pt_regs *); | ||
25 | int sys_vfork(struct pt_regs *); | ||
26 | long sys_execve(const char __user *, | ||
27 | const char __user *const __user *, | ||
28 | const char __user *const __user *); | ||
29 | long sys_clone(unsigned long, unsigned long, void __user *, | ||
30 | void __user *, struct pt_regs *); | ||
31 | |||
32 | /* kernel/ldt.c */ | 23 | /* kernel/ldt.c */ |
33 | asmlinkage int sys_modify_ldt(int, void __user *, unsigned long); | 24 | asmlinkage int sys_modify_ldt(int, void __user *, unsigned long); |
34 | 25 | ||
diff --git a/arch/x86/include/asm/unistd.h b/arch/x86/include/asm/unistd.h index 16f3fc6ebf2e..0e7dea7d3669 100644 --- a/arch/x86/include/asm/unistd.h +++ b/arch/x86/include/asm/unistd.h | |||
@@ -51,6 +51,9 @@ | |||
51 | # define __ARCH_WANT_SYS_UTIME | 51 | # define __ARCH_WANT_SYS_UTIME |
52 | # define __ARCH_WANT_SYS_WAITPID | 52 | # define __ARCH_WANT_SYS_WAITPID |
53 | # define __ARCH_WANT_SYS_EXECVE | 53 | # define __ARCH_WANT_SYS_EXECVE |
54 | # define __ARCH_WANT_SYS_FORK | ||
55 | # define __ARCH_WANT_SYS_VFORK | ||
56 | # define __ARCH_WANT_SYS_CLONE | ||
54 | 57 | ||
55 | /* | 58 | /* |
56 | * "Conditional" syscalls | 59 | * "Conditional" syscalls |
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index ca165ac6793b..9c3ab43a6954 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c | |||
@@ -1173,15 +1173,6 @@ DEFINE_PER_CPU(struct task_struct *, fpu_owner_task); | |||
1173 | DEFINE_PER_CPU_ALIGNED(struct stack_canary, stack_canary); | 1173 | DEFINE_PER_CPU_ALIGNED(struct stack_canary, stack_canary); |
1174 | #endif | 1174 | #endif |
1175 | 1175 | ||
1176 | /* Make sure %fs and %gs are initialized properly in idle threads */ | ||
1177 | struct pt_regs * __cpuinit idle_regs(struct pt_regs *regs) | ||
1178 | { | ||
1179 | memset(regs, 0, sizeof(struct pt_regs)); | ||
1180 | regs->fs = __KERNEL_PERCPU; | ||
1181 | regs->gs = __KERNEL_STACK_CANARY; | ||
1182 | |||
1183 | return regs; | ||
1184 | } | ||
1185 | #endif /* CONFIG_X86_64 */ | 1176 | #endif /* CONFIG_X86_64 */ |
1186 | 1177 | ||
1187 | /* | 1178 | /* |
diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S index 88b725aa1d52..c763116c5359 100644 --- a/arch/x86/kernel/entry_32.S +++ b/arch/x86/kernel/entry_32.S | |||
@@ -739,30 +739,12 @@ ENTRY(ptregs_##name) ; \ | |||
739 | ENDPROC(ptregs_##name) | 739 | ENDPROC(ptregs_##name) |
740 | 740 | ||
741 | PTREGSCALL1(iopl) | 741 | PTREGSCALL1(iopl) |
742 | PTREGSCALL0(fork) | ||
743 | PTREGSCALL0(vfork) | ||
744 | PTREGSCALL2(sigaltstack) | 742 | PTREGSCALL2(sigaltstack) |
745 | PTREGSCALL0(sigreturn) | 743 | PTREGSCALL0(sigreturn) |
746 | PTREGSCALL0(rt_sigreturn) | 744 | PTREGSCALL0(rt_sigreturn) |
747 | PTREGSCALL2(vm86) | 745 | PTREGSCALL2(vm86) |
748 | PTREGSCALL1(vm86old) | 746 | PTREGSCALL1(vm86old) |
749 | 747 | ||
750 | /* Clone is an oddball. The 4th arg is in %edi */ | ||
751 | ENTRY(ptregs_clone) | ||
752 | CFI_STARTPROC | ||
753 | leal 4(%esp),%eax | ||
754 | pushl_cfi %eax | ||
755 | pushl_cfi PT_EDI(%eax) | ||
756 | movl PT_EDX(%eax),%ecx | ||
757 | movl PT_ECX(%eax),%edx | ||
758 | movl PT_EBX(%eax),%eax | ||
759 | call sys_clone | ||
760 | addl $8,%esp | ||
761 | CFI_ADJUST_CFA_OFFSET -8 | ||
762 | ret | ||
763 | CFI_ENDPROC | ||
764 | ENDPROC(ptregs_clone) | ||
765 | |||
766 | .macro FIXUP_ESPFIX_STACK | 748 | .macro FIXUP_ESPFIX_STACK |
767 | /* | 749 | /* |
768 | * Switch back for ESPFIX stack to the normal zerobased stack | 750 | * Switch back for ESPFIX stack to the normal zerobased stack |
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S index 31b46128a63d..70641aff0c25 100644 --- a/arch/x86/kernel/entry_64.S +++ b/arch/x86/kernel/entry_64.S | |||
@@ -845,9 +845,25 @@ ENTRY(\label) | |||
845 | END(\label) | 845 | END(\label) |
846 | .endm | 846 | .endm |
847 | 847 | ||
848 | PTREGSCALL stub_clone, sys_clone, %r8 | 848 | .macro FORK_LIKE func |
849 | PTREGSCALL stub_fork, sys_fork, %rdi | 849 | ENTRY(stub_\func) |
850 | PTREGSCALL stub_vfork, sys_vfork, %rdi | 850 | CFI_STARTPROC |
851 | popq %r11 /* save return address */ | ||
852 | PARTIAL_FRAME 0 | ||
853 | SAVE_REST | ||
854 | pushq %r11 /* put it back on stack */ | ||
855 | FIXUP_TOP_OF_STACK %r11, 8 | ||
856 | DEFAULT_FRAME 0 8 /* offset 8: return address */ | ||
857 | call sys_\func | ||
858 | RESTORE_TOP_OF_STACK %r11, 8 | ||
859 | ret $REST_SKIP /* pop extended registers */ | ||
860 | CFI_ENDPROC | ||
861 | END(stub_\func) | ||
862 | .endm | ||
863 | |||
864 | FORK_LIKE clone | ||
865 | FORK_LIKE fork | ||
866 | FORK_LIKE vfork | ||
851 | PTREGSCALL stub_sigaltstack, sys_sigaltstack, %rdx | 867 | PTREGSCALL stub_sigaltstack, sys_sigaltstack, %rdx |
852 | PTREGSCALL stub_iopl, sys_iopl, %rsi | 868 | PTREGSCALL stub_iopl, sys_iopl, %rsi |
853 | 869 | ||
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c index 2f99e3121875..2ed787f15bf0 100644 --- a/arch/x86/kernel/process.c +++ b/arch/x86/kernel/process.c | |||
@@ -262,36 +262,6 @@ void __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p, | |||
262 | propagate_user_return_notify(prev_p, next_p); | 262 | propagate_user_return_notify(prev_p, next_p); |
263 | } | 263 | } |
264 | 264 | ||
265 | int sys_fork(struct pt_regs *regs) | ||
266 | { | ||
267 | return do_fork(SIGCHLD, regs->sp, regs, 0, NULL, NULL); | ||
268 | } | ||
269 | |||
270 | /* | ||
271 | * This is trivial, and on the face of it looks like it | ||
272 | * could equally well be done in user mode. | ||
273 | * | ||
274 | * Not so, for quite unobvious reasons - register pressure. | ||
275 | * In user mode vfork() cannot have a stack frame, and if | ||
276 | * done by calling the "clone()" system call directly, you | ||
277 | * do not have enough call-clobbered registers to hold all | ||
278 | * the information you need. | ||
279 | */ | ||
280 | int sys_vfork(struct pt_regs *regs) | ||
281 | { | ||
282 | return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->sp, regs, 0, | ||
283 | NULL, NULL); | ||
284 | } | ||
285 | |||
286 | long | ||
287 | sys_clone(unsigned long clone_flags, unsigned long newsp, | ||
288 | void __user *parent_tid, void __user *child_tid, struct pt_regs *regs) | ||
289 | { | ||
290 | if (!newsp) | ||
291 | newsp = regs->sp; | ||
292 | return do_fork(clone_flags, newsp, regs, 0, parent_tid, child_tid); | ||
293 | } | ||
294 | |||
295 | /* | 265 | /* |
296 | * Idle related variables and functions | 266 | * Idle related variables and functions |
297 | */ | 267 | */ |
diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c index 44e0bff38e72..b5a8905785e6 100644 --- a/arch/x86/kernel/process_32.c +++ b/arch/x86/kernel/process_32.c | |||
@@ -128,8 +128,7 @@ void release_thread(struct task_struct *dead_task) | |||
128 | } | 128 | } |
129 | 129 | ||
130 | int copy_thread(unsigned long clone_flags, unsigned long sp, | 130 | int copy_thread(unsigned long clone_flags, unsigned long sp, |
131 | unsigned long arg, | 131 | unsigned long arg, struct task_struct *p) |
132 | struct task_struct *p, struct pt_regs *regs) | ||
133 | { | 132 | { |
134 | struct pt_regs *childregs = task_pt_regs(p); | 133 | struct pt_regs *childregs = task_pt_regs(p); |
135 | struct task_struct *tsk; | 134 | struct task_struct *tsk; |
@@ -138,7 +137,7 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, | |||
138 | p->thread.sp = (unsigned long) childregs; | 137 | p->thread.sp = (unsigned long) childregs; |
139 | p->thread.sp0 = (unsigned long) (childregs+1); | 138 | p->thread.sp0 = (unsigned long) (childregs+1); |
140 | 139 | ||
141 | if (unlikely(!regs)) { | 140 | if (unlikely(p->flags & PF_KTHREAD)) { |
142 | /* kernel thread */ | 141 | /* kernel thread */ |
143 | memset(childregs, 0, sizeof(struct pt_regs)); | 142 | memset(childregs, 0, sizeof(struct pt_regs)); |
144 | p->thread.ip = (unsigned long) ret_from_kernel_thread; | 143 | p->thread.ip = (unsigned long) ret_from_kernel_thread; |
@@ -156,12 +155,13 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, | |||
156 | memset(p->thread.ptrace_bps, 0, sizeof(p->thread.ptrace_bps)); | 155 | memset(p->thread.ptrace_bps, 0, sizeof(p->thread.ptrace_bps)); |
157 | return 0; | 156 | return 0; |
158 | } | 157 | } |
159 | *childregs = *regs; | 158 | *childregs = *current_pt_regs(); |
160 | childregs->ax = 0; | 159 | childregs->ax = 0; |
161 | childregs->sp = sp; | 160 | if (sp) |
161 | childregs->sp = sp; | ||
162 | 162 | ||
163 | p->thread.ip = (unsigned long) ret_from_fork; | 163 | p->thread.ip = (unsigned long) ret_from_fork; |
164 | task_user_gs(p) = get_user_gs(regs); | 164 | task_user_gs(p) = get_user_gs(current_pt_regs()); |
165 | 165 | ||
166 | p->fpu_counter = 0; | 166 | p->fpu_counter = 0; |
167 | p->thread.io_bitmap_ptr = NULL; | 167 | p->thread.io_bitmap_ptr = NULL; |
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index 16c6365e2b86..6e68a6194965 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c | |||
@@ -146,8 +146,7 @@ static inline u32 read_32bit_tls(struct task_struct *t, int tls) | |||
146 | } | 146 | } |
147 | 147 | ||
148 | int copy_thread(unsigned long clone_flags, unsigned long sp, | 148 | int copy_thread(unsigned long clone_flags, unsigned long sp, |
149 | unsigned long arg, | 149 | unsigned long arg, struct task_struct *p) |
150 | struct task_struct *p, struct pt_regs *regs) | ||
151 | { | 150 | { |
152 | int err; | 151 | int err; |
153 | struct pt_regs *childregs; | 152 | struct pt_regs *childregs; |
@@ -169,7 +168,7 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, | |||
169 | savesegment(ds, p->thread.ds); | 168 | savesegment(ds, p->thread.ds); |
170 | memset(p->thread.ptrace_bps, 0, sizeof(p->thread.ptrace_bps)); | 169 | memset(p->thread.ptrace_bps, 0, sizeof(p->thread.ptrace_bps)); |
171 | 170 | ||
172 | if (unlikely(!regs)) { | 171 | if (unlikely(p->flags & PF_KTHREAD)) { |
173 | /* kernel thread */ | 172 | /* kernel thread */ |
174 | memset(childregs, 0, sizeof(struct pt_regs)); | 173 | memset(childregs, 0, sizeof(struct pt_regs)); |
175 | childregs->sp = (unsigned long)childregs; | 174 | childregs->sp = (unsigned long)childregs; |
@@ -181,10 +180,11 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, | |||
181 | childregs->flags = X86_EFLAGS_IF | X86_EFLAGS_BIT1; | 180 | childregs->flags = X86_EFLAGS_IF | X86_EFLAGS_BIT1; |
182 | return 0; | 181 | return 0; |
183 | } | 182 | } |
184 | *childregs = *regs; | 183 | *childregs = *current_pt_regs(); |
185 | 184 | ||
186 | childregs->ax = 0; | 185 | childregs->ax = 0; |
187 | childregs->sp = sp; | 186 | if (sp) |
187 | childregs->sp = sp; | ||
188 | 188 | ||
189 | err = -ENOMEM; | 189 | err = -ENOMEM; |
190 | memset(p->thread.ptrace_bps, 0, sizeof(p->thread.ptrace_bps)); | 190 | memset(p->thread.ptrace_bps, 0, sizeof(p->thread.ptrace_bps)); |
diff --git a/arch/x86/syscalls/syscall_32.tbl b/arch/x86/syscalls/syscall_32.tbl index a47103fbc692..ee3c220ee500 100644 --- a/arch/x86/syscalls/syscall_32.tbl +++ b/arch/x86/syscalls/syscall_32.tbl | |||
@@ -8,7 +8,7 @@ | |||
8 | # | 8 | # |
9 | 0 i386 restart_syscall sys_restart_syscall | 9 | 0 i386 restart_syscall sys_restart_syscall |
10 | 1 i386 exit sys_exit | 10 | 1 i386 exit sys_exit |
11 | 2 i386 fork ptregs_fork stub32_fork | 11 | 2 i386 fork sys_fork stub32_fork |
12 | 3 i386 read sys_read | 12 | 3 i386 read sys_read |
13 | 4 i386 write sys_write | 13 | 4 i386 write sys_write |
14 | 5 i386 open sys_open compat_sys_open | 14 | 5 i386 open sys_open compat_sys_open |
@@ -126,7 +126,7 @@ | |||
126 | 117 i386 ipc sys_ipc sys32_ipc | 126 | 117 i386 ipc sys_ipc sys32_ipc |
127 | 118 i386 fsync sys_fsync | 127 | 118 i386 fsync sys_fsync |
128 | 119 i386 sigreturn ptregs_sigreturn stub32_sigreturn | 128 | 119 i386 sigreturn ptregs_sigreturn stub32_sigreturn |
129 | 120 i386 clone ptregs_clone stub32_clone | 129 | 120 i386 clone sys_clone stub32_clone |
130 | 121 i386 setdomainname sys_setdomainname | 130 | 121 i386 setdomainname sys_setdomainname |
131 | 122 i386 uname sys_newuname | 131 | 122 i386 uname sys_newuname |
132 | 123 i386 modify_ldt sys_modify_ldt | 132 | 123 i386 modify_ldt sys_modify_ldt |
@@ -196,7 +196,7 @@ | |||
196 | 187 i386 sendfile sys_sendfile sys32_sendfile | 196 | 187 i386 sendfile sys_sendfile sys32_sendfile |
197 | 188 i386 getpmsg | 197 | 188 i386 getpmsg |
198 | 189 i386 putpmsg | 198 | 189 i386 putpmsg |
199 | 190 i386 vfork ptregs_vfork stub32_vfork | 199 | 190 i386 vfork sys_vfork stub32_vfork |
200 | 191 i386 ugetrlimit sys_getrlimit compat_sys_getrlimit | 200 | 191 i386 ugetrlimit sys_getrlimit compat_sys_getrlimit |
201 | 192 i386 mmap2 sys_mmap_pgoff | 201 | 192 i386 mmap2 sys_mmap_pgoff |
202 | 193 i386 truncate64 sys_truncate64 sys32_truncate64 | 202 | 193 i386 truncate64 sys_truncate64 sys32_truncate64 |
diff --git a/arch/x86/um/Kconfig b/arch/x86/um/Kconfig index b0c30dae9f55..983997041963 100644 --- a/arch/x86/um/Kconfig +++ b/arch/x86/um/Kconfig | |||
@@ -25,6 +25,7 @@ config X86_32 | |||
25 | select HAVE_AOUT | 25 | select HAVE_AOUT |
26 | select ARCH_WANT_IPC_PARSE_VERSION | 26 | select ARCH_WANT_IPC_PARSE_VERSION |
27 | select MODULES_USE_ELF_REL | 27 | select MODULES_USE_ELF_REL |
28 | select CLONE_BACKWARDS | ||
28 | 29 | ||
29 | config X86_64 | 30 | config X86_64 |
30 | def_bool 64BIT | 31 | def_bool 64BIT |
diff --git a/arch/x86/um/shared/sysdep/syscalls.h b/arch/x86/um/shared/sysdep/syscalls.h index ca255a805ed9..bd9a89b67e41 100644 --- a/arch/x86/um/shared/sysdep/syscalls.h +++ b/arch/x86/um/shared/sysdep/syscalls.h | |||
@@ -1,5 +1,3 @@ | |||
1 | extern long sys_clone(unsigned long clone_flags, unsigned long newsp, | ||
2 | void __user *parent_tid, void __user *child_tid); | ||
3 | #ifdef __i386__ | 1 | #ifdef __i386__ |
4 | #include "syscalls_32.h" | 2 | #include "syscalls_32.h" |
5 | #else | 3 | #else |
diff --git a/arch/x86/um/sys_call_table_32.c b/arch/x86/um/sys_call_table_32.c index 232e60504b3a..812e98c098e4 100644 --- a/arch/x86/um/sys_call_table_32.c +++ b/arch/x86/um/sys_call_table_32.c | |||
@@ -24,13 +24,10 @@ | |||
24 | 24 | ||
25 | #define old_mmap sys_old_mmap | 25 | #define old_mmap sys_old_mmap |
26 | 26 | ||
27 | #define ptregs_fork sys_fork | ||
28 | #define ptregs_iopl sys_iopl | 27 | #define ptregs_iopl sys_iopl |
29 | #define ptregs_vm86old sys_vm86old | 28 | #define ptregs_vm86old sys_vm86old |
30 | #define ptregs_clone i386_clone | ||
31 | #define ptregs_vm86 sys_vm86 | 29 | #define ptregs_vm86 sys_vm86 |
32 | #define ptregs_sigaltstack sys_sigaltstack | 30 | #define ptregs_sigaltstack sys_sigaltstack |
33 | #define ptregs_vfork sys_vfork | ||
34 | 31 | ||
35 | #define __SYSCALL_I386(nr, sym, compat) extern asmlinkage void sym(void) ; | 32 | #define __SYSCALL_I386(nr, sym, compat) extern asmlinkage void sym(void) ; |
36 | #include <asm/syscalls_32.h> | 33 | #include <asm/syscalls_32.h> |
diff --git a/arch/x86/um/syscalls_32.c b/arch/x86/um/syscalls_32.c index db444c7218fe..e8bcea99acdb 100644 --- a/arch/x86/um/syscalls_32.c +++ b/arch/x86/um/syscalls_32.c | |||
@@ -6,21 +6,6 @@ | |||
6 | #include <linux/syscalls.h> | 6 | #include <linux/syscalls.h> |
7 | #include <sysdep/syscalls.h> | 7 | #include <sysdep/syscalls.h> |
8 | 8 | ||
9 | /* | ||
10 | * The prototype on i386 is: | ||
11 | * | ||
12 | * int clone(int flags, void * child_stack, int * parent_tidptr, struct user_desc * newtls | ||
13 | * | ||
14 | * and the "newtls" arg. on i386 is read by copy_thread directly from the | ||
15 | * register saved on the stack. | ||
16 | */ | ||
17 | long i386_clone(unsigned long clone_flags, unsigned long newsp, | ||
18 | int __user *parent_tid, void *newtls, int __user *child_tid) | ||
19 | { | ||
20 | return sys_clone(clone_flags, newsp, parent_tid, child_tid); | ||
21 | } | ||
22 | |||
23 | |||
24 | long sys_sigaction(int sig, const struct old_sigaction __user *act, | 9 | long sys_sigaction(int sig, const struct old_sigaction __user *act, |
25 | struct old_sigaction __user *oact) | 10 | struct old_sigaction __user *oact) |
26 | { | 11 | { |