diff options
| author | Al Viro <viro@zeniv.linux.org.uk> | 2012-10-10 21:35:42 -0400 |
|---|---|---|
| committer | Al Viro <viro@zeniv.linux.org.uk> | 2012-10-12 13:35:22 -0400 |
| commit | 22e2430d60dbdfcdd732a086e9ef2dbd74c266d1 (patch) | |
| tree | 687067fcaf2761015639178033ee16c8511703b8 | |
| parent | a74fb73c12398b250fdc5e333a11e15a9e3a84fc (diff) | |
x86, um: convert to saner kernel_execve() semantics
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
| -rw-r--r-- | arch/um/include/asm/processor-generic.h | 2 | ||||
| -rw-r--r-- | arch/um/include/shared/os.h | 1 | ||||
| -rw-r--r-- | arch/um/kernel/exec.c | 5 | ||||
| -rw-r--r-- | arch/um/kernel/process.c | 10 | ||||
| -rw-r--r-- | arch/um/os-Linux/process.c | 13 | ||||
| -rw-r--r-- | arch/x86/Kconfig | 1 | ||||
| -rw-r--r-- | arch/x86/include/asm/unistd.h | 1 | ||||
| -rw-r--r-- | arch/x86/kernel/entry_32.S | 31 | ||||
| -rw-r--r-- | arch/x86/kernel/entry_64.S | 24 | ||||
| -rw-r--r-- | arch/x86/um/Kconfig | 1 |
10 files changed, 21 insertions, 68 deletions
diff --git a/arch/um/include/asm/processor-generic.h b/arch/um/include/asm/processor-generic.h index 5d9ab0c4f48..62435a00e70 100644 --- a/arch/um/include/asm/processor-generic.h +++ b/arch/um/include/asm/processor-generic.h | |||
| @@ -26,7 +26,6 @@ struct thread_struct { | |||
| 26 | jmp_buf *fault_catcher; | 26 | jmp_buf *fault_catcher; |
| 27 | struct task_struct *prev_sched; | 27 | struct task_struct *prev_sched; |
| 28 | unsigned long temp_stack; | 28 | unsigned long temp_stack; |
| 29 | jmp_buf *exec_buf; | ||
| 30 | struct arch_thread arch; | 29 | struct arch_thread arch; |
| 31 | jmp_buf switch_buf; | 30 | jmp_buf switch_buf; |
| 32 | int mm_count; | 31 | int mm_count; |
| @@ -54,7 +53,6 @@ struct thread_struct { | |||
| 54 | .fault_addr = NULL, \ | 53 | .fault_addr = NULL, \ |
| 55 | .prev_sched = NULL, \ | 54 | .prev_sched = NULL, \ |
| 56 | .temp_stack = 0, \ | 55 | .temp_stack = 0, \ |
| 57 | .exec_buf = NULL, \ | ||
| 58 | .arch = INIT_ARCH_THREAD, \ | 56 | .arch = INIT_ARCH_THREAD, \ |
| 59 | .request = { 0 } \ | 57 | .request = { 0 } \ |
| 60 | } | 58 | } |
diff --git a/arch/um/include/shared/os.h b/arch/um/include/shared/os.h index 89b686c1a3e..25dbd372d32 100644 --- a/arch/um/include/shared/os.h +++ b/arch/um/include/shared/os.h | |||
| @@ -191,7 +191,6 @@ extern int os_getpid(void); | |||
| 191 | extern int os_getpgrp(void); | 191 | extern int os_getpgrp(void); |
| 192 | 192 | ||
| 193 | extern void init_new_thread_signals(void); | 193 | extern void init_new_thread_signals(void); |
| 194 | extern int run_kernel_thread(int (*fn)(void *), void *arg, jmp_buf **jmp_ptr); | ||
| 195 | 194 | ||
| 196 | extern int os_map_memory(void *virt, int fd, unsigned long long off, | 195 | extern int os_map_memory(void *virt, int fd, unsigned long long off, |
| 197 | unsigned long len, int r, int w, int x); | 196 | unsigned long len, int r, int w, int x); |
diff --git a/arch/um/kernel/exec.c b/arch/um/kernel/exec.c index e427301f55d..565ca396d83 100644 --- a/arch/um/kernel/exec.c +++ b/arch/um/kernel/exec.c | |||
| @@ -47,8 +47,3 @@ void start_thread(struct pt_regs *regs, unsigned long eip, unsigned long esp) | |||
| 47 | #endif | 47 | #endif |
| 48 | } | 48 | } |
| 49 | EXPORT_SYMBOL(start_thread); | 49 | EXPORT_SYMBOL(start_thread); |
| 50 | |||
| 51 | void __noreturn ret_from_kernel_execve(struct pt_regs *unused) | ||
| 52 | { | ||
| 53 | UML_LONGJMP(current->thread.exec_buf, 1); | ||
| 54 | } | ||
diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c index a1b50add48a..94b0d8b9810 100644 --- a/arch/um/kernel/process.c +++ b/arch/um/kernel/process.c | |||
| @@ -135,14 +135,10 @@ void new_thread_handler(void) | |||
| 135 | arg = current->thread.request.u.thread.arg; | 135 | arg = current->thread.request.u.thread.arg; |
| 136 | 136 | ||
| 137 | /* | 137 | /* |
| 138 | * The return value is 1 if the kernel thread execs a process, | 138 | * callback returns only if the kernel thread execs a process |
| 139 | * 0 if it just exits | ||
| 140 | */ | 139 | */ |
| 141 | n = run_kernel_thread(fn, arg, ¤t->thread.exec_buf); | 140 | n = fn(arg); |
| 142 | if (n == 1) | 141 | userspace(¤t->thread.regs.regs); |
| 143 | userspace(¤t->thread.regs.regs); | ||
| 144 | else | ||
| 145 | do_exit(0); | ||
| 146 | } | 142 | } |
| 147 | 143 | ||
| 148 | /* Called magically, see new_thread_handler above */ | 144 | /* Called magically, see new_thread_handler above */ |
diff --git a/arch/um/os-Linux/process.c b/arch/um/os-Linux/process.c index 307f173e7f8..a04ec167a9c 100644 --- a/arch/um/os-Linux/process.c +++ b/arch/um/os-Linux/process.c | |||
| @@ -244,16 +244,3 @@ void init_new_thread_signals(void) | |||
| 244 | signal(SIGWINCH, SIG_IGN); | 244 | signal(SIGWINCH, SIG_IGN); |
| 245 | signal(SIGTERM, SIG_DFL); | 245 | signal(SIGTERM, SIG_DFL); |
| 246 | } | 246 | } |
| 247 | |||
| 248 | int run_kernel_thread(int (*fn)(void *), void *arg, jmp_buf **jmp_ptr) | ||
| 249 | { | ||
| 250 | jmp_buf buf; | ||
| 251 | int n; | ||
| 252 | |||
| 253 | *jmp_ptr = &buf; | ||
| 254 | n = UML_SETJMP(&buf); | ||
| 255 | if (n != 0) | ||
| 256 | return n; | ||
| 257 | (*fn)(arg); | ||
| 258 | return 0; | ||
| 259 | } | ||
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index d93eb9d1bb9..45edcba41e3 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig | |||
| @@ -98,6 +98,7 @@ config X86 | |||
| 98 | select GENERIC_STRNCPY_FROM_USER | 98 | select GENERIC_STRNCPY_FROM_USER |
| 99 | select GENERIC_STRNLEN_USER | 99 | select GENERIC_STRNLEN_USER |
| 100 | select GENERIC_KERNEL_THREAD | 100 | select GENERIC_KERNEL_THREAD |
| 101 | select GENERIC_KERNEL_EXECVE | ||
| 101 | 102 | ||
| 102 | config INSTRUCTION_DECODER | 103 | config INSTRUCTION_DECODER |
| 103 | def_bool (KPROBES || PERF_EVENTS || UPROBES) | 104 | def_bool (KPROBES || PERF_EVENTS || UPROBES) |
diff --git a/arch/x86/include/asm/unistd.h b/arch/x86/include/asm/unistd.h index 55d155560fd..16f3fc6ebf2 100644 --- a/arch/x86/include/asm/unistd.h +++ b/arch/x86/include/asm/unistd.h | |||
| @@ -51,7 +51,6 @@ | |||
| 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_KERNEL_EXECVE | ||
| 55 | 54 | ||
| 56 | /* | 55 | /* |
| 57 | * "Conditional" syscalls | 56 | * "Conditional" syscalls |
diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S index fe4cc305d8d..91d295908c3 100644 --- a/arch/x86/kernel/entry_32.S +++ b/arch/x86/kernel/entry_32.S | |||
| @@ -298,12 +298,20 @@ 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) | 301 | ENTRY(ret_from_kernel_thread) |
| 302 | movl %eax, %esp | 302 | CFI_STARTPROC |
| 303 | movl $0,PT_EAX(%esp) | 303 | pushl_cfi %eax |
| 304 | call schedule_tail | ||
| 304 | GET_THREAD_INFO(%ebp) | 305 | GET_THREAD_INFO(%ebp) |
| 306 | popl_cfi %eax | ||
| 307 | pushl_cfi $0x0202 # Reset kernel eflags | ||
| 308 | popfl_cfi | ||
| 309 | movl PT_EBP(%esp),%eax | ||
| 310 | call *PT_EBX(%esp) | ||
| 311 | movl $0,PT_EAX(%esp) | ||
| 305 | jmp syscall_exit | 312 | jmp syscall_exit |
| 306 | END(ret_from_kernel_execve) | 313 | CFI_ENDPROC |
| 314 | ENDPROC(ret_from_kernel_thread) | ||
| 307 | 315 | ||
| 308 | /* | 316 | /* |
| 309 | * Interrupt exit functions should be protected against kprobes | 317 | * Interrupt exit functions should be protected against kprobes |
| @@ -994,21 +1002,6 @@ END(spurious_interrupt_bug) | |||
| 994 | */ | 1002 | */ |
| 995 | .popsection | 1003 | .popsection |
| 996 | 1004 | ||
| 997 | ENTRY(ret_from_kernel_thread) | ||
| 998 | CFI_STARTPROC | ||
| 999 | pushl_cfi %eax | ||
| 1000 | call schedule_tail | ||
| 1001 | GET_THREAD_INFO(%ebp) | ||
| 1002 | popl_cfi %eax | ||
| 1003 | pushl_cfi $0x0202 # Reset kernel eflags | ||
| 1004 | popfl_cfi | ||
| 1005 | movl PT_EBP(%esp),%eax | ||
| 1006 | call *PT_EBX(%esp) | ||
| 1007 | call do_exit | ||
| 1008 | ud2 # padding for call trace | ||
| 1009 | CFI_ENDPROC | ||
| 1010 | ENDPROC(ret_from_kernel_thread) | ||
| 1011 | |||
| 1012 | #ifdef CONFIG_XEN | 1005 | #ifdef CONFIG_XEN |
| 1013 | /* Xen doesn't set %esp to be precisely what the normal sysenter | 1006 | /* Xen doesn't set %esp to be precisely what the normal sysenter |
| 1014 | entrypoint expects, so fix it up before using the normal path. */ | 1007 | entrypoint expects, so fix it up before using the normal path. */ |
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S index 053c9552ffd..e1f98c22003 100644 --- a/arch/x86/kernel/entry_64.S +++ b/arch/x86/kernel/entry_64.S | |||
| @@ -459,15 +459,13 @@ ENTRY(ret_from_fork) | |||
| 459 | jmp ret_from_sys_call # go to the SYSRET fastpath | 459 | jmp ret_from_sys_call # go to the SYSRET fastpath |
| 460 | 460 | ||
| 461 | 1: | 461 | 1: |
| 462 | subq $REST_SKIP, %rsp # move the stack pointer back | 462 | subq $REST_SKIP, %rsp # leave space for volatiles |
| 463 | CFI_ADJUST_CFA_OFFSET REST_SKIP | 463 | CFI_ADJUST_CFA_OFFSET REST_SKIP |
| 464 | movq %rbp, %rdi | 464 | movq %rbp, %rdi |
| 465 | call *%rbx | 465 | call *%rbx |
| 466 | # exit | 466 | movl $0, RAX(%rsp) |
| 467 | mov %eax, %edi | 467 | RESTORE_REST |
| 468 | call do_exit | 468 | jmp int_ret_from_sys_call |
| 469 | ud2 # padding for call trace | ||
| 470 | |||
| 471 | CFI_ENDPROC | 469 | CFI_ENDPROC |
| 472 | END(ret_from_fork) | 470 | END(ret_from_fork) |
| 473 | 471 | ||
| @@ -1214,20 +1212,6 @@ bad_gs: | |||
| 1214 | jmp 2b | 1212 | jmp 2b |
| 1215 | .previous | 1213 | .previous |
| 1216 | 1214 | ||
| 1217 | ENTRY(ret_from_kernel_execve) | ||
| 1218 | movq %rdi, %rsp | ||
| 1219 | movl $0, RAX(%rsp) | ||
| 1220 | // RESTORE_REST | ||
| 1221 | movq 0*8(%rsp), %r15 | ||
| 1222 | movq 1*8(%rsp), %r14 | ||
| 1223 | movq 2*8(%rsp), %r13 | ||
| 1224 | movq 3*8(%rsp), %r12 | ||
| 1225 | movq 4*8(%rsp), %rbp | ||
| 1226 | movq 5*8(%rsp), %rbx | ||
| 1227 | addq $(6*8), %rsp | ||
| 1228 | jmp int_ret_from_sys_call | ||
| 1229 | END(ret_from_kernel_execve) | ||
| 1230 | |||
| 1231 | /* Call softirq on interrupt stack. Interrupts are off. */ | 1215 | /* Call softirq on interrupt stack. Interrupts are off. */ |
| 1232 | ENTRY(call_softirq) | 1216 | ENTRY(call_softirq) |
| 1233 | CFI_STARTPROC | 1217 | CFI_STARTPROC |
diff --git a/arch/x86/um/Kconfig b/arch/x86/um/Kconfig index da85b6fc8e8..cab8eb88dd2 100644 --- a/arch/x86/um/Kconfig +++ b/arch/x86/um/Kconfig | |||
| @@ -14,6 +14,7 @@ config UML_X86 | |||
| 14 | def_bool y | 14 | def_bool y |
| 15 | select GENERIC_FIND_FIRST_BIT | 15 | select GENERIC_FIND_FIRST_BIT |
| 16 | select GENERIC_KERNEL_THREAD | 16 | select GENERIC_KERNEL_THREAD |
| 17 | select GENERIC_KERNEL_EXECVE | ||
| 17 | 18 | ||
| 18 | config 64BIT | 19 | config 64BIT |
| 19 | bool "64-bit kernel" if SUBARCH = "x86" | 20 | bool "64-bit kernel" if SUBARCH = "x86" |
