aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2012-08-02 15:05:11 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2012-09-30 22:53:32 -0400
commit6783eaa2e1253fbcbe2c2f6bb4c843abf1343caf (patch)
tree457e7b1d54396ed31ba92b7fe7024723d26ba565
parent7076aada1040de4ed79a5977dbabdb5e5ea5e249 (diff)
x86, um/x86: switch to generic sys_execve and kernel_execve
32bit wrapper is lost on that; 64bit one is *not*, since we need to arrange for full pt_regs on stack when we call sys_execve() and we need to load callee-saved ones from there afterwards. Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r--arch/um/kernel/exec.c25
-rw-r--r--arch/um/kernel/internal.h1
-rw-r--r--arch/um/kernel/syscall.c17
-rw-r--r--arch/x86/ia32/ia32entry.S2
-rw-r--r--arch/x86/ia32/sys_ia32.c15
-rw-r--r--arch/x86/include/asm/sys_ia32.h2
-rw-r--r--arch/x86/include/asm/syscalls.h2
-rw-r--r--arch/x86/include/asm/unistd.h2
-rw-r--r--arch/x86/kernel/Makefile2
-rw-r--r--arch/x86/kernel/asm-offsets.c3
-rw-r--r--arch/x86/kernel/entry_32.S11
-rw-r--r--arch/x86/kernel/entry_64.S47
-rw-r--r--arch/x86/kernel/process.c19
-rw-r--r--arch/x86/kernel/process_32.c1
-rw-r--r--arch/x86/kernel/sys_i386_32.c40
-rw-r--r--arch/x86/syscalls/syscall_32.tbl2
-rw-r--r--arch/x86/um/sys_call_table_32.c1
17 files changed, 34 insertions, 158 deletions
diff --git a/arch/um/kernel/exec.c b/arch/um/kernel/exec.c
index 8c82786da823..e427301f55d6 100644
--- a/arch/um/kernel/exec.c
+++ b/arch/um/kernel/exec.c
@@ -16,7 +16,6 @@
16#include "mem_user.h" 16#include "mem_user.h"
17#include "skas.h" 17#include "skas.h"
18#include "os.h" 18#include "os.h"
19#include "internal.h"
20 19
21void flush_thread(void) 20void flush_thread(void)
22{ 21{
@@ -49,27 +48,7 @@ void start_thread(struct pt_regs *regs, unsigned long eip, unsigned long esp)
49} 48}
50EXPORT_SYMBOL(start_thread); 49EXPORT_SYMBOL(start_thread);
51 50
52long um_execve(const char *file, const char __user *const __user *argv, const char __user *const __user *env) 51void __noreturn ret_from_kernel_execve(struct pt_regs *unused)
53{ 52{
54 long err; 53 UML_LONGJMP(current->thread.exec_buf, 1);
55
56 err = do_execve(file, argv, env, &current->thread.regs);
57 if (!err)
58 UML_LONGJMP(current->thread.exec_buf, 1);
59 return err;
60}
61
62long sys_execve(const char __user *file, const char __user *const __user *argv,
63 const char __user *const __user *env)
64{
65 long error;
66 char *filename;
67
68 filename = getname(file);
69 error = PTR_ERR(filename);
70 if (IS_ERR(filename)) goto out;
71 error = do_execve(filename, argv, env, &current->thread.regs);
72 putname(filename);
73 out:
74 return error;
75} 54}
diff --git a/arch/um/kernel/internal.h b/arch/um/kernel/internal.h
deleted file mode 100644
index 5bf97db24a04..000000000000
--- a/arch/um/kernel/internal.h
+++ /dev/null
@@ -1 +0,0 @@
1extern long um_execve(const char *file, const char __user *const __user *argv, const char __user *const __user *env);
diff --git a/arch/um/kernel/syscall.c b/arch/um/kernel/syscall.c
index a4c6d8eee74c..a5639c472772 100644
--- a/arch/um/kernel/syscall.c
+++ b/arch/um/kernel/syscall.c
@@ -13,7 +13,6 @@
13#include "asm/mman.h" 13#include "asm/mman.h"
14#include "asm/uaccess.h" 14#include "asm/uaccess.h"
15#include "asm/unistd.h" 15#include "asm/unistd.h"
16#include "internal.h"
17 16
18long sys_fork(void) 17long sys_fork(void)
19{ 18{
@@ -50,19 +49,3 @@ long old_mmap(unsigned long addr, unsigned long len,
50 out: 49 out:
51 return err; 50 return err;
52} 51}
53
54int kernel_execve(const char *filename,
55 const char *const argv[],
56 const char *const envp[])
57{
58 mm_segment_t fs;
59 int ret;
60
61 fs = get_fs();
62 set_fs(KERNEL_DS);
63 ret = um_execve(filename, (const char __user *const __user *)argv,
64 (const char __user *const __user *) envp);
65 set_fs(fs);
66
67 return ret;
68}
diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S
index 20e5f7ba0e6b..e75f941bd2b2 100644
--- a/arch/x86/ia32/ia32entry.S
+++ b/arch/x86/ia32/ia32entry.S
@@ -459,7 +459,7 @@ GLOBAL(\label)
459 PTREGSCALL stub32_rt_sigreturn, sys32_rt_sigreturn, %rdi 459 PTREGSCALL stub32_rt_sigreturn, sys32_rt_sigreturn, %rdi
460 PTREGSCALL stub32_sigreturn, sys32_sigreturn, %rdi 460 PTREGSCALL stub32_sigreturn, sys32_sigreturn, %rdi
461 PTREGSCALL stub32_sigaltstack, sys32_sigaltstack, %rdx 461 PTREGSCALL stub32_sigaltstack, sys32_sigaltstack, %rdx
462 PTREGSCALL stub32_execve, sys32_execve, %rcx 462 PTREGSCALL stub32_execve, compat_sys_execve, %rcx
463 PTREGSCALL stub32_fork, sys_fork, %rdi 463 PTREGSCALL stub32_fork, sys_fork, %rdi
464 PTREGSCALL stub32_clone, sys32_clone, %rdx 464 PTREGSCALL stub32_clone, sys32_clone, %rdx
465 PTREGSCALL stub32_vfork, sys_vfork, %rdi 465 PTREGSCALL stub32_vfork, sys_vfork, %rdi
diff --git a/arch/x86/ia32/sys_ia32.c b/arch/x86/ia32/sys_ia32.c
index 4540bece0946..6b31144589d0 100644
--- a/arch/x86/ia32/sys_ia32.c
+++ b/arch/x86/ia32/sys_ia32.c
@@ -385,21 +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_execve(const char __user *name, compat_uptr_t __user *argv,
389 compat_uptr_t __user *envp, struct pt_regs *regs)
390{
391 long error;
392 char *filename;
393
394 filename = getname(name);
395 error = PTR_ERR(filename);
396 if (IS_ERR(filename))
397 return error;
398 error = compat_do_execve(filename, argv, envp, regs);
399 putname(filename);
400 return error;
401}
402
403asmlinkage long sys32_clone(unsigned int clone_flags, unsigned int newsp, 388asmlinkage long sys32_clone(unsigned int clone_flags, unsigned int newsp,
404 struct pt_regs *regs) 389 struct pt_regs *regs)
405{ 390{
diff --git a/arch/x86/include/asm/sys_ia32.h b/arch/x86/include/asm/sys_ia32.h
index 3fda9db48819..1ac127f41fe6 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_execve(const char __user *, compat_uptr_t __user *,
58 compat_uptr_t __user *, struct pt_regs *);
59asmlinkage long sys32_clone(unsigned int, unsigned int, struct pt_regs *); 57asmlinkage long sys32_clone(unsigned int, unsigned int, struct pt_regs *);
60 58
61long sys32_lseek(unsigned int, int, unsigned int); 59long sys32_lseek(unsigned int, int, unsigned int);
diff --git a/arch/x86/include/asm/syscalls.h b/arch/x86/include/asm/syscalls.h
index f1d8b441fc77..2be0b880417e 100644
--- a/arch/x86/include/asm/syscalls.h
+++ b/arch/x86/include/asm/syscalls.h
@@ -25,7 +25,7 @@ int sys_fork(struct pt_regs *);
25int sys_vfork(struct pt_regs *); 25int sys_vfork(struct pt_regs *);
26long sys_execve(const char __user *, 26long sys_execve(const char __user *,
27 const char __user *const __user *, 27 const char __user *const __user *,
28 const char __user *const __user *, struct pt_regs *); 28 const char __user *const __user *);
29long sys_clone(unsigned long, unsigned long, void __user *, 29long sys_clone(unsigned long, unsigned long, void __user *,
30 void __user *, struct pt_regs *); 30 void __user *, struct pt_regs *);
31 31
diff --git a/arch/x86/include/asm/unistd.h b/arch/x86/include/asm/unistd.h
index 0d9776e9e2dc..55d155560fdf 100644
--- a/arch/x86/include/asm/unistd.h
+++ b/arch/x86/include/asm/unistd.h
@@ -50,6 +50,8 @@
50# define __ARCH_WANT_SYS_TIME 50# define __ARCH_WANT_SYS_TIME
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
54# define __ARCH_WANT_KERNEL_EXECVE
53 55
54/* 56/*
55 * "Conditional" syscalls 57 * "Conditional" syscalls
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index 8215e5652d97..566100002233 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -23,7 +23,7 @@ obj-y += time.o ioport.o ldt.o dumpstack.o nmi.o
23obj-y += setup.o x86_init.o i8259.o irqinit.o jump_label.o 23obj-y += setup.o x86_init.o i8259.o irqinit.o jump_label.o
24obj-$(CONFIG_IRQ_WORK) += irq_work.o 24obj-$(CONFIG_IRQ_WORK) += irq_work.o
25obj-y += probe_roms.o 25obj-y += probe_roms.o
26obj-$(CONFIG_X86_32) += sys_i386_32.o i386_ksyms_32.o 26obj-$(CONFIG_X86_32) += i386_ksyms_32.o
27obj-$(CONFIG_X86_64) += sys_x86_64.o x8664_ksyms_64.o 27obj-$(CONFIG_X86_64) += sys_x86_64.o x8664_ksyms_64.o
28obj-y += syscall_$(BITS).o 28obj-y += syscall_$(BITS).o
29obj-$(CONFIG_X86_64) += vsyscall_64.o 29obj-$(CONFIG_X86_64) += vsyscall_64.o
diff --git a/arch/x86/kernel/asm-offsets.c b/arch/x86/kernel/asm-offsets.c
index 68de2dc962ec..28610822fb3c 100644
--- a/arch/x86/kernel/asm-offsets.c
+++ b/arch/x86/kernel/asm-offsets.c
@@ -69,4 +69,7 @@ void common(void) {
69 OFFSET(BP_kernel_alignment, boot_params, hdr.kernel_alignment); 69 OFFSET(BP_kernel_alignment, boot_params, hdr.kernel_alignment);
70 OFFSET(BP_pref_address, boot_params, hdr.pref_address); 70 OFFSET(BP_pref_address, boot_params, hdr.pref_address);
71 OFFSET(BP_code32_start, boot_params, hdr.code32_start); 71 OFFSET(BP_code32_start, boot_params, hdr.code32_start);
72
73 BLANK();
74 DEFINE(PTREGS_SIZE, sizeof(struct pt_regs));
72} 75}
diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S
index ac1107346fc9..b6bb69239296 100644
--- a/arch/x86/kernel/entry_32.S
+++ b/arch/x86/kernel/entry_32.S
@@ -298,6 +298,13 @@ ENTRY(ret_from_fork)
298 CFI_ENDPROC 298 CFI_ENDPROC
299END(ret_from_fork) 299END(ret_from_fork)
300 300
301ENTRY(ret_from_kernel_execve)
302 movl %eax, %esp
303 movl $0,PT_EAX(%esp)
304 GET_THREAD_INFO(%ebp)
305 jmp syscall_exit
306END(ret_from_kernel_execve)
307
301/* 308/*
302 * Interrupt exit functions should be protected against kprobes 309 * Interrupt exit functions should be protected against kprobes
303 */ 310 */
@@ -322,8 +329,7 @@ ret_from_intr:
322 andl $(X86_EFLAGS_VM | SEGMENT_RPL_MASK), %eax 329 andl $(X86_EFLAGS_VM | SEGMENT_RPL_MASK), %eax
323#else 330#else
324 /* 331 /*
325 * We can be coming here from a syscall done in the kernel space, 332 * We can be coming here from child spawned by kernel_thread().
326 * e.g. a failed kernel_execve().
327 */ 333 */
328 movl PT_CS(%esp), %eax 334 movl PT_CS(%esp), %eax
329 andl $SEGMENT_RPL_MASK, %eax 335 andl $SEGMENT_RPL_MASK, %eax
@@ -727,7 +733,6 @@ ENDPROC(ptregs_##name)
727PTREGSCALL1(iopl) 733PTREGSCALL1(iopl)
728PTREGSCALL0(fork) 734PTREGSCALL0(fork)
729PTREGSCALL0(vfork) 735PTREGSCALL0(vfork)
730PTREGSCALL3(execve)
731PTREGSCALL2(sigaltstack) 736PTREGSCALL2(sigaltstack)
732PTREGSCALL0(sigreturn) 737PTREGSCALL0(sigreturn)
733PTREGSCALL0(rt_sigreturn) 738PTREGSCALL0(rt_sigreturn)
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S
index 5526d17db676..053c9552ffd9 100644
--- a/arch/x86/kernel/entry_64.S
+++ b/arch/x86/kernel/entry_64.S
@@ -767,7 +767,6 @@ ENTRY(stub_execve)
767 PARTIAL_FRAME 0 767 PARTIAL_FRAME 0
768 SAVE_REST 768 SAVE_REST
769 FIXUP_TOP_OF_STACK %r11 769 FIXUP_TOP_OF_STACK %r11
770 movq %rsp, %rcx
771 call sys_execve 770 call sys_execve
772 RESTORE_TOP_OF_STACK %r11 771 RESTORE_TOP_OF_STACK %r11
773 movq %rax,RAX(%rsp) 772 movq %rax,RAX(%rsp)
@@ -817,8 +816,7 @@ ENTRY(stub_x32_execve)
817 PARTIAL_FRAME 0 816 PARTIAL_FRAME 0
818 SAVE_REST 817 SAVE_REST
819 FIXUP_TOP_OF_STACK %r11 818 FIXUP_TOP_OF_STACK %r11
820 movq %rsp, %rcx 819 call compat_sys_execve
821 call sys32_execve
822 RESTORE_TOP_OF_STACK %r11 820 RESTORE_TOP_OF_STACK %r11
823 movq %rax,RAX(%rsp) 821 movq %rax,RAX(%rsp)
824 RESTORE_REST 822 RESTORE_REST
@@ -1216,36 +1214,19 @@ bad_gs:
1216 jmp 2b 1214 jmp 2b
1217 .previous 1215 .previous
1218 1216
1219/* 1217ENTRY(ret_from_kernel_execve)
1220 * execve(). This function needs to use IRET, not SYSRET, to set up all state properly. 1218 movq %rdi, %rsp
1221 * 1219 movl $0, RAX(%rsp)
1222 * C extern interface: 1220 // RESTORE_REST
1223 * extern long execve(const char *name, char **argv, char **envp) 1221 movq 0*8(%rsp), %r15
1224 * 1222 movq 1*8(%rsp), %r14
1225 * asm input arguments: 1223 movq 2*8(%rsp), %r13
1226 * rdi: name, rsi: argv, rdx: envp 1224 movq 3*8(%rsp), %r12
1227 * 1225 movq 4*8(%rsp), %rbp
1228 * We want to fallback into: 1226 movq 5*8(%rsp), %rbx
1229 * extern long sys_execve(const char *name, char **argv,char **envp, struct pt_regs *regs) 1227 addq $(6*8), %rsp
1230 * 1228 jmp int_ret_from_sys_call
1231 * do_sys_execve asm fallback arguments: 1229END(ret_from_kernel_execve)
1232 * rdi: name, rsi: argv, rdx: envp, rcx: fake frame on the stack
1233 */
1234ENTRY(kernel_execve)
1235 CFI_STARTPROC
1236 FAKE_STACK_FRAME $0
1237 SAVE_ALL
1238 movq %rsp,%rcx
1239 call sys_execve
1240 movq %rax, RAX(%rsp)
1241 RESTORE_REST
1242 testq %rax,%rax
1243 je int_ret_from_sys_call
1244 RESTORE_ARGS
1245 UNFAKE_STACK_FRAME
1246 ret
1247 CFI_ENDPROC
1248END(kernel_execve)
1249 1230
1250/* Call softirq on interrupt stack. Interrupts are off. */ 1231/* Call softirq on interrupt stack. Interrupts are off. */
1251ENTRY(call_softirq) 1232ENTRY(call_softirq)
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c
index 6947ec968bf8..eae2dd5cd5a0 100644
--- a/arch/x86/kernel/process.c
+++ b/arch/x86/kernel/process.c
@@ -299,25 +299,6 @@ sys_clone(unsigned long clone_flags, unsigned long newsp,
299} 299}
300 300
301/* 301/*
302 * sys_execve() executes a new program.
303 */
304long sys_execve(const char __user *name,
305 const char __user *const __user *argv,
306 const char __user *const __user *envp, struct pt_regs *regs)
307{
308 long error;
309 char *filename;
310
311 filename = getname(name);
312 error = PTR_ERR(filename);
313 if (IS_ERR(filename))
314 return error;
315 error = do_execve(filename, argv, envp, regs);
316 putname(filename);
317 return error;
318}
319
320/*
321 * Idle related variables and functions 302 * Idle related variables and functions
322 */ 303 */
323unsigned long boot_option_idle_override = IDLE_NO_OVERRIDE; 304unsigned long boot_option_idle_override = IDLE_NO_OVERRIDE;
diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c
index c9939875d267..25e7e9390d26 100644
--- a/arch/x86/kernel/process_32.c
+++ b/arch/x86/kernel/process_32.c
@@ -207,6 +207,7 @@ start_thread(struct pt_regs *regs, unsigned long new_ip, unsigned long new_sp)
207 regs->cs = __USER_CS; 207 regs->cs = __USER_CS;
208 regs->ip = new_ip; 208 regs->ip = new_ip;
209 regs->sp = new_sp; 209 regs->sp = new_sp;
210 regs->flags = X86_EFLAGS_IF;
210 /* 211 /*
211 * Free the old FP and other extended state 212 * Free the old FP and other extended state
212 */ 213 */
diff --git a/arch/x86/kernel/sys_i386_32.c b/arch/x86/kernel/sys_i386_32.c
deleted file mode 100644
index 0b0cb5fede19..000000000000
--- a/arch/x86/kernel/sys_i386_32.c
+++ /dev/null
@@ -1,40 +0,0 @@
1/*
2 * This file contains various random system calls that
3 * have a non-standard calling sequence on the Linux/i386
4 * platform.
5 */
6
7#include <linux/errno.h>
8#include <linux/sched.h>
9#include <linux/mm.h>
10#include <linux/fs.h>
11#include <linux/smp.h>
12#include <linux/sem.h>
13#include <linux/msg.h>
14#include <linux/shm.h>
15#include <linux/stat.h>
16#include <linux/syscalls.h>
17#include <linux/mman.h>
18#include <linux/file.h>
19#include <linux/utsname.h>
20#include <linux/ipc.h>
21
22#include <linux/uaccess.h>
23#include <linux/unistd.h>
24
25#include <asm/syscalls.h>
26
27/*
28 * Do a system call from kernel instead of calling sys_execve so we
29 * end up with proper pt_regs.
30 */
31int kernel_execve(const char *filename,
32 const char *const argv[],
33 const char *const envp[])
34{
35 long __res;
36 asm volatile ("int $0x80"
37 : "=a" (__res)
38 : "0" (__NR_execve), "b" (filename), "c" (argv), "d" (envp) : "memory");
39 return __res;
40}
diff --git a/arch/x86/syscalls/syscall_32.tbl b/arch/x86/syscalls/syscall_32.tbl
index 7a35a6e71d44..a47103fbc692 100644
--- a/arch/x86/syscalls/syscall_32.tbl
+++ b/arch/x86/syscalls/syscall_32.tbl
@@ -17,7 +17,7 @@
178 i386 creat sys_creat 178 i386 creat sys_creat
189 i386 link sys_link 189 i386 link sys_link
1910 i386 unlink sys_unlink 1910 i386 unlink sys_unlink
2011 i386 execve ptregs_execve stub32_execve 2011 i386 execve sys_execve stub32_execve
2112 i386 chdir sys_chdir 2112 i386 chdir sys_chdir
2213 i386 time sys_time compat_sys_time 2213 i386 time sys_time compat_sys_time
2314 i386 mknod sys_mknod 2314 i386 mknod sys_mknod
diff --git a/arch/x86/um/sys_call_table_32.c b/arch/x86/um/sys_call_table_32.c
index b5408cecac6c..232e60504b3a 100644
--- a/arch/x86/um/sys_call_table_32.c
+++ b/arch/x86/um/sys_call_table_32.c
@@ -25,7 +25,6 @@
25#define old_mmap sys_old_mmap 25#define old_mmap sys_old_mmap
26 26
27#define ptregs_fork sys_fork 27#define ptregs_fork sys_fork
28#define ptregs_execve sys_execve
29#define ptregs_iopl sys_iopl 28#define ptregs_iopl sys_iopl
30#define ptregs_vm86old sys_vm86old 29#define ptregs_vm86old sys_vm86old
31#define ptregs_clone i386_clone 30#define ptregs_clone i386_clone