/* * The OSF/1 sigprocmask calling sequence is different from the * C sigprocmask() sequence..
*/
SYSCALL_DEFINE2(osf_sigprocmask, int, how, unsignedlong, newmask)
{
sigset_t oldmask;
sigset_t mask; unsignedlong res;
siginitset(&mask, newmask & _BLOCKABLE);
res = sigprocmask(how, &mask, &oldmask); if (!res) {
force_successful_syscall_return();
res = oldmask.sig[0];
} return res;
}
/* If this changes, userland unwinders that Know Things about our signal frame will break. Do not undertake lightly. It also implies an ABI
change wrt the size of siginfo_t, which may cause some pain. */ externchar compile_time_assert
[offsetof(struct rt_sigframe, uc.uc_mcontext) == 176 ? 1 : -1];
/* Note that this syscall is also used by setcontext(3) to install a given sigcontext. This because it's impossible to set *all*
registers and transfer control from userland. */
/* Verify that it's a good sigcontext before using it */ if (!access_ok(sc, sizeof(*sc))) goto give_sigsegv; if (__get_user(set.sig[0], &sc->sc_mask)) goto give_sigsegv;
set_current_blocked(&set);
if (restore_sigcontext(sc, regs)) goto give_sigsegv;
/* Send SIGTRAP if we're single-stepping: */ if (ptrace_cancel_bpt (current)) {
send_sig_fault(SIGTRAP, TRAP_BRKPT, (void __user *) regs->pc,
current);
} return;
/* Verify that it's a good ucontext_t before using it */ if (!access_ok(&frame->uc, sizeof(frame->uc))) goto give_sigsegv; if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) goto give_sigsegv;
set_current_blocked(&set);
if (restore_sigcontext(&frame->uc.uc_mcontext, regs)) goto give_sigsegv;
/* Send SIGTRAP if we're single-stepping: */ if (ptrace_cancel_bpt (current)) {
send_sig_fault(SIGTRAP, TRAP_BRKPT, (void __user *) regs->pc,
current);
} return;
err |= setup_sigcontext(&frame->sc, regs, set->sig[0], oldsp); if (err) return -EFAULT;
/* Set up to return from userspace. If provided, use a stub
already in userspace. */
r26 = (unsignedlong) ksig->ka.ka_restorer; if (!r26) {
err |= __put_user(INSN_MOV_R30_R16, frame->retcode+0);
err |= __put_user(INSN_LDI_R0+__NR_sigreturn, frame->retcode+1);
err |= __put_user(INSN_CALLSYS, frame->retcode+2);
imb();
r26 = (unsignedlong) frame->retcode;
}
/* Check that everything was written properly. */ if (err) return err;
/* Set up to return from userspace. If provided, use a stub
already in userspace. */
r26 = (unsignedlong) ksig->ka.ka_restorer; if (!r26) {
err |= __put_user(INSN_MOV_R30_R16, frame->retcode+0);
err |= __put_user(INSN_LDI_R0+__NR_rt_sigreturn,
frame->retcode+1);
err |= __put_user(INSN_CALLSYS, frame->retcode+2);
imb();
r26 = (unsignedlong) frame->retcode;
}
if (ksig->ka.sa.sa_flags & SA_SIGINFO)
ret = setup_rt_frame(ksig, oldset, regs); else
ret = setup_frame(ksig, oldset, regs);
signal_setup_done(ret, ksig, 0);
}
staticinlinevoid
syscall_restart(unsignedlong r0, unsignedlong r19, struct pt_regs *regs, struct k_sigaction *ka)
{ switch (regs->r0) { case ERESTARTSYS: if (!(ka->sa.sa_flags & SA_RESTART)) { case ERESTARTNOHAND:
regs->r0 = EINTR; break;
}
fallthrough; case ERESTARTNOINTR:
regs->r0 = r0; /* reset v0 and a3 and replay syscall */
regs->r19 = r19;
regs->pc -= 4; break; case ERESTART_RESTARTBLOCK:
regs->r0 = EINTR; break;
}
}
/* * Note that 'init' is a special process: it doesn't get signals it doesn't * want to handle. Thus you cannot kill init even with a SIGKILL even by * mistake. * * Note that we go through the signals twice: once to check the signals that * the kernel can handle, and then we build all the user-level signal handling * stack-frames in one go after that. * * "r0" and "r19" are the registers we need to restore for system call * restart. "r0" is also used as an indicator whether we can restart at * all (if we get here from anything but a syscall return, it will be 0)
*/ staticvoid
do_signal(struct pt_regs *regs, unsignedlong r0, unsignedlong r19)
{ unsignedlong single_stepping = ptrace_cancel_bpt(current); struct ksignal ksig;
/* This lets the debugger run, ... */ if (get_signal(&ksig)) { /* ... so re-check the single stepping. */
single_stepping |= ptrace_cancel_bpt(current); /* Whee! Actually deliver the signal. */ if (r0)
syscall_restart(r0, r19, regs, &ksig.ka);
handle_signal(&ksig, regs);
} else {
single_stepping |= ptrace_cancel_bpt(current); if (r0) { switch (regs->r0) { case ERESTARTNOHAND: case ERESTARTSYS: case ERESTARTNOINTR: /* Reset v0 and a3 and replay syscall. */
regs->r0 = r0;
regs->r19 = r19;
regs->pc -= 4; break; case ERESTART_RESTARTBLOCK: /* Set v0 to the restart_syscall and replay */
regs->r0 = __NR_restart_syscall;
regs->pc -= 4; break;
}
}
restore_saved_sigmask();
} if (single_stepping)
ptrace_set_bpt(current); /* re-set breakpoint */
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.