Пример #1
0
/*
 * Determine which stack to use..
 */
static void __user *get_sigframe(struct ksignal *ksig, struct pt_regs *regs,
				 size_t frame_size,
				 void __user **fpstate)
{
	unsigned long sp;

	/* Default to using normal stack */
	sp = regs->sp;

	/* This is the X/Open sanctioned signal stack switching.  */
	if (ksig->ka.sa.sa_flags & SA_ONSTACK)
		sp = sigsp(sp, ksig);
	/* This is the legacy signal stack switching. */
	else if ((regs->ss & 0xffff) != __USER32_DS &&
		!(ksig->ka.sa.sa_flags & SA_RESTORER) &&
		 ksig->ka.sa.sa_restorer)
		sp = (unsigned long) ksig->ka.sa.sa_restorer;

	if (used_math()) {
		unsigned long fx_aligned, math_size;

		sp = alloc_mathframe(sp, 1, &fx_aligned, &math_size);
		*fpstate = (struct _fpstate_ia32 __user *) sp;
		if (save_xstate_sig(*fpstate, (void __user *)fx_aligned,
				    math_size) < 0)
			return (void __user *) -1L;
	}

	sp -= frame_size;
	/* Align the stack pointer according to the i386 ABI,
	 * i.e. so that on function entry ((sp + 4) & 15) == 0. */
	sp = ((sp - 12) & -16ul) - 4;
	return (void __user *) sp;
}
Пример #2
0
static inline void __user *
get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size,
	     void __user **fpstate)
{
	/* Default to using normal stack */
	unsigned long math_size = 0;
	unsigned long sp = regs->sp;
	unsigned long buf_fx = 0;
	int onsigstack = on_sig_stack(sp);

	/* redzone */
	if (config_enabled(CONFIG_X86_64))
		sp -= 128;

	if (!onsigstack) {
		/* This is the X/Open sanctioned signal stack switching.  */
		if (ka->sa.sa_flags & SA_ONSTACK) {
			if (current->sas_ss_size)
				sp = current->sas_ss_sp + current->sas_ss_size;
		} else if (config_enabled(CONFIG_X86_32) &&
			   (regs->ss & 0xffff) != __USER_DS &&
#ifdef CONFIG_KERNEL_MODE_LINUX
			   (regs->sp > TASK_SIZE) &&
#endif
			   !(ka->sa.sa_flags & SA_RESTORER) &&
			   ka->sa.sa_restorer) {
				/* This is the legacy signal stack switching. */
				sp = (unsigned long) ka->sa.sa_restorer;
		}
	}

	if (used_math()) {
		sp = alloc_mathframe(sp, config_enabled(CONFIG_X86_32),
				     &buf_fx, &math_size);
		*fpstate = (void __user *)sp;
	}

	sp = align_sigframe(sp - frame_size);

	/*
	 * If we are on the alternate signal stack and would overflow it, don't.
	 * Return an always-bogus address instead so we will die with SIGSEGV.
	 */
	if (onsigstack && !likely(on_sig_stack(sp)))
		return (void __user *)-1L;

	/* save i387 and extended state */
	if (used_math() &&
	    save_xstate_sig(*fpstate, (void __user *)buf_fx, math_size) < 0)
		return (void __user *)-1L;

	return (void __user *)sp;
}