Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/signal
Pull pile 2 of execve and kernel_thread unification work from Al Viro: "Stuff in there: kernel_thread/kernel_execve/sys_execve conversions for several more architectures plus assorted signal fixes and cleanups. There'll be more (in particular, real fixes for the alpha do_notify_resume() irq mess)..." * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/signal: (43 commits) alpha: don't open-code trace_report_syscall_{enter,exit} Uninclude linux/freezer.h m32r: trim masks avr32: trim masks tile: don't bother with SIGTRAP in setup_frame microblaze: don't bother with SIGTRAP in setup_rt_frame() mn10300: don't bother with SIGTRAP in setup_frame() frv: no need to raise SIGTRAP in setup_frame() x86: get rid of duplicate code in case of CONFIG_VM86 unicore32: remove pointless test h8300: trim _TIF_WORK_MASK parisc: decide whether to go to slow path (tracesys) based on thread flags parisc: don't bother looping in do_signal() parisc: fix double restarts bury the rest of TIF_IRET sanitize tsk_is_polling() bury _TIF_RESTORE_SIGMASK unicore32: unobfuscate _TIF_WORK_MASK mips: NOTIFY_RESUME is not needed in TIF masks mips: merge the identical "return from syscall" per-ABI code ... Conflicts: arch/arm/include/asm/thread_info.h
This commit is contained in:
@@ -113,6 +113,8 @@ sys_rt_sigreturn(struct pt_regs *regs, int in_syscall)
|
||||
(usp - sigframe_size);
|
||||
DBG(2,"sys_rt_sigreturn: frame is %p\n", frame);
|
||||
|
||||
regs->orig_r28 = 1; /* no restarts for sigreturn */
|
||||
|
||||
#ifdef CONFIG_64BIT
|
||||
compat_frame = (struct compat_rt_sigframe __user *)frame;
|
||||
|
||||
@@ -437,7 +439,7 @@ give_sigsegv:
|
||||
* OK, we're invoking a handler.
|
||||
*/
|
||||
|
||||
static long
|
||||
static void
|
||||
handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
|
||||
struct pt_regs *regs, int in_syscall)
|
||||
{
|
||||
@@ -447,7 +449,7 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
|
||||
|
||||
/* Set up the stack frame */
|
||||
if (!setup_rt_frame(sig, ka, info, oldset, regs, in_syscall))
|
||||
return 0;
|
||||
return;
|
||||
|
||||
signal_delivered(sig, info, ka, regs,
|
||||
test_thread_flag(TIF_SINGLESTEP) ||
|
||||
@@ -455,13 +457,14 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
|
||||
|
||||
DBG(1,KERN_DEBUG "do_signal: Exit (success), regs->gr[28] = %ld\n",
|
||||
regs->gr[28]);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline void
|
||||
syscall_restart(struct pt_regs *regs, struct k_sigaction *ka)
|
||||
{
|
||||
if (regs->orig_r28)
|
||||
return;
|
||||
regs->orig_r28 = 1; /* no more restarts */
|
||||
/* Check the return code */
|
||||
switch (regs->gr[28]) {
|
||||
case -ERESTART_RESTARTBLOCK:
|
||||
@@ -482,8 +485,6 @@ syscall_restart(struct pt_regs *regs, struct k_sigaction *ka)
|
||||
* we have to do is fiddle the return pointer.
|
||||
*/
|
||||
regs->gr[31] -= 8; /* delayed branching */
|
||||
/* Preserve original r28. */
|
||||
regs->gr[28] = regs->orig_r28;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -491,6 +492,9 @@ syscall_restart(struct pt_regs *regs, struct k_sigaction *ka)
|
||||
static inline void
|
||||
insert_restart_trampoline(struct pt_regs *regs)
|
||||
{
|
||||
if (regs->orig_r28)
|
||||
return;
|
||||
regs->orig_r28 = 1; /* no more restarts */
|
||||
switch(regs->gr[28]) {
|
||||
case -ERESTART_RESTARTBLOCK: {
|
||||
/* Restart the system call - no handlers present */
|
||||
@@ -525,9 +529,6 @@ insert_restart_trampoline(struct pt_regs *regs)
|
||||
flush_user_icache_range(regs->gr[30], regs->gr[30] + 4);
|
||||
|
||||
regs->gr[31] = regs->gr[30] + 8;
|
||||
/* Preserve original r28. */
|
||||
regs->gr[28] = regs->orig_r28;
|
||||
|
||||
return;
|
||||
}
|
||||
case -ERESTARTNOHAND:
|
||||
@@ -539,9 +540,6 @@ insert_restart_trampoline(struct pt_regs *regs)
|
||||
* slot of the branch external instruction.
|
||||
*/
|
||||
regs->gr[31] -= 8;
|
||||
/* Preserve original r28. */
|
||||
regs->gr[28] = regs->orig_r28;
|
||||
|
||||
return;
|
||||
}
|
||||
default:
|
||||
@@ -570,30 +568,17 @@ do_signal(struct pt_regs *regs, long in_syscall)
|
||||
DBG(1,"\ndo_signal: regs=0x%p, sr7 %#lx, in_syscall=%d\n",
|
||||
regs, regs->sr[7], in_syscall);
|
||||
|
||||
/* Everyone else checks to see if they are in kernel mode at
|
||||
this point and exits if that's the case. I'm not sure why
|
||||
we would be called in that case, but for some reason we
|
||||
are. */
|
||||
|
||||
/* May need to force signal if handle_signal failed to deliver */
|
||||
while (1) {
|
||||
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
|
||||
DBG(3,"do_signal: signr = %d, regs->gr[28] = %ld\n", signr, regs->gr[28]);
|
||||
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
|
||||
DBG(3,"do_signal: signr = %d, regs->gr[28] = %ld\n", signr, regs->gr[28]);
|
||||
|
||||
if (signr <= 0)
|
||||
break;
|
||||
|
||||
if (signr > 0) {
|
||||
/* Restart a system call if necessary. */
|
||||
if (in_syscall)
|
||||
syscall_restart(regs, &ka);
|
||||
|
||||
/* Whee! Actually deliver the signal. If the
|
||||
delivery failed, we need to continue to iterate in
|
||||
this loop so we can deliver the SIGSEGV... */
|
||||
if (handle_signal(signr, &info, &ka, regs, in_syscall))
|
||||
return;
|
||||
handle_signal(signr, &info, &ka, regs, in_syscall);
|
||||
return;
|
||||
}
|
||||
/* end of while(1) looping forever if we can't force a signal */
|
||||
|
||||
/* Did we come from a system call? */
|
||||
if (in_syscall)
|
||||
|
@@ -156,7 +156,7 @@ linux_gateway_entry:
|
||||
STREG %r26, TASK_PT_GR26(%r1) /* 1st argument */
|
||||
STREG %r27, TASK_PT_GR27(%r1) /* user dp */
|
||||
STREG %r28, TASK_PT_GR28(%r1) /* return value 0 */
|
||||
STREG %r28, TASK_PT_ORIG_R28(%r1) /* return value 0 (saved for signals) */
|
||||
STREG %r0, TASK_PT_ORIG_R28(%r1) /* don't prohibit restarts */
|
||||
STREG %r29, TASK_PT_GR29(%r1) /* return value 1 */
|
||||
STREG %r31, TASK_PT_GR31(%r1) /* preserve syscall return ptr */
|
||||
|
||||
@@ -180,9 +180,10 @@ linux_gateway_entry:
|
||||
|
||||
/* Are we being ptraced? */
|
||||
mfctl %cr30, %r1
|
||||
LDREG TI_TASK(%r1),%r1
|
||||
ldw TASK_PTRACE(%r1), %r1
|
||||
bb,<,n %r1,31,.Ltracesys
|
||||
LDREG TI_FLAGS(%r1),%r1
|
||||
ldi _TIF_SYSCALL_TRACE_MASK, %r19
|
||||
and,COND(=) %r1, %r19, %r0
|
||||
b,n .Ltracesys
|
||||
|
||||
/* Note! We cannot use the syscall table that is mapped
|
||||
nearby since the gateway page is mapped execute-only. */
|
||||
|
Reference in New Issue
Block a user