]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
x86, um/x86: switch to generic sys_execve and kernel_execve
authorAl Viro <viro@zeniv.linux.org.uk>
Thu, 2 Aug 2012 19:05:11 +0000 (23:05 +0400)
committerAl Viro <viro@zeniv.linux.org.uk>
Thu, 6 Sep 2012 17:57:25 +0000 (13:57 -0400)
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>
14 files changed:
arch/um/kernel/exec.c
arch/um/kernel/internal.h [deleted file]
arch/um/kernel/syscall.c
arch/x86/include/asm/syscalls.h
arch/x86/include/asm/unistd.h
arch/x86/kernel/Makefile
arch/x86/kernel/asm-offsets.c
arch/x86/kernel/entry_32.S
arch/x86/kernel/entry_64.S
arch/x86/kernel/process.c
arch/x86/kernel/process_32.c
arch/x86/kernel/sys_i386_32.c [deleted file]
arch/x86/syscalls/syscall_32.tbl
arch/x86/um/sys_call_table_32.c

index 8c82786da823df2cdf53ad9361b9b950d85018c7..bf50949ed5a9fc94399d7bc0203451a1e57ecbbc 100644 (file)
@@ -16,7 +16,6 @@
 #include "mem_user.h"
 #include "skas.h"
 #include "os.h"
-#include "internal.h"
 
 void flush_thread(void)
 {
@@ -49,27 +48,8 @@ void start_thread(struct pt_regs *regs, unsigned long eip, unsigned long esp)
 }
 EXPORT_SYMBOL(start_thread);
 
-long um_execve(const char *file, const char __user *const __user *argv, const char __user *const __user *env)
+void __noreturn ret_from_kernel_execve(struct pt_regs *normal, struct pt_regs *new)
 {
-       long err;
-
-       err = do_execve(file, argv, env, &current->thread.regs);
-       if (!err)
-               UML_LONGJMP(current->thread.exec_buf, 1);
-       return err;
-}
-
-long sys_execve(const char __user *file, const char __user *const __user *argv,
-               const char __user *const __user *env)
-{
-       long error;
-       char *filename;
-
-       filename = getname(file);
-       error = PTR_ERR(filename);
-       if (IS_ERR(filename)) goto out;
-       error = do_execve(filename, argv, env, &current->thread.regs);
-       putname(filename);
- out:
-       return error;
+       memcpy(normal, new, sizeof(struct pt_regs));
+       UML_LONGJMP(current->thread.exec_buf, 1);
 }
diff --git a/arch/um/kernel/internal.h b/arch/um/kernel/internal.h
deleted file mode 100644 (file)
index 5bf97db..0000000
+++ /dev/null
@@ -1 +0,0 @@
-extern long um_execve(const char *file, const char __user *const __user *argv, const char __user *const __user *env);
index f958cb876ee3d3e47ddff71094e8026c0a110f5d..c63242311bb99d2e91598d06083a6bc8fdbde0bc 100644 (file)
@@ -13,7 +13,6 @@
 #include "asm/mman.h"
 #include "asm/uaccess.h"
 #include "asm/unistd.h"
-#include "internal.h"
 
 long sys_fork(void)
 {
@@ -50,19 +49,3 @@ long old_mmap(unsigned long addr, unsigned long len,
  out:
        return err;
 }
-
-int kernel_execve(const char *filename,
-                 const char *const argv[],
-                 const char *const envp[])
-{
-       mm_segment_t fs;
-       int ret;
-
-       fs = get_fs();
-       set_fs(KERNEL_DS);
-       ret = um_execve(filename, (const char __user *const __user *)argv,
-                       (const char __user *const __user *) envp);
-       set_fs(fs);
-
-       return ret;
-}
index f1d8b441fc775b4920b7397d6a151d2eed314a09..2be0b880417e62b3b827fd5b68f18521a4625777 100644 (file)
@@ -25,7 +25,7 @@ int sys_fork(struct pt_regs *);
 int sys_vfork(struct pt_regs *);
 long sys_execve(const char __user *,
                const char __user *const __user *,
-               const char __user *const __user *, struct pt_regs *);
+               const char __user *const __user *);
 long sys_clone(unsigned long, unsigned long, void __user *,
               void __user *, struct pt_regs *);
 
index 0d9776e9e2dc3f2a539015a5f2930e00d2727a99..55d155560fdf80a0834e19fec15dd73306905aa0 100644 (file)
@@ -50,6 +50,8 @@
 # define __ARCH_WANT_SYS_TIME
 # define __ARCH_WANT_SYS_UTIME
 # define __ARCH_WANT_SYS_WAITPID
+# define __ARCH_WANT_SYS_EXECVE
+# define __ARCH_WANT_KERNEL_EXECVE
 
 /*
  * "Conditional" syscalls
index 8215e5652d9747b6a7eb5302abca77446933acf3..5661000022332d5190916bc76bab8c21f48ec300 100644 (file)
@@ -23,7 +23,7 @@ obj-y                 += time.o ioport.o ldt.o dumpstack.o nmi.o
 obj-y                  += setup.o x86_init.o i8259.o irqinit.o jump_label.o
 obj-$(CONFIG_IRQ_WORK)  += irq_work.o
 obj-y                  += probe_roms.o
-obj-$(CONFIG_X86_32)   += sys_i386_32.o i386_ksyms_32.o
+obj-$(CONFIG_X86_32)   += i386_ksyms_32.o
 obj-$(CONFIG_X86_64)   += sys_x86_64.o x8664_ksyms_64.o
 obj-y                  += syscall_$(BITS).o
 obj-$(CONFIG_X86_64)   += vsyscall_64.o
index 68de2dc962ec0dc52a8721578aa0ca9aff40ba39..28610822fb3cc4be10a04c098ee91b6a8b8ab78f 100644 (file)
@@ -69,4 +69,7 @@ void common(void) {
        OFFSET(BP_kernel_alignment, boot_params, hdr.kernel_alignment);
        OFFSET(BP_pref_address, boot_params, hdr.pref_address);
        OFFSET(BP_code32_start, boot_params, hdr.code32_start);
+
+       BLANK();
+       DEFINE(PTREGS_SIZE, sizeof(struct pt_regs));
 }
index 623f288374763286ec9e58aa66ecabb4e3fc2f6b..c9ae24d2e1e426efb1908670d7f7f5cd56eee07f 100644 (file)
@@ -298,6 +298,15 @@ ENTRY(ret_from_fork)
        CFI_ENDPROC
 END(ret_from_fork)
 
+ENTRY(ret_from_kernel_execve)
+       movl $0,PT_EAX(%eax)
+       movl $PTREGS_SIZE, %ecx
+       call memmove
+       movl %eax, %esp
+       GET_THREAD_INFO(%ebp)
+       jmp syscall_exit
+END(ret_from_kernel_execve)
+
 /*
  * Interrupt exit functions should be protected against kprobes
  */
@@ -322,8 +331,7 @@ ret_from_intr:
        andl $(X86_EFLAGS_VM | SEGMENT_RPL_MASK), %eax
 #else
        /*
-        * We can be coming here from a syscall done in the kernel space,
-        * e.g. a failed kernel_execve().
+        * We can be coming here from child spawned by kernel_thread().
         */
        movl PT_CS(%esp), %eax
        andl $SEGMENT_RPL_MASK, %eax
@@ -727,7 +735,6 @@ ENDPROC(ptregs_##name)
 PTREGSCALL1(iopl)
 PTREGSCALL0(fork)
 PTREGSCALL0(vfork)
-PTREGSCALL3(execve)
 PTREGSCALL2(sigaltstack)
 PTREGSCALL0(sigreturn)
 PTREGSCALL0(rt_sigreturn)
index 69babd8c834f920b4d54c48e1f41a08d4f7fef6f..3800ce5ad80c45647e0c2e668ef0b80260fd5145 100644 (file)
@@ -757,7 +757,6 @@ ENTRY(stub_execve)
        PARTIAL_FRAME 0
        SAVE_REST
        FIXUP_TOP_OF_STACK %r11
-       movq %rsp, %rcx
        call sys_execve
        RESTORE_TOP_OF_STACK %r11
        movq %rax,RAX(%rsp)
@@ -1221,36 +1220,21 @@ ENTRY(kernel_thread_helper)
        CFI_ENDPROC
 END(kernel_thread_helper)
 
-/*
- * execve(). This function needs to use IRET, not SYSRET, to set up all state properly.
- *
- * C extern interface:
- *      extern long execve(const char *name, char **argv, char **envp)
- *
- * asm input arguments:
- *     rdi: name, rsi: argv, rdx: envp
- *
- * We want to fallback into:
- *     extern long sys_execve(const char *name, char **argv,char **envp, struct pt_regs *regs)
- *
- * do_sys_execve asm fallback arguments:
- *     rdi: name, rsi: argv, rdx: envp, rcx: fake frame on the stack
- */
-ENTRY(kernel_execve)
-       CFI_STARTPROC
-       FAKE_STACK_FRAME $0
-       SAVE_ALL
-       movq %rsp,%rcx
-       call sys_execve
-       movq %rax, RAX(%rsp)
-       RESTORE_REST
-       testq %rax,%rax
-       je int_ret_from_sys_call
-       RESTORE_ARGS
-       UNFAKE_STACK_FRAME
-       ret
-       CFI_ENDPROC
-END(kernel_execve)
+ENTRY(ret_from_kernel_execve)
+       movl $0, RAX(%rsi)
+       movl $PTREGS_SIZE, %edx
+       call memmove
+       movq %rax, %rsp
+       // RESTORE_REST
+       movq 0*8(%rsp), %r15
+       movq 1*8(%rsp), %r14
+       movq 2*8(%rsp), %r13
+       movq 3*8(%rsp), %r12
+       movq 4*8(%rsp), %rbp
+       movq 5*8(%rsp), %rbx
+       addq $(6*8), %rsp
+       jmp int_ret_from_sys_call
+END(ret_from_kernel_execve)
 
 /* Call softirq on interrupt stack. Interrupts are off. */
 ENTRY(call_softirq)
index 7162e9c1f598f8d8e69ec8559be639a97f6af139..98541538f9e0bd87622d151b0b8d8cd8b2139417 100644 (file)
@@ -336,25 +336,6 @@ int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
 }
 EXPORT_SYMBOL(kernel_thread);
 
-/*
- * sys_execve() executes a new program.
- */
-long sys_execve(const char __user *name,
-               const char __user *const __user *argv,
-               const char __user *const __user *envp, struct pt_regs *regs)
-{
-       long error;
-       char *filename;
-
-       filename = getname(name);
-       error = PTR_ERR(filename);
-       if (IS_ERR(filename))
-               return error;
-       error = do_execve(filename, argv, envp, regs);
-       putname(filename);
-       return error;
-}
-
 /*
  * Idle related variables and functions
  */
index 75fcad146def56309d1d1d45bb4007164f73b5f7..9e84b4f3dd5e498f51b5341a74b4bd2f8b0f081e 100644 (file)
@@ -190,6 +190,7 @@ start_thread(struct pt_regs *regs, unsigned long new_ip, unsigned long new_sp)
        regs->cs                = __USER_CS;
        regs->ip                = new_ip;
        regs->sp                = new_sp;
+       regs->flags             = X86_EFLAGS_IF;
        /*
         * Free the old FP and other extended state
         */
diff --git a/arch/x86/kernel/sys_i386_32.c b/arch/x86/kernel/sys_i386_32.c
deleted file mode 100644 (file)
index 0b0cb5f..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * This file contains various random system calls that
- * have a non-standard calling sequence on the Linux/i386
- * platform.
- */
-
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/fs.h>
-#include <linux/smp.h>
-#include <linux/sem.h>
-#include <linux/msg.h>
-#include <linux/shm.h>
-#include <linux/stat.h>
-#include <linux/syscalls.h>
-#include <linux/mman.h>
-#include <linux/file.h>
-#include <linux/utsname.h>
-#include <linux/ipc.h>
-
-#include <linux/uaccess.h>
-#include <linux/unistd.h>
-
-#include <asm/syscalls.h>
-
-/*
- * Do a system call from kernel instead of calling sys_execve so we
- * end up with proper pt_regs.
- */
-int kernel_execve(const char *filename,
-                 const char *const argv[],
-                 const char *const envp[])
-{
-       long __res;
-       asm volatile ("int $0x80"
-       : "=a" (__res)
-       : "0" (__NR_execve), "b" (filename), "c" (argv), "d" (envp) : "memory");
-       return __res;
-}
index 7a35a6e71d44332d351cdeb9ec28e96c6467c7b6..a47103fbc6925ac7c717ef1ed2d1f9eccaa35fa4 100644 (file)
@@ -17,7 +17,7 @@
 8      i386    creat                   sys_creat
 9      i386    link                    sys_link
 10     i386    unlink                  sys_unlink
-11     i386    execve                  ptregs_execve                   stub32_execve
+11     i386    execve                  sys_execve                      stub32_execve
 12     i386    chdir                   sys_chdir
 13     i386    time                    sys_time                        compat_sys_time
 14     i386    mknod                   sys_mknod
index 68d1dc91b37badeaeff9fe517a06df2be6484f8a..a3de0eafbb20521fc91d86e57beb1b9f3d67fc89 100644 (file)
@@ -25,7 +25,6 @@
 #define old_mmap sys_old_mmap
 
 #define ptregs_fork sys_fork
-#define ptregs_execve sys_execve
 #define ptregs_iopl sys_iopl
 #define ptregs_vm86old sys_vm86old
 #define ptregs_clone sys_clone