示例#1
0
文件: signal.c 项目: 168519/linux
static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
			  struct pt_regs *regs)
{
	struct rt_sigframe __user *frame;
	unsigned long uc_flags, restorer;
	size_t frame_size;

	frame_size = sizeof(struct rt_sigframe) - sizeof(_sigregs_ext);
	/*
	 * gprs_high are only present for a 31-bit task running on
	 * a 64-bit kernel (see compat_signal.c) but the space for
	 * gprs_high need to be allocated if vector registers are
	 * included in the signal frame on a 31-bit system.
	 */
	uc_flags = 0;
#ifdef CONFIG_64BIT
	if (MACHINE_HAS_VX) {
		frame_size += sizeof(_sigregs_ext);
		if (current->thread.vxrs)
			uc_flags |= UC_VXRS;
	}
#endif
	frame = get_sigframe(&ksig->ka, regs, frame_size);
	if (frame == (void __user *) -1UL)
		return -EFAULT;

	/* Set up backchain. */
	if (__put_user(regs->gprs[15], (addr_t __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)
			ksig->ka.sa.sa_restorer | PSW_ADDR_AMODE;
	} else {
		__u16 __user *svc = &frame->svc_insn;
		if (__put_user(S390_SYSCALL_OPCODE | __NR_rt_sigreturn, svc))
			return -EFAULT;
		restorer = (unsigned long) svc | PSW_ADDR_AMODE;
	}

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

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

	/* Create ucontext on the signal stack. */
	if (__put_user(uc_flags, &frame->uc.uc_flags) ||
	    __put_user(NULL, &frame->uc.uc_link) ||
	    __save_altstack(&frame->uc.uc_stack, regs->gprs[15]) ||
	    save_sigregs(regs, &frame->uc.uc_mcontext) ||
	    __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)) ||
	    save_sigregs_ext(regs, &frame->uc.uc_mcontext_ext))
		return -EFAULT;

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

	regs->gprs[2] = map_signal(ksig->sig);
	regs->gprs[3] = (unsigned long) &frame->info;
	regs->gprs[4] = (unsigned long) &frame->uc;
	regs->gprs[5] = task_thread_info(current)->last_break;
	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;
}
示例#3
0
文件: signal.c 项目: 168519/linux
static int setup_frame(int sig, struct k_sigaction *ka,
		       sigset_t *set, struct pt_regs * regs)
{
	struct sigframe __user *frame;
	struct sigcontext sc;
	unsigned long restorer;
	size_t frame_size;

	/*
	 * gprs_high are only present for a 31-bit task running on
	 * a 64-bit kernel (see compat_signal.c) but the space for
	 * gprs_high need to be allocated if vector registers are
	 * included in the signal frame on a 31-bit system.
	 */
	frame_size = sizeof(*frame) - sizeof(frame->sregs_ext);
	if (MACHINE_HAS_VX)
		frame_size += sizeof(frame->sregs_ext);
	frame = get_sigframe(ka, regs, frame_size);
	if (frame == (void __user *) -1UL)
		return -EFAULT;

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

	/* Create struct sigcontext on the signal stack */
	memcpy(&sc.oldmask, &set->sig, _SIGMASK_COPY_SIZE);
	sc.sregs = (_sigregs __user __force *) &frame->sregs;
	if (__copy_to_user(&frame->sc, &sc, sizeof(frame->sc)))
		return -EFAULT;

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

	/* Create _sigregs on the signal stack */
	if (save_sigregs(regs, &frame->sregs))
		return -EFAULT;

	/* Place signal number on stack to allow backtrace from handler.  */
	if (__put_user(regs->gprs[2], (int __user *) &frame->signo))
		return -EFAULT;

	/* Create _sigregs_ext on the signal stack */
	if (save_sigregs_ext(regs, &frame->sregs_ext))
		return -EFAULT;

	/* Set up to return from userspace.  If provided, use a stub
	   already in userspace.  */
	if (ka->sa.sa_flags & SA_RESTORER) {
		restorer = (unsigned long) ka->sa.sa_restorer | PSW_ADDR_AMODE;
	} else {
		/* Signal frame without vector registers are short ! */
		__u16 __user *svc = (void __user *) frame + frame_size - 2;
		if (__put_user(S390_SYSCALL_OPCODE | __NR_sigreturn, svc))
			return -EFAULT;
		restorer = (unsigned long) svc | PSW_ADDR_AMODE;
	}

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

	regs->gprs[2] = map_signal(sig);
	regs->gprs[3] = (unsigned long) &frame->sc;

	/* We forgot to include these in the sigcontext.
	   To avoid breaking binary compatibility, they are passed as args. */
	if (sig == SIGSEGV || sig == SIGBUS || sig == SIGILL ||
	    sig == SIGTRAP || sig == SIGFPE) {
		/* set extra registers only for synchronous signals */
		regs->gprs[4] = regs->int_code & 127;
		regs->gprs[5] = regs->int_parm_long;
		regs->gprs[6] = task_thread_info(current)->last_break;
	}
	return 0;
}
static int setup_frame32(struct ksignal *ksig, sigset_t *set,
                         struct pt_regs *regs)
{
    int sig = ksig->sig;
    sigframe32 __user *frame;
    struct sigcontext32 sc;
    unsigned long restorer;
    size_t frame_size;

    /*
     * gprs_high are always present for 31-bit compat tasks.
     * The space for vector registers is only allocated if
     * the machine supports it
     */
    frame_size = sizeof(*frame) - sizeof(frame->sregs_ext.__reserved);
    if (!MACHINE_HAS_VX)
        frame_size -= sizeof(frame->sregs_ext.vxrs_low) +
                      sizeof(frame->sregs_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 __user *) frame))
        return -EFAULT;

    /* Create struct sigcontext32 on the signal stack */
    sigset_to_sigset32(set->sig, sc.oldmask);
    sc.sregs = (__u32)(unsigned long __force) &frame->sregs;
    if (__copy_to_user(&frame->sc, &sc, sizeof(frame->sc)))
        return -EFAULT;

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

    /* Create _sigregs32 on the signal stack */
    if (save_sigregs32(regs, &frame->sregs))
        return -EFAULT;

    /* Place signal number on stack to allow backtrace from handler.  */
    if (__put_user(regs->gprs[2], (int __force __user *) &frame->signo))
        return -EFAULT;

    /* Create _sigregs_ext32 on the signal stack */
    if (save_sigregs_ext32(regs, &frame->sregs_ext))
        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 {
        /* Signal frames without vectors registers are short ! */
        __u16 __user *svc = (void *) frame + frame_size - 2;
        if (__put_user(S390_SYSCALL_OPCODE | __NR_sigreturn, svc))
            return -EFAULT;
        restorer = (unsigned long __force) svc | PSW32_ADDR_AMODE;
    }

    /* 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 = (__force __u64) ksig->ka.sa.sa_handler;

    regs->gprs[2] = map_signal(sig);
    regs->gprs[3] = (__force __u64) &frame->sc;

    /* We forgot to include these in the sigcontext.
       To avoid breaking binary compatibility, they are passed as args. */
    if (sig == SIGSEGV || sig == SIGBUS || sig == SIGILL ||
            sig == SIGTRAP || sig == SIGFPE) {
        /* set extra registers only for synchronous signals */
        regs->gprs[4] = regs->int_code & 127;
        regs->gprs[5] = regs->int_parm_long;
        regs->gprs[6] = task_thread_info(current)->last_break;
    }

    return 0;
}