Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

Al Viro 6783eaa2 7076aada

+34 -158
+2 -23
arch/um/kernel/exec.c
··· 16 16 #include "mem_user.h" 17 17 #include "skas.h" 18 18 #include "os.h" 19 - #include "internal.h" 20 19 21 20 void flush_thread(void) 22 21 { ··· 48 49 } 49 50 EXPORT_SYMBOL(start_thread); 50 51 51 - long um_execve(const char *file, const char __user *const __user *argv, const char __user *const __user *env) 52 + void __noreturn ret_from_kernel_execve(struct pt_regs *unused) 52 53 { 53 - long err; 54 - 55 - err = do_execve(file, argv, env, &current->thread.regs); 56 - if (!err) 57 - UML_LONGJMP(current->thread.exec_buf, 1); 58 - return err; 59 - } 60 - 61 - long sys_execve(const char __user *file, const char __user *const __user *argv, 62 - const char __user *const __user *env) 63 - { 64 - long error; 65 - char *filename; 66 - 67 - filename = getname(file); 68 - error = PTR_ERR(filename); 69 - if (IS_ERR(filename)) goto out; 70 - error = do_execve(filename, argv, env, &current->thread.regs); 71 - putname(filename); 72 - out: 73 - return error; 54 + UML_LONGJMP(current->thread.exec_buf, 1); 74 55 }
-1
arch/um/kernel/internal.h
··· 1 - extern long um_execve(const char *file, const char __user *const __user *argv, const char __user *const __user *env);
-17
arch/um/kernel/syscall.c
··· 13 13 #include "asm/mman.h" 14 14 #include "asm/uaccess.h" 15 15 #include "asm/unistd.h" 16 - #include "internal.h" 17 16 18 17 long sys_fork(void) 19 18 { ··· 48 49 err = sys_mmap_pgoff(addr, len, prot, flags, fd, offset >> PAGE_SHIFT); 49 50 out: 50 51 return err; 51 - } 52 - 53 - int kernel_execve(const char *filename, 54 - const char *const argv[], 55 - const char *const envp[]) 56 - { 57 - mm_segment_t fs; 58 - int ret; 59 - 60 - fs = get_fs(); 61 - set_fs(KERNEL_DS); 62 - ret = um_execve(filename, (const char __user *const __user *)argv, 63 - (const char __user *const __user *) envp); 64 - set_fs(fs); 65 - 66 - return ret; 67 52 }
+1 -1
arch/x86/ia32/ia32entry.S
··· 459 459 PTREGSCALL stub32_rt_sigreturn, sys32_rt_sigreturn, %rdi 460 460 PTREGSCALL stub32_sigreturn, sys32_sigreturn, %rdi 461 461 PTREGSCALL stub32_sigaltstack, sys32_sigaltstack, %rdx 462 - PTREGSCALL stub32_execve, sys32_execve, %rcx 462 + PTREGSCALL stub32_execve, compat_sys_execve, %rcx 463 463 PTREGSCALL stub32_fork, sys_fork, %rdi 464 464 PTREGSCALL stub32_clone, sys32_clone, %rdx 465 465 PTREGSCALL stub32_vfork, sys_vfork, %rdi
-15
arch/x86/ia32/sys_ia32.c
··· 385 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 388 asmlinkage long sys32_clone(unsigned int clone_flags, unsigned int newsp, 404 389 struct pt_regs *regs) 405 390 {
-2
arch/x86/include/asm/sys_ia32.h
··· 54 54 asmlinkage long sys32_personality(unsigned long); 55 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 57 asmlinkage long sys32_clone(unsigned int, unsigned int, struct pt_regs *); 60 58 61 59 long sys32_lseek(unsigned int, int, unsigned int);
+1 -1
arch/x86/include/asm/syscalls.h
··· 25 25 int sys_vfork(struct pt_regs *); 26 26 long sys_execve(const char __user *, 27 27 const char __user *const __user *, 28 - const char __user *const __user *, struct pt_regs *); 28 + const char __user *const __user *); 29 29 long sys_clone(unsigned long, unsigned long, void __user *, 30 30 void __user *, struct pt_regs *); 31 31
+2
arch/x86/include/asm/unistd.h
··· 50 50 # define __ARCH_WANT_SYS_TIME 51 51 # define __ARCH_WANT_SYS_UTIME 52 52 # define __ARCH_WANT_SYS_WAITPID 53 + # define __ARCH_WANT_SYS_EXECVE 54 + # define __ARCH_WANT_KERNEL_EXECVE 53 55 54 56 /* 55 57 * "Conditional" syscalls
+1 -1
arch/x86/kernel/Makefile
··· 23 23 obj-y += setup.o x86_init.o i8259.o irqinit.o jump_label.o 24 24 obj-$(CONFIG_IRQ_WORK) += irq_work.o 25 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 27 obj-$(CONFIG_X86_64) += sys_x86_64.o x8664_ksyms_64.o 28 28 obj-y += syscall_$(BITS).o 29 29 obj-$(CONFIG_X86_64) += vsyscall_64.o
+3
arch/x86/kernel/asm-offsets.c
··· 69 69 OFFSET(BP_kernel_alignment, boot_params, hdr.kernel_alignment); 70 70 OFFSET(BP_pref_address, boot_params, hdr.pref_address); 71 71 OFFSET(BP_code32_start, boot_params, hdr.code32_start); 72 + 73 + BLANK(); 74 + DEFINE(PTREGS_SIZE, sizeof(struct pt_regs)); 72 75 }
+8 -3
arch/x86/kernel/entry_32.S
··· 298 298 CFI_ENDPROC 299 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 309 * Interrupt exit functions should be protected against kprobes 303 310 */ ··· 329 322 andl $(X86_EFLAGS_VM | SEGMENT_RPL_MASK), %eax 330 323 #else 331 324 /* 332 - * We can be coming here from a syscall done in the kernel space, 333 - * e.g. a failed kernel_execve(). 325 + * We can be coming here from child spawned by kernel_thread(). 334 326 */ 335 327 movl PT_CS(%esp), %eax 336 328 andl $SEGMENT_RPL_MASK, %eax ··· 733 727 PTREGSCALL1(iopl) 734 728 PTREGSCALL0(fork) 735 729 PTREGSCALL0(vfork) 736 - PTREGSCALL3(execve) 737 730 PTREGSCALL2(sigaltstack) 738 731 PTREGSCALL0(sigreturn) 739 732 PTREGSCALL0(rt_sigreturn)
+14 -33
arch/x86/kernel/entry_64.S
··· 767 767 PARTIAL_FRAME 0 768 768 SAVE_REST 769 769 FIXUP_TOP_OF_STACK %r11 770 - movq %rsp, %rcx 771 770 call sys_execve 772 771 RESTORE_TOP_OF_STACK %r11 773 772 movq %rax,RAX(%rsp) ··· 816 817 PARTIAL_FRAME 0 817 818 SAVE_REST 818 819 FIXUP_TOP_OF_STACK %r11 819 - movq %rsp, %rcx 820 - call sys32_execve 820 + call compat_sys_execve 821 821 RESTORE_TOP_OF_STACK %r11 822 822 movq %rax,RAX(%rsp) 823 823 RESTORE_REST ··· 1214 1216 jmp 2b 1215 1217 .previous 1216 1218 1217 - /* 1218 - * execve(). This function needs to use IRET, not SYSRET, to set up all state properly. 1219 - * 1220 - * C extern interface: 1221 - * extern long execve(const char *name, char **argv, char **envp) 1222 - * 1223 - * asm input arguments: 1224 - * rdi: name, rsi: argv, rdx: envp 1225 - * 1226 - * We want to fallback into: 1227 - * extern long sys_execve(const char *name, char **argv,char **envp, struct pt_regs *regs) 1228 - * 1229 - * do_sys_execve asm fallback arguments: 1230 - * rdi: name, rsi: argv, rdx: envp, rcx: fake frame on the stack 1231 - */ 1232 - ENTRY(kernel_execve) 1233 - CFI_STARTPROC 1234 - FAKE_STACK_FRAME $0 1235 - SAVE_ALL 1236 - movq %rsp,%rcx 1237 - call sys_execve 1238 - movq %rax, RAX(%rsp) 1239 - RESTORE_REST 1240 - testq %rax,%rax 1241 - je int_ret_from_sys_call 1242 - RESTORE_ARGS 1243 - UNFAKE_STACK_FRAME 1244 - ret 1245 - CFI_ENDPROC 1246 - END(kernel_execve) 1219 + ENTRY(ret_from_kernel_execve) 1220 + movq %rdi, %rsp 1221 + movl $0, RAX(%rsp) 1222 + // RESTORE_REST 1223 + movq 0*8(%rsp), %r15 1224 + movq 1*8(%rsp), %r14 1225 + movq 2*8(%rsp), %r13 1226 + movq 3*8(%rsp), %r12 1227 + movq 4*8(%rsp), %rbp 1228 + movq 5*8(%rsp), %rbx 1229 + addq $(6*8), %rsp 1230 + jmp int_ret_from_sys_call 1231 + END(ret_from_kernel_execve) 1247 1232 1248 1233 /* Call softirq on interrupt stack. Interrupts are off. */ 1249 1234 ENTRY(call_softirq)
-19
arch/x86/kernel/process.c
··· 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 302 * Idle related variables and functions 322 303 */ 323 304 unsigned long boot_option_idle_override = IDLE_NO_OVERRIDE;
+1
arch/x86/kernel/process_32.c
··· 207 207 regs->cs = __USER_CS; 208 208 regs->ip = new_ip; 209 209 regs->sp = new_sp; 210 + regs->flags = X86_EFLAGS_IF; 210 211 /* 211 212 * Free the old FP and other extended state 212 213 */
-40
arch/x86/kernel/sys_i386_32.c
··· 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 - }
+1 -1
arch/x86/syscalls/syscall_32.tbl
··· 17 17 8 i386 creat sys_creat 18 18 9 i386 link sys_link 19 19 10 i386 unlink sys_unlink 20 - 11 i386 execve ptregs_execve stub32_execve 20 + 11 i386 execve sys_execve stub32_execve 21 21 12 i386 chdir sys_chdir 22 22 13 i386 time sys_time compat_sys_time 23 23 14 i386 mknod sys_mknod
-1
arch/x86/um/sys_call_table_32.c
··· 25 25 #define old_mmap sys_old_mmap 26 26 27 27 #define ptregs_fork sys_fork 28 - #define ptregs_execve sys_execve 29 28 #define ptregs_iopl sys_iopl 30 29 #define ptregs_vm86old sys_vm86old 31 30 #define ptregs_clone i386_clone