FreeBSD/sys/i386/linux/linux_sysvec.c
/*
 * System call to cleanup state after a signal
 * has been taken.  Reset signal mask and
 * stack state from context left by rt_sendsig (above).
 * Return to previous pc and psl as specified by
 * context left by sendsig. Check carefully to
 * make sure that the user has not modified the
 * psl to gain improper privileges or to cause
 * a machine fault.
 */
System call to cleanup state after a signal
has been taken.  Reset signal mask and
stack state from context left by rt_sendsig (above).
Return to previous pc and psl as specified by
context left by sendsig. Check carefully to
make sure that the user has not modified the
psl to gain improper privileges or to cause
a machine fault.
System call to cleanup state after a signal has been taken . Reset signal mask and stack state from context left by rt_sendsig ( above ) . Return to previous pc and psl as specified by context left by sendsig . Check carefully to make sure that the user has not modified the psl to gain improper privileges or to cause a machine fault .
int
linux_rt_sigreturn(struct thread *td, struct linux_rt_sigreturn_args *args)
{
	struct l_ucontext uc;
	struct l_sigcontext *context;
	sigset_t bmask;
	l_stack_t *lss;
	stack_t ss;
	struct trapframe *regs;
	int eflags;
	ksiginfo_t ksi;
	regs = td->td_frame;
#ifdef DEBUG
	if (ldebug(rt_sigreturn))
		printf(ARGS(rt_sigreturn, "%p"), (void *)args->ucp);
#endif
	if (copyin(args->ucp, &uc, sizeof(uc)) != 0)
		return (EFAULT);
	context = &uc.uc_mcontext;
#define	EFLAGS_SECURE(ef, oef)	((((ef) ^ (oef)) & ~PSL_USERCHANGE) == 0)
	eflags = context->sc_eflags;
	if (!EFLAGS_SECURE(eflags, regs->tf_eflags))
		return (EINVAL);
#define	CS_SECURE(cs)	(ISPL(cs) == SEL_UPL)
	if (!CS_SECURE(context->sc_cs)) {
		ksiginfo_init_trap(&ksi);
		ksi.ksi_signo = SIGBUS;
		ksi.ksi_code = BUS_OBJERR;
		ksi.ksi_trapno = T_PROTFLT;
		ksi.ksi_addr = (void *)regs->tf_eip;
		trapsignal(td, &ksi);
		return (EINVAL);
	}
	linux_to_bsd_sigset(&uc.uc_sigmask, &bmask);
	kern_sigprocmask(td, SIG_SETMASK, &bmask, NULL, 0);
	regs->tf_fs     = context->sc_fs;
	regs->tf_es     = context->sc_es;
	regs->tf_ds     = context->sc_ds;
	regs->tf_edi    = context->sc_edi;
	regs->tf_esi    = context->sc_esi;
	regs->tf_ebp    = context->sc_ebp;
	regs->tf_ebx    = context->sc_ebx;
	regs->tf_edx    = context->sc_edx;
	regs->tf_ecx    = context->sc_ecx;
	regs->tf_eax    = context->sc_eax;
	regs->tf_eip    = context->sc_eip;
	regs->tf_cs     = context->sc_cs;
	regs->tf_eflags = eflags;
	regs->tf_esp    = context->sc_esp_at_signal;
	regs->tf_ss     = context->sc_ss;
	lss = &uc.uc_stack;
	ss.ss_sp = lss->ss_sp;
	ss.ss_size = lss->ss_size;
	ss.ss_flags = linux_to_bsd_sigaltstack(lss->ss_flags);
#ifdef DEBUG
	if (ldebug(rt_sigreturn))
		printf(LMSG("rt_sigret flags: 0x%x, sp: %p, ss: 0x%x, mask: 0x%x"),
		    ss.ss_flags, ss.ss_sp, ss.ss_size, context->sc_mask);
#endif
	(void)kern_sigaltstack(td, &ss, NULL);
	return (EJUSTRETURN);
}
int linux_rt_sigreturn ( struct thread * td , struct linux_rt_sigreturn_args * args ) { struct l_ucontext uc ; struct l_sigcontext * context ; sigset_t bmask ; l_stack_t * lss ; stack_t ss ; struct trapframe * regs ; int eflags ; ksiginfo_t ksi ; regs = td -> td_frame ; #ifdef DEBUG if ( ldebug ( rt_sigreturn ) ) printf ( ARGS ( rt_sigreturn , " " ) , ( void * ) args -> ucp ) ; #endif if ( copyin ( args -> ucp , & uc , sizeof ( uc ) ) != 0 ) return ( EFAULT ) ; context = & uc . uc_mcontext ; #define EFLAGS_SECURE ( ef , oef ) 	((((ef) ^ (oef)) & ~PSL_USERCHANGE) == 0) eflags = context -> sc_eflags ; if ( ! EFLAGS_SECURE ( eflags , regs -> tf_eflags ) ) return ( EINVAL ) ; #define CS_SECURE ( cs ) 	(ISPL(cs) == SEL_UPL) if ( ! CS_SECURE ( context -> sc_cs ) ) { ksiginfo_init_trap ( & ksi ) ; ksi . ksi_signo = SIGBUS ; ksi . ksi_code = BUS_OBJERR ; ksi . ksi_trapno = T_PROTFLT ; ksi . ksi_addr = ( void * ) regs -> tf_eip ; trapsignal ( td , & ksi ) ; return ( EINVAL ) ; } linux_to_bsd_sigset ( & uc . uc_sigmask , & bmask ) ; kern_sigprocmask ( td , SIG_SETMASK , & bmask , NULL , 0 ) ; regs -> tf_fs = context -> sc_fs ; regs -> tf_es = context -> sc_es ; regs -> tf_ds = context -> sc_ds ; regs -> tf_edi = context -> sc_edi ; regs -> tf_esi = context -> sc_esi ; regs -> tf_ebp = context -> sc_ebp ; regs -> tf_ebx = context -> sc_ebx ; regs -> tf_edx = context -> sc_edx ; regs -> tf_ecx = context -> sc_ecx ; regs -> tf_eax = context -> sc_eax ; regs -> tf_eip = context -> sc_eip ; regs -> tf_cs = context -> sc_cs ; regs -> tf_eflags = eflags ; regs -> tf_esp = context -> sc_esp_at_signal ; regs -> tf_ss = context -> sc_ss ; lss = & uc . uc_stack ; ss . ss_sp = lss -> ss_sp ; ss . ss_size = lss -> ss_size ; ss . ss_flags = linux_to_bsd_sigaltstack ( lss -> ss_flags ) ; #ifdef DEBUG if ( ldebug ( rt_sigreturn ) ) printf ( LMSG ( " " ) , ss . ss_flags , ss . ss_sp , ss . ss_size , context -> sc_mask ) ; #endif ( void ) kern_sigaltstack ( td , & ss , NULL ) ; return ( EJUSTRETURN ) ; }
System call to cleanup state after a signal
 has been taken.
System call to cleanup state after a signal has been taken .
/*
	 * The trampoline code hands us the ucontext.
	 * It is unsafe to keep track of it ourselves, in the event that a
	 * program jumps out of a signal handler.
	 */ /*
	 * Check for security violations.
	 */ /*
	 * Don't allow users to load a valid privileged %cs.  Let the
	 * hardware check for invalid selectors, excess privilege in
	 * other selectors, invalid %eip's and invalid %esp's.
	 */ /*
	 * Restore signal context
	 */ /* %gs was restored by the trampoline. */ /*
	 * call sigaltstack & ignore results..
	 */