Esempio n. 1
0
int setup_signal_stack_si(unsigned long stack_top, int sig,
			  struct k_sigaction *ka, struct pt_regs *regs,
			  siginfo_t *info, sigset_t *mask)
{
	struct rt_sigframe __user *frame;
	void __user *restorer;
	unsigned long save_sp = PT_REGS_SP(regs);
	int err = 0;

	stack_top &= -8UL;
	frame = (struct rt_sigframe __user *) stack_top - 1;
	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
		return 1;

	restorer = frame->retcode;
	if(ka->sa.sa_flags & SA_RESTORER)
		restorer = ka->sa.sa_restorer;

	/* See comment above about why this is here */
	PT_REGS_SP(regs) = (unsigned long) frame;

	err |= __put_user(restorer, &frame->pretcode);
	err |= __put_user(sig, &frame->sig);
	err |= __put_user(&frame->info, &frame->pinfo);
	err |= __put_user(&frame->uc, &frame->puc);
	err |= copy_siginfo_to_user(&frame->info, info);
	err |= copy_ucontext_to_user(&frame->uc, &frame->fpstate, mask,
				     save_sp);

	/*
	 * This is movl $,%eax ; int $0x80
	 *
	 * WE DO NOT USE IT ANY MORE! It's only left here for historical
	 * reasons and because gdb uses it as a signature to notice
	 * signal handler stack frames.
	 */
	err |= __put_user(0xb8, (char __user *)(frame->retcode+0));
	err |= __put_user(__NR_rt_sigreturn, (int __user *)(frame->retcode+1));
	err |= __put_user(0x80cd, (short __user *)(frame->retcode+5));

	if(err)
		goto err;

	PT_REGS_IP(regs) = (unsigned long) ka->sa.sa_handler;
	PT_REGS_EAX(regs) = (unsigned long) sig;
	PT_REGS_EDX(regs) = (unsigned long) &frame->info;
	PT_REGS_ECX(regs) = (unsigned long) &frame->uc;

	if ((current->ptrace & PT_DTRACE) && (current->ptrace & PT_PTRACED))
		ptrace_notify(SIGTRAP);
	return 0;

err:
	PT_REGS_SP(regs) = save_sp;
	return err;
}
Esempio n. 2
0
long sys_sigreturn(struct pt_regs regs)
{
	unsigned long sp = PT_REGS_SP(&current->thread.regs);
	struct sigframe __user *frame = (struct sigframe __user *)(sp - 8);
	sigset_t set;
	struct sigcontext __user *sc = &frame->sc;
	unsigned long __user *oldmask = &sc->oldmask;
	unsigned long __user *extramask = frame->extramask;
	int sig_size = (_NSIG_WORDS - 1) * sizeof(unsigned long);

	if(copy_from_user(&set.sig[0], oldmask, sizeof(set.sig[0])) ||
	   copy_from_user(&set.sig[1], extramask, sig_size))
		goto segfault;

	sigdelsetmask(&set, ~_BLOCKABLE);

	spin_lock_irq(&current->sighand->siglock);
	current->blocked = set;
	recalc_sigpending();
	spin_unlock_irq(&current->sighand->siglock);

	if(copy_sc_from_user(&current->thread.regs, sc))
		goto segfault;

	/* Avoid ERESTART handling */
	PT_REGS_SYSCALL_NR(&current->thread.regs) = -1;
	return PT_REGS_SYSCALL_RET(&current->thread.regs);

 segfault:
	force_sig(SIGSEGV, current);
	return 0;
}
Esempio n. 3
0
long sys_rt_sigreturn(struct pt_regs regs)
{
	unsigned long sp = PT_REGS_SP(&current->thread.regs);
	struct rt_sigframe __user *frame = (struct rt_sigframe __user *) (sp - 4);
	sigset_t set;
	struct ucontext __user *uc = &frame->uc;
	int sig_size = _NSIG_WORDS * sizeof(unsigned long);

	if(copy_from_user(&set, &uc->uc_sigmask, sig_size))
		goto segfault;

	sigdelsetmask(&set, ~_BLOCKABLE);

	spin_lock_irq(&current->sighand->siglock);
	current->blocked = set;
	recalc_sigpending();
	spin_unlock_irq(&current->sighand->siglock);

	if(copy_sc_from_user(&current->thread.regs, &uc->uc_mcontext))
		goto segfault;

	/* Avoid ERESTART handling */
	PT_REGS_SYSCALL_NR(&current->thread.regs) = -1;
	return PT_REGS_SYSCALL_RET(&current->thread.regs);

 segfault:
	force_sig(SIGSEGV, current);
	return 0;
}
Esempio n. 4
0
int sys_sigreturn(struct pt_regs regs)
{
	void *sc = sp_to_sc(PT_REGS_SP(&current->thread.regs));
	void *mask = sp_to_mask(PT_REGS_SP(&current->thread.regs));
	int sig_size = (_NSIG_WORDS - 1) * sizeof(unsigned long);

	spin_lock_irq(&current->sighand->siglock);
	copy_from_user(&current->blocked.sig[0], sc_sigmask(sc), 
		       sizeof(current->blocked.sig[0]));
	copy_from_user(&current->blocked.sig[1], mask, sig_size);
	sigdelsetmask(&current->blocked, ~_BLOCKABLE);
	recalc_sigpending();
	spin_unlock_irq(&current->sighand->siglock);
	copy_sc_from_user(&current->thread.regs, sc, 
			  &signal_frame_sc.common.arch);
	return(PT_REGS_SYSCALL_RET(&current->thread.regs));
}
Esempio n. 5
0
void show_trace_task(struct task_struct *tsk)
{
	unsigned long esp = PT_REGS_SP(&tsk->thread.regs);

	/* User space on another CPU? */
	if ((esp ^ (unsigned long)tsk) & (PAGE_MASK<<1))
		return;
	show_trace((unsigned long *)esp);
}
Esempio n. 6
0
void start_thread_tt(struct pt_regs *regs, unsigned long eip, 
		     unsigned long esp)
{
	set_fs(USER_DS);
	flush_tlb_mm(current->mm);
	PT_REGS_IP(regs) = eip;
	PT_REGS_SP(regs) = esp;
	PT_FIX_EXEC_STACK(esp);
}
Esempio n. 7
0
void start_thread(struct pt_regs *regs, unsigned long eip, unsigned long esp)
{
	PT_REGS_IP(regs) = eip;
	PT_REGS_SP(regs) = esp;
	current->ptrace &= ~PT_DTRACE;
#ifdef SUBARCH_EXECVE1
	SUBARCH_EXECVE1(regs->regs);
#endif
}
Esempio n. 8
0
int setup_signal_stack_si(unsigned long stack_top, int sig, 
			  struct k_sigaction *ka, struct pt_regs *regs,
			  siginfo_t *info, sigset_t *mask)
{
	unsigned long start;
	void *restorer;
	void *sip, *ucp, *fp;

	start = stack_top - signal_frame_si.common.len;
	sip = (void *) (start + signal_frame_si.si_index);
	ucp = (void *) (start + signal_frame_si.uc_index);
	fp = (void *) (((unsigned long) ucp) + sizeof(struct ucontext));

	restorer = NULL;
	if(ka->sa.sa_flags & SA_RESTORER)
		restorer = ka->sa.sa_restorer;

	if(restorer == NULL)
		panic("setup_signal_stack_si - no restorer");

	if(copy_to_user((void *) start, signal_frame_si.common.data,
			signal_frame_si.common.len) ||
	   copy_to_user((void *) (start + signal_frame_si.common.sig_index), 
			&sig, sizeof(sig)) ||
	   copy_siginfo_to_user(sip, info) ||
	   copy_to_user((void *) (start + signal_frame_si.sip_index), &sip,
			sizeof(sip)) ||
	   copy_ucontext_to_user(ucp, fp, mask, PT_REGS_SP(regs)) ||
	   copy_to_user((void *) (start + signal_frame_si.ucp_index), &ucp,
			sizeof(ucp)) ||
	   copy_restorer(restorer, start, signal_frame_si.common.sr_index,
			 signal_frame_si.common.sr_relative))
		return(1);
	
	PT_REGS_IP(regs) = (unsigned long) ka->sa.sa_handler;
	PT_REGS_SP(regs) = start + signal_frame_si.common.sp_index;
	return(0);
}
/*
 * OK, we're invoking a handler
 */
static int handle_signal(struct pt_regs *regs, unsigned long signr,
			 struct k_sigaction *ka, siginfo_t *info,
			 sigset_t *oldset)
{
	unsigned long sp;
	int err;

	/* Always make any pending restarted system calls return -EINTR */
	current_thread_info()->restart_block.fn = do_no_restart_syscall;

	/* Did we come from a system call? */
	if (PT_REGS_SYSCALL_NR(regs) >= 0) {
		/* If so, check system call restarting.. */
		switch (PT_REGS_SYSCALL_RET(regs)) {
		case -ERESTART_RESTARTBLOCK:
		case -ERESTARTNOHAND:
			PT_REGS_SYSCALL_RET(regs) = -EINTR;
			break;

		case -ERESTARTSYS:
			if (!(ka->sa.sa_flags & SA_RESTART)) {
				PT_REGS_SYSCALL_RET(regs) = -EINTR;
				break;
			}
		/* fallthrough */
		case -ERESTARTNOINTR:
			PT_REGS_RESTART_SYSCALL(regs);
			PT_REGS_ORIG_SYSCALL(regs) = PT_REGS_SYSCALL_NR(regs);
			break;
		}
	}

	sp = PT_REGS_SP(regs);
	if ((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags(sp) == 0))
		sp = current->sas_ss_sp + current->sas_ss_size;

#ifdef CONFIG_ARCH_HAS_SC_SIGNALS
	if (!(ka->sa.sa_flags & SA_SIGINFO))
		err = setup_signal_stack_sc(sp, signr, ka, regs, oldset);
	else
#endif
		err = setup_signal_stack_si(sp, signr, ka, regs, info, oldset);

	if (err)
		force_sigsegv(signr, current);
	else
		block_sigmask(ka, signr);

	return err;
}
Esempio n. 10
0
int setup_signal_stack_sc(unsigned long stack_top, int sig,
			  struct k_sigaction *ka, struct pt_regs *regs,
			  sigset_t *mask)
{
	struct sigframe __user *frame;
	void *restorer;
	int err = 0;

	stack_top &= -8UL;
	frame = (struct sigframe *) stack_top - 1;
	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
		return 1;

	restorer = (void *) frame->retcode;
	if(ka->sa.sa_flags & SA_RESTORER)
		restorer = ka->sa.sa_restorer;

	err |= __put_user(restorer, &frame->pretcode);
	err |= __put_user(sig, &frame->sig);
	err |= copy_sc_to_user(&frame->sc, NULL, regs);
	err |= __put_user(mask->sig[0], &frame->sc.oldmask);
	if (_NSIG_WORDS > 1)
		err |= __copy_to_user(&frame->extramask, &mask->sig[1],
				      sizeof(frame->extramask));

	/*
	 * This is popl %eax ; movl $,%eax ; int $0x80
	 *
	 * WE DO NOT USE IT ANY MORE! It's only left here for historical
	 * reasons and because gdb uses it as a signature to notice
	 * signal handler stack frames.
	 */
	err |= __put_user(0xb858, (short __user *)(frame->retcode+0));
	err |= __put_user(__NR_sigreturn, (int __user *)(frame->retcode+2));
	err |= __put_user(0x80cd, (short __user *)(frame->retcode+6));

	if(err)
		return(err);

	PT_REGS_SP(regs) = (unsigned long) frame;
	PT_REGS_IP(regs) = (unsigned long) ka->sa.sa_handler;
	PT_REGS_EAX(regs) = (unsigned long) sig;
	PT_REGS_EDX(regs) = (unsigned long) 0;
	PT_REGS_ECX(regs) = (unsigned long) 0;

	if ((current->ptrace & PT_DTRACE) && (current->ptrace & PT_PTRACED))
		ptrace_notify(SIGTRAP);
	return(0);
}
Esempio n. 11
0
int sys_rt_sigreturn(struct pt_regs regs)
{
	struct ucontext *uc = sp_to_uc(PT_REGS_SP(&current->thread.regs));
	void *fp;
	int sig_size = _NSIG_WORDS * sizeof(unsigned long);

	spin_lock_irq(&current->sighand->siglock);
	copy_from_user(&current->blocked, &uc->uc_sigmask, sig_size);
	sigdelsetmask(&current->blocked, ~_BLOCKABLE);
	recalc_sigpending();
	spin_unlock_irq(&current->sighand->siglock);
	fp = (void *) (((unsigned long) uc) + sizeof(struct ucontext));
	copy_sc_from_user(&current->thread.regs, &uc->uc_mcontext,
			  &signal_frame_si.common.arch);
	return(PT_REGS_SYSCALL_RET(&current->thread.regs));
}
Esempio n. 12
0
/*
 * OK, we're invoking a handler
 */
static void handle_signal(struct pt_regs *regs, unsigned long signr,
			 struct k_sigaction *ka, siginfo_t *info)
{
	sigset_t *oldset = sigmask_to_save();
	unsigned long sp;
	int err;

	/* Did we come from a system call? */
	if (PT_REGS_SYSCALL_NR(regs) >= 0) {
		/* If so, check system call restarting.. */
		switch (PT_REGS_SYSCALL_RET(regs)) {
		case -ERESTART_RESTARTBLOCK:
		case -ERESTARTNOHAND:
			PT_REGS_SYSCALL_RET(regs) = -EINTR;
			break;

		case -ERESTARTSYS:
			if (!(ka->sa.sa_flags & SA_RESTART)) {
				PT_REGS_SYSCALL_RET(regs) = -EINTR;
				break;
			}
		/* fallthrough */
		case -ERESTARTNOINTR:
			PT_REGS_RESTART_SYSCALL(regs);
			PT_REGS_ORIG_SYSCALL(regs) = PT_REGS_SYSCALL_NR(regs);
			break;
		}
	}

	sp = PT_REGS_SP(regs);
	if ((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags(sp) == 0))
		sp = current->sas_ss_sp + current->sas_ss_size;

#ifdef CONFIG_ARCH_HAS_SC_SIGNALS
	if (!(ka->sa.sa_flags & SA_SIGINFO))
		err = setup_signal_stack_sc(sp, signr, ka, regs, oldset);
	else
#endif
		err = setup_signal_stack_si(sp, signr, ka, regs, info, oldset);

	if (err)
		force_sigsegv(signr, current);
	else
		signal_delivered(signr, info, ka, regs, 0);
}
Esempio n. 13
0
int setup_signal_stack_sc(unsigned long stack_top, int sig, 
			  struct k_sigaction *ka, struct pt_regs *regs,
			  sigset_t *mask)
{
	struct frame_common *frame = &signal_frame_sc_sr.common;
	void *restorer;
	void *user_sc;
	int sig_size = (_NSIG_WORDS - 1) * sizeof(unsigned long);
	unsigned long sigs, sr;
	unsigned long start = stack_top - frame->len - sig_size;

	restorer = NULL;
	if(ka->sa.sa_flags & SA_RESTORER)
		restorer = ka->sa.sa_restorer;

	user_sc = (void *) (start + signal_frame_sc_sr.sc_index);
	if(restorer == NULL){
		frame = &signal_frame_sc.common;
		user_sc = (void *) (start + signal_frame_sc.sc_index);
		sr = (unsigned long) frame->data;
		sr += frame->sr_index;
		sr = *((unsigned long *) sr);
		restorer = ((void (*)(void)) sr);
	}

	sigs = start + frame->len;
	if(copy_to_user((void *) start, frame->data, frame->len) ||
	   copy_to_user((void *) (start + frame->sig_index), &sig, 
			sizeof(sig)) ||
	   copy_sc_to_user(user_sc, NULL, regs, 
			   &signal_frame_sc.common.arch) ||
	   copy_to_user(sc_sigmask(user_sc), mask, sizeof(mask->sig[0])) ||
	   copy_to_user((void *) sigs, &mask->sig[1], sig_size) ||
	   copy_restorer(restorer, start, frame->sr_index, frame->sr_relative))
		return(1);

	PT_REGS_IP(regs) = (unsigned long) ka->sa.sa_handler;
	PT_REGS_SP(regs) = start + frame->sp_index;

	return(0);
}
Esempio n. 14
0
void __show_regs(struct pt_regs *regs)
{
	printk("\n");
	print_modules();
	printk(KERN_INFO "Pid: %d, comm: %.20s %s %s\n", task_pid_nr(current),
		current->comm, print_tainted(), init_utsname()->release);
	printk(KERN_INFO "RIP: %04lx:[<%016lx>]\n", PT_REGS_CS(regs) & 0xffff,
	       PT_REGS_IP(regs));
	printk(KERN_INFO "RSP: %016lx  EFLAGS: %08lx\n", PT_REGS_SP(regs),
	       PT_REGS_EFLAGS(regs));
	printk(KERN_INFO "RAX: %016lx RBX: %016lx RCX: %016lx\n",
	       PT_REGS_AX(regs), PT_REGS_BX(regs), PT_REGS_CX(regs));
	printk(KERN_INFO "RDX: %016lx RSI: %016lx RDI: %016lx\n",
	       PT_REGS_DX(regs), PT_REGS_SI(regs), PT_REGS_DI(regs));
	printk(KERN_INFO "RBP: %016lx R08: %016lx R09: %016lx\n",
	       PT_REGS_BP(regs), PT_REGS_R8(regs), PT_REGS_R9(regs));
	printk(KERN_INFO "R10: %016lx R11: %016lx R12: %016lx\n",
	       PT_REGS_R10(regs), PT_REGS_R11(regs), PT_REGS_R12(regs));
	printk(KERN_INFO "R13: %016lx R14: %016lx R15: %016lx\n",
	       PT_REGS_R13(regs), PT_REGS_R14(regs), PT_REGS_R15(regs));
}
long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss)
{
	return do_sigaltstack(uss, uoss, PT_REGS_SP(&current->thread.regs));
}
Esempio n. 16
0
void start_thread(struct pt_regs *regs, unsigned long eip, unsigned long esp)
{
	PT_REGS_IP(regs) = eip;
	PT_REGS_SP(regs) = esp;
}
Esempio n. 17
0
/*
 * OK, we're invoking a handler
 */	
static int handle_signal(struct pt_regs *regs, unsigned long signr, 
			 struct k_sigaction *ka, siginfo_t *info, 
			 sigset_t *oldset, int error)
{
        __sighandler_t handler;
	void (*restorer)(void);
	unsigned long sp;
	sigset_t save;
	int err, ret;

	ret = 0;
	switch(error){
	case -ERESTART_RESTARTBLOCK:
		current_thread_info()->restart_block.fn = 
			do_no_restart_syscall;
	case -ERESTARTNOHAND:
		ret = -EINTR;
		break;

	case -ERESTARTSYS:
		if (!(ka->sa.sa_flags & SA_RESTART)) {
			ret = -EINTR;
			break;
		}
		/* fallthrough */
	case -ERESTARTNOINTR:
		PT_REGS_RESTART_SYSCALL(regs);
		PT_REGS_ORIG_SYSCALL(regs) = PT_REGS_SYSCALL_NR(regs);

		/* This is because of the UM_SET_SYSCALL_RETURN and the fact
		 * that on i386 the system call number and return value are
		 * in the same register.  When the system call restarts, %eax
		 * had better have the system call number in it.  Since the
		 * return value doesn't matter (except that it shouldn't be
		 * -ERESTART*), we'll stick the system call number there.
		 */
		ret = PT_REGS_SYSCALL_NR(regs);
		break;
	}

	handler = ka->sa.sa_handler;
	save = *oldset;

	if (ka->sa.sa_flags & SA_ONESHOT)
		ka->sa.sa_handler = SIG_DFL;

	if (!(ka->sa.sa_flags & SA_NODEFER)) {
		spin_lock_irq(&current->sighand->siglock);
		sigorsets(&current->blocked, &current->blocked, 
			  &ka->sa.sa_mask);
		sigaddset(&current->blocked, signr);
		recalc_sigpending();
		spin_unlock_irq(&current->sighand->siglock);
	}

	sp = PT_REGS_SP(regs);

	if((ka->sa.sa_flags & SA_ONSTACK) && (sas_ss_flags(sp) == 0))
		sp = current->sas_ss_sp + current->sas_ss_size;
	
	if(error != 0) PT_REGS_SET_SYSCALL_RETURN(regs, ret);

	if (ka->sa.sa_flags & SA_RESTORER) restorer = ka->sa.sa_restorer;
	else restorer = NULL;

	if(ka->sa.sa_flags & SA_SIGINFO)
		err = setup_signal_stack_si(sp, signr, (unsigned long) handler,
					    restorer, regs, info, &save);
	else
		err = setup_signal_stack_sc(sp, signr, (unsigned long) handler,
					    restorer, regs, &save);
	if(err) goto segv;

	return(0);
 segv:
	force_segv(signr);
	return(1);
}
Esempio n. 18
0
int setup_signal_stack_si(unsigned long stack_top, int sig,
			  struct k_sigaction *ka, struct pt_regs * regs,
			  siginfo_t *info, sigset_t *set)
{
	struct rt_sigframe __user *frame;
	struct _fpstate __user *fp = NULL;
	int err = 0;
	struct task_struct *me = current;

	frame = (struct rt_sigframe __user *)
		round_down(stack_top - sizeof(struct rt_sigframe), 16) - 8;
        frame = (struct rt_sigframe *) ((unsigned long) frame - 128);

	if (!access_ok(VERIFY_WRITE, fp, sizeof(struct _fpstate)))
		goto out;

#if 0 /* XXX */
	if (save_i387(fp) < 0)
		err |= -1;
#endif
	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
		goto out;

	if (ka->sa.sa_flags & SA_SIGINFO) {
		err |= copy_siginfo_to_user(&frame->info, info);
		if (err)
			goto out;
	}

	/* Create the ucontext.  */
	err |= __put_user(0, &frame->uc.uc_flags);
	err |= __put_user(0, &frame->uc.uc_link);
	err |= __put_user(me->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
	err |= __put_user(sas_ss_flags(PT_REGS_SP(regs)),
			  &frame->uc.uc_stack.ss_flags);
	err |= __put_user(me->sas_ss_size, &frame->uc.uc_stack.ss_size);
	err |= copy_sc_to_user(&frame->uc.uc_mcontext, fp, regs, set->sig[0]);
	err |= __put_user(fp, &frame->uc.uc_mcontext.fpstate);
	if (sizeof(*set) == 16) {
		__put_user(set->sig[0], &frame->uc.uc_sigmask.sig[0]);
		__put_user(set->sig[1], &frame->uc.uc_sigmask.sig[1]);
	}
	else
		err |= __copy_to_user(&frame->uc.uc_sigmask, set,
				      sizeof(*set));

	/* Set up to return from userspace.  If provided, use a stub
	   already in userspace.  */
	/* x86-64 should always use SA_RESTORER. */
	if (ka->sa.sa_flags & SA_RESTORER)
		err |= __put_user(ka->sa.sa_restorer, &frame->pretcode);
	else
		/* could use a vstub here */
		goto out;

	if (err)
		goto out;

	/* Set up registers for signal handler */
	{
		struct exec_domain *ed = current_thread_info()->exec_domain;
		if (unlikely(ed && ed->signal_invmap && sig < 32))
			sig = ed->signal_invmap[sig];
	}

	PT_REGS_RDI(regs) = sig;
	/* In case the signal handler was declared without prototypes */
	PT_REGS_RAX(regs) = 0;

	/* This also works for non SA_SIGINFO handlers because they expect the
	   next argument after the signal number on the stack. */
	PT_REGS_RSI(regs) = (unsigned long) &frame->info;
	PT_REGS_RDX(regs) = (unsigned long) &frame->uc;
	PT_REGS_RIP(regs) = (unsigned long) ka->sa.sa_handler;

	PT_REGS_RSP(regs) = (unsigned long) frame;
 out:
	return(err);
}
Esempio n. 19
0
int setup_signal_stack_sc(unsigned long stack_top, int sig,
			  struct k_sigaction *ka, struct pt_regs *regs,
			  sigset_t *mask)
{
	struct sigframe __user *frame;
	void __user *restorer;
	unsigned long save_sp = PT_REGS_SP(regs);
	int err = 0;

	/* This is the same calculation as i386 - ((sp + 4) & 15) == 0 */
	stack_top = ((stack_top + 4) & -16UL) - 4;
	frame = (struct sigframe __user *) stack_top - 1;
	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
		return 1;

	restorer = frame->retcode;
	if(ka->sa.sa_flags & SA_RESTORER)
		restorer = ka->sa.sa_restorer;

	/* Update SP now because the page fault handler refuses to extend
	 * the stack if the faulting address is too far below the current
	 * SP, which frame now certainly is.  If there's an error, the original
	 * value is restored on the way out.
	 * When writing the sigcontext to the stack, we have to write the
	 * original value, so that's passed to copy_sc_to_user, which does
	 * the right thing with it.
	 */
	PT_REGS_SP(regs) = (unsigned long) frame;

	err |= __put_user(restorer, &frame->pretcode);
	err |= __put_user(sig, &frame->sig);
	err |= copy_sc_to_user(&frame->sc, NULL, regs, save_sp);
	err |= __put_user(mask->sig[0], &frame->sc.oldmask);
	if (_NSIG_WORDS > 1)
		err |= __copy_to_user(&frame->extramask, &mask->sig[1],
				      sizeof(frame->extramask));

	/*
	 * This is popl %eax ; movl $,%eax ; int $0x80
	 *
	 * WE DO NOT USE IT ANY MORE! It's only left here for historical
	 * reasons and because gdb uses it as a signature to notice
	 * signal handler stack frames.
	 */
	err |= __put_user(0xb858, (short __user *)(frame->retcode+0));
	err |= __put_user(__NR_sigreturn, (int __user *)(frame->retcode+2));
	err |= __put_user(0x80cd, (short __user *)(frame->retcode+6));

	if(err)
		goto err;

	PT_REGS_SP(regs) = (unsigned long) frame;
	PT_REGS_IP(regs) = (unsigned long) ka->sa.sa_handler;
	PT_REGS_EAX(regs) = (unsigned long) sig;
	PT_REGS_EDX(regs) = (unsigned long) 0;
	PT_REGS_ECX(regs) = (unsigned long) 0;

	if ((current->ptrace & PT_DTRACE) && (current->ptrace & PT_PTRACED))
		ptrace_notify(SIGTRAP);
	return 0;

err:
	PT_REGS_SP(regs) = save_sp;
	return err;
}