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 big execve/kernel_thread/fork unification series from Al Viro:
 "All architectures are converted to new model.  Quite a bit of that
  stuff is actually shared with architecture trees; in such cases it's
  literally shared branch pulled by both, not a cherry-pick.

  A lot of ugliness and black magic is gone (-3KLoC total in this one):

   - kernel_thread()/kernel_execve()/sys_execve() redesign.

     We don't do syscalls from kernel anymore for either kernel_thread()
     or kernel_execve():

     kernel_thread() is essentially clone(2) with callback run before we
     return to userland, the callbacks either never return or do
     successful do_execve() before returning.

     kernel_execve() is a wrapper for do_execve() - it doesn't need to
     do transition to user mode anymore.

     As a result kernel_thread() and kernel_execve() are
     arch-independent now - they live in kernel/fork.c and fs/exec.c
     resp.  sys_execve() is also in fs/exec.c and it's completely
     architecture-independent.

   - daemonize() is gone, along with its parts in fs/*.c

   - struct pt_regs * is no longer passed to do_fork/copy_process/
     copy_thread/do_execve/search_binary_handler/->load_binary/do_coredump.

   - sys_fork()/sys_vfork()/sys_clone() unified; some architectures
     still need wrappers (ones with callee-saved registers not saved in
     pt_regs on syscall entry), but the main part of those suckers is in
     kernel/fork.c now."

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/signal: (113 commits)
  do_coredump(): get rid of pt_regs argument
  print_fatal_signal(): get rid of pt_regs argument
  ptrace_signal(): get rid of unused arguments
  get rid of ptrace_signal_deliver() arguments
  new helper: signal_pt_regs()
  unify default ptrace_signal_deliver
  flagday: kill pt_regs argument of do_fork()
  death to idle_regs()
  don't pass regs to copy_process()
  flagday: don't pass regs to copy_thread()
  bfin: switch to generic vfork, get rid of pointless wrappers
  xtensa: switch to generic clone()
  openrisc: switch to use of generic fork and clone
  unicore32: switch to generic clone(2)
  score: switch to generic fork/vfork/clone
  c6x: sanitize copy_thread(), get rid of clone(2) wrapper, switch to generic clone()
  take sys_fork/sys_vfork/sys_clone prototypes to linux/syscalls.h
  mn10300: switch to generic fork/vfork/clone
  h8300: switch to generic fork/vfork/clone
  tile: switch to generic clone()
  ...

Conflicts:
	arch/microblaze/include/asm/Kbuild
  • Loading branch information
Linus Torvalds committed Dec 12, 2012
2 parents cf4af01 + 541880d commit 9977d9b
Show file tree
Hide file tree
Showing 273 changed files with 1,375 additions and 4,221 deletions.
14 changes: 14 additions & 0 deletions arch/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -342,4 +342,18 @@ config MODULES_USE_ELF_REL
Modules only use ELF REL relocations. Modules with ELF RELA
relocations will give an error.

#
# ABI hall of shame
#
config CLONE_BACKWARDS
bool
help
Architecture has tls passed as the 4th argument of clone(2),
not the 5th one.

config CLONE_BACKWARDS2
bool
help
Architecture has the first two arguments of clone(2) swapped.

source "kernel/gcov/Kconfig"
1 change: 1 addition & 0 deletions arch/alpha/include/asm/ptrace.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ struct switch_stack {

#define current_pt_regs() \
((struct pt_regs *) ((char *)current_thread_info() + 2*PAGE_SIZE) - 1)
#define signal_pt_regs current_pt_regs

#define force_successful_syscall_return() (current_pt_regs()->r0 = 0)

Expand Down
3 changes: 0 additions & 3 deletions arch/alpha/include/asm/signal.h
Original file line number Diff line number Diff line change
Expand Up @@ -164,9 +164,6 @@ struct sigstack {

#ifdef __KERNEL__
#include <asm/sigcontext.h>

#define ptrace_signal_deliver(regs, cookie) do { } while (0)

#endif

#endif
3 changes: 3 additions & 0 deletions arch/alpha/include/asm/unistd.h
Original file line number Diff line number Diff line change
Expand Up @@ -482,6 +482,9 @@
#define __ARCH_WANT_SYS_SIGPENDING
#define __ARCH_WANT_SYS_RT_SIGSUSPEND
#define __ARCH_WANT_SYS_EXECVE
#define __ARCH_WANT_SYS_FORK
#define __ARCH_WANT_SYS_VFORK
#define __ARCH_WANT_SYS_CLONE

/* "Conditional" syscalls. What we want is
Expand Down
4 changes: 2 additions & 2 deletions arch/alpha/kernel/binfmt_loader.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
#include <linux/binfmts.h>
#include <linux/a.out.h>

static int load_binary(struct linux_binprm *bprm, struct pt_regs *regs)
static int load_binary(struct linux_binprm *bprm)
{
struct exec *eh = (struct exec *)bprm->buf;
unsigned long loader;
Expand Down Expand Up @@ -37,7 +37,7 @@ static int load_binary(struct linux_binprm *bprm, struct pt_regs *regs)
retval = prepare_binprm(bprm);
if (retval < 0)
return retval;
return search_binary_handler(bprm,regs);
return search_binary_handler(bprm);
}

static struct linux_binfmt loader_format = {
Expand Down
51 changes: 12 additions & 39 deletions arch/alpha/kernel/entry.S
Original file line number Diff line number Diff line change
Expand Up @@ -612,47 +612,24 @@ ret_from_kernel_thread:
* Special system calls. Most of these are special in that they either
* have to play switch_stack games or in some way use the pt_regs struct.
*/
.align 4
.globl sys_fork
.ent sys_fork
sys_fork:
.prologue 0
mov $sp, $21
bsr $1, do_switch_stack
bis $31, SIGCHLD, $16
mov $31, $17
mov $31, $18
mov $31, $19
mov $31, $20
jsr $26, alpha_clone
bsr $1, undo_switch_stack
ret
.end sys_fork

.macro fork_like name
.align 4
.globl sys_clone
.ent sys_clone
sys_clone:
.globl alpha_\name
.ent alpha_\name
alpha_\name:
.prologue 0
mov $sp, $21
bsr $1, do_switch_stack
/* $16, $17, $18, $19, $20 come from the user. */
jsr $26, alpha_clone
bsr $1, undo_switch_stack
jsr $26, sys_\name
ldq $26, 56($sp)
lda $sp, SWITCH_STACK_SIZE($sp)
ret
.end sys_clone
.end alpha_\name
.endm

.align 4
.globl sys_vfork
.ent sys_vfork
sys_vfork:
.prologue 0
mov $sp, $16
bsr $1, do_switch_stack
jsr $26, alpha_vfork
bsr $1, undo_switch_stack
ret
.end sys_vfork
fork_like fork
fork_like vfork
fork_like clone

.align 4
.globl sys_sigreturn
Expand All @@ -661,8 +638,6 @@ sys_sigreturn:
.prologue 0
lda $9, ret_from_straced
cmpult $26, $9, $9
mov $sp, $17
lda $18, -SWITCH_STACK_SIZE($sp)
lda $sp, -SWITCH_STACK_SIZE($sp)
jsr $26, do_sigreturn
bne $9, 1f
Expand All @@ -678,8 +653,6 @@ sys_rt_sigreturn:
.prologue 0
lda $9, ret_from_straced
cmpult $26, $9, $9
mov $sp, $17
lda $18, -SWITCH_STACK_SIZE($sp)
lda $sp, -SWITCH_STACK_SIZE($sp)
jsr $26, do_rt_sigreturn
bne $9, 1f
Expand Down
62 changes: 14 additions & 48 deletions arch/alpha/kernel/process.c
Original file line number Diff line number Diff line change
Expand Up @@ -234,52 +234,29 @@ release_thread(struct task_struct *dead_task)
{
}

/*
* "alpha_clone()".. By the time we get here, the
* non-volatile registers have also been saved on the
* stack. We do some ugly pointer stuff here.. (see
* also copy_thread)
*
* Notice that "fork()" is implemented in terms of clone,
* with parameters (SIGCHLD, 0).
*/
int
alpha_clone(unsigned long clone_flags, unsigned long usp,
int __user *parent_tid, int __user *child_tid,
unsigned long tls_value, struct pt_regs *regs)
{
if (!usp)
usp = rdusp();

return do_fork(clone_flags, usp, regs, 0, parent_tid, child_tid);
}

int
alpha_vfork(struct pt_regs *regs)
{
return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(),
regs, 0, NULL, NULL);
}

/*
* Copy an alpha thread..
*/

int
copy_thread(unsigned long clone_flags, unsigned long usp,
unsigned long arg,
struct task_struct * p, struct pt_regs * regs)
struct task_struct *p)
{
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 = task_pt_regs(p);
struct pt_regs *regs = current_pt_regs();
struct switch_stack *childstack, *stack;
unsigned long settls;

childstack = ((struct switch_stack *) childregs) - 1;
if (unlikely(!regs)) {
childti->pcb.ksp = (unsigned long) childstack;
childti->pcb.flags = 1; /* set FEN, clear everything else */

if (unlikely(p->flags & PF_KTHREAD)) {
/* kernel thread */
memset(childstack, 0,
sizeof(struct switch_stack) + sizeof(struct pt_regs));
Expand All @@ -288,35 +265,24 @@ copy_thread(unsigned long clone_flags, unsigned long usp,
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;
}
/* Note: if CLONE_SETTLS is not set, then we must inherit the
value from the parent, which will have been set by the block
copy in dup_task_struct. This is non-intuitive, but is
required for proper operation in the case of a threaded
application calling fork. */
if (clone_flags & CLONE_SETTLS)
childti->pcb.unique = regs->r20;
childti->pcb.usp = usp ?: rdusp();
*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 = *stack;
childstack->r26 = (unsigned long) ret_from_fork;
childti->pcb.usp = usp;
childti->pcb.ksp = (unsigned long) childstack;
childti->pcb.flags = 1; /* set FEN, clear everything else */

/* Set a new TLS for the child thread? Peek back into the
syscall arguments that we saved on syscall entry. Oops,
except we'd have clobbered it with the parent/child set
of r20. Read the saved copy. */
/* Note: if CLONE_SETTLS is not set, then we must inherit the
value from the parent, which will have been set by the block
copy in dup_task_struct. This is non-intuitive, but is
required for proper operation in the case of a threaded
application calling fork. */
if (clone_flags & CLONE_SETTLS)
childti->pcb.unique = settls;

return 0;
}

Expand Down
16 changes: 8 additions & 8 deletions arch/alpha/kernel/signal.c
Original file line number Diff line number Diff line change
Expand Up @@ -160,10 +160,10 @@ extern char compile_time_assert
#define INSN_CALLSYS 0x00000083

static long
restore_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
struct switch_stack *sw)
restore_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs)
{
unsigned long usp;
struct switch_stack *sw = (struct switch_stack *)regs - 1;
long i, err = __get_user(regs->pc, &sc->sc_pc);

current_thread_info()->restart_block.fn = do_no_restart_syscall;
Expand Down Expand Up @@ -215,9 +215,9 @@ restore_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
registers and transfer control from userland. */

asmlinkage void
do_sigreturn(struct sigcontext __user *sc, struct pt_regs *regs,
struct switch_stack *sw)
do_sigreturn(struct sigcontext __user *sc)
{
struct pt_regs *regs = current_pt_regs();
sigset_t set;

/* Verify that it's a good sigcontext before using it */
Expand All @@ -228,7 +228,7 @@ do_sigreturn(struct sigcontext __user *sc, struct pt_regs *regs,

set_current_blocked(&set);

if (restore_sigcontext(sc, regs, sw))
if (restore_sigcontext(sc, regs))
goto give_sigsegv;

/* Send SIGTRAP if we're single-stepping: */
Expand All @@ -249,9 +249,9 @@ do_sigreturn(struct sigcontext __user *sc, struct pt_regs *regs,
}

asmlinkage void
do_rt_sigreturn(struct rt_sigframe __user *frame, struct pt_regs *regs,
struct switch_stack *sw)
do_rt_sigreturn(struct rt_sigframe __user *frame)
{
struct pt_regs *regs = current_pt_regs();
sigset_t set;

/* Verify that it's a good ucontext_t before using it */
Expand All @@ -262,7 +262,7 @@ do_rt_sigreturn(struct rt_sigframe __user *frame, struct pt_regs *regs,

set_current_blocked(&set);

if (restore_sigcontext(&frame->uc.uc_mcontext, regs, sw))
if (restore_sigcontext(&frame->uc.uc_mcontext, regs))
goto give_sigsegv;

/* Send SIGTRAP if we're single-stepping: */
Expand Down
6 changes: 3 additions & 3 deletions arch/alpha/kernel/systbls.S
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
sys_call_table:
.quad alpha_ni_syscall /* 0 */
.quad sys_exit
.quad sys_fork
.quad alpha_fork
.quad sys_read
.quad sys_write
.quad alpha_ni_syscall /* 5 */
Expand Down Expand Up @@ -76,7 +76,7 @@ sys_call_table:
.quad sys_getpgrp
.quad sys_getpagesize
.quad alpha_ni_syscall /* 65 */
.quad sys_vfork
.quad alpha_vfork
.quad sys_newstat
.quad sys_newlstat
.quad alpha_ni_syscall
Expand Down Expand Up @@ -330,7 +330,7 @@ sys_call_table:
.quad sys_ni_syscall /* 309: old get_kernel_syms */
.quad sys_syslog /* 310 */
.quad sys_reboot
.quad sys_clone
.quad alpha_clone
.quad sys_uselib
.quad sys_mlock
.quad sys_munlock /* 315 */
Expand Down
1 change: 1 addition & 0 deletions arch/arm/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ config ARM
select SYS_SUPPORTS_APM_EMULATION
select HAVE_MOD_ARCH_SPECIFIC if ARM_UNWIND
select MODULES_USE_ELF_REL
select CLONE_BACKWARDS
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
1 change: 0 additions & 1 deletion arch/arm/include/asm/signal.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,4 @@ struct k_sigaction {
};

#include <asm/sigcontext.h>
#define ptrace_signal_deliver(regs, cookie) do { } while (0)
#endif
3 changes: 3 additions & 0 deletions arch/arm/include/asm/unistd.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@
#define __ARCH_WANT_SYS_SOCKETCALL
#endif
#define __ARCH_WANT_SYS_EXECVE
#define __ARCH_WANT_SYS_FORK
#define __ARCH_WANT_SYS_VFORK
#define __ARCH_WANT_SYS_CLONE

/*
* "Conditional" syscalls
Expand Down
6 changes: 3 additions & 3 deletions arch/arm/kernel/calls.S
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
*/
/* 0 */ CALL(sys_restart_syscall)
CALL(sys_exit)
CALL(sys_fork_wrapper)
CALL(sys_fork)
CALL(sys_read)
CALL(sys_write)
/* 5 */ CALL(sys_open)
Expand Down Expand Up @@ -129,7 +129,7 @@
CALL(OBSOLETE(ABI(sys_ipc, sys_oabi_ipc)))
CALL(sys_fsync)
CALL(sys_sigreturn_wrapper)
/* 120 */ CALL(sys_clone_wrapper)
/* 120 */ CALL(sys_clone)
CALL(sys_setdomainname)
CALL(sys_newuname)
CALL(sys_ni_syscall) /* modify_ldt */
Expand Down Expand Up @@ -199,7 +199,7 @@
CALL(sys_sendfile)
CALL(sys_ni_syscall) /* getpmsg */
CALL(sys_ni_syscall) /* putpmsg */
/* 190 */ CALL(sys_vfork_wrapper)
/* 190 */ CALL(sys_vfork)
CALL(sys_getrlimit)
CALL(sys_mmap2)
CALL(ABI(sys_truncate64, sys_oabi_truncate64))
Expand Down
Loading

0 comments on commit 9977d9b

Please sign in to comment.