Skip to content

Commit

Permalink
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel…
Browse files Browse the repository at this point in the history
…/git/viro/signal

Pull generic execve() changes from Al Viro:
 "This introduces the generic kernel_thread() and kernel_execve()
  functions, and switches x86, arm, alpha, um and s390 over to them."

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/signal: (26 commits)
  s390: convert to generic kernel_execve()
  s390: switch to generic kernel_thread()
  s390: fold kernel_thread_helper() into ret_from_fork()
  s390: fold execve_tail() into start_thread(), convert to generic sys_execve()
  um: switch to generic kernel_thread()
  x86, um/x86: switch to generic sys_execve and kernel_execve
  x86: split ret_from_fork
  alpha: introduce ret_from_kernel_execve(), switch to generic kernel_execve()
  alpha: switch to generic kernel_thread()
  alpha: switch to generic sys_execve()
  arm: get rid of execve wrapper, switch to generic execve() implementation
  arm: optimized current_pt_regs()
  arm: introduce ret_from_kernel_execve(), switch to generic kernel_execve()
  arm: split ret_from_fork, simplify kernel_thread() [based on patch by rmk]
  generic sys_execve()
  generic kernel_execve()
  new helper: current_pt_regs()
  preparation for generic kernel_thread()
  um: kill thread->forking
  um: let signal_delivered() do SIGTRAP on singlestepping into handler
  ...
  • Loading branch information
torvalds committed Oct 10, 2012
2 parents f59b51f + f322220 commit 42859ee
Show file tree
Hide file tree
Showing 96 changed files with 390 additions and 899 deletions.
3 changes: 3 additions & 0 deletions arch/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,9 @@ config ARCH_WANT_OLD_COMPAT_IPC
select ARCH_WANT_COMPAT_IPC_PARSE_VERSION
bool

config GENERIC_KERNEL_THREAD
bool

config HAVE_ARCH_SECCOMP_FILTER
bool
help
Expand Down
1 change: 1 addition & 0 deletions arch/alpha/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ config ALPHA
select GENERIC_CMOS_UPDATE
select GENERIC_STRNCPY_FROM_USER
select GENERIC_STRNLEN_USER
select GENERIC_KERNEL_THREAD
help
The Alpha is a 64-bit general-purpose processor designed and
marketed by the Digital Equipment Corporation of blessed memory,
Expand Down
1 change: 1 addition & 0 deletions arch/alpha/include/asm/Kbuild
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ header-y += pal.h
header-y += reg.h
header-y += regdef.h
header-y += sysinfo.h
generic-y += exec.h
6 changes: 0 additions & 6 deletions arch/alpha/include/asm/exec.h

This file was deleted.

3 changes: 0 additions & 3 deletions arch/alpha/include/asm/processor.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,6 @@ extern void start_thread(struct pt_regs *, unsigned long, unsigned long);
/* Free all resources held by a thread. */
extern void release_thread(struct task_struct *);

/* Create a kernel thread without removing it from tasklists. */
extern long kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);

unsigned long get_wchan(struct task_struct *p);

#define KSTK_EIP(tsk) (task_pt_regs(tsk)->pc)
Expand Down
2 changes: 2 additions & 0 deletions arch/alpha/include/asm/unistd.h
Original file line number Diff line number Diff line change
Expand Up @@ -481,6 +481,8 @@
#define __ARCH_WANT_SYS_OLDUMOUNT
#define __ARCH_WANT_SYS_SIGPENDING
#define __ARCH_WANT_SYS_RT_SIGSUSPEND
#define __ARCH_WANT_SYS_EXECVE
#define __ARCH_WANT_KERNEL_EXECVE

/* "Conditional" syscalls. What we want is
Expand Down
3 changes: 0 additions & 3 deletions arch/alpha/kernel/alpha_ksyms.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,6 @@ EXPORT_SYMBOL(alpha_read_fp_reg_s);
EXPORT_SYMBOL(alpha_write_fp_reg);
EXPORT_SYMBOL(alpha_write_fp_reg_s);

/* entry.S */
EXPORT_SYMBOL(kernel_thread);

/* Networking helper routines. */
EXPORT_SYMBOL(csum_tcpudp_magic);
EXPORT_SYMBOL(ip_compute_csum);
Expand Down
69 changes: 18 additions & 51 deletions arch/alpha/kernel/entry.S
Original file line number Diff line number Diff line change
Expand Up @@ -609,59 +609,35 @@ ret_from_fork:
.end ret_from_fork

/*
* kernel_thread(fn, arg, clone_flags)
* ... and new kernel threads - here
*/
.align 4
.globl kernel_thread
.ent kernel_thread
kernel_thread:
/* We can be called from a module. */
ldgp $gp, 0($27)
.prologue 1
subq $sp, SP_OFF+6*8, $sp
br $1, 2f /* load start address */

/* We've now "returned" from a fake system call. */
unop
blt $0, 1f /* error? */
ldi $1, 0x3fff
beq $20, 1f /* parent or child? */

bic $sp, $1, $8 /* in child. */
jsr $26, ($27)
.globl ret_from_kernel_thread
.ent ret_from_kernel_thread
ret_from_kernel_thread:
mov $17, $16
jsr $26, schedule_tail
mov $9, $27
mov $10, $16
jsr $26, ($9)
ldgp $gp, 0($26)
mov $0, $16
mov $31, $26
jmp $31, sys_exit
.end ret_from_kernel_thread

1: ret /* in parent. */

.align 4
2: /* Fake a system call stack frame, as we can't do system calls
from kernel space. Note that we store FN and ARG as they
need to be set up in the child for the call. Also store $8
and $26 for use in the parent. */
stq $31, SP_OFF($sp) /* ps */
stq $1, SP_OFF+8($sp) /* pc */
stq $gp, SP_OFF+16($sp) /* gp */
stq $16, 136($sp) /* $27; FN for child */
stq $17, SP_OFF+24($sp) /* $16; ARG for child */
stq $8, 64($sp) /* $8 */
stq $26, 128($sp) /* $26 */
.globl ret_from_kernel_execve
.align 4
.ent ret_from_kernel_execve
ret_from_kernel_execve:
mov $16, $sp
/* Avoid the HAE being gratuitously wrong, to avoid restoring it. */
ldq $2, alpha_mv+HAE_CACHE
stq $2, 152($sp) /* HAE */
mov $31, $19 /* to disable syscall restarts */
br $31, ret_to_user

/* Shuffle FLAGS to the front; add CLONE_VM. */
ldi $1, CLONE_VM|CLONE_UNTRACED
or $18, $1, $16
bsr $26, sys_clone

/* We don't actually care for a3 success widgetry in the kernel.
Not for positive errno values. */
stq $0, 0($sp) /* $0 */
br ret_to_kernel
.end kernel_thread
.end ret_from_kernel_execve


/*
Expand Down Expand Up @@ -744,15 +720,6 @@ sys_rt_sigreturn:
br ret_from_sys_call
.end sys_rt_sigreturn

.align 4
.globl sys_execve
.ent sys_execve
sys_execve:
.prologue 0
mov $sp, $19
jmp $31, do_sys_execve
.end sys_execve

.align 4
.globl alpha_ni_syscall
.ent alpha_ni_syscall
Expand Down
79 changes: 20 additions & 59 deletions arch/alpha/kernel/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -263,41 +263,42 @@ alpha_vfork(struct pt_regs *regs)

/*
* Copy an alpha thread..
*
* Note the "stack_offset" stuff: when returning to kernel mode, we need
* to have some extra stack-space for the kernel stack that still exists
* after the "ret_from_fork". When returning to user mode, we only want
* the space needed by the syscall stack frame (ie "struct pt_regs").
* Use the passed "regs" pointer to determine how much space we need
* for a kernel fork().
*/

int
copy_thread(unsigned long clone_flags, unsigned long usp,
unsigned long unused,
unsigned long arg,
struct task_struct * p, struct pt_regs * regs)
{
extern void ret_from_fork(void);
extern void ret_from_kernel_thread(void);

struct thread_info *childti = task_thread_info(p);
struct pt_regs * childregs;
struct switch_stack * childstack, *stack;
unsigned long stack_offset, settls;

stack_offset = PAGE_SIZE - sizeof(struct pt_regs);
if (!(regs->ps & 8))
stack_offset = (PAGE_SIZE-1) & (unsigned long) regs;
childregs = (struct pt_regs *)
(stack_offset + PAGE_SIZE + task_stack_page(p));

struct pt_regs *childregs = task_pt_regs(p);
struct switch_stack *childstack, *stack;
unsigned long settls;

childstack = ((struct switch_stack *) childregs) - 1;
if (unlikely(!regs)) {
/* kernel thread */
memset(childstack, 0,
sizeof(struct switch_stack) + sizeof(struct pt_regs));
childstack->r26 = (unsigned long) ret_from_kernel_thread;
childstack->r9 = usp; /* function */
childstack->r10 = arg;
childregs->hae = alpha_mv.hae_cache,
childti->pcb.usp = 0;
childti->pcb.ksp = (unsigned long) childstack;
childti->pcb.flags = 1; /* set FEN, clear everything else */
return 0;
}
*childregs = *regs;
settls = regs->r20;
childregs->r0 = 0;
childregs->r19 = 0;
childregs->r20 = 1; /* OSF/1 has some strange fork() semantics. */
regs->r20 = 0;
stack = ((struct switch_stack *) regs) - 1;
childstack = ((struct switch_stack *) childregs) - 1;
*childstack = *stack;
childstack->r26 = (unsigned long) ret_from_fork;
childti->pcb.usp = usp;
Expand Down Expand Up @@ -385,27 +386,6 @@ dump_elf_task_fp(elf_fpreg_t *dest, struct task_struct *task)
}
EXPORT_SYMBOL(dump_elf_task_fp);

/*
* sys_execve() executes a new program.
*/
asmlinkage int
do_sys_execve(const char __user *ufilename,
const char __user *const __user *argv,
const char __user *const __user *envp, struct pt_regs *regs)
{
int error;
char *filename;

filename = getname(ufilename);
error = PTR_ERR(filename);
if (IS_ERR(filename))
goto out;
error = do_execve(filename, argv, envp, regs);
putname(filename);
out:
return error;
}

/*
* Return saved PC of a blocked thread. This assumes the frame
* pointer is the 6th saved long on the kernel stack and that the
Expand Down Expand Up @@ -459,22 +439,3 @@ get_wchan(struct task_struct *p)
}
return pc;
}

int kernel_execve(const char *path, const char *const argv[], const char *const envp[])
{
/* Avoid the HAE being gratuitously wrong, which would cause us
to do the whole turn off interrupts thing and restore it. */
struct pt_regs regs = {.hae = alpha_mv.hae_cache};
int err = do_execve(path, argv, envp, &regs);
if (!err) {
struct pt_regs *p = current_pt_regs();
/* copy regs to normal position and off to userland we go... */
*p = regs;
__asm__ __volatile__ (
"mov %0, $sp;"
"br $31, ret_from_sys_call"
: : "r"(p));
}
return err;
}
EXPORT_SYMBOL(kernel_execve);
1 change: 1 addition & 0 deletions arch/arm/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ config ARM
select GENERIC_STRNCPY_FROM_USER
select GENERIC_STRNLEN_USER
select DCACHE_WORD_ACCESS if (CPU_V6 || CPU_V6K || CPU_V7) && !CPU_BIG_ENDIAN
select GENERIC_KERNEL_THREAD
help
The ARM series is a line of low-power-consumption RISC chip designs
licensed by ARM Ltd and targeted at embedded applications and
Expand Down
5 changes: 0 additions & 5 deletions arch/arm/include/asm/processor.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,11 +85,6 @@ unsigned long get_wchan(struct task_struct *p);
#define cpu_relax() barrier()
#endif

/*
* Create a new kernel thread
*/
extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);

#define task_pt_regs(p) \
((struct pt_regs *)(THREAD_START_SP + task_stack_page(p)) - 1)

Expand Down
5 changes: 5 additions & 0 deletions arch/arm/include/asm/ptrace.h
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,11 @@ static inline unsigned long user_stack_pointer(struct pt_regs *regs)
return regs->ARM_sp;
}

#define current_pt_regs(void) ({ \
register unsigned long sp asm ("sp"); \
(struct pt_regs *)((sp | (THREAD_SIZE - 1)) - 7) - 1; \
})

#endif /* __KERNEL__ */

#endif /* __ASSEMBLY__ */
Expand Down
1 change: 0 additions & 1 deletion arch/arm/include/asm/system.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
#include <asm/barrier.h>
#include <asm/compiler.h>
#include <asm/cmpxchg.h>
#include <asm/exec.h>
#include <asm/switch_to.h>
#include <asm/system_info.h>
#include <asm/system_misc.h>
2 changes: 2 additions & 0 deletions arch/arm/include/asm/unistd.h
Original file line number Diff line number Diff line change
Expand Up @@ -478,6 +478,8 @@
#define __ARCH_WANT_OLD_READDIR
#define __ARCH_WANT_SYS_SOCKETCALL
#endif
#define __ARCH_WANT_SYS_EXECVE
#define __ARCH_WANT_KERNEL_EXECVE

/*
* "Conditional" syscalls
Expand Down
2 changes: 1 addition & 1 deletion arch/arm/kernel/calls.S
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
CALL(sys_creat)
CALL(sys_link)
/* 10 */ CALL(sys_unlink)
CALL(sys_execve_wrapper)
CALL(sys_execve)
CALL(sys_chdir)
CALL(OBSOLETE(sys_time)) /* used by libc4 */
CALL(sys_mknod)
Expand Down
29 changes: 24 additions & 5 deletions arch/arm/kernel/entry-common.S
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,30 @@ ENTRY(ret_from_fork)
b ret_slow_syscall
ENDPROC(ret_from_fork)

ENTRY(ret_from_kernel_thread)
UNWIND(.fnstart)
UNWIND(.cantunwind)
bl schedule_tail
mov r0, r4
adr lr, BSYM(1f) @ kernel threads should not exit
mov pc, r5
1: bl do_exit
nop
UNWIND(.fnend)
ENDPROC(ret_from_kernel_thread)

/*
* turn a kernel thread into userland process
* use: ret_from_kernel_execve(struct pt_regs *normal)
*/
ENTRY(ret_from_kernel_execve)
mov why, #0 @ not a syscall
str why, [r0, #S_R0] @ ... and we want 0 in ->ARM_r0 as well
get_thread_info tsk @ thread structure
mov sp, r0 @ stack pointer just under pt_regs
b ret_slow_syscall
ENDPROC(ret_from_kernel_execve)

.equ NR_syscalls,0
#define CALL(x) .equ NR_syscalls,NR_syscalls+1
#include "calls.S"
Expand Down Expand Up @@ -517,11 +541,6 @@ sys_vfork_wrapper:
b sys_vfork
ENDPROC(sys_vfork_wrapper)

sys_execve_wrapper:
add r3, sp, #S_OFF
b sys_execve
ENDPROC(sys_execve_wrapper)

sys_clone_wrapper:
add ip, sp, #S_OFF
str ip, [sp, #4]
Expand Down
Loading

0 comments on commit 42859ee

Please sign in to comment.