Exemplo n.º 1
0
static int setup_rt_frame32(int sig, struct k_sigaction *ka, siginfo_t *info,
			   sigset_t *set, struct pt_regs * regs)
{
	int err = 0;
	rt_sigframe32 __user *frame = get_sigframe(ka, regs, sizeof(rt_sigframe32));

	if (frame == (void __user *) -1UL)
		goto give_sigsegv;

	if (copy_siginfo_to_user32(&frame->info, info))
		goto give_sigsegv;

	/* Create the ucontext.  */
	err |= __put_user(UC_EXTENDED, &frame->uc.uc_flags);
	err |= __put_user(0, &frame->uc.uc_link);
	err |= __compat_save_altstack(&frame->uc.uc_stack, regs->gprs[15]);
	err |= save_sigregs32(regs, &frame->uc.uc_mcontext);
	err |= save_sigregs_gprs_high(regs, frame->gprs_high);
	err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
	if (err)
		goto give_sigsegv;

	/* Set up to return from userspace.  If provided, use a stub
	   already in userspace.  */
	if (ka->sa.sa_flags & SA_RESTORER) {
		regs->gprs[14] = (__u64 __force) ka->sa.sa_restorer | PSW32_ADDR_AMODE;
	} else {
		regs->gprs[14] = (__u64 __force) frame->retcode | PSW32_ADDR_AMODE;
		if (__put_user(S390_SYSCALL_OPCODE | __NR_rt_sigreturn,
			       (u16 __force __user *)(frame->retcode)))
			goto give_sigsegv;
	}

	/* Set up backchain. */
	if (__put_user(regs->gprs[15], (unsigned int __force __user *) frame))
		goto give_sigsegv;

	/* Set up registers for signal handler */
	regs->gprs[15] = (__force __u64) frame;
	/* Force 31 bit amode and default user address space control. */
	regs->psw.mask = PSW_MASK_BA |
		(PSW_USER_BITS & PSW_MASK_ASC) |
		(regs->psw.mask & ~PSW_MASK_ASC);
	regs->psw.addr = (__u64 __force) ka->sa.sa_handler;

	regs->gprs[2] = map_signal(sig);
	regs->gprs[3] = (__force __u64) &frame->info;
	regs->gprs[4] = (__force __u64) &frame->uc;
	regs->gprs[5] = task_thread_info(current)->last_break;
	return 0;

give_sigsegv:
	force_sigsegv(sig, current);
	return -EFAULT;
}
static int setup_rt_frame_32(void *sig_return, struct ksignal *ksig,
			     struct pt_regs *regs, sigset_t *set)
{
	struct rt_sigframe32 __user *frame;
	int err = 0;

	frame = get_sigframe(ksig, regs, sizeof(*frame));
	if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
		return -EFAULT;

	/* Convert (siginfo_t -> compat_siginfo_t) and copy to user. */
	err |= copy_siginfo_to_user32(&frame->rs_info, &ksig->info);

	/* Create the ucontext.	 */
	err |= __put_user(0, &frame->rs_uc.uc_flags);
	err |= __put_user(0, &frame->rs_uc.uc_link);
	err |= __compat_save_altstack(&frame->rs_uc.uc_stack, regs->regs[29]);
	err |= setup_sigcontext32(regs, &frame->rs_uc.uc_mcontext);
	err |= __copy_conv_sigset_to_user(&frame->rs_uc.uc_sigmask, set);

	if (err)
		return -EFAULT;

	/*
	 * Arguments to signal handler:
	 *
	 *   a0 = signal number
	 *   a1 = 0 (should be cause)
	 *   a2 = pointer to ucontext
	 *
	 * $25 and c0_epc point to the signal handler, $29 points to
	 * the struct rt_sigframe32.
	 */
	regs->regs[ 4] = ksig->sig;
	regs->regs[ 5] = (unsigned long) &frame->rs_info;
	regs->regs[ 6] = (unsigned long) &frame->rs_uc;
	regs->regs[29] = (unsigned long) frame;
	regs->regs[31] = (unsigned long) sig_return;
	regs->cp0_epc = regs->regs[25] = (unsigned long) ksig->ka.sa.sa_handler;

	DEBUGP("SIG deliver (%s:%d): sp=0x%p pc=0x%lx ra=0x%lx\n",
	       current->comm, current->pid,
	       frame, regs->cp0_epc, regs->regs[31]);

	return 0;
}
static int setup_rt_frame32(struct ksignal *ksig, sigset_t *set,
                            struct pt_regs *regs)
{
    compat_sigset_t cset;
    rt_sigframe32 __user *frame;
    unsigned long restorer;
    size_t frame_size;
    u32 uc_flags;

    frame_size = sizeof(*frame) -
                 sizeof(frame->uc.uc_mcontext_ext.__reserved);
    /*
     * gprs_high are always present for 31-bit compat tasks.
     * The space for vector registers is only allocated if
     * the machine supports it
     */
    uc_flags = UC_GPRS_HIGH;
    if (MACHINE_HAS_VX) {
        if (current->thread.vxrs)
            uc_flags |= UC_VXRS;
    } else
        frame_size -= sizeof(frame->uc.uc_mcontext_ext.vxrs_low) +
                      sizeof(frame->uc.uc_mcontext_ext.vxrs_high);
    frame = get_sigframe(&ksig->ka, regs, frame_size);
    if (frame == (void __user *) -1UL)
        return -EFAULT;

    /* Set up backchain. */
    if (__put_user(regs->gprs[15], (unsigned int __force __user *) frame))
        return -EFAULT;

    /* Set up to return from userspace.  If provided, use a stub
       already in userspace.  */
    if (ksig->ka.sa.sa_flags & SA_RESTORER) {
        restorer = (unsigned long __force)
                   ksig->ka.sa.sa_restorer | PSW32_ADDR_AMODE;
    } else {
        __u16 __user *svc = &frame->svc_insn;
        if (__put_user(S390_SYSCALL_OPCODE | __NR_rt_sigreturn, svc))
            return -EFAULT;
        restorer = (unsigned long __force) svc | PSW32_ADDR_AMODE;
    }

    /* Create siginfo on the signal stack */
    if (copy_siginfo_to_user32(&frame->info, &ksig->info))
        return -EFAULT;

    /* Store registers needed to create the signal frame */
    store_sigregs();

    /* Create ucontext on the signal stack. */
    sigset_to_sigset32(set->sig, cset.sig);
    if (__put_user(uc_flags, &frame->uc.uc_flags) ||
            __put_user(0, &frame->uc.uc_link) ||
            __compat_save_altstack(&frame->uc.uc_stack, regs->gprs[15]) ||
            save_sigregs32(regs, &frame->uc.uc_mcontext) ||
            __copy_to_user(&frame->uc.uc_sigmask, &cset, sizeof(cset)) ||
            save_sigregs_ext32(regs, &frame->uc.uc_mcontext_ext))
        return -EFAULT;

    /* Set up registers for signal handler */
    regs->gprs[14] = restorer;
    regs->gprs[15] = (__force __u64) frame;
    /* Force 31 bit amode and default user address space control. */
    regs->psw.mask = PSW_MASK_BA |
                     (PSW_USER_BITS & PSW_MASK_ASC) |
                     (regs->psw.mask & ~PSW_MASK_ASC);
    regs->psw.addr = (__u64 __force) ksig->ka.sa.sa_handler;

    regs->gprs[2] = map_signal(ksig->sig);
    regs->gprs[3] = (__force __u64) &frame->info;
    regs->gprs[4] = (__force __u64) &frame->uc;
    regs->gprs[5] = task_thread_info(current)->last_break;
    return 0;
}