diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2012-08-02 15:05:11 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2012-09-30 22:53:32 -0400 |
commit | 6783eaa2e1253fbcbe2c2f6bb4c843abf1343caf (patch) | |
tree | 457e7b1d54396ed31ba92b7fe7024723d26ba565 /arch/x86 | |
parent | 7076aada1040de4ed79a5977dbabdb5e5ea5e249 (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>
Diffstat (limited to 'arch/x86')
-rw-r--r-- | arch/x86/ia32/ia32entry.S | 2 | ||||
-rw-r--r-- | arch/x86/ia32/sys_ia32.c | 15 | ||||
-rw-r--r-- | arch/x86/include/asm/sys_ia32.h | 2 | ||||
-rw-r--r-- | arch/x86/include/asm/syscalls.h | 2 | ||||
-rw-r--r-- | arch/x86/include/asm/unistd.h | 2 | ||||
-rw-r--r-- | arch/x86/kernel/Makefile | 2 | ||||
-rw-r--r-- | arch/x86/kernel/asm-offsets.c | 3 | ||||
-rw-r--r-- | arch/x86/kernel/entry_32.S | 11 | ||||
-rw-r--r-- | arch/x86/kernel/entry_64.S | 47 | ||||
-rw-r--r-- | arch/x86/kernel/process.c | 19 | ||||
-rw-r--r-- | arch/x86/kernel/process_32.c | 1 | ||||
-rw-r--r-- | arch/x86/kernel/sys_i386_32.c | 40 | ||||
-rw-r--r-- | arch/x86/syscalls/syscall_32.tbl | 2 | ||||
-rw-r--r-- | arch/x86/um/sys_call_table_32.c | 1 |
14 files changed, 32 insertions, 117 deletions
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 | ||
388 | asmlinkage 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 | |||
403 | asmlinkage long sys32_clone(unsigned int clone_flags, unsigned int newsp, | 388 | asmlinkage 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); | |||
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_execve(const char __user *, compat_uptr_t __user *, | ||
58 | compat_uptr_t __user *, struct pt_regs *); | ||
59 | asmlinkage long sys32_clone(unsigned int, unsigned int, struct pt_regs *); | 57 | asmlinkage long sys32_clone(unsigned int, unsigned int, struct pt_regs *); |
60 | 58 | ||
61 | long sys32_lseek(unsigned int, int, unsigned int); | 59 | long 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 *); | |||
25 | int sys_vfork(struct pt_regs *); | 25 | int sys_vfork(struct pt_regs *); |
26 | long sys_execve(const char __user *, | 26 | long 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 *); |
29 | long sys_clone(unsigned long, unsigned long, void __user *, | 29 | long 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 | |||
23 | obj-y += setup.o x86_init.o i8259.o irqinit.o jump_label.o | 23 | obj-y += setup.o x86_init.o i8259.o irqinit.o jump_label.o |
24 | obj-$(CONFIG_IRQ_WORK) += irq_work.o | 24 | obj-$(CONFIG_IRQ_WORK) += irq_work.o |
25 | obj-y += probe_roms.o | 25 | obj-y += probe_roms.o |
26 | obj-$(CONFIG_X86_32) += sys_i386_32.o i386_ksyms_32.o | 26 | obj-$(CONFIG_X86_32) += i386_ksyms_32.o |
27 | obj-$(CONFIG_X86_64) += sys_x86_64.o x8664_ksyms_64.o | 27 | obj-$(CONFIG_X86_64) += sys_x86_64.o x8664_ksyms_64.o |
28 | obj-y += syscall_$(BITS).o | 28 | obj-y += syscall_$(BITS).o |
29 | obj-$(CONFIG_X86_64) += vsyscall_64.o | 29 | obj-$(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 |
299 | END(ret_from_fork) | 299 | END(ret_from_fork) |
300 | 300 | ||
301 | ENTRY(ret_from_kernel_execve) | ||
302 | movl %eax, %esp | ||
303 | movl $0,PT_EAX(%esp) | ||
304 | GET_THREAD_INFO(%ebp) | ||
305 | jmp syscall_exit | ||
306 | END(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) | |||
727 | PTREGSCALL1(iopl) | 733 | PTREGSCALL1(iopl) |
728 | PTREGSCALL0(fork) | 734 | PTREGSCALL0(fork) |
729 | PTREGSCALL0(vfork) | 735 | PTREGSCALL0(vfork) |
730 | PTREGSCALL3(execve) | ||
731 | PTREGSCALL2(sigaltstack) | 736 | PTREGSCALL2(sigaltstack) |
732 | PTREGSCALL0(sigreturn) | 737 | PTREGSCALL0(sigreturn) |
733 | PTREGSCALL0(rt_sigreturn) | 738 | PTREGSCALL0(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 | /* | 1217 | ENTRY(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: | 1229 | END(ret_from_kernel_execve) |
1232 | * rdi: name, rsi: argv, rdx: envp, rcx: fake frame on the stack | ||
1233 | */ | ||
1234 | ENTRY(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 | ||
1248 | END(kernel_execve) | ||
1249 | 1230 | ||
1250 | /* Call softirq on interrupt stack. Interrupts are off. */ | 1231 | /* Call softirq on interrupt stack. Interrupts are off. */ |
1251 | ENTRY(call_softirq) | 1232 | ENTRY(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 | */ | ||
304 | long 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 | */ |
323 | unsigned long boot_option_idle_override = IDLE_NO_OVERRIDE; | 304 | unsigned 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 | */ | ||
31 | int 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 @@ | |||
17 | 8 i386 creat sys_creat | 17 | 8 i386 creat sys_creat |
18 | 9 i386 link sys_link | 18 | 9 i386 link sys_link |
19 | 10 i386 unlink sys_unlink | 19 | 10 i386 unlink sys_unlink |
20 | 11 i386 execve ptregs_execve stub32_execve | 20 | 11 i386 execve sys_execve stub32_execve |
21 | 12 i386 chdir sys_chdir | 21 | 12 i386 chdir sys_chdir |
22 | 13 i386 time sys_time compat_sys_time | 22 | 13 i386 time sys_time compat_sys_time |
23 | 14 i386 mknod sys_mknod | 23 | 14 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 |