aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/um/kernel/syscall.c19
-rw-r--r--arch/x86/Kconfig1
-rw-r--r--arch/x86/ia32/ia32entry.S7
-rw-r--r--arch/x86/ia32/sys_ia32.c11
-rw-r--r--arch/x86/include/asm/sys_ia32.h2
-rw-r--r--arch/x86/include/asm/syscalls.h13
-rw-r--r--arch/x86/include/asm/unistd.h3
-rw-r--r--arch/x86/kernel/entry_32.S18
-rw-r--r--arch/x86/kernel/entry_64.S22
-rw-r--r--arch/x86/kernel/process.c30
-rw-r--r--arch/x86/kernel/process_32.c11
-rw-r--r--arch/x86/kernel/process_64.c7
-rw-r--r--arch/x86/syscalls/syscall_32.tbl6
-rw-r--r--arch/x86/um/Kconfig1
-rw-r--r--arch/x86/um/sys_call_table_32.c3
-rw-r--r--arch/x86/um/syscalls_32.c15
16 files changed, 52 insertions, 117 deletions
diff --git a/arch/um/kernel/syscall.c b/arch/um/kernel/syscall.c
index 3a875226c8ef..c1d0ae069b53 100644
--- a/arch/um/kernel/syscall.c
+++ b/arch/um/kernel/syscall.c
@@ -14,25 +14,6 @@
14#include <asm/uaccess.h> 14#include <asm/uaccess.h>
15#include <asm/unistd.h> 15#include <asm/unistd.h>
16 16
17long sys_fork(void)
18{
19 return do_fork(SIGCHLD, 0,
20 &current->thread.regs, 0, NULL, NULL);
21}
22
23long sys_vfork(void)
24{
25 return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, 0,
26 &current->thread.regs, 0, NULL, NULL);
27}
28
29long sys_clone(unsigned long clone_flags, unsigned long newsp,
30 void __user *parent_tid, void __user *child_tid)
31{
32 return do_fork(clone_flags, newsp, &current->thread.regs, 0, parent_tid,
33 child_tid);
34}
35
36long old_mmap(unsigned long addr, unsigned long len, 17long old_mmap(unsigned long addr, unsigned long len,
37 unsigned long prot, unsigned long flags, 18 unsigned long prot, unsigned long flags,
38 unsigned long fd, unsigned long offset) 19 unsigned long fd, unsigned long offset)
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 46c3bff3ced2..0df6e7d84539 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
116config INSTRUCTION_DECODER 117config INSTRUCTION_DECODER
117 def_bool y 118 def_bool y
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
474GLOBAL(stub32_clone)
475 leaq sys_clone(%rip),%rax
476 mov %r8, %rcx
477 jmp ia32_ptregs_common
478
479 ALIGN
475ia32_ptregs_common: 480ia32_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
388asmlinkage 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/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);
54asmlinkage long sys32_personality(unsigned long); 54asmlinkage long sys32_personality(unsigned long);
55asmlinkage long sys32_sendfile(int, int, compat_off_t __user *, s32); 55asmlinkage long sys32_sendfile(int, int, compat_off_t __user *, s32);
56 56
57asmlinkage long sys32_clone(unsigned int, unsigned int, struct pt_regs *);
58
59long sys32_lseek(unsigned int, int, unsigned int); 57long sys32_lseek(unsigned int, int, unsigned int);
60long sys32_kill(int, int); 58long sys32_kill(int, int);
61long sys32_fadvise64_64(int, __u32, __u32, __u32, __u32, int); 59long 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 9e5aef3a2598..f7252d11416b 100644
--- a/arch/x86/include/asm/syscalls.h
+++ b/arch/x86/include/asm/syscalls.h
@@ -21,10 +21,15 @@ asmlinkage long sys_ioperm(unsigned long, unsigned long, int);
21long sys_iopl(unsigned int, struct pt_regs *); 21long sys_iopl(unsigned int, struct pt_regs *);
22 22
23/* kernel/process.c */ 23/* kernel/process.c */
24int sys_fork(struct pt_regs *); 24asmlinkage long sys_fork(void);
25int sys_vfork(struct pt_regs *); 25asmlinkage long sys_vfork(void);
26long sys_clone(unsigned long, unsigned long, void __user *, 26#ifdef CONFIG_CLONE_BACKWARDS
27 void __user *, struct pt_regs *); 27asmlinkage long sys_clone(unsigned long, unsigned long, void __user *, int,
28 void __user *);
29#else
30asmlinkage long sys_clone(unsigned long, unsigned long, void __user *,
31 void __user *, int);
32#endif
28 33
29/* kernel/ldt.c */ 34/* kernel/ldt.c */
30asmlinkage int sys_modify_ldt(int, void __user *, unsigned long); 35asmlinkage int sys_modify_ldt(int, void __user *, unsigned long);
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/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) ; \
739ENDPROC(ptregs_##name) 739ENDPROC(ptregs_##name)
740 740
741PTREGSCALL1(iopl) 741PTREGSCALL1(iopl)
742PTREGSCALL0(fork)
743PTREGSCALL0(vfork)
744PTREGSCALL2(sigaltstack) 742PTREGSCALL2(sigaltstack)
745PTREGSCALL0(sigreturn) 743PTREGSCALL0(sigreturn)
746PTREGSCALL0(rt_sigreturn) 744PTREGSCALL0(rt_sigreturn)
747PTREGSCALL2(vm86) 745PTREGSCALL2(vm86)
748PTREGSCALL1(vm86old) 746PTREGSCALL1(vm86old)
749 747
750/* Clone is an oddball. The 4th arg is in %edi */
751ENTRY(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
764ENDPROC(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 1328fe49a3f1..2363e820ed68 100644
--- a/arch/x86/kernel/entry_64.S
+++ b/arch/x86/kernel/entry_64.S
@@ -845,9 +845,25 @@ ENTRY(\label)
845END(\label) 845END(\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 849ENTRY(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
861END(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 b644e1c765dc..fe9459593257 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
265int 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 */
280int 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
286long
287sys_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..16efa974532b 100644
--- a/arch/x86/kernel/process_32.c
+++ b/arch/x86/kernel/process_32.c
@@ -129,7 +129,7 @@ void release_thread(struct task_struct *dead_task)
129 129
130int copy_thread(unsigned long clone_flags, unsigned long sp, 130int copy_thread(unsigned long clone_flags, unsigned long sp,
131 unsigned long arg, 131 unsigned long arg,
132 struct task_struct *p, struct pt_regs *regs) 132 struct task_struct *p, struct pt_regs *unused)
133{ 133{
134 struct pt_regs *childregs = task_pt_regs(p); 134 struct pt_regs *childregs = task_pt_regs(p);
135 struct task_struct *tsk; 135 struct task_struct *tsk;
@@ -138,7 +138,7 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,
138 p->thread.sp = (unsigned long) childregs; 138 p->thread.sp = (unsigned long) childregs;
139 p->thread.sp0 = (unsigned long) (childregs+1); 139 p->thread.sp0 = (unsigned long) (childregs+1);
140 140
141 if (unlikely(!regs)) { 141 if (unlikely(p->flags & PF_KTHREAD)) {
142 /* kernel thread */ 142 /* kernel thread */
143 memset(childregs, 0, sizeof(struct pt_regs)); 143 memset(childregs, 0, sizeof(struct pt_regs));
144 p->thread.ip = (unsigned long) ret_from_kernel_thread; 144 p->thread.ip = (unsigned long) ret_from_kernel_thread;
@@ -156,12 +156,13 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,
156 memset(p->thread.ptrace_bps, 0, sizeof(p->thread.ptrace_bps)); 156 memset(p->thread.ptrace_bps, 0, sizeof(p->thread.ptrace_bps));
157 return 0; 157 return 0;
158 } 158 }
159 *childregs = *regs; 159 *childregs = *current_pt_regs();
160 childregs->ax = 0; 160 childregs->ax = 0;
161 childregs->sp = sp; 161 if (sp)
162 childregs->sp = sp;
162 163
163 p->thread.ip = (unsigned long) ret_from_fork; 164 p->thread.ip = (unsigned long) ret_from_fork;
164 task_user_gs(p) = get_user_gs(regs); 165 task_user_gs(p) = get_user_gs(current_pt_regs());
165 166
166 p->fpu_counter = 0; 167 p->fpu_counter = 0;
167 p->thread.io_bitmap_ptr = NULL; 168 p->thread.io_bitmap_ptr = NULL;
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
index 16c6365e2b86..74aac76c6e34 100644
--- a/arch/x86/kernel/process_64.c
+++ b/arch/x86/kernel/process_64.c
@@ -169,7 +169,7 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,
169 savesegment(ds, p->thread.ds); 169 savesegment(ds, p->thread.ds);
170 memset(p->thread.ptrace_bps, 0, sizeof(p->thread.ptrace_bps)); 170 memset(p->thread.ptrace_bps, 0, sizeof(p->thread.ptrace_bps));
171 171
172 if (unlikely(!regs)) { 172 if (unlikely(p->flags & PF_KTHREAD)) {
173 /* kernel thread */ 173 /* kernel thread */
174 memset(childregs, 0, sizeof(struct pt_regs)); 174 memset(childregs, 0, sizeof(struct pt_regs));
175 childregs->sp = (unsigned long)childregs; 175 childregs->sp = (unsigned long)childregs;
@@ -181,10 +181,11 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,
181 childregs->flags = X86_EFLAGS_IF | X86_EFLAGS_BIT1; 181 childregs->flags = X86_EFLAGS_IF | X86_EFLAGS_BIT1;
182 return 0; 182 return 0;
183 } 183 }
184 *childregs = *regs; 184 *childregs = *current_pt_regs();
185 185
186 childregs->ax = 0; 186 childregs->ax = 0;
187 childregs->sp = sp; 187 if (sp)
188 childregs->sp = sp;
188 189
189 err = -ENOMEM; 190 err = -ENOMEM;
190 memset(p->thread.ptrace_bps, 0, sizeof(p->thread.ptrace_bps)); 191 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#
90 i386 restart_syscall sys_restart_syscall 90 i386 restart_syscall sys_restart_syscall
101 i386 exit sys_exit 101 i386 exit sys_exit
112 i386 fork ptregs_fork stub32_fork 112 i386 fork sys_fork stub32_fork
123 i386 read sys_read 123 i386 read sys_read
134 i386 write sys_write 134 i386 write sys_write
145 i386 open sys_open compat_sys_open 145 i386 open sys_open compat_sys_open
@@ -126,7 +126,7 @@
126117 i386 ipc sys_ipc sys32_ipc 126117 i386 ipc sys_ipc sys32_ipc
127118 i386 fsync sys_fsync 127118 i386 fsync sys_fsync
128119 i386 sigreturn ptregs_sigreturn stub32_sigreturn 128119 i386 sigreturn ptregs_sigreturn stub32_sigreturn
129120 i386 clone ptregs_clone stub32_clone 129120 i386 clone sys_clone stub32_clone
130121 i386 setdomainname sys_setdomainname 130121 i386 setdomainname sys_setdomainname
131122 i386 uname sys_newuname 131122 i386 uname sys_newuname
132123 i386 modify_ldt sys_modify_ldt 132123 i386 modify_ldt sys_modify_ldt
@@ -196,7 +196,7 @@
196187 i386 sendfile sys_sendfile sys32_sendfile 196187 i386 sendfile sys_sendfile sys32_sendfile
197188 i386 getpmsg 197188 i386 getpmsg
198189 i386 putpmsg 198189 i386 putpmsg
199190 i386 vfork ptregs_vfork stub32_vfork 199190 i386 vfork sys_vfork stub32_vfork
200191 i386 ugetrlimit sys_getrlimit compat_sys_getrlimit 200191 i386 ugetrlimit sys_getrlimit compat_sys_getrlimit
201192 i386 mmap2 sys_mmap_pgoff 201192 i386 mmap2 sys_mmap_pgoff
202193 i386 truncate64 sys_truncate64 sys32_truncate64 202193 i386 truncate64 sys_truncate64 sys32_truncate64
diff --git a/arch/x86/um/Kconfig b/arch/x86/um/Kconfig
index 07611759ce35..8f51c39750d1 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
29config X86_64 30config X86_64
30 def_bool 64BIT 31 def_bool 64BIT
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 */
17long 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
24long sys_sigaction(int sig, const struct old_sigaction __user *act, 9long sys_sigaction(int sig, const struct old_sigaction __user *act,
25 struct old_sigaction __user *oact) 10 struct old_sigaction __user *oact)
26{ 11{