diff options
96 files changed, 390 insertions, 899 deletions
diff --git a/arch/Kconfig b/arch/Kconfig index 550cce4dd648..26a28419cafc 100644 --- a/arch/Kconfig +++ b/arch/Kconfig | |||
| @@ -271,6 +271,9 @@ config ARCH_WANT_OLD_COMPAT_IPC | |||
| 271 | select ARCH_WANT_COMPAT_IPC_PARSE_VERSION | 271 | select ARCH_WANT_COMPAT_IPC_PARSE_VERSION |
| 272 | bool | 272 | bool |
| 273 | 273 | ||
| 274 | config GENERIC_KERNEL_THREAD | ||
| 275 | bool | ||
| 276 | |||
| 274 | config HAVE_ARCH_SECCOMP_FILTER | 277 | config HAVE_ARCH_SECCOMP_FILTER |
| 275 | bool | 278 | bool |
| 276 | help | 279 | help |
diff --git a/arch/alpha/Kconfig b/arch/alpha/Kconfig index 9944dedee5b1..7da91246e279 100644 --- a/arch/alpha/Kconfig +++ b/arch/alpha/Kconfig | |||
| @@ -20,6 +20,7 @@ config ALPHA | |||
| 20 | select GENERIC_CMOS_UPDATE | 20 | select GENERIC_CMOS_UPDATE |
| 21 | select GENERIC_STRNCPY_FROM_USER | 21 | select GENERIC_STRNCPY_FROM_USER |
| 22 | select GENERIC_STRNLEN_USER | 22 | select GENERIC_STRNLEN_USER |
| 23 | select GENERIC_KERNEL_THREAD | ||
| 23 | help | 24 | help |
| 24 | The Alpha is a 64-bit general-purpose processor designed and | 25 | The Alpha is a 64-bit general-purpose processor designed and |
| 25 | marketed by the Digital Equipment Corporation of blessed memory, | 26 | marketed by the Digital Equipment Corporation of blessed memory, |
diff --git a/arch/alpha/include/asm/Kbuild b/arch/alpha/include/asm/Kbuild index d97d66334e6f..64ffc9e9e548 100644 --- a/arch/alpha/include/asm/Kbuild +++ b/arch/alpha/include/asm/Kbuild | |||
| @@ -10,3 +10,4 @@ header-y += pal.h | |||
| 10 | header-y += reg.h | 10 | header-y += reg.h |
| 11 | header-y += regdef.h | 11 | header-y += regdef.h |
| 12 | header-y += sysinfo.h | 12 | header-y += sysinfo.h |
| 13 | generic-y += exec.h | ||
diff --git a/arch/alpha/include/asm/exec.h b/arch/alpha/include/asm/exec.h deleted file mode 100644 index 4a5a41f30779..000000000000 --- a/arch/alpha/include/asm/exec.h +++ /dev/null | |||
| @@ -1,6 +0,0 @@ | |||
| 1 | #ifndef __ALPHA_EXEC_H | ||
| 2 | #define __ALPHA_EXEC_H | ||
| 3 | |||
| 4 | #define arch_align_stack(x) (x) | ||
| 5 | |||
| 6 | #endif /* __ALPHA_EXEC_H */ | ||
diff --git a/arch/alpha/include/asm/processor.h b/arch/alpha/include/asm/processor.h index e37b887b3d9f..6cb7fe85c4b5 100644 --- a/arch/alpha/include/asm/processor.h +++ b/arch/alpha/include/asm/processor.h | |||
| @@ -49,9 +49,6 @@ extern void start_thread(struct pt_regs *, unsigned long, unsigned long); | |||
| 49 | /* Free all resources held by a thread. */ | 49 | /* Free all resources held by a thread. */ |
| 50 | extern void release_thread(struct task_struct *); | 50 | extern void release_thread(struct task_struct *); |
| 51 | 51 | ||
| 52 | /* Create a kernel thread without removing it from tasklists. */ | ||
| 53 | extern long kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); | ||
| 54 | |||
| 55 | unsigned long get_wchan(struct task_struct *p); | 52 | unsigned long get_wchan(struct task_struct *p); |
| 56 | 53 | ||
| 57 | #define KSTK_EIP(tsk) (task_pt_regs(tsk)->pc) | 54 | #define KSTK_EIP(tsk) (task_pt_regs(tsk)->pc) |
diff --git a/arch/alpha/include/asm/unistd.h b/arch/alpha/include/asm/unistd.h index a31a78eac9b9..3cb6c1188984 100644 --- a/arch/alpha/include/asm/unistd.h +++ b/arch/alpha/include/asm/unistd.h | |||
| @@ -481,6 +481,8 @@ | |||
| 481 | #define __ARCH_WANT_SYS_OLDUMOUNT | 481 | #define __ARCH_WANT_SYS_OLDUMOUNT |
| 482 | #define __ARCH_WANT_SYS_SIGPENDING | 482 | #define __ARCH_WANT_SYS_SIGPENDING |
| 483 | #define __ARCH_WANT_SYS_RT_SIGSUSPEND | 483 | #define __ARCH_WANT_SYS_RT_SIGSUSPEND |
| 484 | #define __ARCH_WANT_SYS_EXECVE | ||
| 485 | #define __ARCH_WANT_KERNEL_EXECVE | ||
| 484 | 486 | ||
| 485 | /* "Conditional" syscalls. What we want is | 487 | /* "Conditional" syscalls. What we want is |
| 486 | 488 | ||
diff --git a/arch/alpha/kernel/alpha_ksyms.c b/arch/alpha/kernel/alpha_ksyms.c index 15fa821d09cd..89566b346c0f 100644 --- a/arch/alpha/kernel/alpha_ksyms.c +++ b/arch/alpha/kernel/alpha_ksyms.c | |||
| @@ -50,9 +50,6 @@ EXPORT_SYMBOL(alpha_read_fp_reg_s); | |||
| 50 | EXPORT_SYMBOL(alpha_write_fp_reg); | 50 | EXPORT_SYMBOL(alpha_write_fp_reg); |
| 51 | EXPORT_SYMBOL(alpha_write_fp_reg_s); | 51 | EXPORT_SYMBOL(alpha_write_fp_reg_s); |
| 52 | 52 | ||
| 53 | /* entry.S */ | ||
| 54 | EXPORT_SYMBOL(kernel_thread); | ||
| 55 | |||
| 56 | /* Networking helper routines. */ | 53 | /* Networking helper routines. */ |
| 57 | EXPORT_SYMBOL(csum_tcpudp_magic); | 54 | EXPORT_SYMBOL(csum_tcpudp_magic); |
| 58 | EXPORT_SYMBOL(ip_compute_csum); | 55 | EXPORT_SYMBOL(ip_compute_csum); |
diff --git a/arch/alpha/kernel/entry.S b/arch/alpha/kernel/entry.S index ec0da0567ab5..7e43e1156d10 100644 --- a/arch/alpha/kernel/entry.S +++ b/arch/alpha/kernel/entry.S | |||
| @@ -609,59 +609,35 @@ ret_from_fork: | |||
| 609 | .end ret_from_fork | 609 | .end ret_from_fork |
| 610 | 610 | ||
| 611 | /* | 611 | /* |
| 612 | * kernel_thread(fn, arg, clone_flags) | 612 | * ... and new kernel threads - here |
| 613 | */ | 613 | */ |
| 614 | .align 4 | 614 | .align 4 |
| 615 | .globl kernel_thread | 615 | .globl ret_from_kernel_thread |
| 616 | .ent kernel_thread | 616 | .ent ret_from_kernel_thread |
| 617 | kernel_thread: | 617 | ret_from_kernel_thread: |
| 618 | /* We can be called from a module. */ | 618 | mov $17, $16 |
| 619 | ldgp $gp, 0($27) | 619 | jsr $26, schedule_tail |
| 620 | .prologue 1 | 620 | mov $9, $27 |
| 621 | subq $sp, SP_OFF+6*8, $sp | 621 | mov $10, $16 |
| 622 | br $1, 2f /* load start address */ | 622 | jsr $26, ($9) |
| 623 | |||
| 624 | /* We've now "returned" from a fake system call. */ | ||
| 625 | unop | ||
| 626 | blt $0, 1f /* error? */ | ||
| 627 | ldi $1, 0x3fff | ||
| 628 | beq $20, 1f /* parent or child? */ | ||
| 629 | |||
| 630 | bic $sp, $1, $8 /* in child. */ | ||
| 631 | jsr $26, ($27) | ||
| 632 | ldgp $gp, 0($26) | 623 | ldgp $gp, 0($26) |
| 633 | mov $0, $16 | 624 | mov $0, $16 |
| 634 | mov $31, $26 | 625 | mov $31, $26 |
| 635 | jmp $31, sys_exit | 626 | jmp $31, sys_exit |
| 627 | .end ret_from_kernel_thread | ||
| 636 | 628 | ||
| 637 | 1: ret /* in parent. */ | 629 | .globl ret_from_kernel_execve |
| 638 | 630 | .align 4 | |
| 639 | .align 4 | 631 | .ent ret_from_kernel_execve |
| 640 | 2: /* Fake a system call stack frame, as we can't do system calls | 632 | ret_from_kernel_execve: |
| 641 | from kernel space. Note that we store FN and ARG as they | 633 | mov $16, $sp |
| 642 | need to be set up in the child for the call. Also store $8 | ||
| 643 | and $26 for use in the parent. */ | ||
| 644 | stq $31, SP_OFF($sp) /* ps */ | ||
| 645 | stq $1, SP_OFF+8($sp) /* pc */ | ||
| 646 | stq $gp, SP_OFF+16($sp) /* gp */ | ||
| 647 | stq $16, 136($sp) /* $27; FN for child */ | ||
| 648 | stq $17, SP_OFF+24($sp) /* $16; ARG for child */ | ||
| 649 | stq $8, 64($sp) /* $8 */ | ||
| 650 | stq $26, 128($sp) /* $26 */ | ||
| 651 | /* Avoid the HAE being gratuitously wrong, to avoid restoring it. */ | 634 | /* Avoid the HAE being gratuitously wrong, to avoid restoring it. */ |
| 652 | ldq $2, alpha_mv+HAE_CACHE | 635 | ldq $2, alpha_mv+HAE_CACHE |
| 653 | stq $2, 152($sp) /* HAE */ | 636 | stq $2, 152($sp) /* HAE */ |
| 637 | mov $31, $19 /* to disable syscall restarts */ | ||
| 638 | br $31, ret_to_user | ||
| 654 | 639 | ||
| 655 | /* Shuffle FLAGS to the front; add CLONE_VM. */ | 640 | .end ret_from_kernel_execve |
| 656 | ldi $1, CLONE_VM|CLONE_UNTRACED | ||
| 657 | or $18, $1, $16 | ||
| 658 | bsr $26, sys_clone | ||
| 659 | |||
| 660 | /* We don't actually care for a3 success widgetry in the kernel. | ||
| 661 | Not for positive errno values. */ | ||
| 662 | stq $0, 0($sp) /* $0 */ | ||
| 663 | br ret_to_kernel | ||
| 664 | .end kernel_thread | ||
| 665 | 641 | ||
| 666 | 642 | ||
| 667 | /* | 643 | /* |
| @@ -745,15 +721,6 @@ sys_rt_sigreturn: | |||
| 745 | .end sys_rt_sigreturn | 721 | .end sys_rt_sigreturn |
| 746 | 722 | ||
| 747 | .align 4 | 723 | .align 4 |
| 748 | .globl sys_execve | ||
| 749 | .ent sys_execve | ||
| 750 | sys_execve: | ||
| 751 | .prologue 0 | ||
| 752 | mov $sp, $19 | ||
| 753 | jmp $31, do_sys_execve | ||
| 754 | .end sys_execve | ||
| 755 | |||
| 756 | .align 4 | ||
| 757 | .globl alpha_ni_syscall | 724 | .globl alpha_ni_syscall |
| 758 | .ent alpha_ni_syscall | 725 | .ent alpha_ni_syscall |
| 759 | alpha_ni_syscall: | 726 | alpha_ni_syscall: |
diff --git a/arch/alpha/kernel/process.c b/arch/alpha/kernel/process.c index 83638aa096d5..4054e0ffe2b2 100644 --- a/arch/alpha/kernel/process.c +++ b/arch/alpha/kernel/process.c | |||
| @@ -263,33 +263,35 @@ alpha_vfork(struct pt_regs *regs) | |||
| 263 | 263 | ||
| 264 | /* | 264 | /* |
| 265 | * Copy an alpha thread.. | 265 | * Copy an alpha thread.. |
| 266 | * | ||
| 267 | * Note the "stack_offset" stuff: when returning to kernel mode, we need | ||
| 268 | * to have some extra stack-space for the kernel stack that still exists | ||
| 269 | * after the "ret_from_fork". When returning to user mode, we only want | ||
| 270 | * the space needed by the syscall stack frame (ie "struct pt_regs"). | ||
| 271 | * Use the passed "regs" pointer to determine how much space we need | ||
| 272 | * for a kernel fork(). | ||
| 273 | */ | 266 | */ |
| 274 | 267 | ||
| 275 | int | 268 | int |
| 276 | copy_thread(unsigned long clone_flags, unsigned long usp, | 269 | copy_thread(unsigned long clone_flags, unsigned long usp, |
| 277 | unsigned long unused, | 270 | unsigned long arg, |
| 278 | struct task_struct * p, struct pt_regs * regs) | 271 | struct task_struct * p, struct pt_regs * regs) |
| 279 | { | 272 | { |
| 280 | extern void ret_from_fork(void); | 273 | extern void ret_from_fork(void); |
| 274 | extern void ret_from_kernel_thread(void); | ||
| 281 | 275 | ||
| 282 | struct thread_info *childti = task_thread_info(p); | 276 | struct thread_info *childti = task_thread_info(p); |
| 283 | struct pt_regs * childregs; | 277 | struct pt_regs *childregs = task_pt_regs(p); |
| 284 | struct switch_stack * childstack, *stack; | 278 | struct switch_stack *childstack, *stack; |
| 285 | unsigned long stack_offset, settls; | 279 | unsigned long settls; |
| 286 | 280 | ||
| 287 | stack_offset = PAGE_SIZE - sizeof(struct pt_regs); | 281 | childstack = ((struct switch_stack *) childregs) - 1; |
| 288 | if (!(regs->ps & 8)) | 282 | if (unlikely(!regs)) { |
| 289 | stack_offset = (PAGE_SIZE-1) & (unsigned long) regs; | 283 | /* kernel thread */ |
| 290 | childregs = (struct pt_regs *) | 284 | memset(childstack, 0, |
| 291 | (stack_offset + PAGE_SIZE + task_stack_page(p)); | 285 | sizeof(struct switch_stack) + sizeof(struct pt_regs)); |
| 292 | 286 | childstack->r26 = (unsigned long) ret_from_kernel_thread; | |
| 287 | childstack->r9 = usp; /* function */ | ||
| 288 | childstack->r10 = arg; | ||
| 289 | childregs->hae = alpha_mv.hae_cache, | ||
| 290 | childti->pcb.usp = 0; | ||
| 291 | childti->pcb.ksp = (unsigned long) childstack; | ||
| 292 | childti->pcb.flags = 1; /* set FEN, clear everything else */ | ||
| 293 | return 0; | ||
| 294 | } | ||
| 293 | *childregs = *regs; | 295 | *childregs = *regs; |
| 294 | settls = regs->r20; | 296 | settls = regs->r20; |
| 295 | childregs->r0 = 0; | 297 | childregs->r0 = 0; |
| @@ -297,7 +299,6 @@ copy_thread(unsigned long clone_flags, unsigned long usp, | |||
| 297 | childregs->r20 = 1; /* OSF/1 has some strange fork() semantics. */ | 299 | childregs->r20 = 1; /* OSF/1 has some strange fork() semantics. */ |
| 298 | regs->r20 = 0; | 300 | regs->r20 = 0; |
| 299 | stack = ((struct switch_stack *) regs) - 1; | 301 | stack = ((struct switch_stack *) regs) - 1; |
| 300 | childstack = ((struct switch_stack *) childregs) - 1; | ||
| 301 | *childstack = *stack; | 302 | *childstack = *stack; |
| 302 | childstack->r26 = (unsigned long) ret_from_fork; | 303 | childstack->r26 = (unsigned long) ret_from_fork; |
| 303 | childti->pcb.usp = usp; | 304 | childti->pcb.usp = usp; |
| @@ -386,27 +387,6 @@ dump_elf_task_fp(elf_fpreg_t *dest, struct task_struct *task) | |||
| 386 | EXPORT_SYMBOL(dump_elf_task_fp); | 387 | EXPORT_SYMBOL(dump_elf_task_fp); |
| 387 | 388 | ||
| 388 | /* | 389 | /* |
| 389 | * sys_execve() executes a new program. | ||
| 390 | */ | ||
| 391 | asmlinkage int | ||
| 392 | do_sys_execve(const char __user *ufilename, | ||
| 393 | const char __user *const __user *argv, | ||
| 394 | const char __user *const __user *envp, struct pt_regs *regs) | ||
| 395 | { | ||
| 396 | int error; | ||
| 397 | char *filename; | ||
| 398 | |||
| 399 | filename = getname(ufilename); | ||
| 400 | error = PTR_ERR(filename); | ||
| 401 | if (IS_ERR(filename)) | ||
| 402 | goto out; | ||
| 403 | error = do_execve(filename, argv, envp, regs); | ||
| 404 | putname(filename); | ||
| 405 | out: | ||
| 406 | return error; | ||
| 407 | } | ||
| 408 | |||
| 409 | /* | ||
| 410 | * Return saved PC of a blocked thread. This assumes the frame | 390 | * Return saved PC of a blocked thread. This assumes the frame |
| 411 | * pointer is the 6th saved long on the kernel stack and that the | 391 | * pointer is the 6th saved long on the kernel stack and that the |
| 412 | * saved return address is the first long in the frame. This all | 392 | * saved return address is the first long in the frame. This all |
| @@ -459,22 +439,3 @@ get_wchan(struct task_struct *p) | |||
| 459 | } | 439 | } |
| 460 | return pc; | 440 | return pc; |
| 461 | } | 441 | } |
| 462 | |||
| 463 | int kernel_execve(const char *path, const char *const argv[], const char *const envp[]) | ||
| 464 | { | ||
| 465 | /* Avoid the HAE being gratuitously wrong, which would cause us | ||
| 466 | to do the whole turn off interrupts thing and restore it. */ | ||
| 467 | struct pt_regs regs = {.hae = alpha_mv.hae_cache}; | ||
| 468 | int err = do_execve(path, argv, envp, ®s); | ||
| 469 | if (!err) { | ||
| 470 | struct pt_regs *p = current_pt_regs(); | ||
| 471 | /* copy regs to normal position and off to userland we go... */ | ||
| 472 | *p = regs; | ||
| 473 | __asm__ __volatile__ ( | ||
| 474 | "mov %0, $sp;" | ||
| 475 | "br $31, ret_from_sys_call" | ||
| 476 | : : "r"(p)); | ||
| 477 | } | ||
| 478 | return err; | ||
| 479 | } | ||
| 480 | EXPORT_SYMBOL(kernel_execve); | ||
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 2867a7742306..e40eefb5d32d 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig | |||
| @@ -52,6 +52,7 @@ config ARM | |||
| 52 | select GENERIC_STRNCPY_FROM_USER | 52 | select GENERIC_STRNCPY_FROM_USER |
| 53 | select GENERIC_STRNLEN_USER | 53 | select GENERIC_STRNLEN_USER |
| 54 | select DCACHE_WORD_ACCESS if (CPU_V6 || CPU_V6K || CPU_V7) && !CPU_BIG_ENDIAN | 54 | select DCACHE_WORD_ACCESS if (CPU_V6 || CPU_V6K || CPU_V7) && !CPU_BIG_ENDIAN |
| 55 | select GENERIC_KERNEL_THREAD | ||
| 55 | help | 56 | help |
| 56 | The ARM series is a line of low-power-consumption RISC chip designs | 57 | The ARM series is a line of low-power-consumption RISC chip designs |
| 57 | licensed by ARM Ltd and targeted at embedded applications and | 58 | licensed by ARM Ltd and targeted at embedded applications and |
diff --git a/arch/arm/include/asm/processor.h b/arch/arm/include/asm/processor.h index 99afa7498260..06e7d509eaac 100644 --- a/arch/arm/include/asm/processor.h +++ b/arch/arm/include/asm/processor.h | |||
| @@ -85,11 +85,6 @@ unsigned long get_wchan(struct task_struct *p); | |||
| 85 | #define cpu_relax() barrier() | 85 | #define cpu_relax() barrier() |
| 86 | #endif | 86 | #endif |
| 87 | 87 | ||
| 88 | /* | ||
| 89 | * Create a new kernel thread | ||
| 90 | */ | ||
| 91 | extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); | ||
| 92 | |||
| 93 | #define task_pt_regs(p) \ | 88 | #define task_pt_regs(p) \ |
| 94 | ((struct pt_regs *)(THREAD_START_SP + task_stack_page(p)) - 1) | 89 | ((struct pt_regs *)(THREAD_START_SP + task_stack_page(p)) - 1) |
| 95 | 90 | ||
diff --git a/arch/arm/include/asm/ptrace.h b/arch/arm/include/asm/ptrace.h index 355ece523f41..44fe998269d9 100644 --- a/arch/arm/include/asm/ptrace.h +++ b/arch/arm/include/asm/ptrace.h | |||
| @@ -254,6 +254,11 @@ static inline unsigned long user_stack_pointer(struct pt_regs *regs) | |||
| 254 | return regs->ARM_sp; | 254 | return regs->ARM_sp; |
| 255 | } | 255 | } |
| 256 | 256 | ||
| 257 | #define current_pt_regs(void) ({ \ | ||
| 258 | register unsigned long sp asm ("sp"); \ | ||
| 259 | (struct pt_regs *)((sp | (THREAD_SIZE - 1)) - 7) - 1; \ | ||
| 260 | }) | ||
| 261 | |||
| 257 | #endif /* __KERNEL__ */ | 262 | #endif /* __KERNEL__ */ |
| 258 | 263 | ||
| 259 | #endif /* __ASSEMBLY__ */ | 264 | #endif /* __ASSEMBLY__ */ |
diff --git a/arch/arm/include/asm/system.h b/arch/arm/include/asm/system.h index 74542c52f9be..368165e33c1c 100644 --- a/arch/arm/include/asm/system.h +++ b/arch/arm/include/asm/system.h | |||
| @@ -2,7 +2,6 @@ | |||
| 2 | #include <asm/barrier.h> | 2 | #include <asm/barrier.h> |
| 3 | #include <asm/compiler.h> | 3 | #include <asm/compiler.h> |
| 4 | #include <asm/cmpxchg.h> | 4 | #include <asm/cmpxchg.h> |
| 5 | #include <asm/exec.h> | ||
| 6 | #include <asm/switch_to.h> | 5 | #include <asm/switch_to.h> |
| 7 | #include <asm/system_info.h> | 6 | #include <asm/system_info.h> |
| 8 | #include <asm/system_misc.h> | 7 | #include <asm/system_misc.h> |
diff --git a/arch/arm/include/asm/unistd.h b/arch/arm/include/asm/unistd.h index d9ff5cc3a506..f259921edfe9 100644 --- a/arch/arm/include/asm/unistd.h +++ b/arch/arm/include/asm/unistd.h | |||
| @@ -478,6 +478,8 @@ | |||
| 478 | #define __ARCH_WANT_OLD_READDIR | 478 | #define __ARCH_WANT_OLD_READDIR |
| 479 | #define __ARCH_WANT_SYS_SOCKETCALL | 479 | #define __ARCH_WANT_SYS_SOCKETCALL |
| 480 | #endif | 480 | #endif |
| 481 | #define __ARCH_WANT_SYS_EXECVE | ||
| 482 | #define __ARCH_WANT_KERNEL_EXECVE | ||
| 481 | 483 | ||
| 482 | /* | 484 | /* |
| 483 | * "Conditional" syscalls | 485 | * "Conditional" syscalls |
diff --git a/arch/arm/kernel/calls.S b/arch/arm/kernel/calls.S index e337879595e5..831cd38c8d99 100644 --- a/arch/arm/kernel/calls.S +++ b/arch/arm/kernel/calls.S | |||
| @@ -20,7 +20,7 @@ | |||
| 20 | CALL(sys_creat) | 20 | CALL(sys_creat) |
| 21 | CALL(sys_link) | 21 | CALL(sys_link) |
| 22 | /* 10 */ CALL(sys_unlink) | 22 | /* 10 */ CALL(sys_unlink) |
| 23 | CALL(sys_execve_wrapper) | 23 | CALL(sys_execve) |
| 24 | CALL(sys_chdir) | 24 | CALL(sys_chdir) |
| 25 | CALL(OBSOLETE(sys_time)) /* used by libc4 */ | 25 | CALL(OBSOLETE(sys_time)) /* used by libc4 */ |
| 26 | CALL(sys_mknod) | 26 | CALL(sys_mknod) |
diff --git a/arch/arm/kernel/entry-common.S b/arch/arm/kernel/entry-common.S index f45987037bf1..e340fa1db203 100644 --- a/arch/arm/kernel/entry-common.S +++ b/arch/arm/kernel/entry-common.S | |||
| @@ -91,6 +91,30 @@ ENTRY(ret_from_fork) | |||
| 91 | b ret_slow_syscall | 91 | b ret_slow_syscall |
| 92 | ENDPROC(ret_from_fork) | 92 | ENDPROC(ret_from_fork) |
| 93 | 93 | ||
| 94 | ENTRY(ret_from_kernel_thread) | ||
| 95 | UNWIND(.fnstart) | ||
| 96 | UNWIND(.cantunwind) | ||
| 97 | bl schedule_tail | ||
| 98 | mov r0, r4 | ||
| 99 | adr lr, BSYM(1f) @ kernel threads should not exit | ||
| 100 | mov pc, r5 | ||
| 101 | 1: bl do_exit | ||
| 102 | nop | ||
| 103 | UNWIND(.fnend) | ||
| 104 | ENDPROC(ret_from_kernel_thread) | ||
| 105 | |||
| 106 | /* | ||
| 107 | * turn a kernel thread into userland process | ||
| 108 | * use: ret_from_kernel_execve(struct pt_regs *normal) | ||
| 109 | */ | ||
| 110 | ENTRY(ret_from_kernel_execve) | ||
| 111 | mov why, #0 @ not a syscall | ||
| 112 | str why, [r0, #S_R0] @ ... and we want 0 in ->ARM_r0 as well | ||
| 113 | get_thread_info tsk @ thread structure | ||
| 114 | mov sp, r0 @ stack pointer just under pt_regs | ||
| 115 | b ret_slow_syscall | ||
| 116 | ENDPROC(ret_from_kernel_execve) | ||
| 117 | |||
| 94 | .equ NR_syscalls,0 | 118 | .equ NR_syscalls,0 |
| 95 | #define CALL(x) .equ NR_syscalls,NR_syscalls+1 | 119 | #define CALL(x) .equ NR_syscalls,NR_syscalls+1 |
| 96 | #include "calls.S" | 120 | #include "calls.S" |
| @@ -517,11 +541,6 @@ sys_vfork_wrapper: | |||
| 517 | b sys_vfork | 541 | b sys_vfork |
| 518 | ENDPROC(sys_vfork_wrapper) | 542 | ENDPROC(sys_vfork_wrapper) |
| 519 | 543 | ||
| 520 | sys_execve_wrapper: | ||
| 521 | add r3, sp, #S_OFF | ||
| 522 | b sys_execve | ||
| 523 | ENDPROC(sys_execve_wrapper) | ||
| 524 | |||
| 525 | sys_clone_wrapper: | 544 | sys_clone_wrapper: |
| 526 | add ip, sp, #S_OFF | 545 | add ip, sp, #S_OFF |
| 527 | str ip, [sp, #4] | 546 | str ip, [sp, #4] |
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index 04eea22d7958..f98c17ff1957 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c | |||
| @@ -373,6 +373,7 @@ void release_thread(struct task_struct *dead_task) | |||
| 373 | } | 373 | } |
| 374 | 374 | ||
| 375 | asmlinkage void ret_from_fork(void) __asm__("ret_from_fork"); | 375 | asmlinkage void ret_from_fork(void) __asm__("ret_from_fork"); |
| 376 | asmlinkage void ret_from_kernel_thread(void) __asm__("ret_from_kernel_thread"); | ||
| 376 | 377 | ||
| 377 | int | 378 | int |
| 378 | copy_thread(unsigned long clone_flags, unsigned long stack_start, | 379 | copy_thread(unsigned long clone_flags, unsigned long stack_start, |
| @@ -381,13 +382,20 @@ copy_thread(unsigned long clone_flags, unsigned long stack_start, | |||
| 381 | struct thread_info *thread = task_thread_info(p); | 382 | struct thread_info *thread = task_thread_info(p); |
| 382 | struct pt_regs *childregs = task_pt_regs(p); | 383 | struct pt_regs *childregs = task_pt_regs(p); |
| 383 | 384 | ||
| 384 | *childregs = *regs; | ||
| 385 | childregs->ARM_r0 = 0; | ||
| 386 | childregs->ARM_sp = stack_start; | ||
| 387 | |||
| 388 | memset(&thread->cpu_context, 0, sizeof(struct cpu_context_save)); | 385 | memset(&thread->cpu_context, 0, sizeof(struct cpu_context_save)); |
| 386 | |||
| 387 | if (likely(regs)) { | ||
| 388 | *childregs = *regs; | ||
| 389 | childregs->ARM_r0 = 0; | ||
| 390 | childregs->ARM_sp = stack_start; | ||
| 391 | thread->cpu_context.pc = (unsigned long)ret_from_fork; | ||
| 392 | } else { | ||
| 393 | thread->cpu_context.r4 = stk_sz; | ||
| 394 | thread->cpu_context.r5 = stack_start; | ||
| 395 | thread->cpu_context.pc = (unsigned long)ret_from_kernel_thread; | ||
| 396 | childregs->ARM_cpsr = SVC_MODE; | ||
| 397 | } | ||
| 389 | thread->cpu_context.sp = (unsigned long)childregs; | 398 | thread->cpu_context.sp = (unsigned long)childregs; |
| 390 | thread->cpu_context.pc = (unsigned long)ret_from_fork; | ||
| 391 | 399 | ||
| 392 | clear_ptrace_hw_breakpoint(p); | 400 | clear_ptrace_hw_breakpoint(p); |
| 393 | 401 | ||
| @@ -423,63 +431,6 @@ int dump_fpu (struct pt_regs *regs, struct user_fp *fp) | |||
| 423 | } | 431 | } |
| 424 | EXPORT_SYMBOL(dump_fpu); | 432 | EXPORT_SYMBOL(dump_fpu); |
| 425 | 433 | ||
| 426 | /* | ||
| 427 | * Shuffle the argument into the correct register before calling the | ||
| 428 | * thread function. r4 is the thread argument, r5 is the pointer to | ||
| 429 | * the thread function, and r6 points to the exit function. | ||
| 430 | */ | ||
| 431 | extern void kernel_thread_helper(void); | ||
| 432 | asm( ".pushsection .text\n" | ||
| 433 | " .align\n" | ||
| 434 | " .type kernel_thread_helper, #function\n" | ||
| 435 | "kernel_thread_helper:\n" | ||
| 436 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
| 437 | " bl trace_hardirqs_on\n" | ||
| 438 | #endif | ||
| 439 | " msr cpsr_c, r7\n" | ||
| 440 | " mov r0, r4\n" | ||
| 441 | " mov lr, r6\n" | ||
| 442 | " mov pc, r5\n" | ||
| 443 | " .size kernel_thread_helper, . - kernel_thread_helper\n" | ||
| 444 | " .popsection"); | ||
| 445 | |||
| 446 | #ifdef CONFIG_ARM_UNWIND | ||
| 447 | extern void kernel_thread_exit(long code); | ||
| 448 | asm( ".pushsection .text\n" | ||
| 449 | " .align\n" | ||
| 450 | " .type kernel_thread_exit, #function\n" | ||
| 451 | "kernel_thread_exit:\n" | ||
| 452 | " .fnstart\n" | ||
| 453 | " .cantunwind\n" | ||
| 454 | " bl do_exit\n" | ||
| 455 | " nop\n" | ||
| 456 | " .fnend\n" | ||
| 457 | " .size kernel_thread_exit, . - kernel_thread_exit\n" | ||
| 458 | " .popsection"); | ||
| 459 | #else | ||
| 460 | #define kernel_thread_exit do_exit | ||
| 461 | #endif | ||
| 462 | |||
| 463 | /* | ||
| 464 | * Create a kernel thread. | ||
| 465 | */ | ||
| 466 | pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) | ||
| 467 | { | ||
| 468 | struct pt_regs regs; | ||
| 469 | |||
| 470 | memset(®s, 0, sizeof(regs)); | ||
| 471 | |||
| 472 | regs.ARM_r4 = (unsigned long)arg; | ||
| 473 | regs.ARM_r5 = (unsigned long)fn; | ||
| 474 | regs.ARM_r6 = (unsigned long)kernel_thread_exit; | ||
| 475 | regs.ARM_r7 = SVC_MODE | PSR_ENDSTATE | PSR_ISETSTATE; | ||
| 476 | regs.ARM_pc = (unsigned long)kernel_thread_helper; | ||
| 477 | regs.ARM_cpsr = regs.ARM_r7 | PSR_I_BIT; | ||
| 478 | |||
| 479 | return do_fork(flags|CLONE_VM|CLONE_UNTRACED, 0, ®s, 0, NULL, NULL); | ||
| 480 | } | ||
| 481 | EXPORT_SYMBOL(kernel_thread); | ||
| 482 | |||
| 483 | unsigned long get_wchan(struct task_struct *p) | 434 | unsigned long get_wchan(struct task_struct *p) |
| 484 | { | 435 | { |
| 485 | struct stackframe frame; | 436 | struct stackframe frame; |
diff --git a/arch/arm/kernel/sys_arm.c b/arch/arm/kernel/sys_arm.c index 76cbb055dd05..c2a898aa57aa 100644 --- a/arch/arm/kernel/sys_arm.c +++ b/arch/arm/kernel/sys_arm.c | |||
| @@ -59,69 +59,6 @@ asmlinkage int sys_vfork(struct pt_regs *regs) | |||
| 59 | return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->ARM_sp, regs, 0, NULL, NULL); | 59 | return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->ARM_sp, regs, 0, NULL, NULL); |
| 60 | } | 60 | } |
| 61 | 61 | ||
| 62 | /* sys_execve() executes a new program. | ||
| 63 | * This is called indirectly via a small wrapper | ||
| 64 | */ | ||
| 65 | asmlinkage int sys_execve(const char __user *filenamei, | ||
| 66 | const char __user *const __user *argv, | ||
| 67 | const char __user *const __user *envp, struct pt_regs *regs) | ||
| 68 | { | ||
| 69 | int error; | ||
| 70 | char * filename; | ||
| 71 | |||
| 72 | filename = getname(filenamei); | ||
| 73 | error = PTR_ERR(filename); | ||
| 74 | if (IS_ERR(filename)) | ||
| 75 | goto out; | ||
| 76 | error = do_execve(filename, argv, envp, regs); | ||
| 77 | putname(filename); | ||
| 78 | out: | ||
| 79 | return error; | ||
| 80 | } | ||
| 81 | |||
| 82 | int kernel_execve(const char *filename, | ||
| 83 | const char *const argv[], | ||
| 84 | const char *const envp[]) | ||
| 85 | { | ||
| 86 | struct pt_regs regs; | ||
| 87 | int ret; | ||
| 88 | |||
| 89 | memset(®s, 0, sizeof(struct pt_regs)); | ||
| 90 | ret = do_execve(filename, | ||
| 91 | (const char __user *const __user *)argv, | ||
| 92 | (const char __user *const __user *)envp, ®s); | ||
| 93 | if (ret < 0) | ||
| 94 | goto out; | ||
| 95 | |||
| 96 | /* | ||
| 97 | * Save argc to the register structure for userspace. | ||
| 98 | */ | ||
| 99 | regs.ARM_r0 = ret; | ||
| 100 | |||
| 101 | /* | ||
| 102 | * We were successful. We won't be returning to our caller, but | ||
| 103 | * instead to user space by manipulating the kernel stack. | ||
| 104 | */ | ||
| 105 | asm( "add r0, %0, %1\n\t" | ||
| 106 | "mov r1, %2\n\t" | ||
| 107 | "mov r2, %3\n\t" | ||
| 108 | "bl memmove\n\t" /* copy regs to top of stack */ | ||
| 109 | "mov r8, #0\n\t" /* not a syscall */ | ||
| 110 | "mov r9, %0\n\t" /* thread structure */ | ||
| 111 | "mov sp, r0\n\t" /* reposition stack pointer */ | ||
| 112 | "b ret_to_user" | ||
| 113 | : | ||
| 114 | : "r" (current_thread_info()), | ||
| 115 | "Ir" (THREAD_START_SP - sizeof(regs)), | ||
| 116 | "r" (®s), | ||
| 117 | "Ir" (sizeof(regs)) | ||
| 118 | : "r0", "r1", "r2", "r3", "r8", "r9", "ip", "lr", "memory"); | ||
| 119 | |||
| 120 | out: | ||
| 121 | return ret; | ||
| 122 | } | ||
| 123 | EXPORT_SYMBOL(kernel_execve); | ||
| 124 | |||
| 125 | /* | 62 | /* |
| 126 | * Since loff_t is a 64 bit type we avoid a lot of ABI hassle | 63 | * Since loff_t is a 64 bit type we avoid a lot of ABI hassle |
| 127 | * with a different argument ordering. | 64 | * with a different argument ordering. |
diff --git a/arch/avr32/include/asm/Kbuild b/arch/avr32/include/asm/Kbuild index e3ba7bca06fa..be0433ee5a8e 100644 --- a/arch/avr32/include/asm/Kbuild +++ b/arch/avr32/include/asm/Kbuild | |||
| @@ -1,5 +1,6 @@ | |||
| 1 | include include/asm-generic/Kbuild.asm | 1 | include include/asm-generic/Kbuild.asm |
| 2 | 2 | ||
| 3 | generic-y += clkdev.h | 3 | generic-y += clkdev.h |
| 4 | generic-y += exec.h | ||
| 4 | 5 | ||
| 5 | header-y += cachectl.h | 6 | header-y += cachectl.h |
diff --git a/arch/avr32/include/asm/exec.h b/arch/avr32/include/asm/exec.h deleted file mode 100644 index f467be8bf823..000000000000 --- a/arch/avr32/include/asm/exec.h +++ /dev/null | |||
| @@ -1,13 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2004-2006 Atmel Corporation | ||
| 3 | * | ||
| 4 | * This program is free software; you can redistribute it and/or modify | ||
| 5 | * it under the terms of the GNU General Public License version 2 as | ||
| 6 | * published by the Free Software Foundation. | ||
| 7 | */ | ||
| 8 | #ifndef __ASM_AVR32_EXEC_H | ||
| 9 | #define __ASM_AVR32_EXEC_H | ||
| 10 | |||
| 11 | #define arch_align_stack(x) (x) | ||
| 12 | |||
| 13 | #endif /* __ASM_AVR32_EXEC_H */ | ||
diff --git a/arch/c6x/include/asm/Kbuild b/arch/c6x/include/asm/Kbuild index 277f1a4ecb09..4e4e98da8192 100644 --- a/arch/c6x/include/asm/Kbuild +++ b/arch/c6x/include/asm/Kbuild | |||
| @@ -12,6 +12,7 @@ generic-y += div64.h | |||
| 12 | generic-y += dma.h | 12 | generic-y += dma.h |
| 13 | generic-y += emergency-restart.h | 13 | generic-y += emergency-restart.h |
| 14 | generic-y += errno.h | 14 | generic-y += errno.h |
| 15 | generic-y += exec.h | ||
| 15 | generic-y += fb.h | 16 | generic-y += fb.h |
| 16 | generic-y += fcntl.h | 17 | generic-y += fcntl.h |
| 17 | generic-y += futex.h | 18 | generic-y += futex.h |
diff --git a/arch/c6x/include/asm/exec.h b/arch/c6x/include/asm/exec.h deleted file mode 100644 index 0fea482cdc84..000000000000 --- a/arch/c6x/include/asm/exec.h +++ /dev/null | |||
| @@ -1,6 +0,0 @@ | |||
| 1 | #ifndef _ASM_C6X_EXEC_H | ||
| 2 | #define _ASM_C6X_EXEC_H | ||
| 3 | |||
| 4 | #define arch_align_stack(x) (x) | ||
| 5 | |||
| 6 | #endif /* _ASM_C6X_EXEC_H */ | ||
diff --git a/arch/cris/include/asm/Kbuild b/arch/cris/include/asm/Kbuild index a8eab26a1ec7..ff1bf7fcae8e 100644 --- a/arch/cris/include/asm/Kbuild +++ b/arch/cris/include/asm/Kbuild | |||
| @@ -9,3 +9,4 @@ header-y += rs485.h | |||
| 9 | header-y += sync_serial.h | 9 | header-y += sync_serial.h |
| 10 | 10 | ||
| 11 | generic-y += clkdev.h | 11 | generic-y += clkdev.h |
| 12 | generic-y += exec.h | ||
diff --git a/arch/cris/include/asm/exec.h b/arch/cris/include/asm/exec.h deleted file mode 100644 index 9665dab7e25b..000000000000 --- a/arch/cris/include/asm/exec.h +++ /dev/null | |||
| @@ -1,6 +0,0 @@ | |||
| 1 | #ifndef __ASM_CRIS_EXEC_H | ||
| 2 | #define __ASM_CRIS_EXEC_H | ||
| 3 | |||
| 4 | #define arch_align_stack(x) (x) | ||
| 5 | |||
| 6 | #endif /* __ASM_CRIS_EXEC_H */ | ||
diff --git a/arch/frv/include/asm/Kbuild b/arch/frv/include/asm/Kbuild index 13cd044aabdf..251bd7125576 100644 --- a/arch/frv/include/asm/Kbuild +++ b/arch/frv/include/asm/Kbuild | |||
| @@ -3,3 +3,4 @@ include include/asm-generic/Kbuild.asm | |||
| 3 | header-y += registers.h | 3 | header-y += registers.h |
| 4 | header-y += termios.h | 4 | header-y += termios.h |
| 5 | generic-y += clkdev.h | 5 | generic-y += clkdev.h |
| 6 | generic-y += exec.h | ||
diff --git a/arch/frv/include/asm/exec.h b/arch/frv/include/asm/exec.h deleted file mode 100644 index 65c91305d4a7..000000000000 --- a/arch/frv/include/asm/exec.h +++ /dev/null | |||
| @@ -1,17 +0,0 @@ | |||
| 1 | /* FR-V CPU executable handling | ||
| 2 | * | ||
| 3 | * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved. | ||
| 4 | * Written by David Howells (dhowells@redhat.com) | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of the GNU General Public License | ||
| 8 | * as published by the Free Software Foundation; either version | ||
| 9 | * 2 of the License, or (at your option) any later version. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #ifndef _ASM_EXEC_H | ||
| 13 | #define _ASM_EXEC_H | ||
| 14 | |||
| 15 | #define arch_align_stack(x) (x) | ||
| 16 | |||
| 17 | #endif /* _ASM_EXEC_H */ | ||
diff --git a/arch/h8300/include/asm/Kbuild b/arch/h8300/include/asm/Kbuild index 0e152a93c125..fccd81eddff1 100644 --- a/arch/h8300/include/asm/Kbuild +++ b/arch/h8300/include/asm/Kbuild | |||
| @@ -1,3 +1,4 @@ | |||
| 1 | include include/asm-generic/Kbuild.asm | 1 | include include/asm-generic/Kbuild.asm |
| 2 | 2 | ||
| 3 | generic-y += clkdev.h | 3 | generic-y += clkdev.h |
| 4 | generic-y += exec.h | ||
diff --git a/arch/h8300/include/asm/exec.h b/arch/h8300/include/asm/exec.h deleted file mode 100644 index c01c45ccadf9..000000000000 --- a/arch/h8300/include/asm/exec.h +++ /dev/null | |||
| @@ -1,6 +0,0 @@ | |||
| 1 | #ifndef _H8300_EXEC_H | ||
| 2 | #define _H8300_EXEC_H | ||
| 3 | |||
| 4 | #define arch_align_stack(x) (x) | ||
| 5 | |||
| 6 | #endif /* _H8300_EXEC_H */ | ||
diff --git a/arch/hexagon/kernel/syscall.c b/arch/hexagon/kernel/syscall.c index 620dd18197a0..553cd60ee659 100644 --- a/arch/hexagon/kernel/syscall.c +++ b/arch/hexagon/kernel/syscall.c | |||
| @@ -87,4 +87,3 @@ int kernel_execve(const char *filename, | |||
| 87 | 87 | ||
| 88 | return retval; | 88 | return retval; |
| 89 | } | 89 | } |
| 90 | EXPORT_SYMBOL(kernel_execve); | ||
diff --git a/arch/ia64/include/asm/Kbuild b/arch/ia64/include/asm/Kbuild index 58f3d14a6cd4..562f59315847 100644 --- a/arch/ia64/include/asm/Kbuild +++ b/arch/ia64/include/asm/Kbuild | |||
| @@ -14,3 +14,4 @@ header-y += rse.h | |||
| 14 | header-y += ucontext.h | 14 | header-y += ucontext.h |
| 15 | header-y += ustack.h | 15 | header-y += ustack.h |
| 16 | generic-y += clkdev.h | 16 | generic-y += clkdev.h |
| 17 | generic-y += exec.h | ||
diff --git a/arch/ia64/include/asm/exec.h b/arch/ia64/include/asm/exec.h deleted file mode 100644 index b26242490e36..000000000000 --- a/arch/ia64/include/asm/exec.h +++ /dev/null | |||
| @@ -1,14 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Process execution defines. | ||
| 3 | * | ||
| 4 | * Copyright (C) 1998-2003 Hewlett-Packard Co | ||
| 5 | * David Mosberger-Tang <davidm@hpl.hp.com> | ||
| 6 | * Copyright (C) 1999 Asit Mallick <asit.k.mallick@intel.com> | ||
| 7 | * Copyright (C) 1999 Don Dugger <don.dugger@intel.com> | ||
| 8 | */ | ||
| 9 | #ifndef _ASM_IA64_EXEC_H | ||
| 10 | #define _ASM_IA64_EXEC_H | ||
| 11 | |||
| 12 | #define arch_align_stack(x) (x) | ||
| 13 | |||
| 14 | #endif /* _ASM_IA64_EXEC_H */ | ||
diff --git a/arch/m32r/include/asm/Kbuild b/arch/m32r/include/asm/Kbuild index 0e152a93c125..fccd81eddff1 100644 --- a/arch/m32r/include/asm/Kbuild +++ b/arch/m32r/include/asm/Kbuild | |||
| @@ -1,3 +1,4 @@ | |||
| 1 | include include/asm-generic/Kbuild.asm | 1 | include include/asm-generic/Kbuild.asm |
| 2 | 2 | ||
| 3 | generic-y += clkdev.h | 3 | generic-y += clkdev.h |
| 4 | generic-y += exec.h | ||
diff --git a/arch/m32r/include/asm/exec.h b/arch/m32r/include/asm/exec.h deleted file mode 100644 index c805dbd75b5d..000000000000 --- a/arch/m32r/include/asm/exec.h +++ /dev/null | |||
| @@ -1,14 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * This file is subject to the terms and conditions of the GNU General Public | ||
| 3 | * License. See the file "COPYING" in the main directory of this archive | ||
| 4 | * for more details. | ||
| 5 | * | ||
| 6 | * Copyright (C) 2001 Hiroyuki Kondo, Hirokazu Takata, and Hitoshi Yamamoto | ||
| 7 | * Copyright (C) 2004, 2006 Hirokazu Takata <takata at linux-m32r.org> | ||
| 8 | */ | ||
| 9 | #ifndef _ASM_M32R_EXEC_H | ||
| 10 | #define _ASM_M32R_EXEC_H | ||
| 11 | |||
| 12 | #define arch_align_stack(x) (x) | ||
| 13 | |||
| 14 | #endif /* _ASM_M32R_EXEC_H */ | ||
diff --git a/arch/m68k/include/asm/Kbuild b/arch/m68k/include/asm/Kbuild index bfe675f0faee..ecb540810ab3 100644 --- a/arch/m68k/include/asm/Kbuild +++ b/arch/m68k/include/asm/Kbuild | |||
| @@ -7,6 +7,7 @@ generic-y += cputime.h | |||
| 7 | generic-y += device.h | 7 | generic-y += device.h |
| 8 | generic-y += emergency-restart.h | 8 | generic-y += emergency-restart.h |
| 9 | generic-y += errno.h | 9 | generic-y += errno.h |
| 10 | generic-y += exec.h | ||
| 10 | generic-y += futex.h | 11 | generic-y += futex.h |
| 11 | generic-y += ioctl.h | 12 | generic-y += ioctl.h |
| 12 | generic-y += ipcbuf.h | 13 | generic-y += ipcbuf.h |
diff --git a/arch/m68k/include/asm/exec.h b/arch/m68k/include/asm/exec.h deleted file mode 100644 index 0499adf90230..000000000000 --- a/arch/m68k/include/asm/exec.h +++ /dev/null | |||
| @@ -1,6 +0,0 @@ | |||
| 1 | #ifndef _M68K_EXEC_H | ||
| 2 | #define _M68K_EXEC_H | ||
| 3 | |||
| 4 | #define arch_align_stack(x) (x) | ||
| 5 | |||
| 6 | #endif /* _M68K_EXEC_H */ | ||
diff --git a/arch/microblaze/include/asm/Kbuild b/arch/microblaze/include/asm/Kbuild index 48510f6cec8f..8653072d7e9f 100644 --- a/arch/microblaze/include/asm/Kbuild +++ b/arch/microblaze/include/asm/Kbuild | |||
| @@ -2,3 +2,4 @@ include include/asm-generic/Kbuild.asm | |||
| 2 | 2 | ||
| 3 | header-y += elf.h | 3 | header-y += elf.h |
| 4 | generic-y += clkdev.h | 4 | generic-y += clkdev.h |
| 5 | generic-y += exec.h | ||
diff --git a/arch/microblaze/include/asm/exec.h b/arch/microblaze/include/asm/exec.h deleted file mode 100644 index e750de1fe8fb..000000000000 --- a/arch/microblaze/include/asm/exec.h +++ /dev/null | |||
| @@ -1,14 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2006 Atmark Techno, Inc. | ||
| 3 | * | ||
| 4 | * This file is subject to the terms and conditions of the GNU General Public | ||
| 5 | * License. See the file "COPYING" in the main directory of this archive | ||
| 6 | * for more details. | ||
| 7 | */ | ||
| 8 | |||
| 9 | #ifndef _ASM_MICROBLAZE_EXEC_H | ||
| 10 | #define _ASM_MICROBLAZE_EXEC_H | ||
| 11 | |||
| 12 | #define arch_align_stack(x) (x) | ||
| 13 | |||
| 14 | #endif /* _ASM_MICROBLAZE_EXEC_H */ | ||
diff --git a/arch/mn10300/include/asm/Kbuild b/arch/mn10300/include/asm/Kbuild index 0d20f5526dd8..fccd81eddff1 100644 --- a/arch/mn10300/include/asm/Kbuild +++ b/arch/mn10300/include/asm/Kbuild | |||
| @@ -1,3 +1,4 @@ | |||
| 1 | include include/asm-generic/Kbuild.asm | 1 | include include/asm-generic/Kbuild.asm |
| 2 | 2 | ||
| 3 | generic-y += clkdev.h | 3 | generic-y += clkdev.h |
| 4 | generic-y += exec.h | ||
diff --git a/arch/mn10300/include/asm/exec.h b/arch/mn10300/include/asm/exec.h deleted file mode 100644 index c74e367f4b9d..000000000000 --- a/arch/mn10300/include/asm/exec.h +++ /dev/null | |||
| @@ -1,16 +0,0 @@ | |||
| 1 | /* MN10300 process execution definitions | ||
| 2 | * | ||
| 3 | * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. | ||
| 4 | * Written by David Howells (dhowells@redhat.com) | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of the GNU General Public Licence | ||
| 8 | * as published by the Free Software Foundation; either version | ||
| 9 | * 2 of the Licence, or (at your option) any later version. | ||
| 10 | */ | ||
| 11 | #ifndef _ASM_EXEC_H | ||
| 12 | #define _ASM_EXEC_H | ||
| 13 | |||
| 14 | #define arch_align_stack(x) (x) | ||
| 15 | |||
| 16 | #endif /* _ASM_EXEC_H */ | ||
diff --git a/arch/parisc/include/asm/Kbuild b/arch/parisc/include/asm/Kbuild index 0587f62e5b76..458371a1565a 100644 --- a/arch/parisc/include/asm/Kbuild +++ b/arch/parisc/include/asm/Kbuild | |||
| @@ -3,3 +3,4 @@ include include/asm-generic/Kbuild.asm | |||
| 3 | header-y += pdc.h | 3 | header-y += pdc.h |
| 4 | generic-y += clkdev.h | 4 | generic-y += clkdev.h |
| 5 | generic-y += word-at-a-time.h | 5 | generic-y += word-at-a-time.h |
| 6 | generic-y += exec.h | ||
diff --git a/arch/parisc/include/asm/exec.h b/arch/parisc/include/asm/exec.h deleted file mode 100644 index 6bb5af75b17a..000000000000 --- a/arch/parisc/include/asm/exec.h +++ /dev/null | |||
| @@ -1,6 +0,0 @@ | |||
| 1 | #ifndef __PARISC_EXEC_H | ||
| 2 | #define __PARISC_EXEC_H | ||
| 3 | |||
| 4 | #define arch_align_stack(x) (x) | ||
| 5 | |||
| 6 | #endif /* __PARISC_EXEC_H */ | ||
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index ceff7aef2477..99d2d790d152 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig | |||
| @@ -135,6 +135,7 @@ config S390 | |||
| 135 | select GENERIC_CLOCKEVENTS | 135 | select GENERIC_CLOCKEVENTS |
| 136 | select KTIME_SCALAR if 32BIT | 136 | select KTIME_SCALAR if 32BIT |
| 137 | select HAVE_ARCH_SECCOMP_FILTER | 137 | select HAVE_ARCH_SECCOMP_FILTER |
| 138 | select GENERIC_KERNEL_THREAD | ||
| 138 | 139 | ||
| 139 | config SCHED_OMIT_FRAME_POINTER | 140 | config SCHED_OMIT_FRAME_POINTER |
| 140 | def_bool y | 141 | def_bool y |
diff --git a/arch/s390/include/asm/processor.h b/arch/s390/include/asm/processor.h index 56831dfa9198..94e749c90230 100644 --- a/arch/s390/include/asm/processor.h +++ b/arch/s390/include/asm/processor.h | |||
| @@ -35,6 +35,7 @@ static inline void get_cpu_id(struct cpuid *ptr) | |||
| 35 | extern void s390_adjust_jiffies(void); | 35 | extern void s390_adjust_jiffies(void); |
| 36 | extern const struct seq_operations cpuinfo_op; | 36 | extern const struct seq_operations cpuinfo_op; |
| 37 | extern int sysctl_ieee_emulation_warnings; | 37 | extern int sysctl_ieee_emulation_warnings; |
| 38 | extern void execve_tail(void); | ||
| 38 | 39 | ||
| 39 | /* | 40 | /* |
| 40 | * User space process size: 2GB for 31 bit, 4TB or 8PT for 64 bit. | 41 | * User space process size: 2GB for 31 bit, 4TB or 8PT for 64 bit. |
| @@ -126,6 +127,7 @@ struct stack_frame { | |||
| 126 | regs->psw.mask = psw_user_bits | PSW_MASK_EA | PSW_MASK_BA; \ | 127 | regs->psw.mask = psw_user_bits | PSW_MASK_EA | PSW_MASK_BA; \ |
| 127 | regs->psw.addr = new_psw | PSW_ADDR_AMODE; \ | 128 | regs->psw.addr = new_psw | PSW_ADDR_AMODE; \ |
| 128 | regs->gprs[15] = new_stackp; \ | 129 | regs->gprs[15] = new_stackp; \ |
| 130 | execve_tail(); \ | ||
| 129 | } while (0) | 131 | } while (0) |
| 130 | 132 | ||
| 131 | #define start_thread31(regs, new_psw, new_stackp) do { \ | 133 | #define start_thread31(regs, new_psw, new_stackp) do { \ |
| @@ -135,6 +137,7 @@ struct stack_frame { | |||
| 135 | __tlb_flush_mm(current->mm); \ | 137 | __tlb_flush_mm(current->mm); \ |
| 136 | crst_table_downgrade(current->mm, 1UL << 31); \ | 138 | crst_table_downgrade(current->mm, 1UL << 31); \ |
| 137 | update_mm(current->mm, current); \ | 139 | update_mm(current->mm, current); \ |
| 140 | execve_tail(); \ | ||
| 138 | } while (0) | 141 | } while (0) |
| 139 | 142 | ||
| 140 | /* Forward declaration, a strange C thing */ | 143 | /* Forward declaration, a strange C thing */ |
| @@ -150,7 +153,6 @@ static inline void show_cacheinfo(struct seq_file *m) { } | |||
| 150 | 153 | ||
| 151 | /* Free all resources held by a thread. */ | 154 | /* Free all resources held by a thread. */ |
| 152 | extern void release_thread(struct task_struct *); | 155 | extern void release_thread(struct task_struct *); |
| 153 | extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); | ||
| 154 | 156 | ||
| 155 | /* | 157 | /* |
| 156 | * Return saved PC of a blocked thread. | 158 | * Return saved PC of a blocked thread. |
diff --git a/arch/s390/include/asm/unistd.h b/arch/s390/include/asm/unistd.h index 4e64b5cd1558..8192e292753a 100644 --- a/arch/s390/include/asm/unistd.h +++ b/arch/s390/include/asm/unistd.h | |||
| @@ -417,6 +417,8 @@ | |||
| 417 | # define __ARCH_WANT_COMPAT_SYS_TIME | 417 | # define __ARCH_WANT_COMPAT_SYS_TIME |
| 418 | # define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND | 418 | # define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND |
| 419 | # endif | 419 | # endif |
| 420 | #define __ARCH_WANT_SYS_EXECVE | ||
| 421 | #define __ARCH_WANT_KERNEL_EXECVE | ||
| 420 | 422 | ||
| 421 | /* | 423 | /* |
| 422 | * "Conditional" syscalls | 424 | * "Conditional" syscalls |
diff --git a/arch/s390/kernel/compat_linux.c b/arch/s390/kernel/compat_linux.c index 189963c90c6e..65cca95843e1 100644 --- a/arch/s390/kernel/compat_linux.c +++ b/arch/s390/kernel/compat_linux.c | |||
| @@ -432,32 +432,6 @@ sys32_rt_sigqueueinfo(int pid, int sig, compat_siginfo_t __user *uinfo) | |||
| 432 | return ret; | 432 | return ret; |
| 433 | } | 433 | } |
| 434 | 434 | ||
| 435 | /* | ||
| 436 | * sys32_execve() executes a new program after the asm stub has set | ||
| 437 | * things up for us. This should basically do what I want it to. | ||
| 438 | */ | ||
| 439 | asmlinkage long sys32_execve(const char __user *name, compat_uptr_t __user *argv, | ||
| 440 | compat_uptr_t __user *envp) | ||
| 441 | { | ||
| 442 | struct pt_regs *regs = task_pt_regs(current); | ||
| 443 | char *filename; | ||
| 444 | long rc; | ||
| 445 | |||
| 446 | filename = getname(name); | ||
| 447 | rc = PTR_ERR(filename); | ||
| 448 | if (IS_ERR(filename)) | ||
| 449 | return rc; | ||
| 450 | rc = compat_do_execve(filename, argv, envp, regs); | ||
| 451 | if (rc) | ||
| 452 | goto out; | ||
| 453 | current->thread.fp_regs.fpc=0; | ||
| 454 | asm volatile("sfpc %0,0" : : "d" (0)); | ||
| 455 | rc = regs->gprs[2]; | ||
| 456 | out: | ||
| 457 | putname(filename); | ||
| 458 | return rc; | ||
| 459 | } | ||
| 460 | |||
| 461 | asmlinkage long sys32_pread64(unsigned int fd, char __user *ubuf, | 435 | asmlinkage long sys32_pread64(unsigned int fd, char __user *ubuf, |
| 462 | size_t count, u32 poshi, u32 poslo) | 436 | size_t count, u32 poshi, u32 poslo) |
| 463 | { | 437 | { |
diff --git a/arch/s390/kernel/compat_linux.h b/arch/s390/kernel/compat_linux.h index 90887bd98cf0..d4d0239970ac 100644 --- a/arch/s390/kernel/compat_linux.h +++ b/arch/s390/kernel/compat_linux.h | |||
| @@ -125,8 +125,6 @@ long sys32_rt_sigprocmask(int how, compat_sigset_t __user *set, | |||
| 125 | compat_sigset_t __user *oset, size_t sigsetsize); | 125 | compat_sigset_t __user *oset, size_t sigsetsize); |
| 126 | long sys32_rt_sigpending(compat_sigset_t __user *set, size_t sigsetsize); | 126 | long sys32_rt_sigpending(compat_sigset_t __user *set, size_t sigsetsize); |
| 127 | long sys32_rt_sigqueueinfo(int pid, int sig, compat_siginfo_t __user *uinfo); | 127 | long sys32_rt_sigqueueinfo(int pid, int sig, compat_siginfo_t __user *uinfo); |
| 128 | long sys32_execve(const char __user *name, compat_uptr_t __user *argv, | ||
| 129 | compat_uptr_t __user *envp); | ||
| 130 | long sys32_init_module(void __user *umod, unsigned long len, | 128 | long sys32_init_module(void __user *umod, unsigned long len, |
| 131 | const char __user *uargs); | 129 | const char __user *uargs); |
| 132 | long sys32_delete_module(const char __user *name_user, unsigned int flags); | 130 | long sys32_delete_module(const char __user *name_user, unsigned int flags); |
diff --git a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S index 3afba804fe97..ad79b846535c 100644 --- a/arch/s390/kernel/compat_wrapper.S +++ b/arch/s390/kernel/compat_wrapper.S | |||
| @@ -1576,7 +1576,7 @@ ENTRY(sys32_execve_wrapper) | |||
| 1576 | llgtr %r2,%r2 # char * | 1576 | llgtr %r2,%r2 # char * |
| 1577 | llgtr %r3,%r3 # compat_uptr_t * | 1577 | llgtr %r3,%r3 # compat_uptr_t * |
| 1578 | llgtr %r4,%r4 # compat_uptr_t * | 1578 | llgtr %r4,%r4 # compat_uptr_t * |
| 1579 | jg sys32_execve # branch to system call | 1579 | jg compat_sys_execve # branch to system call |
| 1580 | 1580 | ||
| 1581 | ENTRY(sys_fanotify_init_wrapper) | 1581 | ENTRY(sys_fanotify_init_wrapper) |
| 1582 | llgfr %r2,%r2 # unsigned int | 1582 | llgfr %r2,%r2 # unsigned int |
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S index 870bad6d56fc..ef46f66bc0d6 100644 --- a/arch/s390/kernel/entry.S +++ b/arch/s390/kernel/entry.S | |||
| @@ -331,45 +331,38 @@ ENTRY(ret_from_fork) | |||
| 331 | l %r12,__LC_THREAD_INFO | 331 | l %r12,__LC_THREAD_INFO |
| 332 | l %r13,__LC_SVC_NEW_PSW+4 | 332 | l %r13,__LC_SVC_NEW_PSW+4 |
| 333 | tm __PT_PSW+1(%r11),0x01 # forking a kernel thread ? | 333 | tm __PT_PSW+1(%r11),0x01 # forking a kernel thread ? |
| 334 | jo 0f | 334 | je 1f |
| 335 | st %r15,__PT_R15(%r11) # store stack pointer for new kthread | 335 | l %r1,BASED(.Lschedule_tail) |
| 336 | 0: l %r1,BASED(.Lschedule_tail) | ||
| 337 | basr %r14,%r1 # call schedule_tail | 336 | basr %r14,%r1 # call schedule_tail |
| 338 | TRACE_IRQS_ON | 337 | TRACE_IRQS_ON |
| 339 | ssm __LC_SVC_NEW_PSW # reenable interrupts | 338 | ssm __LC_SVC_NEW_PSW # reenable interrupts |
| 340 | j sysc_tracenogo | 339 | j sysc_tracenogo |
| 341 | 340 | ||
| 341 | 1: # it's a kernel thread | ||
| 342 | st %r15,__PT_R15(%r11) # store stack pointer for new kthread | ||
| 343 | l %r1,BASED(.Lschedule_tail) | ||
| 344 | basr %r14,%r1 # call schedule_tail | ||
| 345 | TRACE_IRQS_ON | ||
| 346 | ssm __LC_SVC_NEW_PSW # reenable interrupts | ||
| 347 | lm %r9,%r11,__PT_R9(%r11) # load gprs | ||
| 348 | ENTRY(kernel_thread_starter) | ||
| 349 | la %r2,0(%r10) | ||
| 350 | basr %r14,%r9 | ||
| 351 | la %r2,0 | ||
| 352 | br %r11 # do_exit | ||
| 353 | |||
| 342 | # | 354 | # |
| 343 | # kernel_execve function needs to deal with pt_regs that is not | 355 | # kernel_execve function needs to deal with pt_regs that is not |
| 344 | # at the usual place | 356 | # at the usual place |
| 345 | # | 357 | # |
| 346 | ENTRY(kernel_execve) | 358 | ENTRY(ret_from_kernel_execve) |
| 347 | stm %r12,%r15,48(%r15) | 359 | ssm __LC_PGM_NEW_PSW # disable I/O and ext. interrupts |
| 348 | lr %r14,%r15 | 360 | lr %r15,%r2 |
| 349 | l %r13,__LC_SVC_NEW_PSW+4 | 361 | lr %r11,%r2 |
| 350 | ahi %r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE) | 362 | ahi %r15,-STACK_FRAME_OVERHEAD |
| 351 | st %r14,__SF_BACKCHAIN(%r15) | ||
| 352 | la %r12,STACK_FRAME_OVERHEAD(%r15) | ||
| 353 | xc 0(__PT_SIZE,%r12),0(%r12) | ||
| 354 | l %r1,BASED(.Ldo_execve) | ||
| 355 | lr %r5,%r12 | ||
| 356 | basr %r14,%r1 # call do_execve | ||
| 357 | ltr %r2,%r2 | ||
| 358 | je 0f | ||
| 359 | ahi %r15,(STACK_FRAME_OVERHEAD + __PT_SIZE) | ||
| 360 | lm %r12,%r15,48(%r15) | ||
| 361 | br %r14 | ||
| 362 | # execve succeeded. | ||
| 363 | 0: ssm __LC_PGM_NEW_PSW # disable I/O and ext. interrupts | ||
| 364 | l %r15,__LC_KERNEL_STACK # load ksp | ||
| 365 | ahi %r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE) | ||
| 366 | la %r11,STACK_FRAME_OVERHEAD(%r15) | ||
| 367 | mvc 0(__PT_SIZE,%r11),0(%r12) # copy pt_regs | ||
| 368 | l %r12,__LC_THREAD_INFO | ||
| 369 | xc __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) | 363 | xc __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15) |
| 364 | l %r12,__LC_THREAD_INFO | ||
| 370 | ssm __LC_SVC_NEW_PSW # reenable interrupts | 365 | ssm __LC_SVC_NEW_PSW # reenable interrupts |
| 371 | l %r1,BASED(.Lexecve_tail) | ||
| 372 | basr %r14,%r1 # call execve_tail | ||
| 373 | j sysc_return | 366 | j sysc_return |
| 374 | 367 | ||
| 375 | /* | 368 | /* |
| @@ -931,8 +924,6 @@ cleanup_idle_wait: | |||
| 931 | .Ldo_signal: .long do_signal | 924 | .Ldo_signal: .long do_signal |
| 932 | .Ldo_notify_resume: .long do_notify_resume | 925 | .Ldo_notify_resume: .long do_notify_resume |
| 933 | .Ldo_per_trap: .long do_per_trap | 926 | .Ldo_per_trap: .long do_per_trap |
| 934 | .Ldo_execve: .long do_execve | ||
| 935 | .Lexecve_tail: .long execve_tail | ||
| 936 | .Ljump_table: .long pgm_check_table | 927 | .Ljump_table: .long pgm_check_table |
| 937 | .Lschedule: .long schedule | 928 | .Lschedule: .long schedule |
| 938 | #ifdef CONFIG_PREEMPT | 929 | #ifdef CONFIG_PREEMPT |
diff --git a/arch/s390/kernel/entry.h b/arch/s390/kernel/entry.h index a5f4dc42a5db..d0d3f69a7346 100644 --- a/arch/s390/kernel/entry.h +++ b/arch/s390/kernel/entry.h | |||
| @@ -58,9 +58,6 @@ long sys_fork(void); | |||
| 58 | long sys_clone(unsigned long newsp, unsigned long clone_flags, | 58 | long sys_clone(unsigned long newsp, unsigned long clone_flags, |
| 59 | int __user *parent_tidptr, int __user *child_tidptr); | 59 | int __user *parent_tidptr, int __user *child_tidptr); |
| 60 | long sys_vfork(void); | 60 | long sys_vfork(void); |
| 61 | void execve_tail(void); | ||
| 62 | long sys_execve(const char __user *name, const char __user *const __user *argv, | ||
| 63 | const char __user *const __user *envp); | ||
| 64 | long sys_sigsuspend(int history0, int history1, old_sigset_t mask); | 61 | long sys_sigsuspend(int history0, int history1, old_sigset_t mask); |
| 65 | long sys_sigaction(int sig, const struct old_sigaction __user *act, | 62 | long sys_sigaction(int sig, const struct old_sigaction __user *act, |
| 66 | struct old_sigaction __user *oact); | 63 | struct old_sigaction __user *oact); |
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S index 7549985402f7..f9761f806c9e 100644 --- a/arch/s390/kernel/entry64.S +++ b/arch/s390/kernel/entry64.S | |||
| @@ -353,41 +353,31 @@ ENTRY(ret_from_fork) | |||
| 353 | la %r11,STACK_FRAME_OVERHEAD(%r15) | 353 | la %r11,STACK_FRAME_OVERHEAD(%r15) |
| 354 | lg %r12,__LC_THREAD_INFO | 354 | lg %r12,__LC_THREAD_INFO |
| 355 | tm __PT_PSW+1(%r11),0x01 # forking a kernel thread ? | 355 | tm __PT_PSW+1(%r11),0x01 # forking a kernel thread ? |
| 356 | jo 0f | 356 | je 1f |
| 357 | stg %r15,__PT_R15(%r11) # store stack pointer for new kthread | 357 | brasl %r14,schedule_tail |
| 358 | 0: brasl %r14,schedule_tail | ||
| 359 | TRACE_IRQS_ON | 358 | TRACE_IRQS_ON |
| 360 | ssm __LC_SVC_NEW_PSW # reenable interrupts | 359 | ssm __LC_SVC_NEW_PSW # reenable interrupts |
| 361 | j sysc_tracenogo | 360 | j sysc_tracenogo |
| 362 | 361 | 1: # it's a kernel thread | |
| 363 | # | 362 | stg %r15,__PT_R15(%r11) # store stack pointer for new kthread |
| 364 | # kernel_execve function needs to deal with pt_regs that is not | 363 | brasl %r14,schedule_tail |
| 365 | # at the usual place | 364 | TRACE_IRQS_ON |
| 366 | # | 365 | ssm __LC_SVC_NEW_PSW # reenable interrupts |
| 367 | ENTRY(kernel_execve) | 366 | lmg %r9,%r11,__PT_R9(%r11) # load gprs |
| 368 | stmg %r12,%r15,96(%r15) | 367 | ENTRY(kernel_thread_starter) |
| 369 | lgr %r14,%r15 | 368 | la %r2,0(%r10) |
| 370 | aghi %r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE) | 369 | basr %r14,%r9 |
| 371 | stg %r14,__SF_BACKCHAIN(%r15) | 370 | la %r2,0 |
| 372 | la %r12,STACK_FRAME_OVERHEAD(%r15) | 371 | br %r11 # do_exit |
| 373 | xc 0(__PT_SIZE,%r12),0(%r12) | 372 | |
| 374 | lgr %r5,%r12 | 373 | ENTRY(ret_from_kernel_execve) |
| 375 | brasl %r14,do_execve | 374 | ssm __LC_PGM_NEW_PSW # disable I/O and ext. interrupts |
| 376 | ltgfr %r2,%r2 | 375 | lgr %r15,%r2 |
| 377 | je 0f | 376 | lgr %r11,%r2 |
| 378 | aghi %r15,(STACK_FRAME_OVERHEAD + __PT_SIZE) | 377 | aghi %r15,-STACK_FRAME_OVERHEAD |
| 379 | lmg %r12,%r15,96(%r15) | ||
| 380 | br %r14 | ||
| 381 | # execve succeeded. | ||
| 382 | 0: ssm __LC_PGM_NEW_PSW # disable I/O and ext. interrupts | ||
| 383 | lg %r15,__LC_KERNEL_STACK # load ksp | ||
| 384 | aghi %r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE) | ||
| 385 | la %r11,STACK_FRAME_OVERHEAD(%r15) | ||
| 386 | mvc 0(__PT_SIZE,%r11),0(%r12) # copy pt_regs | ||
| 387 | lg %r12,__LC_THREAD_INFO | ||
| 388 | xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) | 378 | xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) |
| 379 | lg %r12,__LC_THREAD_INFO | ||
| 389 | ssm __LC_SVC_NEW_PSW # reenable interrupts | 380 | ssm __LC_SVC_NEW_PSW # reenable interrupts |
| 390 | brasl %r14,execve_tail | ||
| 391 | j sysc_return | 381 | j sysc_return |
| 392 | 382 | ||
| 393 | /* | 383 | /* |
diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c index 5024be27df44..cd31ad457a9b 100644 --- a/arch/s390/kernel/process.c +++ b/arch/s390/kernel/process.c | |||
| @@ -100,35 +100,6 @@ void cpu_idle(void) | |||
| 100 | 100 | ||
| 101 | extern void __kprobes kernel_thread_starter(void); | 101 | extern void __kprobes kernel_thread_starter(void); |
| 102 | 102 | ||
| 103 | asm( | ||
| 104 | ".section .kprobes.text, \"ax\"\n" | ||
| 105 | ".global kernel_thread_starter\n" | ||
| 106 | "kernel_thread_starter:\n" | ||
| 107 | " la 2,0(10)\n" | ||
| 108 | " basr 14,9\n" | ||
| 109 | " la 2,0\n" | ||
| 110 | " br 11\n" | ||
| 111 | ".previous\n"); | ||
| 112 | |||
| 113 | int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) | ||
| 114 | { | ||
| 115 | struct pt_regs regs; | ||
| 116 | |||
| 117 | memset(®s, 0, sizeof(regs)); | ||
| 118 | regs.psw.mask = psw_kernel_bits | | ||
| 119 | PSW_MASK_DAT | PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK; | ||
| 120 | regs.psw.addr = (unsigned long) kernel_thread_starter | PSW_ADDR_AMODE; | ||
| 121 | regs.gprs[9] = (unsigned long) fn; | ||
| 122 | regs.gprs[10] = (unsigned long) arg; | ||
| 123 | regs.gprs[11] = (unsigned long) do_exit; | ||
| 124 | regs.orig_gpr2 = -1; | ||
| 125 | |||
| 126 | /* Ok, create the new process.. */ | ||
| 127 | return do_fork(flags | CLONE_VM | CLONE_UNTRACED, | ||
| 128 | 0, ®s, 0, NULL, NULL); | ||
| 129 | } | ||
| 130 | EXPORT_SYMBOL(kernel_thread); | ||
| 131 | |||
| 132 | /* | 103 | /* |
| 133 | * Free current thread data structures etc.. | 104 | * Free current thread data structures etc.. |
| 134 | */ | 105 | */ |
| @@ -146,7 +117,7 @@ void release_thread(struct task_struct *dead_task) | |||
| 146 | } | 117 | } |
| 147 | 118 | ||
| 148 | int copy_thread(unsigned long clone_flags, unsigned long new_stackp, | 119 | int copy_thread(unsigned long clone_flags, unsigned long new_stackp, |
| 149 | unsigned long unused, | 120 | unsigned long arg, |
| 150 | struct task_struct *p, struct pt_regs *regs) | 121 | struct task_struct *p, struct pt_regs *regs) |
| 151 | { | 122 | { |
| 152 | struct thread_info *ti; | 123 | struct thread_info *ti; |
| @@ -158,20 +129,44 @@ int copy_thread(unsigned long clone_flags, unsigned long new_stackp, | |||
| 158 | 129 | ||
| 159 | frame = container_of(task_pt_regs(p), struct fake_frame, childregs); | 130 | frame = container_of(task_pt_regs(p), struct fake_frame, childregs); |
| 160 | p->thread.ksp = (unsigned long) frame; | 131 | p->thread.ksp = (unsigned long) frame; |
| 161 | /* Store access registers to kernel stack of new process. */ | 132 | /* Save access registers to new thread structure. */ |
| 162 | frame->childregs = *regs; | 133 | save_access_regs(&p->thread.acrs[0]); |
| 163 | frame->childregs.gprs[2] = 0; /* child returns 0 on fork. */ | 134 | /* start new process with ar4 pointing to the correct address space */ |
| 164 | frame->childregs.gprs[15] = new_stackp; | 135 | p->thread.mm_segment = get_fs(); |
| 165 | frame->sf.back_chain = 0; | 136 | /* Don't copy debug registers */ |
| 137 | memset(&p->thread.per_user, 0, sizeof(p->thread.per_user)); | ||
| 138 | memset(&p->thread.per_event, 0, sizeof(p->thread.per_event)); | ||
| 139 | clear_tsk_thread_flag(p, TIF_SINGLE_STEP); | ||
| 140 | clear_tsk_thread_flag(p, TIF_PER_TRAP); | ||
| 141 | /* Initialize per thread user and system timer values */ | ||
| 142 | ti = task_thread_info(p); | ||
| 143 | ti->user_timer = 0; | ||
| 144 | ti->system_timer = 0; | ||
| 166 | 145 | ||
| 146 | frame->sf.back_chain = 0; | ||
| 167 | /* new return point is ret_from_fork */ | 147 | /* new return point is ret_from_fork */ |
| 168 | frame->sf.gprs[8] = (unsigned long) ret_from_fork; | 148 | frame->sf.gprs[8] = (unsigned long) ret_from_fork; |
| 169 | |||
| 170 | /* fake return stack for resume(), don't go back to schedule */ | 149 | /* fake return stack for resume(), don't go back to schedule */ |
| 171 | frame->sf.gprs[9] = (unsigned long) frame; | 150 | frame->sf.gprs[9] = (unsigned long) frame; |
| 172 | 151 | ||
| 173 | /* Save access registers to new thread structure. */ | 152 | /* Store access registers to kernel stack of new process. */ |
| 174 | save_access_regs(&p->thread.acrs[0]); | 153 | if (unlikely(!regs)) { |
| 154 | /* kernel thread */ | ||
| 155 | memset(&frame->childregs, 0, sizeof(struct pt_regs)); | ||
| 156 | frame->childregs.psw.mask = psw_kernel_bits | PSW_MASK_DAT | | ||
| 157 | PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK; | ||
| 158 | frame->childregs.psw.addr = PSW_ADDR_AMODE | | ||
| 159 | (unsigned long) kernel_thread_starter; | ||
| 160 | frame->childregs.gprs[9] = new_stackp; /* function */ | ||
| 161 | frame->childregs.gprs[10] = arg; | ||
| 162 | frame->childregs.gprs[11] = (unsigned long) do_exit; | ||
| 163 | frame->childregs.orig_gpr2 = -1; | ||
| 164 | |||
| 165 | return 0; | ||
| 166 | } | ||
| 167 | frame->childregs = *regs; | ||
| 168 | frame->childregs.gprs[2] = 0; /* child returns 0 on fork. */ | ||
| 169 | frame->childregs.gprs[15] = new_stackp; | ||
| 175 | 170 | ||
| 176 | /* Don't copy runtime instrumentation info */ | 171 | /* Don't copy runtime instrumentation info */ |
| 177 | p->thread.ri_cb = NULL; | 172 | p->thread.ri_cb = NULL; |
| @@ -202,17 +197,6 @@ int copy_thread(unsigned long clone_flags, unsigned long new_stackp, | |||
| 202 | } | 197 | } |
| 203 | } | 198 | } |
| 204 | #endif /* CONFIG_64BIT */ | 199 | #endif /* CONFIG_64BIT */ |
| 205 | /* start new process with ar4 pointing to the correct address space */ | ||
| 206 | p->thread.mm_segment = get_fs(); | ||
| 207 | /* Don't copy debug registers */ | ||
| 208 | memset(&p->thread.per_user, 0, sizeof(p->thread.per_user)); | ||
| 209 | memset(&p->thread.per_event, 0, sizeof(p->thread.per_event)); | ||
| 210 | clear_tsk_thread_flag(p, TIF_SINGLE_STEP); | ||
| 211 | clear_tsk_thread_flag(p, TIF_PER_TRAP); | ||
| 212 | /* Initialize per thread user and system timer values */ | ||
| 213 | ti = task_thread_info(p); | ||
| 214 | ti->user_timer = 0; | ||
| 215 | ti->system_timer = 0; | ||
| 216 | return 0; | 200 | return 0; |
| 217 | } | 201 | } |
| 218 | 202 | ||
| @@ -258,31 +242,6 @@ asmlinkage void execve_tail(void) | |||
| 258 | } | 242 | } |
| 259 | 243 | ||
| 260 | /* | 244 | /* |
| 261 | * sys_execve() executes a new program. | ||
| 262 | */ | ||
| 263 | SYSCALL_DEFINE3(execve, const char __user *, name, | ||
| 264 | const char __user *const __user *, argv, | ||
| 265 | const char __user *const __user *, envp) | ||
| 266 | { | ||
| 267 | struct pt_regs *regs = task_pt_regs(current); | ||
| 268 | char *filename; | ||
| 269 | long rc; | ||
| 270 | |||
| 271 | filename = getname(name); | ||
| 272 | rc = PTR_ERR(filename); | ||
| 273 | if (IS_ERR(filename)) | ||
| 274 | return rc; | ||
| 275 | rc = do_execve(filename, argv, envp, regs); | ||
| 276 | if (rc) | ||
| 277 | goto out; | ||
| 278 | execve_tail(); | ||
| 279 | rc = regs->gprs[2]; | ||
| 280 | out: | ||
| 281 | putname(filename); | ||
| 282 | return rc; | ||
| 283 | } | ||
| 284 | |||
| 285 | /* | ||
| 286 | * fill in the FPU structure for a core dump. | 245 | * fill in the FPU structure for a core dump. |
| 287 | */ | 246 | */ |
| 288 | int dump_fpu (struct pt_regs * regs, s390_fp_regs *fpregs) | 247 | int dump_fpu (struct pt_regs * regs, s390_fp_regs *fpregs) |
diff --git a/arch/sh/include/asm/Kbuild b/arch/sh/include/asm/Kbuild index 7b673ddcd555..86eadceff097 100644 --- a/arch/sh/include/asm/Kbuild +++ b/arch/sh/include/asm/Kbuild | |||
| @@ -7,6 +7,7 @@ generic-y += delay.h | |||
| 7 | generic-y += div64.h | 7 | generic-y += div64.h |
| 8 | generic-y += emergency-restart.h | 8 | generic-y += emergency-restart.h |
| 9 | generic-y += errno.h | 9 | generic-y += errno.h |
| 10 | generic-y += exec.h | ||
| 10 | generic-y += fcntl.h | 11 | generic-y += fcntl.h |
| 11 | generic-y += ioctl.h | 12 | generic-y += ioctl.h |
| 12 | generic-y += ipcbuf.h | 13 | generic-y += ipcbuf.h |
diff --git a/arch/sh/include/asm/exec.h b/arch/sh/include/asm/exec.h deleted file mode 100644 index 69486a9497f7..000000000000 --- a/arch/sh/include/asm/exec.h +++ /dev/null | |||
| @@ -1,10 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 1999, 2000 Niibe Yutaka & Kaz Kojima | ||
| 3 | * Copyright (C) 2002 Paul Mundt | ||
| 4 | */ | ||
| 5 | #ifndef __ASM_SH_EXEC_H | ||
| 6 | #define __ASM_SH_EXEC_H | ||
| 7 | |||
| 8 | #define arch_align_stack(x) (x) | ||
| 9 | |||
| 10 | #endif /* __ASM_SH_EXEC_H */ | ||
diff --git a/arch/sparc/include/asm/Kbuild b/arch/sparc/include/asm/Kbuild index 61d41c11ee0a..10d54e5e37f5 100644 --- a/arch/sparc/include/asm/Kbuild +++ b/arch/sparc/include/asm/Kbuild | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | 3 | ||
| 4 | generic-y += clkdev.h | 4 | generic-y += clkdev.h |
| 5 | generic-y += div64.h | 5 | generic-y += div64.h |
| 6 | generic-y += exec.h | ||
| 6 | generic-y += local64.h | 7 | generic-y += local64.h |
| 7 | generic-y += irq_regs.h | 8 | generic-y += irq_regs.h |
| 8 | generic-y += local.h | 9 | generic-y += local.h |
diff --git a/arch/sparc/include/asm/exec.h b/arch/sparc/include/asm/exec.h deleted file mode 100644 index 2e085881e0d1..000000000000 --- a/arch/sparc/include/asm/exec.h +++ /dev/null | |||
| @@ -1,6 +0,0 @@ | |||
| 1 | #ifndef __SPARC_EXEC_H | ||
| 2 | #define __SPARC_EXEC_H | ||
| 3 | |||
| 4 | #define arch_align_stack(x) (x) | ||
| 5 | |||
| 6 | #endif /* __SPARC_EXEC_H */ | ||
diff --git a/arch/tile/include/asm/Kbuild b/arch/tile/include/asm/Kbuild index ea2e8ea3eb61..5cd98fac9899 100644 --- a/arch/tile/include/asm/Kbuild +++ b/arch/tile/include/asm/Kbuild | |||
| @@ -13,6 +13,7 @@ generic-y += cputime.h | |||
| 13 | generic-y += div64.h | 13 | generic-y += div64.h |
| 14 | generic-y += emergency-restart.h | 14 | generic-y += emergency-restart.h |
| 15 | generic-y += errno.h | 15 | generic-y += errno.h |
| 16 | generic-y += exec.h | ||
| 16 | generic-y += fb.h | 17 | generic-y += fb.h |
| 17 | generic-y += fcntl.h | 18 | generic-y += fcntl.h |
| 18 | generic-y += ioctl.h | 19 | generic-y += ioctl.h |
diff --git a/arch/tile/include/asm/exec.h b/arch/tile/include/asm/exec.h deleted file mode 100644 index a714e1950867..000000000000 --- a/arch/tile/include/asm/exec.h +++ /dev/null | |||
| @@ -1,20 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2010 Tilera Corporation. All Rights Reserved. | ||
| 3 | * | ||
| 4 | * This program is free software; you can redistribute it and/or | ||
| 5 | * modify it under the terms of the GNU General Public License | ||
| 6 | * as published by the Free Software Foundation, version 2. | ||
| 7 | * | ||
| 8 | * This program is distributed in the hope that it will be useful, but | ||
| 9 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 10 | * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or | ||
| 11 | * NON INFRINGEMENT. See the GNU General Public License for | ||
| 12 | * more details. | ||
| 13 | */ | ||
| 14 | |||
| 15 | #ifndef _ASM_TILE_EXEC_H | ||
| 16 | #define _ASM_TILE_EXEC_H | ||
| 17 | |||
| 18 | #define arch_align_stack(x) (x) | ||
| 19 | |||
| 20 | #endif /* _ASM_TILE_EXEC_H */ | ||
diff --git a/arch/um/include/asm/processor-generic.h b/arch/um/include/asm/processor-generic.h index 24e97be814bc..1e82e954e978 100644 --- a/arch/um/include/asm/processor-generic.h +++ b/arch/um/include/asm/processor-generic.h | |||
| @@ -63,8 +63,6 @@ static inline void release_thread(struct task_struct *task) | |||
| 63 | { | 63 | { |
| 64 | } | 64 | } |
| 65 | 65 | ||
| 66 | extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); | ||
| 67 | |||
| 68 | extern unsigned long thread_saved_pc(struct task_struct *t); | 66 | extern unsigned long thread_saved_pc(struct task_struct *t); |
| 69 | 67 | ||
| 70 | static inline void mm_copy_segments(struct mm_struct *from_mm, | 68 | static inline void mm_copy_segments(struct mm_struct *from_mm, |
diff --git a/arch/um/kernel/exec.c b/arch/um/kernel/exec.c index de66c421ae9d..ab019c7f0b57 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 | ||
| 21 | void flush_thread(void) | 20 | void flush_thread(void) |
| 22 | { | 21 | { |
| @@ -49,27 +48,7 @@ void start_thread(struct pt_regs *regs, unsigned long eip, unsigned long esp) | |||
| 49 | } | 48 | } |
| 50 | EXPORT_SYMBOL(start_thread); | 49 | EXPORT_SYMBOL(start_thread); |
| 51 | 50 | ||
| 52 | long um_execve(const char *file, const char __user *const __user *argv, const char __user *const __user *env) | 51 | void __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, ¤t->thread.regs); | ||
| 57 | if (!err) | ||
| 58 | UML_LONGJMP(current->thread.exec_buf, 1); | ||
| 59 | return err; | ||
| 60 | } | ||
| 61 | |||
| 62 | long 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, ¤t->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 @@ | |||
| 1 | extern long um_execve(const char *file, const char __user *const __user *argv, const char __user *const __user *env); | ||
diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c index 41f53240e794..30629783b3e0 100644 --- a/arch/um/kernel/process.c +++ b/arch/um/kernel/process.c | |||
| @@ -69,18 +69,6 @@ unsigned long alloc_stack(int order, int atomic) | |||
| 69 | return page; | 69 | return page; |
| 70 | } | 70 | } |
| 71 | 71 | ||
| 72 | int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) | ||
| 73 | { | ||
| 74 | int pid; | ||
| 75 | |||
| 76 | current->thread.request.u.thread.proc = fn; | ||
| 77 | current->thread.request.u.thread.arg = arg; | ||
| 78 | pid = do_fork(CLONE_VM | CLONE_UNTRACED | flags, 0, | ||
| 79 | ¤t->thread.regs, 0, NULL, NULL); | ||
| 80 | return pid; | ||
| 81 | } | ||
| 82 | EXPORT_SYMBOL(kernel_thread); | ||
| 83 | |||
| 84 | static inline void set_current(struct task_struct *task) | 72 | static inline void set_current(struct task_struct *task) |
| 85 | { | 73 | { |
| 86 | cpu_tasks[task_thread_info(task)->cpu] = ((struct cpu_task) | 74 | cpu_tasks[task_thread_info(task)->cpu] = ((struct cpu_task) |
| @@ -177,7 +165,7 @@ void fork_handler(void) | |||
| 177 | } | 165 | } |
| 178 | 166 | ||
| 179 | int copy_thread(unsigned long clone_flags, unsigned long sp, | 167 | int copy_thread(unsigned long clone_flags, unsigned long sp, |
| 180 | unsigned long stack_top, struct task_struct * p, | 168 | unsigned long arg, struct task_struct * p, |
| 181 | struct pt_regs *regs) | 169 | struct pt_regs *regs) |
| 182 | { | 170 | { |
| 183 | void (*handler)(void); | 171 | void (*handler)(void); |
| @@ -198,7 +186,8 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, | |||
| 198 | arch_copy_thread(¤t->thread.arch, &p->thread.arch); | 186 | arch_copy_thread(¤t->thread.arch, &p->thread.arch); |
| 199 | } else { | 187 | } else { |
| 200 | get_safe_registers(p->thread.regs.regs.gp, p->thread.regs.regs.fp); | 188 | get_safe_registers(p->thread.regs.regs.gp, p->thread.regs.regs.fp); |
| 201 | p->thread.request.u.thread = current->thread.request.u.thread; | 189 | p->thread.request.u.thread.proc = (int (*)(void *))sp; |
| 190 | p->thread.request.u.thread.arg = (void *)arg; | ||
| 202 | handler = new_thread_handler; | 191 | handler = new_thread_handler; |
| 203 | } | 192 | } |
| 204 | 193 | ||
diff --git a/arch/um/kernel/syscall.c b/arch/um/kernel/syscall.c index 10808bda3671..a81f3705e90f 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 | ||
| 18 | long sys_fork(void) | 17 | long 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 | |||
| 54 | int 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/unicore32/include/asm/Kbuild b/arch/unicore32/include/asm/Kbuild index 123c59a06c14..c910c9857e11 100644 --- a/arch/unicore32/include/asm/Kbuild +++ b/arch/unicore32/include/asm/Kbuild | |||
| @@ -11,6 +11,7 @@ generic-y += device.h | |||
| 11 | generic-y += div64.h | 11 | generic-y += div64.h |
| 12 | generic-y += emergency-restart.h | 12 | generic-y += emergency-restart.h |
| 13 | generic-y += errno.h | 13 | generic-y += errno.h |
| 14 | generic-y += exec.h | ||
| 14 | generic-y += fb.h | 15 | generic-y += fb.h |
| 15 | generic-y += fcntl.h | 16 | generic-y += fcntl.h |
| 16 | generic-y += ftrace.h | 17 | generic-y += ftrace.h |
diff --git a/arch/unicore32/include/asm/exec.h b/arch/unicore32/include/asm/exec.h deleted file mode 100644 index 06d1f0f57888..000000000000 --- a/arch/unicore32/include/asm/exec.h +++ /dev/null | |||
| @@ -1,15 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Process execution bits for PKUnity SoC and UniCore ISA | ||
| 3 | * | ||
| 4 | * Copyright (C) 2001-2012 GUAN Xue-tao | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License version 2 as | ||
| 8 | * published by the Free Software Foundation. | ||
| 9 | */ | ||
| 10 | #ifndef __UNICORE_EXEC_H__ | ||
| 11 | #define __UNICORE_EXEC_H__ | ||
| 12 | |||
| 13 | #define arch_align_stack(x) (x) | ||
| 14 | |||
| 15 | #endif /* __UNICORE_EXEC_H__ */ | ||
diff --git a/arch/unicore32/kernel/sys.c b/arch/unicore32/kernel/sys.c index 3afe60a39ac9..5fd9af773e15 100644 --- a/arch/unicore32/kernel/sys.c +++ b/arch/unicore32/kernel/sys.c | |||
| @@ -104,7 +104,6 @@ int kernel_execve(const char *filename, | |||
| 104 | out: | 104 | out: |
| 105 | return ret; | 105 | return ret; |
| 106 | } | 106 | } |
| 107 | EXPORT_SYMBOL(kernel_execve); | ||
| 108 | 107 | ||
| 109 | /* Note: used by the compat code even in 64-bit Linux. */ | 108 | /* Note: used by the compat code even in 64-bit Linux. */ |
| 110 | SYSCALL_DEFINE6(mmap2, unsigned long, addr, unsigned long, len, | 109 | SYSCALL_DEFINE6(mmap2, unsigned long, addr, unsigned long, len, |
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 1ae94bcae5d9..42d2c35a5bbd 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig | |||
| @@ -108,6 +108,7 @@ config X86 | |||
| 108 | select GENERIC_STRNLEN_USER | 108 | select GENERIC_STRNLEN_USER |
| 109 | select HAVE_RCU_USER_QS if X86_64 | 109 | select HAVE_RCU_USER_QS if X86_64 |
| 110 | select HAVE_IRQ_TIME_ACCOUNTING | 110 | select HAVE_IRQ_TIME_ACCOUNTING |
| 111 | select GENERIC_KERNEL_THREAD | ||
| 111 | 112 | ||
| 112 | config INSTRUCTION_DECODER | 113 | config INSTRUCTION_DECODER |
| 113 | def_bool y | 114 | def_bool y |
diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S index 9c289504e680..076745fc8045 100644 --- a/arch/x86/ia32/ia32entry.S +++ b/arch/x86/ia32/ia32entry.S | |||
| @@ -465,7 +465,7 @@ GLOBAL(\label) | |||
| 465 | PTREGSCALL stub32_rt_sigreturn, sys32_rt_sigreturn, %rdi | 465 | PTREGSCALL stub32_rt_sigreturn, sys32_rt_sigreturn, %rdi |
| 466 | PTREGSCALL stub32_sigreturn, sys32_sigreturn, %rdi | 466 | PTREGSCALL stub32_sigreturn, sys32_sigreturn, %rdi |
| 467 | PTREGSCALL stub32_sigaltstack, sys32_sigaltstack, %rdx | 467 | PTREGSCALL stub32_sigaltstack, sys32_sigaltstack, %rdx |
| 468 | PTREGSCALL stub32_execve, sys32_execve, %rcx | 468 | PTREGSCALL stub32_execve, compat_sys_execve, %rcx |
| 469 | PTREGSCALL stub32_fork, sys_fork, %rdi | 469 | PTREGSCALL stub32_fork, sys_fork, %rdi |
| 470 | PTREGSCALL stub32_clone, sys32_clone, %rdx | 470 | PTREGSCALL stub32_clone, sys32_clone, %rdx |
| 471 | PTREGSCALL stub32_vfork, sys_vfork, %rdi | 471 | PTREGSCALL stub32_vfork, sys_vfork, %rdi |
diff --git a/arch/x86/ia32/sys_ia32.c b/arch/x86/ia32/sys_ia32.c index c5b938d92eab..86d68d1c8806 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/processor.h b/arch/x86/include/asm/processor.h index b98c0d958ebb..ad1fc8511674 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h | |||
| @@ -588,11 +588,6 @@ typedef struct { | |||
| 588 | } mm_segment_t; | 588 | } mm_segment_t; |
| 589 | 589 | ||
| 590 | 590 | ||
| 591 | /* | ||
| 592 | * create a kernel thread without removing it from tasklists | ||
| 593 | */ | ||
| 594 | extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); | ||
| 595 | |||
| 596 | /* Free all resources held by a thread. */ | 591 | /* Free all resources held by a thread. */ |
| 597 | extern void release_thread(struct task_struct *); | 592 | extern void release_thread(struct task_struct *); |
| 598 | 593 | ||
diff --git a/arch/x86/include/asm/sys_ia32.h b/arch/x86/include/asm/sys_ia32.h index 4ca1c611b552..a9a8cf3da49d 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/thread_info.h b/arch/x86/include/asm/thread_info.h index c535d847e3b5..2d946e63ee82 100644 --- a/arch/x86/include/asm/thread_info.h +++ b/arch/x86/include/asm/thread_info.h | |||
| @@ -79,7 +79,6 @@ struct thread_info { | |||
| 79 | #define TIF_SIGPENDING 2 /* signal pending */ | 79 | #define TIF_SIGPENDING 2 /* signal pending */ |
| 80 | #define TIF_NEED_RESCHED 3 /* rescheduling necessary */ | 80 | #define TIF_NEED_RESCHED 3 /* rescheduling necessary */ |
| 81 | #define TIF_SINGLESTEP 4 /* reenable singlestep on user return*/ | 81 | #define TIF_SINGLESTEP 4 /* reenable singlestep on user return*/ |
| 82 | #define TIF_IRET 5 /* force IRET */ | ||
| 83 | #define TIF_SYSCALL_EMU 6 /* syscall emulation active */ | 82 | #define TIF_SYSCALL_EMU 6 /* syscall emulation active */ |
| 84 | #define TIF_SYSCALL_AUDIT 7 /* syscall auditing active */ | 83 | #define TIF_SYSCALL_AUDIT 7 /* syscall auditing active */ |
| 85 | #define TIF_SECCOMP 8 /* secure computing */ | 84 | #define TIF_SECCOMP 8 /* secure computing */ |
| @@ -105,7 +104,6 @@ struct thread_info { | |||
| 105 | #define _TIF_SIGPENDING (1 << TIF_SIGPENDING) | 104 | #define _TIF_SIGPENDING (1 << TIF_SIGPENDING) |
| 106 | #define _TIF_SINGLESTEP (1 << TIF_SINGLESTEP) | 105 | #define _TIF_SINGLESTEP (1 << TIF_SINGLESTEP) |
| 107 | #define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED) | 106 | #define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED) |
| 108 | #define _TIF_IRET (1 << TIF_IRET) | ||
| 109 | #define _TIF_SYSCALL_EMU (1 << TIF_SYSCALL_EMU) | 107 | #define _TIF_SYSCALL_EMU (1 << TIF_SYSCALL_EMU) |
| 110 | #define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT) | 108 | #define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT) |
| 111 | #define _TIF_SECCOMP (1 << TIF_SECCOMP) | 109 | #define _TIF_SECCOMP (1 << TIF_SECCOMP) |
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 a48ea05157d3..91ce48f05f9f 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 0750e3ba87c0..8f9ed1afde8f 100644 --- a/arch/x86/kernel/entry_32.S +++ b/arch/x86/kernel/entry_32.S | |||
| @@ -299,6 +299,13 @@ ENTRY(ret_from_fork) | |||
| 299 | CFI_ENDPROC | 299 | CFI_ENDPROC |
| 300 | END(ret_from_fork) | 300 | END(ret_from_fork) |
| 301 | 301 | ||
| 302 | ENTRY(ret_from_kernel_execve) | ||
| 303 | movl %eax, %esp | ||
| 304 | movl $0,PT_EAX(%esp) | ||
| 305 | GET_THREAD_INFO(%ebp) | ||
| 306 | jmp syscall_exit | ||
| 307 | END(ret_from_kernel_execve) | ||
| 308 | |||
| 302 | /* | 309 | /* |
| 303 | * Interrupt exit functions should be protected against kprobes | 310 | * Interrupt exit functions should be protected against kprobes |
| 304 | */ | 311 | */ |
| @@ -323,8 +330,7 @@ ret_from_intr: | |||
| 323 | andl $(X86_EFLAGS_VM | SEGMENT_RPL_MASK), %eax | 330 | andl $(X86_EFLAGS_VM | SEGMENT_RPL_MASK), %eax |
| 324 | #else | 331 | #else |
| 325 | /* | 332 | /* |
| 326 | * We can be coming here from a syscall done in the kernel space, | 333 | * We can be coming here from child spawned by kernel_thread(). |
| 327 | * e.g. a failed kernel_execve(). | ||
| 328 | */ | 334 | */ |
| 329 | movl PT_CS(%esp), %eax | 335 | movl PT_CS(%esp), %eax |
| 330 | andl $SEGMENT_RPL_MASK, %eax | 336 | andl $SEGMENT_RPL_MASK, %eax |
| @@ -732,7 +738,6 @@ ENDPROC(ptregs_##name) | |||
| 732 | PTREGSCALL1(iopl) | 738 | PTREGSCALL1(iopl) |
| 733 | PTREGSCALL0(fork) | 739 | PTREGSCALL0(fork) |
| 734 | PTREGSCALL0(vfork) | 740 | PTREGSCALL0(vfork) |
| 735 | PTREGSCALL3(execve) | ||
| 736 | PTREGSCALL2(sigaltstack) | 741 | PTREGSCALL2(sigaltstack) |
| 737 | PTREGSCALL0(sigreturn) | 742 | PTREGSCALL0(sigreturn) |
| 738 | PTREGSCALL0(rt_sigreturn) | 743 | PTREGSCALL0(rt_sigreturn) |
| @@ -1015,15 +1020,20 @@ END(spurious_interrupt_bug) | |||
| 1015 | */ | 1020 | */ |
| 1016 | .popsection | 1021 | .popsection |
| 1017 | 1022 | ||
| 1018 | ENTRY(kernel_thread_helper) | 1023 | ENTRY(ret_from_kernel_thread) |
| 1019 | pushl $0 # fake return address for unwinder | ||
| 1020 | CFI_STARTPROC | 1024 | CFI_STARTPROC |
| 1021 | movl %edi,%eax | 1025 | pushl_cfi %eax |
| 1022 | call *%esi | 1026 | call schedule_tail |
| 1027 | GET_THREAD_INFO(%ebp) | ||
| 1028 | popl_cfi %eax | ||
| 1029 | pushl_cfi $0x0202 # Reset kernel eflags | ||
| 1030 | popfl_cfi | ||
| 1031 | movl PT_EBP(%esp),%eax | ||
| 1032 | call *PT_EBX(%esp) | ||
| 1023 | call do_exit | 1033 | call do_exit |
| 1024 | ud2 # padding for call trace | 1034 | ud2 # padding for call trace |
| 1025 | CFI_ENDPROC | 1035 | CFI_ENDPROC |
| 1026 | ENDPROC(kernel_thread_helper) | 1036 | ENDPROC(ret_from_kernel_thread) |
| 1027 | 1037 | ||
| 1028 | #ifdef CONFIG_XEN | 1038 | #ifdef CONFIG_XEN |
| 1029 | /* Xen doesn't set %esp to be precisely what the normal sysenter | 1039 | /* Xen doesn't set %esp to be precisely what the normal sysenter |
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S index 44531acd9a81..cdc790c78f32 100644 --- a/arch/x86/kernel/entry_64.S +++ b/arch/x86/kernel/entry_64.S | |||
| @@ -554,7 +554,7 @@ ENTRY(ret_from_fork) | |||
| 554 | RESTORE_REST | 554 | RESTORE_REST |
| 555 | 555 | ||
| 556 | testl $3, CS-ARGOFFSET(%rsp) # from kernel_thread? | 556 | testl $3, CS-ARGOFFSET(%rsp) # from kernel_thread? |
| 557 | jz retint_restore_args | 557 | jz 1f |
| 558 | 558 | ||
| 559 | testl $_TIF_IA32, TI_flags(%rcx) # 32-bit compat task needs IRET | 559 | testl $_TIF_IA32, TI_flags(%rcx) # 32-bit compat task needs IRET |
| 560 | jnz int_ret_from_sys_call | 560 | jnz int_ret_from_sys_call |
| @@ -562,6 +562,16 @@ ENTRY(ret_from_fork) | |||
| 562 | RESTORE_TOP_OF_STACK %rdi, -ARGOFFSET | 562 | RESTORE_TOP_OF_STACK %rdi, -ARGOFFSET |
| 563 | jmp ret_from_sys_call # go to the SYSRET fastpath | 563 | jmp ret_from_sys_call # go to the SYSRET fastpath |
| 564 | 564 | ||
| 565 | 1: | ||
| 566 | subq $REST_SKIP, %rsp # move the stack pointer back | ||
| 567 | CFI_ADJUST_CFA_OFFSET REST_SKIP | ||
| 568 | movq %rbp, %rdi | ||
| 569 | call *%rbx | ||
| 570 | # exit | ||
| 571 | mov %eax, %edi | ||
| 572 | call do_exit | ||
| 573 | ud2 # padding for call trace | ||
| 574 | |||
| 565 | CFI_ENDPROC | 575 | CFI_ENDPROC |
| 566 | END(ret_from_fork) | 576 | END(ret_from_fork) |
| 567 | 577 | ||
| @@ -862,7 +872,6 @@ ENTRY(stub_execve) | |||
| 862 | PARTIAL_FRAME 0 | 872 | PARTIAL_FRAME 0 |
| 863 | SAVE_REST | 873 | SAVE_REST |
| 864 | FIXUP_TOP_OF_STACK %r11 | 874 | FIXUP_TOP_OF_STACK %r11 |
| 865 | movq %rsp, %rcx | ||
| 866 | call sys_execve | 875 | call sys_execve |
| 867 | RESTORE_TOP_OF_STACK %r11 | 876 | RESTORE_TOP_OF_STACK %r11 |
| 868 | movq %rax,RAX(%rsp) | 877 | movq %rax,RAX(%rsp) |
| @@ -912,8 +921,7 @@ ENTRY(stub_x32_execve) | |||
| 912 | PARTIAL_FRAME 0 | 921 | PARTIAL_FRAME 0 |
| 913 | SAVE_REST | 922 | SAVE_REST |
| 914 | FIXUP_TOP_OF_STACK %r11 | 923 | FIXUP_TOP_OF_STACK %r11 |
| 915 | movq %rsp, %rcx | 924 | call compat_sys_execve |
| 916 | call sys32_execve | ||
| 917 | RESTORE_TOP_OF_STACK %r11 | 925 | RESTORE_TOP_OF_STACK %r11 |
| 918 | movq %rax,RAX(%rsp) | 926 | movq %rax,RAX(%rsp) |
| 919 | RESTORE_REST | 927 | RESTORE_REST |
| @@ -1318,51 +1326,19 @@ bad_gs: | |||
| 1318 | jmp 2b | 1326 | jmp 2b |
| 1319 | .previous | 1327 | .previous |
| 1320 | 1328 | ||
| 1321 | ENTRY(kernel_thread_helper) | 1329 | ENTRY(ret_from_kernel_execve) |
| 1322 | pushq $0 # fake return address | 1330 | movq %rdi, %rsp |
| 1323 | CFI_STARTPROC | 1331 | movl $0, RAX(%rsp) |
| 1324 | /* | 1332 | // RESTORE_REST |
| 1325 | * Here we are in the child and the registers are set as they were | 1333 | movq 0*8(%rsp), %r15 |
| 1326 | * at kernel_thread() invocation in the parent. | 1334 | movq 1*8(%rsp), %r14 |
| 1327 | */ | 1335 | movq 2*8(%rsp), %r13 |
| 1328 | call *%rsi | 1336 | movq 3*8(%rsp), %r12 |
| 1329 | # exit | 1337 | movq 4*8(%rsp), %rbp |
| 1330 | mov %eax, %edi | 1338 | movq 5*8(%rsp), %rbx |
| 1331 | call do_exit | 1339 | addq $(6*8), %rsp |
| 1332 | ud2 # padding for call trace | 1340 | jmp int_ret_from_sys_call |
| 1333 | CFI_ENDPROC | 1341 | END(ret_from_kernel_execve) |
| 1334 | END(kernel_thread_helper) | ||
| 1335 | |||
| 1336 | /* | ||
| 1337 | * execve(). This function needs to use IRET, not SYSRET, to set up all state properly. | ||
| 1338 | * | ||
| 1339 | * C extern interface: | ||
| 1340 | * extern long execve(const char *name, char **argv, char **envp) | ||
| 1341 | * | ||
| 1342 | * asm input arguments: | ||
| 1343 | * rdi: name, rsi: argv, rdx: envp | ||
| 1344 | * | ||
| 1345 | * We want to fallback into: | ||
| 1346 | * extern long sys_execve(const char *name, char **argv,char **envp, struct pt_regs *regs) | ||
| 1347 | * | ||
| 1348 | * do_sys_execve asm fallback arguments: | ||
| 1349 | * rdi: name, rsi: argv, rdx: envp, rcx: fake frame on the stack | ||
| 1350 | */ | ||
| 1351 | ENTRY(kernel_execve) | ||
| 1352 | CFI_STARTPROC | ||
| 1353 | FAKE_STACK_FRAME $0 | ||
| 1354 | SAVE_ALL | ||
| 1355 | movq %rsp,%rcx | ||
| 1356 | call sys_execve | ||
| 1357 | movq %rax, RAX(%rsp) | ||
| 1358 | RESTORE_REST | ||
| 1359 | testq %rax,%rax | ||
| 1360 | je int_ret_from_sys_call | ||
| 1361 | RESTORE_ARGS | ||
| 1362 | UNFAKE_STACK_FRAME | ||
| 1363 | ret | ||
| 1364 | CFI_ENDPROC | ||
| 1365 | END(kernel_execve) | ||
| 1366 | 1342 | ||
| 1367 | /* Call softirq on interrupt stack. Interrupts are off. */ | 1343 | /* Call softirq on interrupt stack. Interrupts are off. */ |
| 1368 | ENTRY(call_softirq) | 1344 | ENTRY(call_softirq) |
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c index dc3567e083f9..b644e1c765dc 100644 --- a/arch/x86/kernel/process.c +++ b/arch/x86/kernel/process.c | |||
| @@ -293,71 +293,6 @@ sys_clone(unsigned long clone_flags, unsigned long newsp, | |||
| 293 | } | 293 | } |
| 294 | 294 | ||
| 295 | /* | 295 | /* |
| 296 | * This gets run with %si containing the | ||
| 297 | * function to call, and %di containing | ||
| 298 | * the "args". | ||
| 299 | */ | ||
| 300 | extern void kernel_thread_helper(void); | ||
| 301 | |||
| 302 | /* | ||
| 303 | * Create a kernel thread | ||
| 304 | */ | ||
| 305 | int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) | ||
| 306 | { | ||
| 307 | struct pt_regs regs; | ||
| 308 | |||
| 309 | memset(®s, 0, sizeof(regs)); | ||
| 310 | |||
| 311 | regs.si = (unsigned long) fn; | ||
| 312 | regs.di = (unsigned long) arg; | ||
| 313 | |||
| 314 | #ifdef CONFIG_X86_32 | ||
| 315 | regs.ds = __USER_DS; | ||
| 316 | regs.es = __USER_DS; | ||
| 317 | regs.fs = __KERNEL_PERCPU; | ||
| 318 | regs.gs = __KERNEL_STACK_CANARY; | ||
| 319 | #else | ||
| 320 | regs.ss = __KERNEL_DS; | ||
| 321 | #endif | ||
| 322 | |||
| 323 | regs.orig_ax = -1; | ||
| 324 | regs.ip = (unsigned long) kernel_thread_helper; | ||
| 325 | regs.cs = __KERNEL_CS | get_kernel_rpl(); | ||
| 326 | regs.flags = X86_EFLAGS_IF | X86_EFLAGS_BIT1; | ||
| 327 | |||
| 328 | /* Ok, create the new process.. */ | ||
| 329 | return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s, 0, NULL, NULL); | ||
| 330 | } | ||
| 331 | EXPORT_SYMBOL(kernel_thread); | ||
| 332 | |||
| 333 | /* | ||
| 334 | * sys_execve() executes a new program. | ||
| 335 | */ | ||
| 336 | long sys_execve(const char __user *name, | ||
| 337 | const char __user *const __user *argv, | ||
| 338 | const char __user *const __user *envp, struct pt_regs *regs) | ||
| 339 | { | ||
| 340 | long error; | ||
| 341 | char *filename; | ||
| 342 | |||
| 343 | filename = getname(name); | ||
| 344 | error = PTR_ERR(filename); | ||
| 345 | if (IS_ERR(filename)) | ||
| 346 | return error; | ||
| 347 | error = do_execve(filename, argv, envp, regs); | ||
| 348 | |||
| 349 | #ifdef CONFIG_X86_32 | ||
| 350 | if (error == 0) { | ||
| 351 | /* Make sure we don't return using sysenter.. */ | ||
| 352 | set_thread_flag(TIF_IRET); | ||
| 353 | } | ||
| 354 | #endif | ||
| 355 | |||
| 356 | putname(filename); | ||
| 357 | return error; | ||
| 358 | } | ||
| 359 | |||
| 360 | /* | ||
| 361 | * Idle related variables and functions | 296 | * Idle related variables and functions |
| 362 | */ | 297 | */ |
| 363 | unsigned long boot_option_idle_override = IDLE_NO_OVERRIDE; | 298 | 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 b9ff83c7135b..44e0bff38e72 100644 --- a/arch/x86/kernel/process_32.c +++ b/arch/x86/kernel/process_32.c | |||
| @@ -57,6 +57,7 @@ | |||
| 57 | #include <asm/switch_to.h> | 57 | #include <asm/switch_to.h> |
| 58 | 58 | ||
| 59 | asmlinkage void ret_from_fork(void) __asm__("ret_from_fork"); | 59 | asmlinkage void ret_from_fork(void) __asm__("ret_from_fork"); |
| 60 | asmlinkage void ret_from_kernel_thread(void) __asm__("ret_from_kernel_thread"); | ||
| 60 | 61 | ||
| 61 | /* | 62 | /* |
| 62 | * Return saved PC of a blocked thread. | 63 | * Return saved PC of a blocked thread. |
| @@ -127,23 +128,39 @@ void release_thread(struct task_struct *dead_task) | |||
| 127 | } | 128 | } |
| 128 | 129 | ||
| 129 | int copy_thread(unsigned long clone_flags, unsigned long sp, | 130 | int copy_thread(unsigned long clone_flags, unsigned long sp, |
| 130 | unsigned long unused, | 131 | unsigned long arg, |
| 131 | struct task_struct *p, struct pt_regs *regs) | 132 | struct task_struct *p, struct pt_regs *regs) |
| 132 | { | 133 | { |
| 133 | struct pt_regs *childregs; | 134 | struct pt_regs *childregs = task_pt_regs(p); |
| 134 | struct task_struct *tsk; | 135 | struct task_struct *tsk; |
| 135 | int err; | 136 | int err; |
| 136 | 137 | ||
| 137 | childregs = task_pt_regs(p); | 138 | p->thread.sp = (unsigned long) childregs; |
| 139 | p->thread.sp0 = (unsigned long) (childregs+1); | ||
| 140 | |||
| 141 | if (unlikely(!regs)) { | ||
| 142 | /* kernel thread */ | ||
| 143 | memset(childregs, 0, sizeof(struct pt_regs)); | ||
| 144 | p->thread.ip = (unsigned long) ret_from_kernel_thread; | ||
| 145 | task_user_gs(p) = __KERNEL_STACK_CANARY; | ||
| 146 | childregs->ds = __USER_DS; | ||
| 147 | childregs->es = __USER_DS; | ||
| 148 | childregs->fs = __KERNEL_PERCPU; | ||
| 149 | childregs->bx = sp; /* function */ | ||
| 150 | childregs->bp = arg; | ||
| 151 | childregs->orig_ax = -1; | ||
| 152 | childregs->cs = __KERNEL_CS | get_kernel_rpl(); | ||
| 153 | childregs->flags = X86_EFLAGS_IF | X86_EFLAGS_BIT1; | ||
| 154 | p->fpu_counter = 0; | ||
| 155 | p->thread.io_bitmap_ptr = NULL; | ||
| 156 | memset(p->thread.ptrace_bps, 0, sizeof(p->thread.ptrace_bps)); | ||
| 157 | return 0; | ||
| 158 | } | ||
| 138 | *childregs = *regs; | 159 | *childregs = *regs; |
| 139 | childregs->ax = 0; | 160 | childregs->ax = 0; |
| 140 | childregs->sp = sp; | 161 | childregs->sp = sp; |
| 141 | 162 | ||
| 142 | p->thread.sp = (unsigned long) childregs; | ||
| 143 | p->thread.sp0 = (unsigned long) (childregs+1); | ||
| 144 | |||
| 145 | p->thread.ip = (unsigned long) ret_from_fork; | 163 | p->thread.ip = (unsigned long) ret_from_fork; |
| 146 | |||
| 147 | task_user_gs(p) = get_user_gs(regs); | 164 | task_user_gs(p) = get_user_gs(regs); |
| 148 | 165 | ||
| 149 | p->fpu_counter = 0; | 166 | p->fpu_counter = 0; |
| @@ -190,6 +207,12 @@ start_thread(struct pt_regs *regs, unsigned long new_ip, unsigned long new_sp) | |||
| 190 | regs->cs = __USER_CS; | 207 | regs->cs = __USER_CS; |
| 191 | regs->ip = new_ip; | 208 | regs->ip = new_ip; |
| 192 | regs->sp = new_sp; | 209 | regs->sp = new_sp; |
| 210 | regs->flags = X86_EFLAGS_IF; | ||
| 211 | /* | ||
| 212 | * force it to the iret return path by making it look as if there was | ||
| 213 | * some work pending. | ||
| 214 | */ | ||
| 215 | set_thread_flag(TIF_NOTIFY_RESUME); | ||
| 193 | } | 216 | } |
| 194 | EXPORT_SYMBOL_GPL(start_thread); | 217 | EXPORT_SYMBOL_GPL(start_thread); |
| 195 | 218 | ||
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index 8a6d20ce1978..16c6365e2b86 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c | |||
| @@ -146,29 +146,18 @@ static inline u32 read_32bit_tls(struct task_struct *t, int tls) | |||
| 146 | } | 146 | } |
| 147 | 147 | ||
| 148 | int copy_thread(unsigned long clone_flags, unsigned long sp, | 148 | int copy_thread(unsigned long clone_flags, unsigned long sp, |
| 149 | unsigned long unused, | 149 | unsigned long arg, |
| 150 | struct task_struct *p, struct pt_regs *regs) | 150 | struct task_struct *p, struct pt_regs *regs) |
| 151 | { | 151 | { |
| 152 | int err; | 152 | int err; |
| 153 | struct pt_regs *childregs; | 153 | struct pt_regs *childregs; |
| 154 | struct task_struct *me = current; | 154 | struct task_struct *me = current; |
| 155 | 155 | ||
| 156 | childregs = ((struct pt_regs *) | 156 | p->thread.sp0 = (unsigned long)task_stack_page(p) + THREAD_SIZE; |
| 157 | (THREAD_SIZE + task_stack_page(p))) - 1; | 157 | childregs = task_pt_regs(p); |
| 158 | *childregs = *regs; | ||
| 159 | |||
| 160 | childregs->ax = 0; | ||
| 161 | if (user_mode(regs)) | ||
| 162 | childregs->sp = sp; | ||
| 163 | else | ||
| 164 | childregs->sp = (unsigned long)childregs; | ||
| 165 | |||
| 166 | p->thread.sp = (unsigned long) childregs; | 158 | p->thread.sp = (unsigned long) childregs; |
| 167 | p->thread.sp0 = (unsigned long) (childregs+1); | ||
| 168 | p->thread.usersp = me->thread.usersp; | 159 | p->thread.usersp = me->thread.usersp; |
| 169 | |||
| 170 | set_tsk_thread_flag(p, TIF_FORK); | 160 | set_tsk_thread_flag(p, TIF_FORK); |
| 171 | |||
| 172 | p->fpu_counter = 0; | 161 | p->fpu_counter = 0; |
| 173 | p->thread.io_bitmap_ptr = NULL; | 162 | p->thread.io_bitmap_ptr = NULL; |
| 174 | 163 | ||
| @@ -178,6 +167,24 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, | |||
| 178 | p->thread.fs = p->thread.fsindex ? 0 : me->thread.fs; | 167 | p->thread.fs = p->thread.fsindex ? 0 : me->thread.fs; |
| 179 | savesegment(es, p->thread.es); | 168 | savesegment(es, p->thread.es); |
| 180 | savesegment(ds, p->thread.ds); | 169 | savesegment(ds, p->thread.ds); |
| 170 | memset(p->thread.ptrace_bps, 0, sizeof(p->thread.ptrace_bps)); | ||
| 171 | |||
| 172 | if (unlikely(!regs)) { | ||
| 173 | /* kernel thread */ | ||
| 174 | memset(childregs, 0, sizeof(struct pt_regs)); | ||
| 175 | childregs->sp = (unsigned long)childregs; | ||
| 176 | childregs->ss = __KERNEL_DS; | ||
| 177 | childregs->bx = sp; /* function */ | ||
| 178 | childregs->bp = arg; | ||
| 179 | childregs->orig_ax = -1; | ||
| 180 | childregs->cs = __KERNEL_CS | get_kernel_rpl(); | ||
| 181 | childregs->flags = X86_EFLAGS_IF | X86_EFLAGS_BIT1; | ||
| 182 | return 0; | ||
| 183 | } | ||
| 184 | *childregs = *regs; | ||
| 185 | |||
| 186 | childregs->ax = 0; | ||
| 187 | childregs->sp = sp; | ||
| 181 | 188 | ||
| 182 | err = -ENOMEM; | 189 | err = -ENOMEM; |
| 183 | memset(p->thread.ptrace_bps, 0, sizeof(p->thread.ptrace_bps)); | 190 | memset(p->thread.ptrace_bps, 0, sizeof(p->thread.ptrace_bps)); |
diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c index b33144c8b309..29ad351804e9 100644 --- a/arch/x86/kernel/signal.c +++ b/arch/x86/kernel/signal.c | |||
| @@ -840,10 +840,6 @@ do_notify_resume(struct pt_regs *regs, void *unused, __u32 thread_info_flags) | |||
| 840 | if (thread_info_flags & _TIF_USER_RETURN_NOTIFY) | 840 | if (thread_info_flags & _TIF_USER_RETURN_NOTIFY) |
| 841 | fire_user_return_notifiers(); | 841 | fire_user_return_notifiers(); |
| 842 | 842 | ||
| 843 | #ifdef CONFIG_X86_32 | ||
| 844 | clear_thread_flag(TIF_IRET); | ||
| 845 | #endif /* CONFIG_X86_32 */ | ||
| 846 | |||
| 847 | rcu_user_enter(); | 843 | rcu_user_enter(); |
| 848 | } | 844 | } |
| 849 | 845 | ||
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/kernel/vm86_32.c b/arch/x86/kernel/vm86_32.c index 54abcc0baf23..5c9687b1bde6 100644 --- a/arch/x86/kernel/vm86_32.c +++ b/arch/x86/kernel/vm86_32.c | |||
| @@ -561,9 +561,9 @@ int handle_vm86_trap(struct kernel_vm86_regs *regs, long error_code, int trapno) | |||
| 561 | if ((trapno == 3) || (trapno == 1)) { | 561 | if ((trapno == 3) || (trapno == 1)) { |
| 562 | KVM86->regs32->ax = VM86_TRAP + (trapno << 8); | 562 | KVM86->regs32->ax = VM86_TRAP + (trapno << 8); |
| 563 | /* setting this flag forces the code in entry_32.S to | 563 | /* setting this flag forces the code in entry_32.S to |
| 564 | call save_v86_state() and change the stack pointer | 564 | the path where we call save_v86_state() and change |
| 565 | to KVM86->regs32 */ | 565 | the stack pointer to KVM86->regs32 */ |
| 566 | set_thread_flag(TIF_IRET); | 566 | set_thread_flag(TIF_NOTIFY_RESUME); |
| 567 | return 0; | 567 | return 0; |
| 568 | } | 568 | } |
| 569 | do_int(regs, trapno, (unsigned char __user *) (regs->pt.ss << 4), SP(regs)); | 569 | do_int(regs, trapno, (unsigned char __user *) (regs->pt.ss << 4), SP(regs)); |
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/Kconfig b/arch/x86/um/Kconfig index aeaff8bef2f1..30c4eec033af 100644 --- a/arch/x86/um/Kconfig +++ b/arch/x86/um/Kconfig | |||
| @@ -13,6 +13,7 @@ endmenu | |||
| 13 | config UML_X86 | 13 | 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 | 17 | ||
| 17 | config 64BIT | 18 | config 64BIT |
| 18 | bool "64-bit kernel" if SUBARCH = "x86" | 19 | bool "64-bit kernel" if SUBARCH = "x86" |
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 |
diff --git a/arch/xtensa/include/asm/Kbuild b/arch/xtensa/include/asm/Kbuild index 0d20f5526dd8..fccd81eddff1 100644 --- a/arch/xtensa/include/asm/Kbuild +++ b/arch/xtensa/include/asm/Kbuild | |||
| @@ -1,3 +1,4 @@ | |||
| 1 | include include/asm-generic/Kbuild.asm | 1 | include include/asm-generic/Kbuild.asm |
| 2 | 2 | ||
| 3 | generic-y += clkdev.h | 3 | generic-y += clkdev.h |
| 4 | generic-y += exec.h | ||
diff --git a/arch/xtensa/include/asm/exec.h b/arch/xtensa/include/asm/exec.h deleted file mode 100644 index af949e28cb32..000000000000 --- a/arch/xtensa/include/asm/exec.h +++ /dev/null | |||
| @@ -1,14 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * This file is subject to the terms and conditions of the GNU General Public | ||
| 3 | * License. See the file "COPYING" in the main directory of this archive | ||
| 4 | * for more details. | ||
| 5 | * | ||
| 6 | * Copyright (C) 2001 - 2005 Tensilica Inc. | ||
| 7 | */ | ||
| 8 | |||
| 9 | #ifndef _XTENSA_EXEC_H | ||
| 10 | #define _XTENSA_EXEC_H | ||
| 11 | |||
| 12 | #define arch_align_stack(x) (x) | ||
| 13 | |||
| 14 | #endif /* _XTENSA_EXEC_H */ | ||
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index e800dec958c3..fbd9f60bd763 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c | |||
| @@ -36,7 +36,6 @@ | |||
| 36 | #include <asm/uaccess.h> | 36 | #include <asm/uaccess.h> |
| 37 | #include <asm/param.h> | 37 | #include <asm/param.h> |
| 38 | #include <asm/page.h> | 38 | #include <asm/page.h> |
| 39 | #include <asm/exec.h> | ||
| 40 | 39 | ||
| 41 | #ifndef user_long_t | 40 | #ifndef user_long_t |
| 42 | #define user_long_t long | 41 | #define user_long_t long |
diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c index 262db114ff01..a46049154107 100644 --- a/fs/binfmt_elf_fdpic.c +++ b/fs/binfmt_elf_fdpic.c | |||
| @@ -39,7 +39,6 @@ | |||
| 39 | #include <asm/uaccess.h> | 39 | #include <asm/uaccess.h> |
| 40 | #include <asm/param.h> | 40 | #include <asm/param.h> |
| 41 | #include <asm/pgalloc.h> | 41 | #include <asm/pgalloc.h> |
| 42 | #include <asm/exec.h> | ||
| 43 | 42 | ||
| 44 | typedef char *elf_caddr_t; | 43 | typedef char *elf_caddr_t; |
| 45 | 44 | ||
| @@ -59,7 +59,6 @@ | |||
| 59 | #include <asm/uaccess.h> | 59 | #include <asm/uaccess.h> |
| 60 | #include <asm/mmu_context.h> | 60 | #include <asm/mmu_context.h> |
| 61 | #include <asm/tlb.h> | 61 | #include <asm/tlb.h> |
| 62 | #include <asm/exec.h> | ||
| 63 | 62 | ||
| 64 | #include <trace/events/task.h> | 63 | #include <trace/events/task.h> |
| 65 | #include "internal.h" | 64 | #include "internal.h" |
| @@ -392,7 +391,7 @@ struct user_arg_ptr { | |||
| 392 | union { | 391 | union { |
| 393 | const char __user *const __user *native; | 392 | const char __user *const __user *native; |
| 394 | #ifdef CONFIG_COMPAT | 393 | #ifdef CONFIG_COMPAT |
| 395 | compat_uptr_t __user *compat; | 394 | const compat_uptr_t __user *compat; |
| 396 | #endif | 395 | #endif |
| 397 | } ptr; | 396 | } ptr; |
| 398 | }; | 397 | }; |
| @@ -1574,9 +1573,9 @@ int do_execve(const char *filename, | |||
| 1574 | } | 1573 | } |
| 1575 | 1574 | ||
| 1576 | #ifdef CONFIG_COMPAT | 1575 | #ifdef CONFIG_COMPAT |
| 1577 | int compat_do_execve(char *filename, | 1576 | int compat_do_execve(const char *filename, |
| 1578 | compat_uptr_t __user *__argv, | 1577 | const compat_uptr_t __user *__argv, |
| 1579 | compat_uptr_t __user *__envp, | 1578 | const compat_uptr_t __user *__envp, |
| 1580 | struct pt_regs *regs) | 1579 | struct pt_regs *regs) |
| 1581 | { | 1580 | { |
| 1582 | struct user_arg_ptr argv = { | 1581 | struct user_arg_ptr argv = { |
| @@ -1658,3 +1657,55 @@ int get_dumpable(struct mm_struct *mm) | |||
| 1658 | { | 1657 | { |
| 1659 | return __get_dumpable(mm->flags); | 1658 | return __get_dumpable(mm->flags); |
| 1660 | } | 1659 | } |
| 1660 | |||
| 1661 | #ifdef __ARCH_WANT_SYS_EXECVE | ||
| 1662 | SYSCALL_DEFINE3(execve, | ||
| 1663 | const char __user *, filename, | ||
| 1664 | const char __user *const __user *, argv, | ||
| 1665 | const char __user *const __user *, envp) | ||
| 1666 | { | ||
| 1667 | const char *path = getname(filename); | ||
| 1668 | int error = PTR_ERR(path); | ||
| 1669 | if (!IS_ERR(path)) { | ||
| 1670 | error = do_execve(path, argv, envp, current_pt_regs()); | ||
| 1671 | putname(path); | ||
| 1672 | } | ||
| 1673 | return error; | ||
| 1674 | } | ||
| 1675 | #ifdef CONFIG_COMPAT | ||
| 1676 | asmlinkage long compat_sys_execve(const char __user * filename, | ||
| 1677 | const compat_uptr_t __user * argv, | ||
| 1678 | const compat_uptr_t __user * envp) | ||
| 1679 | { | ||
| 1680 | const char *path = getname(filename); | ||
| 1681 | int error = PTR_ERR(path); | ||
| 1682 | if (!IS_ERR(path)) { | ||
| 1683 | error = compat_do_execve(path, argv, envp, current_pt_regs()); | ||
| 1684 | putname(path); | ||
| 1685 | } | ||
| 1686 | return error; | ||
| 1687 | } | ||
| 1688 | #endif | ||
| 1689 | #endif | ||
| 1690 | |||
| 1691 | #ifdef __ARCH_WANT_KERNEL_EXECVE | ||
| 1692 | int kernel_execve(const char *filename, | ||
| 1693 | const char *const argv[], | ||
| 1694 | const char *const envp[]) | ||
| 1695 | { | ||
| 1696 | struct pt_regs *p = current_pt_regs(); | ||
| 1697 | int ret; | ||
| 1698 | |||
| 1699 | ret = do_execve(filename, | ||
| 1700 | (const char __user *const __user *)argv, | ||
| 1701 | (const char __user *const __user *)envp, p); | ||
| 1702 | if (ret < 0) | ||
| 1703 | return ret; | ||
| 1704 | |||
| 1705 | /* | ||
| 1706 | * We were successful. We won't be returning to our caller, but | ||
| 1707 | * instead to user space by manipulating the kernel stack. | ||
| 1708 | */ | ||
| 1709 | ret_from_kernel_execve(p); | ||
| 1710 | } | ||
| 1711 | #endif | ||
diff --git a/include/linux/binfmts.h b/include/linux/binfmts.h index 37935c2d2e8f..26531f32bbb2 100644 --- a/include/linux/binfmts.h +++ b/include/linux/binfmts.h | |||
| @@ -19,6 +19,8 @@ struct pt_regs; | |||
| 19 | 19 | ||
| 20 | #ifdef __KERNEL__ | 20 | #ifdef __KERNEL__ |
| 21 | #include <linux/sched.h> | 21 | #include <linux/sched.h> |
| 22 | #include <linux/unistd.h> | ||
| 23 | #include <asm/exec.h> | ||
| 22 | 24 | ||
| 23 | #define CORENAME_MAX_SIZE 128 | 25 | #define CORENAME_MAX_SIZE 128 |
| 24 | 26 | ||
| @@ -135,5 +137,9 @@ extern void install_exec_creds(struct linux_binprm *bprm); | |||
| 135 | extern void set_binfmt(struct linux_binfmt *new); | 137 | extern void set_binfmt(struct linux_binfmt *new); |
| 136 | extern void free_bprm(struct linux_binprm *); | 138 | extern void free_bprm(struct linux_binprm *); |
| 137 | 139 | ||
| 140 | #ifdef __ARCH_WANT_KERNEL_EXECVE | ||
| 141 | extern void ret_from_kernel_execve(struct pt_regs *normal) __noreturn; | ||
| 142 | #endif | ||
| 143 | |||
| 138 | #endif /* __KERNEL__ */ | 144 | #endif /* __KERNEL__ */ |
| 139 | #endif /* _LINUX_BINFMTS_H */ | 145 | #endif /* _LINUX_BINFMTS_H */ |
diff --git a/include/linux/compat.h b/include/linux/compat.h index 3f53d002c7c5..d0ced1011f2f 100644 --- a/include/linux/compat.h +++ b/include/linux/compat.h | |||
| @@ -284,8 +284,12 @@ asmlinkage ssize_t compat_sys_pwritev(unsigned long fd, | |||
| 284 | const struct compat_iovec __user *vec, | 284 | const struct compat_iovec __user *vec, |
| 285 | unsigned long vlen, u32 pos_low, u32 pos_high); | 285 | unsigned long vlen, u32 pos_low, u32 pos_high); |
| 286 | 286 | ||
| 287 | int compat_do_execve(char *filename, compat_uptr_t __user *argv, | 287 | int compat_do_execve(const char *filename, const compat_uptr_t __user *argv, |
| 288 | compat_uptr_t __user *envp, struct pt_regs *regs); | 288 | const compat_uptr_t __user *envp, struct pt_regs *regs); |
| 289 | #ifdef __ARCH_WANT_SYS_EXECVE | ||
| 290 | asmlinkage long compat_sys_execve(const char __user *filename, const compat_uptr_t __user *argv, | ||
| 291 | const compat_uptr_t __user *envp); | ||
| 292 | #endif | ||
| 289 | 293 | ||
| 290 | asmlinkage long compat_sys_select(int n, compat_ulong_t __user *inp, | 294 | asmlinkage long compat_sys_select(int n, compat_ulong_t __user *inp, |
| 291 | compat_ulong_t __user *outp, compat_ulong_t __user *exp, | 295 | compat_ulong_t __user *outp, compat_ulong_t __user *exp, |
diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h index 3db698aee34c..1d24ffad59c5 100644 --- a/include/linux/ptrace.h +++ b/include/linux/ptrace.h | |||
| @@ -401,6 +401,10 @@ static inline void user_single_step_siginfo(struct task_struct *tsk, | |||
| 401 | #define arch_ptrace_stop(code, info) do { } while (0) | 401 | #define arch_ptrace_stop(code, info) do { } while (0) |
| 402 | #endif | 402 | #endif |
| 403 | 403 | ||
| 404 | #ifndef current_pt_regs | ||
| 405 | #define current_pt_regs() task_pt_regs(current) | ||
| 406 | #endif | ||
| 407 | |||
| 404 | extern int task_current_syscall(struct task_struct *target, long *callno, | 408 | extern int task_current_syscall(struct task_struct *target, long *callno, |
| 405 | unsigned long args[6], unsigned int maxargs, | 409 | unsigned long args[6], unsigned int maxargs, |
| 406 | unsigned long *sp, unsigned long *pc); | 410 | unsigned long *sp, unsigned long *pc); |
diff --git a/include/linux/sched.h b/include/linux/sched.h index c2070e92a9d6..a83ca5816ecb 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h | |||
| @@ -2332,6 +2332,9 @@ extern int do_execve(const char *, | |||
| 2332 | const char __user * const __user *, struct pt_regs *); | 2332 | const char __user * const __user *, struct pt_regs *); |
| 2333 | extern long do_fork(unsigned long, unsigned long, struct pt_regs *, unsigned long, int __user *, int __user *); | 2333 | extern long do_fork(unsigned long, unsigned long, struct pt_regs *, unsigned long, int __user *, int __user *); |
| 2334 | struct task_struct *fork_idle(int); | 2334 | struct task_struct *fork_idle(int); |
| 2335 | #ifdef CONFIG_GENERIC_KERNEL_THREAD | ||
| 2336 | extern pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); | ||
| 2337 | #endif | ||
| 2335 | 2338 | ||
| 2336 | extern void set_task_comm(struct task_struct *tsk, char *from); | 2339 | extern void set_task_comm(struct task_struct *tsk, char *from); |
| 2337 | extern char *get_task_comm(char *to, struct task_struct *tsk); | 2340 | extern char *get_task_comm(char *to, struct task_struct *tsk); |
diff --git a/kernel/fork.c b/kernel/fork.c index 1cd7d581b3b2..8b20ab7d3aa2 100644 --- a/kernel/fork.c +++ b/kernel/fork.c | |||
| @@ -1584,7 +1584,7 @@ long do_fork(unsigned long clone_flags, | |||
| 1584 | * requested, no event is reported; otherwise, report if the event | 1584 | * requested, no event is reported; otherwise, report if the event |
| 1585 | * for the type of forking is enabled. | 1585 | * for the type of forking is enabled. |
| 1586 | */ | 1586 | */ |
| 1587 | if (likely(user_mode(regs)) && !(clone_flags & CLONE_UNTRACED)) { | 1587 | if (!(clone_flags & CLONE_UNTRACED) && likely(user_mode(regs))) { |
| 1588 | if (clone_flags & CLONE_VFORK) | 1588 | if (clone_flags & CLONE_VFORK) |
| 1589 | trace = PTRACE_EVENT_VFORK; | 1589 | trace = PTRACE_EVENT_VFORK; |
| 1590 | else if ((clone_flags & CSIGNAL) != SIGCHLD) | 1590 | else if ((clone_flags & CSIGNAL) != SIGCHLD) |
| @@ -1634,6 +1634,17 @@ long do_fork(unsigned long clone_flags, | |||
| 1634 | return nr; | 1634 | return nr; |
| 1635 | } | 1635 | } |
| 1636 | 1636 | ||
| 1637 | #ifdef CONFIG_GENERIC_KERNEL_THREAD | ||
| 1638 | /* | ||
| 1639 | * Create a kernel thread. | ||
| 1640 | */ | ||
| 1641 | pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags) | ||
| 1642 | { | ||
| 1643 | return do_fork(flags|CLONE_VM|CLONE_UNTRACED, (unsigned long)fn, NULL, | ||
| 1644 | (unsigned long)arg, NULL, NULL); | ||
| 1645 | } | ||
| 1646 | #endif | ||
| 1647 | |||
| 1637 | #ifndef ARCH_MIN_MMSTRUCT_ALIGN | 1648 | #ifndef ARCH_MIN_MMSTRUCT_ALIGN |
| 1638 | #define ARCH_MIN_MMSTRUCT_ALIGN 0 | 1649 | #define ARCH_MIN_MMSTRUCT_ALIGN 0 |
| 1639 | #endif | 1650 | #endif |
