#include <linux/stddef.h>
#include <linux/tty.h>
#include <linux/binfmts.h>
+#include <linux/bitops.h>
-#include <asm/bitops.h>
#include <asm/uaccess.h>
#include <asm/sigcontext.h>
#include <asm/ucontext.h>
* operation, as all of this is local to this thread.
*/
asmlinkage unsigned long
-osf_sigprocmask(int how, unsigned long newmask, long a2, long a3,
- long a4, long a5, struct pt_regs regs)
+do_osf_sigprocmask(int how, unsigned long newmask, struct pt_regs *regs)
{
unsigned long oldmask = -EINVAL;
recalc_sigpending();
spin_unlock_irq(¤t->sighand->siglock);
- (®s)->r0 = 0; /* special no error return */
+ regs->r0 = 0; /* special no error return */
}
return oldmask;
}
if (act) {
old_sigset_t mask;
- if (verify_area(VERIFY_READ, act, sizeof(*act)) ||
+ if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
__get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
__get_user(new_ka.sa.sa_flags, &act->sa_flags))
return -EFAULT;
ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
if (!ret && oact) {
- if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||
+ if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
__put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
__put_user(old_ka.sa.sa_flags, &oact->sa_flags))
return -EFAULT;
* Atomically swap in the new signal mask, and wait for a signal.
*/
asmlinkage int
-do_sigsuspend(old_sigset_t mask, struct pt_regs *reg, struct switch_stack *sw)
+do_sigsuspend(old_sigset_t mask, struct pt_regs *regs, struct switch_stack *sw)
{
sigset_t oldset;
recalc_sigpending();
spin_unlock_irq(¤t->sighand->siglock);
+ /* Indicate EINTR on return from any possible signal handler,
+ which will not come back through here, but via sigreturn. */
+ regs->r0 = EINTR;
+ regs->r19 = 1;
+
while (1) {
current->state = TASK_INTERRUPTIBLE;
schedule();
- if (do_signal(&oldset, reg, sw, 0, 0))
+ if (do_signal(&oldset, regs, sw, 0, 0))
return -EINTR;
}
}
asmlinkage int
do_rt_sigsuspend(sigset_t __user *uset, size_t sigsetsize,
- struct pt_regs *reg, struct switch_stack *sw)
+ struct pt_regs *regs, struct switch_stack *sw)
{
sigset_t oldset, set;
recalc_sigpending();
spin_unlock_irq(¤t->sighand->siglock);
+ /* Indicate EINTR on return from any possible signal handler,
+ which will not come back through here, but via sigreturn. */
+ regs->r0 = EINTR;
+ regs->r19 = 1;
+
while (1) {
current->state = TASK_INTERRUPTIBLE;
schedule();
- if (do_signal(&oldset, reg, sw, 0, 0))
+ if (do_signal(&oldset, regs, sw, 0, 0))
return -EINTR;
}
}
unsigned int retcode[3];
};
+/* 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. */
+extern char compile_time_assert
+ [offsetof(struct rt_sigframe, uc.uc_mcontext) == 176 ? 1 : -1];
+
#define INSN_MOV_R30_R16 0x47fe0410
#define INSN_LDI_R0 0x201f0000
#define INSN_CALLSYS 0x00000083
sigset_t set;
/* Verify that it's a good sigcontext before using it */
- if (verify_area(VERIFY_READ, sc, sizeof(*sc)))
+ if (!access_ok(VERIFY_READ, sc, sizeof(*sc)))
goto give_sigsegv;
if (__get_user(set.sig[0], &sc->sc_mask))
goto give_sigsegv;
sigset_t set;
/* Verify that it's a good ucontext_t before using it */
- if (verify_area(VERIFY_READ, &frame->uc, sizeof(frame->uc)))
+ if (!access_ok(VERIFY_READ, &frame->uc, sizeof(frame->uc)))
goto give_sigsegv;
if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
goto give_sigsegv;
static inline void __user *
get_sigframe(struct k_sigaction *ka, unsigned long sp, size_t frame_size)
{
- if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! on_sig_stack(sp))
+ if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! sas_ss_flags(sp))
sp = current->sas_ss_sp + current->sas_ss_size;
return (void __user *)((sp - frame_size) & -32ul);
oldsp = rdusp();
frame = get_sigframe(ka, oldsp, sizeof(*frame));
- if (verify_area(VERIFY_WRITE, frame, sizeof(*frame)))
+ if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
goto give_sigsegv;
err |= setup_sigcontext(&frame->sc, regs, sw, set->sig[0], oldsp);
return;
give_sigsegv:
- if (sig == SIGSEGV)
- ka->sa.sa_handler = SIG_DFL;
- force_sig(SIGSEGV, current);
+ force_sigsegv(sig, current);
}
static void
oldsp = rdusp();
frame = get_sigframe(ka, oldsp, sizeof(*frame));
- if (verify_area(VERIFY_WRITE, frame, sizeof(*frame)))
+ if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
goto give_sigsegv;
err |= copy_siginfo_to_user(&frame->info, info);
return;
give_sigsegv:
- if (sig == SIGSEGV)
- ka->sa.sa_handler = SIG_DFL;
- force_sig(SIGSEGV, current);
+ force_sigsegv(sig, current);
}
if (ka->sa.sa_flags & SA_RESETHAND)
ka->sa.sa_handler = SIG_DFL;
- if (!(ka->sa.sa_flags & SA_NODEFER)) {
- spin_lock_irq(¤t->sighand->siglock);
- sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask);
+ spin_lock_irq(¤t->sighand->siglock);
+ sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask);
+ if (!(ka->sa.sa_flags & SA_NODEFER))
sigaddset(¤t->blocked,sig);
- recalc_sigpending();
- spin_unlock_irq(¤t->sighand->siglock);
- }
+ recalc_sigpending();
+ spin_unlock_irq(¤t->sighand->siglock);
}
static inline void
siginfo_t info;
int signr;
unsigned long single_stepping = ptrace_cancel_bpt(current);
+ struct k_sigaction ka;
if (!oldset)
oldset = ¤t->blocked;
/* This lets the debugger run, ... */
- signr = get_signal_to_deliver(&info, regs, NULL);
+ signr = get_signal_to_deliver(&info, &ka, regs, NULL);
/* ... so re-check the single stepping. */
single_stepping |= ptrace_cancel_bpt(current);
if (signr > 0) {
/* Whee! Actually deliver the signal. */
- struct k_sigaction *ka = ¤t->sighand->action[signr-1];
-
- if (r0) syscall_restart(r0, r19, regs, ka);
- handle_signal(signr, ka, &info, oldset, regs, sw);
+ if (r0) syscall_restart(r0, r19, regs, &ka);
+ handle_signal(signr, &ka, &info, oldset, regs, sw);
if (single_stepping)
ptrace_set_bpt(current); /* re-set bpt */
return 1;