Skip to content

Commit 4e21fc1

Browse files
committed
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/signal
Pull third pile of kernel_execve() patches from Al Viro: "The last bits of infrastructure for kernel_thread() et.al., with alpha/arm/x86 use of those. Plus sanitizing the asm glue and do_notify_resume() on alpha, fixing the "disabled irq while running task_work stuff" breakage there. At that point the rest of kernel_thread/kernel_execve/sys_execve work can be done independently for different architectures. The only pending bits that do depend on having all architectures converted are restrictred to fs/* and kernel/* - that'll obviously have to wait for the next cycle. I thought we'd have to wait for all of them done before we start eliminating the longjump-style insanity in kernel_execve(), but it turned out there's a very simple way to do that without flagday-style changes." * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/signal: alpha: switch to saner kernel_execve() semantics arm: switch to saner kernel_execve() semantics x86, um: convert to saner kernel_execve() semantics infrastructure for saner ret_from_kernel_thread semantics make sure that kernel_thread() callbacks call do_exit() themselves make sure that we always have a return path from kernel_execve() ppc: eeh_event should just use kthread_run() don't bother with kernel_thread/kernel_execve for launching linuxrc alpha: get rid of switch_stack argument of do_work_pending() alpha: don't bother passing switch_stack separately from regs alpha: take SIGPENDING/NOTIFY_RESUME loop into signal.c alpha: simplify TIF_NEED_RESCHED handling
2 parents 8418263 + 5522be6 commit 4e21fc1

File tree

25 files changed

+137
-223
lines changed

25 files changed

+137
-223
lines changed

arch/Kconfig

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,9 @@ config ARCH_WANT_OLD_COMPAT_IPC
274274
config GENERIC_KERNEL_THREAD
275275
bool
276276

277+
config GENERIC_KERNEL_EXECVE
278+
bool
279+
277280
config HAVE_ARCH_SECCOMP_FILTER
278281
bool
279282
help

arch/alpha/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ config ALPHA
2121
select GENERIC_STRNCPY_FROM_USER
2222
select GENERIC_STRNLEN_USER
2323
select GENERIC_KERNEL_THREAD
24+
select GENERIC_KERNEL_EXECVE
2425
help
2526
The Alpha is a 64-bit general-purpose processor designed and
2627
marketed by the Digital Equipment Corporation of blessed memory,

arch/alpha/include/asm/unistd.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -482,7 +482,6 @@
482482
#define __ARCH_WANT_SYS_SIGPENDING
483483
#define __ARCH_WANT_SYS_RT_SIGSUSPEND
484484
#define __ARCH_WANT_SYS_EXECVE
485-
#define __ARCH_WANT_KERNEL_EXECVE
486485

487486
/* "Conditional" syscalls. What we want is
488487

arch/alpha/kernel/entry.S

Lines changed: 28 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,7 @@ entSys:
311311

312312
.align 4
313313
ret_from_sys_call:
314-
cmovne $26, 0, $19 /* $19 = 0 => non-restartable */
314+
cmovne $26, 0, $18 /* $18 = 0 => non-restartable */
315315
ldq $0, SP_OFF($sp)
316316
and $0, 8, $0
317317
beq $0, ret_to_kernel
@@ -320,8 +320,8 @@ ret_to_user:
320320
sampling and the rti. */
321321
lda $16, 7
322322
call_pal PAL_swpipl
323-
ldl $5, TI_FLAGS($8)
324-
and $5, _TIF_WORK_MASK, $2
323+
ldl $17, TI_FLAGS($8)
324+
and $17, _TIF_WORK_MASK, $2
325325
bne $2, work_pending
326326
restore_all:
327327
RESTORE_ALL
@@ -341,10 +341,10 @@ $syscall_error:
341341
* frame to indicate that a negative return value wasn't an
342342
* error number..
343343
*/
344-
ldq $19, 0($sp) /* old syscall nr (zero if success) */
345-
beq $19, $ret_success
344+
ldq $18, 0($sp) /* old syscall nr (zero if success) */
345+
beq $18, $ret_success
346346

347-
ldq $20, 72($sp) /* .. and this a3 */
347+
ldq $19, 72($sp) /* .. and this a3 */
348348
subq $31, $0, $0 /* with error in v0 */
349349
addq $31, 1, $1 /* set a3 for errno return */
350350
stq $0, 0($sp)
@@ -362,51 +362,35 @@ $ret_success:
362362
* Do all cleanup when returning from all interrupts and system calls.
363363
*
364364
* Arguments:
365-
* $5: TI_FLAGS.
366365
* $8: current.
367-
* $19: The old syscall number, or zero if this is not a return
366+
* $17: TI_FLAGS.
367+
* $18: The old syscall number, or zero if this is not a return
368368
* from a syscall that errored and is possibly restartable.
369-
* $20: The old a3 value
369+
* $19: The old a3 value
370370
*/
371371

372372
.align 4
373373
.ent work_pending
374374
work_pending:
375-
and $5, _TIF_NEED_RESCHED, $2
376-
beq $2, $work_notifysig
375+
and $17, _TIF_NOTIFY_RESUME | _TIF_SIGPENDING, $2
376+
bne $2, $work_notifysig
377377

378378
$work_resched:
379-
subq $sp, 16, $sp
380-
stq $19, 0($sp) /* save syscall nr */
381-
stq $20, 8($sp) /* and error indication (a3) */
379+
/*
380+
* We can get here only if we returned from syscall without SIGPENDING
381+
* or got through work_notifysig already. Either case means no syscall
382+
* restarts for us, so let $18 and $19 burn.
383+
*/
382384
jsr $26, schedule
383-
ldq $19, 0($sp)
384-
ldq $20, 8($sp)
385-
addq $sp, 16, $sp
386-
/* Make sure need_resched and sigpending don't change between
387-
sampling and the rti. */
388-
lda $16, 7
389-
call_pal PAL_swpipl
390-
ldl $5, TI_FLAGS($8)
391-
and $5, _TIF_WORK_MASK, $2
392-
beq $2, restore_all
393-
and $5, _TIF_NEED_RESCHED, $2
394-
bne $2, $work_resched
385+
mov 0, $18
386+
br ret_to_user
395387

396388
$work_notifysig:
397389
mov $sp, $16
398390
bsr $1, do_switch_stack
399-
mov $sp, $17
400-
mov $5, $18
401-
mov $19, $9 /* save old syscall number */
402-
mov $20, $10 /* save old a3 */
403-
and $5, _TIF_SIGPENDING, $2
404-
cmovne $2, 0, $9 /* we don't want double syscall restarts */
405-
jsr $26, do_notify_resume
406-
mov $9, $19
407-
mov $10, $20
391+
jsr $26, do_work_pending
408392
bsr $1, undo_switch_stack
409-
br ret_to_user
393+
br restore_all
410394
.end work_pending
411395

412396
/*
@@ -454,21 +438,21 @@ $strace_success:
454438

455439
.align 3
456440
$strace_error:
457-
ldq $19, 0($sp) /* old syscall nr (zero if success) */
458-
beq $19, $strace_success
459-
ldq $20, 72($sp) /* .. and this a3 */
441+
ldq $18, 0($sp) /* old syscall nr (zero if success) */
442+
beq $18, $strace_success
443+
ldq $19, 72($sp) /* .. and this a3 */
460444

461445
subq $31, $0, $0 /* with error in v0 */
462446
addq $31, 1, $1 /* set a3 for errno return */
463447
stq $0, 0($sp)
464448
stq $1, 72($sp) /* a3 for return */
465449

466450
bsr $1, do_switch_stack
467-
mov $19, $9 /* save old syscall number */
468-
mov $20, $10 /* save old a3 */
451+
mov $18, $9 /* save old syscall number */
452+
mov $19, $10 /* save old a3 */
469453
jsr $26, syscall_trace_leave
470-
mov $9, $19
471-
mov $10, $20
454+
mov $9, $18
455+
mov $10, $19
472456
bsr $1, undo_switch_stack
473457

474458
mov $31, $26 /* tell "ret_from_sys_call" we can restart */
@@ -619,24 +603,9 @@ ret_from_kernel_thread:
619603
mov $9, $27
620604
mov $10, $16
621605
jsr $26, ($9)
622-
ldgp $gp, 0($26)
623-
mov $0, $16
624-
mov $31, $26
625-
jmp $31, sys_exit
626-
.end ret_from_kernel_thread
627-
628-
.globl ret_from_kernel_execve
629-
.align 4
630-
.ent ret_from_kernel_execve
631-
ret_from_kernel_execve:
632-
mov $16, $sp
633-
/* Avoid the HAE being gratuitously wrong, to avoid restoring it. */
634-
ldq $2, alpha_mv+HAE_CACHE
635-
stq $2, 152($sp) /* HAE */
636606
mov $31, $19 /* to disable syscall restarts */
637607
br $31, ret_to_user
638-
639-
.end ret_from_kernel_execve
608+
.end ret_from_kernel_thread
640609

641610

642611
/*

arch/alpha/kernel/signal.c

Lines changed: 28 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -298,8 +298,9 @@ get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size)
298298

299299
static long
300300
setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
301-
struct switch_stack *sw, unsigned long mask, unsigned long sp)
301+
unsigned long mask, unsigned long sp)
302302
{
303+
struct switch_stack *sw = (struct switch_stack *)regs - 1;
303304
long i, err = 0;
304305

305306
err |= __put_user(on_sig_stack((unsigned long)sc), &sc->sc_onstack);
@@ -354,7 +355,7 @@ setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
354355

355356
static int
356357
setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
357-
struct pt_regs *regs, struct switch_stack * sw)
358+
struct pt_regs *regs)
358359
{
359360
unsigned long oldsp, r26, err = 0;
360361
struct sigframe __user *frame;
@@ -364,7 +365,7 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
364365
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
365366
return -EFAULT;
366367

367-
err |= setup_sigcontext(&frame->sc, regs, sw, set->sig[0], oldsp);
368+
err |= setup_sigcontext(&frame->sc, regs, set->sig[0], oldsp);
368369
if (err)
369370
return -EFAULT;
370371

@@ -401,7 +402,7 @@ setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
401402

402403
static int
403404
setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
404-
sigset_t *set, struct pt_regs *regs, struct switch_stack * sw)
405+
sigset_t *set, struct pt_regs *regs)
405406
{
406407
unsigned long oldsp, r26, err = 0;
407408
struct rt_sigframe __user *frame;
@@ -420,7 +421,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
420421
err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
421422
err |= __put_user(sas_ss_flags(oldsp), &frame->uc.uc_stack.ss_flags);
422423
err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
423-
err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, sw,
424+
err |= setup_sigcontext(&frame->uc.uc_mcontext, regs,
424425
set->sig[0], oldsp);
425426
err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
426427
if (err)
@@ -464,15 +465,15 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
464465
*/
465466
static inline void
466467
handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
467-
struct pt_regs * regs, struct switch_stack *sw)
468+
struct pt_regs * regs)
468469
{
469470
sigset_t *oldset = sigmask_to_save();
470471
int ret;
471472

472473
if (ka->sa.sa_flags & SA_SIGINFO)
473-
ret = setup_rt_frame(sig, ka, info, oldset, regs, sw);
474+
ret = setup_rt_frame(sig, ka, info, oldset, regs);
474475
else
475-
ret = setup_frame(sig, ka, oldset, regs, sw);
476+
ret = setup_frame(sig, ka, oldset, regs);
476477

477478
if (ret) {
478479
force_sigsegv(sig, current);
@@ -519,8 +520,7 @@ syscall_restart(unsigned long r0, unsigned long r19,
519520
* all (if we get here from anything but a syscall return, it will be 0)
520521
*/
521522
static void
522-
do_signal(struct pt_regs * regs, struct switch_stack * sw,
523-
unsigned long r0, unsigned long r19)
523+
do_signal(struct pt_regs *regs, unsigned long r0, unsigned long r19)
524524
{
525525
siginfo_t info;
526526
int signr;
@@ -537,7 +537,7 @@ do_signal(struct pt_regs * regs, struct switch_stack * sw,
537537
/* Whee! Actually deliver the signal. */
538538
if (r0)
539539
syscall_restart(r0, r19, regs, &ka);
540-
handle_signal(signr, &ka, &info, regs, sw);
540+
handle_signal(signr, &ka, &info, regs);
541541
if (single_stepping)
542542
ptrace_set_bpt(current); /* re-set bpt */
543543
return;
@@ -568,15 +568,23 @@ do_signal(struct pt_regs * regs, struct switch_stack * sw,
568568
}
569569

570570
void
571-
do_notify_resume(struct pt_regs *regs, struct switch_stack *sw,
572-
unsigned long thread_info_flags,
571+
do_work_pending(struct pt_regs *regs, unsigned long thread_flags,
573572
unsigned long r0, unsigned long r19)
574573
{
575-
if (thread_info_flags & _TIF_SIGPENDING)
576-
do_signal(regs, sw, r0, r19);
577-
578-
if (thread_info_flags & _TIF_NOTIFY_RESUME) {
579-
clear_thread_flag(TIF_NOTIFY_RESUME);
580-
tracehook_notify_resume(regs);
581-
}
574+
do {
575+
if (thread_flags & _TIF_NEED_RESCHED) {
576+
schedule();
577+
} else {
578+
local_irq_enable();
579+
if (thread_flags & _TIF_SIGPENDING) {
580+
do_signal(regs, r0, r19);
581+
r0 = 0;
582+
} else {
583+
clear_thread_flag(TIF_NOTIFY_RESUME);
584+
tracehook_notify_resume(regs);
585+
}
586+
}
587+
local_irq_disable();
588+
thread_flags = current_thread_info()->flags;
589+
} while (thread_flags & _TIF_WORK_MASK);
582590
}

arch/arm/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ config ARM
5353
select GENERIC_STRNLEN_USER
5454
select DCACHE_WORD_ACCESS if (CPU_V6 || CPU_V6K || CPU_V7) && !CPU_BIG_ENDIAN
5555
select GENERIC_KERNEL_THREAD
56+
select GENERIC_KERNEL_EXECVE
5657
help
5758
The ARM series is a line of low-power-consumption RISC chip designs
5859
licensed by ARM Ltd and targeted at embedded applications and

arch/arm/include/asm/unistd.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -479,7 +479,6 @@
479479
#define __ARCH_WANT_SYS_SOCKETCALL
480480
#endif
481481
#define __ARCH_WANT_SYS_EXECVE
482-
#define __ARCH_WANT_KERNEL_EXECVE
483482

484483
/*
485484
* "Conditional" syscalls

arch/arm/kernel/entry-common.S

Lines changed: 4 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -86,35 +86,14 @@ ENDPROC(ret_to_user)
8686
*/
8787
ENTRY(ret_from_fork)
8888
bl schedule_tail
89+
cmp r5, #0
90+
movne r0, r4
91+
movne lr, pc
92+
movne pc, r5
8993
get_thread_info tsk
90-
mov why, #1
9194
b ret_slow_syscall
9295
ENDPROC(ret_from_fork)
9396

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-
11897
.equ NR_syscalls,0
11998
#define CALL(x) .equ NR_syscalls,NR_syscalls+1
12099
#include "calls.S"

arch/arm/kernel/process.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -373,7 +373,6 @@ void release_thread(struct task_struct *dead_task)
373373
}
374374

375375
asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
376-
asmlinkage void ret_from_kernel_thread(void) __asm__("ret_from_kernel_thread");
377376

378377
int
379378
copy_thread(unsigned long clone_flags, unsigned long stack_start,
@@ -388,13 +387,13 @@ copy_thread(unsigned long clone_flags, unsigned long stack_start,
388387
*childregs = *regs;
389388
childregs->ARM_r0 = 0;
390389
childregs->ARM_sp = stack_start;
391-
thread->cpu_context.pc = (unsigned long)ret_from_fork;
392390
} else {
391+
memset(childregs, 0, sizeof(struct pt_regs));
393392
thread->cpu_context.r4 = stk_sz;
394393
thread->cpu_context.r5 = stack_start;
395-
thread->cpu_context.pc = (unsigned long)ret_from_kernel_thread;
396394
childregs->ARM_cpsr = SVC_MODE;
397395
}
396+
thread->cpu_context.pc = (unsigned long)ret_from_fork;
398397
thread->cpu_context.sp = (unsigned long)childregs;
399398

400399
clear_ptrace_hw_breakpoint(p);

0 commit comments

Comments
 (0)