Пример #1
0
int sigaction( int sig, const struct sigaction *act, struct sigaction *oact )
{
	struct sigaction tmp, *my_act = &tmp;

	if( act ) {
		*my_act = *act;
	} else {
		my_act = NULL;
	}

	if ( MappingFileDescriptors() && act ) {		/* called by User code */
		switch (sig) {
			case SIGUSR2:
			case SIGTSTP:
			case SIGCONT: /* don't let user code mess with these signals */
				errno = EINVAL;
				return -1;
			default: /* block checkpointing inside users signal handler */
				sigaddset( &(my_act->sa_mask), SIGTSTP );
				sigaddset( &(my_act->sa_mask), SIGUSR2 );
		}
	}

	return SIGACTION( sig, my_act, oact);
}
Пример #2
0
static void
sendsig_siginfo(const ksiginfo_t *ksi, const sigset_t *mask)
{
	struct lwp *l = curlwp;
	struct proc *p = l->l_proc;
	struct sigacts *ps = p->p_sigacts;
	struct trapframe *tf = l->l_md.md_regs;
	int sig = ksi->ksi_signo, error;
	sig_t catcher = SIGACTION(p, sig).sa_handler;
	struct sigframe_siginfo *fp, frame;
	int onstack;

	switch (ps->sa_sigdesc[sig].sd_vers) {
	case 0:		/* FALLTHROUGH */ /* handled by sendsig_sigcontext */
	case 1:		/* FALLTHROUGH */ /* handled by sendsig_sigcontext */
	default:	/* unknown version */
		printf("sendsig_siginfo: bad version %d\n",
		       ps->sa_sigdesc[sig].sd_vers);
		sigexit(l, SIGILL);
		/* NOTREACHED */
	case 2:
		break;
	}

	fp = getframe(l, sig, &onstack);
	--fp;

	frame.sf_si._info = ksi->ksi_info;
	frame.sf_uc.uc_link = l->l_ctxlink;
	frame.sf_uc.uc_sigmask = *mask;
	frame.sf_uc.uc_flags = _UC_SIGMASK;
	frame.sf_uc.uc_flags |= (l->l_sigstk.ss_flags & SS_ONSTACK)
		? _UC_SETSTACK : _UC_CLRSTACK;
	memset(&frame.sf_uc.uc_stack, 0, sizeof(frame.sf_uc.uc_stack));
	sendsig_reset(l, sig);
	mutex_exit(p->p_lock);
	cpu_getmcontext(l, &frame.sf_uc.uc_mcontext, &frame.sf_uc.uc_flags);
	error = copyout(&frame, fp, sizeof(frame));
	mutex_enter(p->p_lock);

	if (error != 0) {
		/*
		 * Process has trashed its stack; give it an illegal
		 * instruction to halt it in its tracks.
		 */
		sigexit(l, SIGILL);
		/* NOTREACHED */
	}

	tf->tf_r4 = sig;		/* "signum" argument for handler */
	tf->tf_r5 = (int)&fp->sf_si;	/* "sip" argument for handler */
	tf->tf_r6 = (int)&fp->sf_uc;	/* "ucp" argument for handler */
 	tf->tf_spc = (int)catcher;
	tf->tf_r15 = (int)fp;
	tf->tf_pr = (int)ps->sa_sigdesc[sig].sd_tramp;

	/* Remember if we're now on the signal stack. */
	if (onstack)
		l->l_sigstk.ss_flags |= SS_ONSTACK;
}
Пример #3
0
int
wmain(int argc, wchar_t *argv[])
{
	STARTW(argc, argv, "vmem_create_win");

	if (argc < 2 || argc > 3)
		UT_FATAL("usage: %s directory", ut_toUTF8(argv[0]));

	Vmp = vmem_createW(argv[1], VMEM_MIN_POOL);

	if (Vmp == NULL)
		UT_OUT("!vmem_create");
	else {
		struct sigaction v;
		sigemptyset(&v.sa_mask);
		v.sa_flags = 0;
		v.sa_handler = signal_handler;
		if (SIGACTION(SIGSEGV, &v, NULL) != 0)
			UT_FATAL("!sigaction");

		/* try to dereference the opaque handle */
		char x = *(char *)Vmp;
		UT_OUT("x = %c", x);
	}

	UT_FATAL("no signal received");
}
Пример #4
0
void
linux_sendsig(const ksiginfo_t *ksi, const sigset_t *mask)
{
	if (SIGACTION(curproc, ksi->ksi_signo).sa_flags & SA_SIGINFO)
		linux_rt_sendsig(ksi, mask);
	else
		linux_old_sendsig(ksi, mask);
}
Пример #5
0
/*
 * Send a signal to process.
 */
void
sendsig_siginfo(const ksiginfo_t *ksi, const sigset_t *mask)
{
	struct lwp * const l = curlwp;
	struct proc * const p = l->l_proc;
	struct sigacts * const sa = p->p_sigacts;
	struct trapframe * const tf = l->l_md.md_utf;
	const int signo = ksi->ksi_signo;
	const sig_t catcher = SIGACTION(p, signo).sa_handler;
	bool onstack;
	struct COMPATNAME2(sigframe_siginfo) *sf =
	    cpu_sendsig_getframe(l, signo, &onstack);
	struct COMPATNAME2(sigframe_siginfo) ksf;

	sf--;		// allocate sigframe

	COPY_SIGINFO(&ksf, ksi);
	ksf.sf_uc.uc_flags = _UC_SIGMASK
	    | (l->l_sigstk.ss_flags & SS_ONSTACK ? _UC_SETSTACK : _UC_CLRSTACK);
	ksf.sf_uc.uc_sigmask = *mask;
	UCLINK_SET(&ksf.sf_uc, l->l_ctxlink);
	memset(&ksf.sf_uc.uc_stack, 0, sizeof(ksf.sf_uc.uc_stack));
	sendsig_reset(l, signo);

	mutex_exit(p->p_lock);
	COMPATNAME2(cpu_getmcontext)(l, &ksf.sf_uc.uc_mcontext,
	     &ksf.sf_uc.uc_flags);
	int error = copyout(&ksf, sf, sizeof(ksf));
	mutex_enter(p->p_lock);

	if (error != 0) {
		/*
		 * Process has trashed its stack; give it an illegal
		 * instruction to halt it in its tracks.
		 */
		sigexit(l, SIGILL);
		/* NOTREACHED */
	}

	/*
	 * Set up the registers to directly invoke the signal
	 * handler.  The return address will be set up to point
	 * to the signal trampoline to bounce us back.
	 */
	tf->tf_a0 = signo;
	tf->tf_a1 = (intptr_t)&sf->sf_si;
	tf->tf_a2 = (intptr_t)&sf->sf_uc;

	tf->tf_pc = (intptr_t)catcher;
	tf->tf_sp = (intptr_t)sf;
	tf->tf_ra = (intptr_t)sa->sa_sigdesc[signo].sd_tramp;

	/* Remember that we're now on the signal stack. */
	if (onstack)
		l->l_sigstk.ss_flags |= SS_ONSTACK;
}
Пример #6
0
void *	
cpu_sendsig_getframe(struct lwp *l, int signo, bool *onstack)
{
	struct trapframe * const tf = l->l_md.md_utf;
	struct proc * const p = l->l_proc;
 
	/* Do we need to jump onto the signal stack? */
	*onstack = (l->l_sigstk.ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0
	    && (SIGACTION(p, signo).sa_flags & SA_ONSTACK) != 0;
	if (*onstack)
		return (char *)stack_align((intptr_t)l->l_sigstk.ss_sp + l->l_sigstk.ss_size);
	return (void *)(intptr_t)stack_align(tf->tf_sp);
}
Пример #7
0
void *
getframe(struct proc *p, int sig, int *onstack)
{
	struct sigctx *ctx = &p->p_sigctx;
	struct trapframe *tf = process_frame(l);

	/* Do we need to jump onto the signal stack? */
	*onstack = (ctx->ps_sigstk.ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0
	    && (SIGACTION(p, sig).sa_flags & SA_ONSTACK) != 0;
	if (*onstack)
		return (char *)ctx->ps_sigstk.ss_sp + ctx->ps_sigstk.ss_size;
	return (void *)tf->tf_usr_sp;
}
Пример #8
0
/*
 * Get the base address of the signal frame either on the lwp's stack
 * or on the signal stack and set *onstack accordingly.  Caller then
 * just subtracts the size of appropriate struct sigframe_foo.
 */
static void *
getframe(struct lwp *l, int sig, int *onstack)
{
	struct proc *p = l->l_proc;
	struct sigaltstack *sigstk= &l->l_sigstk;

	/* Do we need to jump onto the signal stack? */
	*onstack = (sigstk->ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0
		&& (SIGACTION(p, sig).sa_flags & SA_ONSTACK) != 0;

	if (*onstack)
		return ((char *)sigstk->ss_sp + sigstk->ss_size);
	else
		return ((void *)l->l_md.md_regs->tf_r15);
}
Пример #9
0
/*
 * Send an interrupt to process.
 *
 * Stack is set up to allow sigcode stored
 * in u. to call routine, followed by kcall
 * to sigreturn routine below.  After sigreturn
 * resets the signal mask, the stack, and the
 * frame pointer, it returns to the user
 * specified pc, psl.
 */
void
linux_sendsig(const ksiginfo_t *ksi, const sigset_t *mask)
{
	struct lwp *l = curlwp;
	struct proc *p = l->l_proc;
	struct trapframe *tf = l->l_md.md_tf;
	const int sig = ksi->ksi_signo;
	sig_t catcher = SIGACTION(p, sig).sa_handler;
#ifdef notyet
	struct linux_emuldata *edp;

	/* Setup the signal frame (and part of the trapframe) */
	/*OLD: if (p->p_sigacts->ps_siginfo & sigmask(sig))*/
/*	XXX XAX this is broken now.  need someplace to store what
	XXX XAX kind of signal handler a signal has.*/
#if 0
	edp = (struct linux_emuldata *)p->p_emuldata;
#else
	edp = 0;
#endif
	if (edp && sigismember(&edp->ps_siginfo, sig))
		setup_linux_rt_sigframe(tf, ksi, mask);
	else
#endif /* notyet */
		setup_linux_sigframe(tf, ksi, mask);

	/* Signal handler for trampoline code */
	tf->tf_regs[FRAME_T12] = (u_int64_t)catcher;
	tf->tf_regs[FRAME_A0] = native_to_linux_signo[sig];

	/*
	 * Linux has a custom restorer option.  To support it we would
	 * need to store an array of restorers and a sigcode block
	 * which knew to use it.  Doesn't seem worth the trouble.
	 * -erh
	 */

#ifdef DEBUG
	if (sigdebug & SDB_FOLLOW)
		printf("sendsig(%d): pc %lx, catcher %lx\n", l->l_proc->p_pid,
		    tf->tf_regs[FRAME_PC], tf->tf_regs[FRAME_A3]);
	if ((sigdebug & SDB_KSTACK) && l->l_proc->p_pid == sigpid)
		printf("sendsig(%d): sig %d returns\n", l->l_proc->p_pid, sig);
#endif
}
Пример #10
0
int
main(int argc, char *argv[])
{
	PMEMlogpool *plp;

	START(argc, argv, "log_walker");

	if (argc != 2)
		UT_FATAL("usage: %s file-name", argv[0]);

	const char *path = argv[1];

	int fd = OPEN(path, O_RDWR);

	/* pre-allocate 2MB of persistent memory */
	errno = posix_fallocate(fd, (off_t)0, (size_t)(2 * 1024 * 1024));
	if (errno != 0)
		UT_FATAL("!posix_fallocate");

	CLOSE(fd);

	if ((plp = pmemlog_create(path, 0, S_IWUSR | S_IRUSR)) == NULL)
		UT_FATAL("!pmemlog_create: %s", path);

	/* append some data */
	do_append(plp);

	/* arrange to catch SEGV */
	struct sigaction v;
	sigemptyset(&v.sa_mask);
	v.sa_flags = 0;
	v.sa_handler = signal_handler;
	SIGACTION(SIGSEGV, &v, NULL);

	if (!sigsetjmp(Jmp, 1)) {
		do_walk(plp);
	}

	pmemlog_close(plp);

	DONE(NULL);
}
Пример #11
0
/*
 * do_check -- check the mapping
 */
static void
do_check(int fd, void *addr, size_t mlen)
{
	/* arrange to catch SEGV */
	struct sigaction v;
	sigemptyset(&v.sa_mask);
	v.sa_flags = 0;
	v.sa_handler = signal_handler;
	SIGACTION(SIGSEGV, &v, NULL);

	char pat[CHECK_BYTES];
	char buf[CHECK_BYTES];

	/* write some pattern to the file */
	memset(pat, 0x5A, CHECK_BYTES);
	WRITE(fd, pat, CHECK_BYTES);

	if (memcmp(pat, addr, CHECK_BYTES))
		UT_OUT("first %d bytes do not match", CHECK_BYTES);

	/* fill up mapped region with new pattern */
	memset(pat, 0xA5, CHECK_BYTES);
	memcpy(addr, pat, CHECK_BYTES);

	UT_ASSERTeq(pmem_msync(addr, CHECK_BYTES), 0);

	UT_ASSERTeq(pmem_unmap(addr, mlen), 0);

	if (!ut_sigsetjmp(Jmp)) {
		/* same memcpy from above should now fail */
		memcpy(addr, pat, CHECK_BYTES);
	} else {
		UT_OUT("unmap successful");
	}

	LSEEK(fd, (os_off_t)0, SEEK_SET);
	if (READ(fd, buf, CHECK_BYTES) == CHECK_BYTES) {
		if (memcmp(pat, buf, CHECK_BYTES))
			UT_OUT("first %d bytes do not match", CHECK_BYTES);
	}
}
Пример #12
0
/*
 * check_access -- check access to mapped memory
 */
static void
check_access(char *addr, size_t len, int prot)
{
	volatile int i;

	/* arrange to catch SEGV */
	struct sigaction v;
	sigemptyset(&v.sa_mask);
	v.sa_flags = 0;
	v.sa_handler = signal_handler;
	SIGACTION(SIGSEGV, &v, NULL);

	char pat[PAGE_SIZE];
	char buf[PAGE_SIZE];

	for (i = 0; i < len / PAGE_SIZE; i++) {
		/* check read access */
		if (!ut_sigsetjmp(Jmp)) {
			memcpy(buf, addr + PAGE_SIZE * i, PAGE_SIZE);
			if ((prot & PROT_READ) == 0)
				UT_FATAL("memory can be read");
		} else {
			if (prot & PROT_READ)
				UT_FATAL("memory cannot be read");
		}
	}

	/* fill up mapped region with new pattern */
	memset(pat, 0xA5, PAGE_SIZE);
	for (i = 0; i < len / PAGE_SIZE; i++) {
		if (!ut_sigsetjmp(Jmp)) {
			memcpy(addr + PAGE_SIZE * i, pat, PAGE_SIZE);
			if ((prot & PROT_WRITE) == 0)
				UT_FATAL("memory can be written");
		} else {
			if (prot & PROT_WRITE)
				UT_FATAL("memory cannot be written");
		}
	}
}
Пример #13
0
static void
setup_sync_signal_handlers()
{
    /*
     * Setup synchronous handlers.  Note that we get the current state of
     * each signal and then just change the handler field.  Reputed to
     * be better for some implementations.
     */

#ifdef HAVE_OS_WIN32
#define SIGACTION(_sig) signal(_sig, sync_signal_handler)
#else
#define SIGACTION(_sig) \
{ \
    struct sigaction action; \
    (void)sigaction((_sig), (struct sigaction *)0, &action); \
    if (action.sa_handler == SIG_DFL) \
        action.sa_handler = (__sighandler_t) sync_signal_handler; \
    (void)sigaction((_sig), &action, (struct sigaction *)0); \
};
#endif

/*
 *  initialize the PER-PROCESS sync signal policy table,
 *  if it hasnt already been done. 
 */

    pthread_once(&_dce_exclib_syncsig_setdefault, 
		     _set_dceexc_syncsignals_default);
	
#if defined(SIGIOT)    
    if (_dce_exclib_syncsig_catch[SIGIOT]) SIGACTION(SIGIOT);
#endif    
#if defined(SIGEMT)    
    if (_dce_exclib_syncsig_catch[SIGEMT]) SIGACTION(SIGEMT);
#endif    


#if defined(SIGILL)    
    if (_dce_exclib_syncsig_catch[SIGILL]) SIGACTION(SIGILL);
#endif    
#if defined(SIGTRAP)    
    if (_dce_exclib_syncsig_catch[SIGTRAP]) SIGACTION(SIGTRAP);
#endif    
#if defined(SIGFPE)    
    if (_dce_exclib_syncsig_catch[SIGFPE]) SIGACTION(SIGFPE);
#endif    
#if defined(SIGBUS)    
    if (_dce_exclib_syncsig_catch[SIGBUS]) SIGACTION(SIGBUS);
#endif    
#if defined(SIGSEGV)    
    if (_dce_exclib_syncsig_catch[SIGSEGV]) SIGACTION(SIGSEGV);
#endif    

#if defined(SIGSYS)
    if (_dce_exclib_syncsig_catch[SIGSYS]) SIGACTION(SIGSYS);
#endif    
#if defined(SIGPIPE)    
    if (_dce_exclib_syncsig_catch[SIGPIPE]) SIGACTION(SIGPIPE);
#endif    

#undef SIGACTION
}
Пример #14
0
/*
 * Send an interrupt to process.
 */
void
sendsig(const struct ksiginfo *ksi, const sigset_t *mask)
{
	/* XXX we don't deliver siginfo yet */
	int sig = ksi->ksi_signo;
	u_long code = ksi->ksi_trap;

	struct lwp *l = curlwp;
	struct proc *p = l->l_proc;
	struct sigacts *ps = p->p_sigacts;
	struct sigframe *fp, kf;
	caddr_t sp;
	struct trapframe *tf;
	int onstack, fsize;
	sig_t catcher = SIGACTION(p, sig).sa_handler;

	tf = (struct trapframe *)l->l_md.md_regs;

	/* Do we need to jump onto the signal stack? */
	onstack =
	    (p->p_sigctx.ps_sigstk.ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 &&
	    (SIGACTION(p, sig).sa_flags & SA_ONSTACK) != 0;

	/*
	 * Allocate space for the signal handler context.
	 * The PA-RISC calling convention mandates that
	 * the stack pointer must always be 64-byte aligned,
	 * and points to the first *unused* byte.
	 */
	fsize = sizeof(struct sigframe);
	sp = (onstack ?
	      (caddr_t)p->p_sigctx.ps_sigstk.ss_sp :
	      (caddr_t)tf->tf_sp);
	sp = (caddr_t)(((u_int)(sp + fsize + 63)) & ~63);
	fp = (struct sigframe *) (sp - fsize);

#ifdef DEBUG
	if ((sigdebug & SDB_FOLLOW) && (!sigpid || p->p_pid == sigpid))
		printf("sendsig: %s[%d] sig %d catcher %p\n",
		    p->p_comm, p->p_pid, sig, catcher);
#endif

	/*
	 * Save necessary hardware state.  Currently this includes:
	 *      - original exception frame
	 *      - FP coprocessor state
	 */
	kf.sf_state.ss_flags = SS_USERREGS;
	memcpy(&kf.sf_state.ss_frame, tf, sizeof(*tf));
	/* XXX FP state */

	/* Build the signal context to be used by sigreturn. */
	kf.sf_sc.sc_sp = tf->tf_sp;
	kf.sf_sc.sc_fp = tf->tf_sp;	/* XXX fredette - is this right? */
	kf.sf_sc.sc_ap = (int)&fp->sf_state;
	kf.sf_sc.sc_pcsqh = tf->tf_iisq_head;
	kf.sf_sc.sc_pcoqh = tf->tf_iioq_head;
	kf.sf_sc.sc_pcsqt = tf->tf_iisq_tail;
	kf.sf_sc.sc_pcoqt = tf->tf_iioq_tail;
	kf.sf_sc.sc_ps = tf->tf_ipsw;

	/* Save signal stack. */
	kf.sf_sc.sc_onstack = p->p_sigctx.ps_sigstk.ss_flags & SS_ONSTACK;

	/* Save signal mask. */
	kf.sf_sc.sc_mask = *mask;

	/* Fill the calling convention part of the signal frame. */
	kf.sf_psp = 0;
	kf.sf_clup = 0;		/* XXX fredette - is this right? */
	kf.sf_sl = 0;		/* XXX fredette - is this right? */
	kf.sf_edp = 0;		/* XXX fredette - is this right? */

	/* Copy out the signal frame. */
	if (copyout(&kf, fp, fsize)) {
#ifdef DEBUG
		if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
			printf("sendsig(%d): copyout failed on sig %d\n",
			       p->p_pid, sig);
#endif
		/*
		 * Process has trashed its stack; give it an illegal
		 * instruction to halt it in its tracks.
		 */
		sigexit(l, SIGILL);
		/* NOTREACHED */
	}
#ifdef DEBUG
	if (sigdebug & SDB_FOLLOW)
		printf("sendsig(%d): sig %d scp %p fp %p sc_sp %x sc_ap %x\n",
		       p->p_pid, sig, &fp->sf_sc, fp,
		       kf.sf_sc.sc_sp, kf.sf_sc.sc_ap);
#endif

	/* Set up the registers to return to sigcode. */
	switch (ps->sa_sigdesc[sig].sd_vers) {
#if 1 /* COMPAT_16 */
	case 0:		/* legacy on-stack sigtramp */
		tf->tf_iioq_head =
		    (int)p->p_sigctx.ps_sigcode | HPPA_PC_PRIV_USER;
		tf->tf_iioq_tail = tf->tf_iioq_head + 4;
		break;
#endif

	case 1:
		tf->tf_iioq_head =
		    (int)ps->sa_sigdesc[sig].sd_tramp | HPPA_PC_PRIV_USER;
		tf->tf_iioq_tail = tf->tf_iioq_head + 4;
		break;

	default:
		/* Don't know what trampoline version; kill it. */
		sigexit(l, SIGILL);
	}

	tf->tf_sp = (int)sp;
	tf->tf_r3 = (int)&fp->sf_sc;
	tf->tf_arg0 = sig;
	tf->tf_arg1 = code;
	tf->tf_arg2 = (int)&fp->sf_sc;
	tf->tf_arg3 = (int)catcher;

	/* Remember that we're now on the signal stack. */
	if (onstack)
		p->p_sigctx.ps_sigstk.ss_flags |= SS_ONSTACK;
	
#ifdef DEBUG    
	if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
		printf("sendsig(%d): sig %d returns\n",
		       p->p_pid, sig);
#endif 
}
Пример #15
0
/*
 * Stack is set up to allow sigcode stored
 * in u. to call routine, followed by kcall
 * to sigreturn routine below.  After sigreturn
 * resets the signal mask, the stack, and the
 * frame pointer, it returns to the user
 * specified pc, psl.
 */
static void
sendsig_sigcontext(const ksiginfo_t *ksi, const sigset_t *mask)
{
	struct lwp *l = curlwp;
	struct proc *p = l->l_proc;
	struct sigacts *ps = p->p_sigacts;
	struct trapframe *tf = l->l_md.md_regs;
	int sig = ksi->ksi_info._signo;
	sig_t catcher = SIGACTION(p, sig).sa_handler;
	struct sigframe_sigcontext *fp, frame;
	int onstack, error;

	fp = getframe(l, sig, &onstack);
	--fp;

	/* Save register context. */
	frame.sf_sc.sc_ssr = tf->tf_ssr;
	frame.sf_sc.sc_spc = tf->tf_spc;
	frame.sf_sc.sc_pr = tf->tf_pr;
	frame.sf_sc.sc_r15 = tf->tf_r15;
	frame.sf_sc.sc_r14 = tf->tf_r14;
	frame.sf_sc.sc_r13 = tf->tf_r13;
	frame.sf_sc.sc_r12 = tf->tf_r12;
	frame.sf_sc.sc_r11 = tf->tf_r11;
	frame.sf_sc.sc_r10 = tf->tf_r10;
	frame.sf_sc.sc_r9 = tf->tf_r9;
	frame.sf_sc.sc_r8 = tf->tf_r8;
	frame.sf_sc.sc_r7 = tf->tf_r7;
	frame.sf_sc.sc_r6 = tf->tf_r6;
	frame.sf_sc.sc_r5 = tf->tf_r5;
	frame.sf_sc.sc_r4 = tf->tf_r4;
	frame.sf_sc.sc_r3 = tf->tf_r3;
	frame.sf_sc.sc_r2 = tf->tf_r2;
	frame.sf_sc.sc_r1 = tf->tf_r1;
	frame.sf_sc.sc_r0 = tf->tf_r0;
	frame.sf_sc.sc_expevt = tf->tf_expevt;

	/* Save signal stack. */
	frame.sf_sc.sc_onstack = l->l_sigstk.ss_flags & SS_ONSTACK;

	/* Save signal mask. */
	frame.sf_sc.sc_mask = *mask;

	sendsig_reset(l, sig);

	mutex_exit(p->p_lock);
	error = copyout(&frame, fp, sizeof(frame));
	mutex_enter(p->p_lock);

	if (error != 0) {
		/*
		 * Process has trashed its stack; give it an illegal
		 * instruction to halt it in its tracks.
		 */
		sigexit(l, SIGILL);
		/* NOTREACHED */
	}

	/*
	 * Build context to run handler in.  We invoke the handler
	 * directly, only returning via the trampoline.
	 */
	switch (ps->sa_sigdesc[sig].sd_vers) {
	case 0:		/* legacy on-stack sigtramp */
		tf->tf_pr = (int)p->p_sigctx.ps_sigcode;
		break;

	case 1:
		tf->tf_pr = (int)ps->sa_sigdesc[sig].sd_tramp;
		break;

	default:
		/* Don't know what trampoline version; kill it. */
		printf("sendsig_sigcontext: bad version %d\n",
		       ps->sa_sigdesc[sig].sd_vers);
		sigexit(l, SIGILL);
	}

	tf->tf_r4 = sig;
	tf->tf_r5 = ksi->ksi_code;
	tf->tf_r6 = (int)&fp->sf_sc;
 	tf->tf_spc = (int)catcher;
	tf->tf_r15 = (int)fp;

	/* Remember if we're now on the signal stack. */
	if (onstack)
		l->l_sigstk.ss_flags |= SS_ONSTACK;
}
Пример #16
0
int
main(int argc, char *argv[])
{
	START(argc, argv, "blk_recovery");

	if (argc != 5)
		FATAL("usage: %s bsize file first_lba lba", argv[0]);

	Bsize = strtoul(argv[1], NULL, 0);
	const char *path = argv[2];

	PMEMblkpool *handle;
	if ((handle = pmemblk_create(path, Bsize, 0,
			S_IWUSR | S_IRUSR)) == NULL)
		FATAL("!%s: pmemblk_create", path);

	OUT("%s block size %zu usable blocks %zu",
			argv[1], Bsize, pmemblk_nblock(handle));

	/* write the first lba */
	off_t lba = strtoul(argv[3], NULL, 0);
	unsigned char buf[Bsize];

	construct(buf);
	if (pmemblk_write(handle, buf, lba) < 0)
		FATAL("!write     lba %zu", lba);

	OUT("write     lba %zu: %s", lba, ident(buf));

	/* reach into the layout and write-protect the map */
	struct btt_info *infop = (void *)handle +
		roundup(sizeof (struct pmemblk), BLK_FORMAT_DATA_ALIGN);

	void *mapaddr = (void *)infop + le32toh(infop->mapoff);
	void *flogaddr = (void *)infop + le32toh(infop->flogoff);

	OUT("write-protecting map, length %zu", (size_t)(flogaddr - mapaddr));
	MPROTECT(mapaddr, (size_t)(flogaddr - mapaddr), PROT_READ);

	/* arrange to catch SEGV */
	struct sigaction v;
	sigemptyset(&v.sa_mask);
	v.sa_flags = 0;
	v.sa_handler = signal_handler;
	SIGACTION(SIGSEGV, &v, NULL);

	/* map each file argument with the given map type */
	lba = strtoul(argv[4], NULL, 0);

	construct(buf);

	if (!sigsetjmp(Jmp, 1)) {
		if (pmemblk_write(handle, buf, lba) < 0)
			FATAL("!write     lba %zu", lba);
		else
			FATAL("write     lba %zu: %s", lba, ident(buf));
	}

	pmemblk_close(handle);

	int result = pmemblk_check(path);
	if (result < 0)
		OUT("!%s: pmemblk_check", path);
	else if (result == 0)
		OUT("%s: pmemblk_check: not consistent", path);
	else
		OUT("%s: consistent", path);

	DONE(NULL);
}
Пример #17
0
static void
netbsd32_sendsig_siginfo(const ksiginfo_t *ksi, const sigset_t *mask)
{
	struct lwp *l = curlwp;
	struct proc *p = l->l_proc;
	struct sigacts *ps = p->p_sigacts;
	int onstack;
	int sig = ksi->ksi_signo;
	ucontext32_t uc;
	struct sparc32_sigframe_siginfo *fp;
	siginfo32_t si32;	
	netbsd32_intptr_t catcher;
	struct trapframe64 *tf = l->l_md.md_tf;
	struct rwindow32 *oldsp, *newsp;
	register32_t sp;
	int ucsz, error;

	/* Need to attempt to zero extend this 32-bit pointer */
	oldsp = (struct rwindow32*)(u_long)(u_int)tf->tf_out[6];
	/* Do we need to jump onto the signal stack? */
	onstack =
	    (l->l_sigstk.ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 &&
	    (SIGACTION(p, sig).sa_flags & SA_ONSTACK) != 0;

	/* Allocate space for the signal handler context. */
	if (onstack)
		fp = (struct sparc32_sigframe_siginfo *)
		    ((char *)l->l_sigstk.ss_sp +
					  l->l_sigstk.ss_size);
	else
		fp = (struct sparc32_sigframe_siginfo *)oldsp;
	fp = (struct sparc32_sigframe_siginfo*)((u_long)(fp - 1) & ~7);

	/*
	 * Build the signal context to be used by sigreturn.
	 */
	memset(&uc, 0, sizeof uc);
	uc.uc_flags = _UC_SIGMASK |
		((l->l_sigstk.ss_flags & SS_ONSTACK)
			? _UC_SETSTACK : _UC_CLRSTACK);
	uc.uc_sigmask = *mask;
	uc.uc_link = (uint32_t)(uintptr_t)l->l_ctxlink;

	sendsig_reset(l, sig);

	/*
	 * Now copy the stack contents out to user space.
	 * We need to make sure that when we start the signal handler,
	 * its %i6 (%fp), which is loaded from the newly allocated stack area,
	 * joins seamlessly with the frame it was in when the signal occurred,
	 * so that the debugger and _longjmp code can back up through it.
	 * Since we're calling the handler directly, allocate a full size
	 * C stack frame.
	 */
	mutex_exit(p->p_lock);
	cpu_getmcontext32(l, &uc.uc_mcontext, &uc.uc_flags);
	netbsd32_si_to_si32(&si32, (const siginfo_t *)&ksi->ksi_info);
	ucsz = (int)(intptr_t)&uc.__uc_pad - (int)(intptr_t)&uc;
	newsp = (struct rwindow32*)((intptr_t)fp - sizeof(struct frame32));
	sp = NETBSD32PTR32I(oldsp);
	error = (copyout(&si32, &fp->sf_si, sizeof si32) ||
	    copyout(&uc, &fp->sf_uc, ucsz) ||
	    copyout(&sp, &newsp->rw_in[6], sizeof(sp)));
	mutex_enter(p->p_lock);

	if (error) {
		/*
		 * Process has trashed its stack; give it an illegal
		 * instruction to halt it in its tracks.
		 */
		sigexit(l, SIGILL);
		/* NOTREACHED */
	}

	switch (ps->sa_sigdesc[sig].sd_vers) {
	default:
		/* Unsupported trampoline version; kill the process. */
		sigexit(l, SIGILL);
	case 2:
		/*
		 * Arrange to continue execution at the user's handler.
		 * It needs a new stack pointer, a return address and
		 * three arguments: (signo, siginfo *, ucontext *).
		 */
		catcher = (intptr_t)SIGACTION(p, sig).sa_handler;
		tf->tf_pc = catcher;
		tf->tf_npc = catcher + 4;
		tf->tf_out[0] = sig;
		tf->tf_out[1] = (intptr_t)&fp->sf_si;
		tf->tf_out[2] = (intptr_t)&fp->sf_uc;
		tf->tf_out[6] = (intptr_t)newsp;
		tf->tf_out[7] = (intptr_t)ps->sa_sigdesc[sig].sd_tramp - 8;
		break;
	}

	/* Remember that we're now on the signal stack. */
	if (onstack)
		l->l_sigstk.ss_flags |= SS_ONSTACK;
}
Пример #18
0
/*
 * Send an interrupt to process.
 */
void
sendsig_sigcontext(const ksiginfo_t *ksi, const sigset_t *mask)
{
	struct lwp *l = curlwp;
	struct proc *p = l->l_proc;
	struct sigacts *ps = p->p_sigacts;
	struct frame *frame = (struct frame *)l->l_md.md_regs;
	int onstack;
	int sig = ksi->ksi_signo;
	u_long code = KSI_TRAPCODE(ksi);
	struct sigframe_sigcontext *fp = getframe(l, sig, &onstack), kf;
	sig_t catcher = SIGACTION(p, sig).sa_handler;
	short ft = frame->f_format;

	fp--;

#ifdef DEBUG
	if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
		printf("sendsig(%d): sig %d ssp %p usp %p scp %p ft %d\n",
		       p->p_pid, sig, &onstack, fp, &fp->sf_sc, ft);
#endif

	/* Build stack frame for signal trampoline. */
	switch (ps->sa_sigdesc[sig].sd_vers) {
	case 0:		/* legacy on-stack sigtramp */
		kf.sf_ra = (int)p->p_sigctx.ps_sigcode;
		break;

	case 1:
		kf.sf_ra = (int)ps->sa_sigdesc[sig].sd_tramp;
		break;

	default:
		/* Don't know what trampoline version; kill it. */
		sigexit(l, SIGILL);
	}

	kf.sf_signum = sig;
	kf.sf_code = code;
	kf.sf_scp = &fp->sf_sc;

	/*
	 * Save necessary hardware state.  Currently this includes:
	 *	- general registers
	 *	- original exception frame (if not a "normal" frame)
	 *	- FP coprocessor state
	 */
	kf.sf_state.ss_flags = SS_USERREGS;
	memcpy(kf.sf_state.ss_frame.f_regs, frame->f_regs,
	    sizeof(frame->f_regs));
	if (ft >= FMT4) {
#ifdef DEBUG
		if (ft > 15 || exframesize[ft] < 0)
			panic("sendsig: bogus frame type");
#endif
		kf.sf_state.ss_flags |= SS_RTEFRAME;
		kf.sf_state.ss_frame.f_format = frame->f_format;
		kf.sf_state.ss_frame.f_vector = frame->f_vector;
		memcpy(&kf.sf_state.ss_frame.F_u, &frame->F_u,
		    (size_t) exframesize[ft]);
		/*
		 * Leave an indicator that we need to clean up the kernel
		 * stack.  We do this by setting the "pad word" above the
		 * hardware stack frame to the amount the stack must be
		 * adjusted by.
		 *
		 * N.B. we increment rather than just set f_stackadj in
		 * case we are called from syscall when processing a
		 * sigreturn.  In that case, f_stackadj may be non-zero.
		 */
		frame->f_stackadj += exframesize[ft];
		frame->f_format = frame->f_vector = 0;
#ifdef DEBUG
		if (sigdebug & SDB_FOLLOW)
			printf("sendsig(%d): copy out %d of frame %d\n",
			       p->p_pid, exframesize[ft], ft);
#endif
	}

	if (fputype) {
		kf.sf_state.ss_flags |= SS_FPSTATE;
		m68881_save(&kf.sf_state.ss_fpstate);
	}
#ifdef DEBUG
	if ((sigdebug & SDB_FPSTATE) && *(char *)&kf.sf_state.ss_fpstate)
		printf("sendsig(%d): copy out FP state (%x) to %p\n",
		       p->p_pid, *(u_int *)&kf.sf_state.ss_fpstate,
		       &kf.sf_state.ss_fpstate);
#endif

	/* Build the signal context to be used by sigreturn. */
	kf.sf_sc.sc_sp = frame->f_regs[SP];
	kf.sf_sc.sc_fp = frame->f_regs[A6];
	kf.sf_sc.sc_ap = (int)&fp->sf_state;
	kf.sf_sc.sc_pc = frame->f_pc;
	kf.sf_sc.sc_ps = frame->f_sr;

	/* Save signal stack. */
	kf.sf_sc.sc_onstack = p->p_sigctx.ps_sigstk.ss_flags & SS_ONSTACK;

	/* Save signal mask. */
	kf.sf_sc.sc_mask = *mask;

#ifdef COMPAT_13
	/*
	 * XXX We always have to save an old style signal mask because
	 * XXX we might be delivering a signal to a process which will
	 * XXX escape from the signal in a non-standard way and invoke
	 * XXX sigreturn() directly.
	 */
	native_sigset_to_sigset13(mask, &kf.sf_sc.__sc_mask13);
#endif

	if (copyout(&kf, fp, sizeof(kf)) != 0) {
#ifdef DEBUG
		if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
			printf("sendsig(%d): copyout failed on sig %d\n",
			       p->p_pid, sig);
#endif
		/*
		 * Process has trashed its stack; give it an illegal
		 * instruction to halt it in its tracks.
		 */
		sigexit(l, SIGILL);
		/* NOTREACHED */
	}
#ifdef DEBUG
	if (sigdebug & SDB_FOLLOW)
		printf("sendsig(%d): sig %d scp %p fp %p sc_sp %x sc_ap %x\n",
		       p->p_pid, sig, kf.sf_scp, fp,
		       kf.sf_sc.sc_sp, kf.sf_sc.sc_ap);
#endif

	buildcontext(l, catcher, fp);

	/* Remember that we're now on the signal stack. */
	if (onstack)
		p->p_sigctx.ps_sigstk.ss_flags |= SS_ONSTACK;

#ifdef DEBUG
	if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
		printf("sendsig(%d): sig %d returns\n",
		       p->p_pid, sig);
#endif
}
Пример #19
0
static void
linux_old_sendsig(const ksiginfo_t *ksi, const sigset_t *mask)
{
	struct lwp *l = curlwp;
	struct proc *p = l->l_proc;
	struct trapframe *tf;
	struct linux_sigframe *fp, frame;
	int onstack, error;
	int sig = ksi->ksi_signo;
	sig_t catcher = SIGACTION(p, sig).sa_handler;
	struct sigaltstack *sas = &l->l_sigstk;

	tf = l->l_md.md_regs;

	/* Do we need to jump onto the signal stack? */
	onstack = (sas->ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 &&
	    (SIGACTION(p, sig).sa_flags & SA_ONSTACK) != 0;

	/* Allocate space for the signal handler context. */
	if (onstack)
		fp = (struct linux_sigframe *) ((char *)sas->ss_sp +
		    sas->ss_size);
	else
		fp = (struct linux_sigframe *)tf->tf_esp;
	fp--;

	DPRINTF(("old: onstack = %d, fp = %p sig = %d eip = 0x%x cr2 = 0x%x\n",
	    onstack, fp, sig, tf->tf_eip,
	    ((struct pcb *)lwp_getpcb(l))->pcb_cr2));

	/* Build stack frame for signal trampoline. */
	frame.sf_handler = catcher;
	frame.sf_sig = native_to_linux_signo[sig];

	linux_save_sigcontext(l, tf, mask, &frame.sf_sc);
	sendsig_reset(l, sig);

	mutex_exit(p->p_lock);
	error = copyout(&frame, fp, sizeof(frame));
	mutex_enter(p->p_lock);

	if (error != 0) {
		/*
		 * Process has trashed its stack; give it an illegal
		 * instruction to halt it in its tracks.
		 */
		sigexit(l, SIGILL);
		/* NOTREACHED */
	}

	/*
	 * Build context to run handler in.
	 */
	tf->tf_fs = GSEL(GUDATA_SEL, SEL_UPL);
	tf->tf_es = GSEL(GUDATA_SEL, SEL_UPL);
	tf->tf_ds = GSEL(GUDATA_SEL, SEL_UPL);
	tf->tf_eip = (int)p->p_sigctx.ps_sigcode;
	tf->tf_cs = GSEL(GUCODEBIG_SEL, SEL_UPL);
	tf->tf_eflags &= ~PSL_CLEARSIG;
	tf->tf_esp = (int)fp;
	tf->tf_ss = GSEL(GUDATA_SEL, SEL_UPL);

	/* Remember that we're now on the signal stack. */
	if (onstack)
		sas->ss_flags |= SS_ONSTACK;
}
Пример #20
0
/**
 * Eventually calls exit(), passing @p code, therefore does not return.
 *
 * @param code one of the RERR_* codes from errcode.h.
 **/
NORETURN void _exit_cleanup(int code, const char *file, int line)
{
	static int switch_step = 0;
	static int exit_code = 0, exit_line = 0;
	static const char *exit_file = NULL;
	static int first_code = 0;

	SIGACTION(SIGUSR1, SIG_IGN);
	SIGACTION(SIGUSR2, SIG_IGN);

	if (!exit_code) { /* Preserve first error exit info when recursing. */
		exit_code = code;
		exit_file = file;
		exit_line = line < 0 ? -line : line;
	}

	/* If this is the exit at the end of the run, the server side
	 * should not attempt to output a message (see log_exit()). */
	if (am_server && code == 0)
		am_server = 2;

	/* Some of our actions might cause a recursive call back here, so we
	 * keep track of where we are in the cleanup and never repeat a step. */
	switch (switch_step) {
#include "case_N.h" /* case 0: */
		switch_step++;

		first_code = code;

		if (output_needs_newline) {
			fputc('\n', stdout);
			output_needs_newline = 0;
		}

		if (DEBUG_GTE(EXIT, 2)) {
			rprintf(FINFO,
				"[%s] _exit_cleanup(code=%d, file=%s, line=%d): entered\n",
				who_am_i(), code, file, line);
		}

		/* FALLTHROUGH */
#include "case_N.h"
		switch_step++;

		if (cleanup_child_pid != -1) {
			int status;
			int pid = wait_process(cleanup_child_pid, &status, WNOHANG);
			if (pid == cleanup_child_pid) {
				status = WEXITSTATUS(status);
				if (status > exit_code)
					exit_code = status;
			}
		}

		/* FALLTHROUGH */
#include "case_N.h"
		switch_step++;

		if (cleanup_got_literal && (cleanup_fname || cleanup_fd_w != -1)) {
			if (cleanup_fd_r != -1) {
				close(cleanup_fd_r);
				cleanup_fd_r = -1;
			}
			if (cleanup_fd_w != -1) {
				flush_write_file(cleanup_fd_w);
				close(cleanup_fd_w);
				cleanup_fd_w = -1;
			}
			if (cleanup_fname && cleanup_new_fname && keep_partial
			 && handle_partial_dir(cleanup_new_fname, PDIR_CREATE)) {
				int tweak_modtime = 0;
				const char *fname = cleanup_fname;
				cleanup_fname = NULL;
				if (!partial_dir) {
				    /* We don't want to leave a partial file with a modern time or it
				     * could be skipped via --update.  Setting the time to something
				     * really old also helps it to stand out as unfinished in an ls. */
				    tweak_modtime = 1;
				    cleanup_file->modtime = 0;
				}
				finish_transfer(cleanup_new_fname, fname, NULL, NULL,
						cleanup_file, tweak_modtime, !partial_dir);
			}
		}

		/* FALLTHROUGH */
#include "case_N.h"
		switch_step++;

		if (flush_ok_after_signal) {
			flush_ok_after_signal = False;
			if (code == RERR_SIGNAL)
				io_flush(FULL_FLUSH);
		}
		if (!exit_code && !code)
			io_flush(FULL_FLUSH);

		/* FALLTHROUGH */
#include "case_N.h"
		switch_step++;

		if (cleanup_fname)
			do_unlink(cleanup_fname);
		if (exit_code)
			kill_all(SIGUSR1);
		if (cleanup_pid && cleanup_pid == getpid()) {
			char *pidf = lp_pid_file();
			if (pidf && *pidf)
				unlink(lp_pid_file());
		}

		if (exit_code == 0) {
			if (code)
				exit_code = code;
			if (io_error & IOERR_DEL_LIMIT)
				exit_code = RERR_DEL_LIMIT;
			if (io_error & IOERR_VANISHED)
				exit_code = RERR_VANISHED;
			if (io_error & IOERR_GENERAL || got_xfer_error)
				exit_code = RERR_PARTIAL;
		}

		/* If line < 0, this exit is after a MSG_ERROR_EXIT event, so
		 * we don't want to output a duplicate error. */
		if ((exit_code && line > 0)
		 || am_daemon || (logfile_name && (am_server || !INFO_GTE(STATS, 1))))
			log_exit(exit_code, exit_file, exit_line);

		/* FALLTHROUGH */
#include "case_N.h"
		switch_step++;

		if (DEBUG_GTE(EXIT, 1)) {
			rprintf(FINFO,
				"[%s] _exit_cleanup(code=%d, file=%s, line=%d): "
				"about to call exit(%d)\n",
				who_am_i(), first_code, exit_file, exit_line, exit_code);
		}

		/* FALLTHROUGH */
#include "case_N.h"
		switch_step++;

		if (exit_code && exit_code != RERR_SOCKETIO && exit_code != RERR_STREAMIO && exit_code != RERR_SIGNAL1
		 && exit_code != RERR_TIMEOUT && !shutting_down && (protocol_version >= 31 || am_receiver)) {
			if (line > 0) {
				if (DEBUG_GTE(EXIT, 3)) {
					rprintf(FINFO, "[%s] sending MSG_ERROR_EXIT with exit_code %d\n",
						who_am_i(), exit_code);
				}
				send_msg_int(MSG_ERROR_EXIT, exit_code);
			}
			noop_io_until_death();
		}

		/* FALLTHROUGH */
#include "case_N.h"
		switch_step++;

		if (am_server && exit_code)
			msleep(100);
		close_all();

		/* FALLTHROUGH */
	default:
		break;
	}

	exit(exit_code);
}
Пример #21
0
/*
 * check_mapping -- check access to memory mapped file
 */
static void
check_mapping(int fd, char *addr, size_t len, int prot, int flags, off_t offset)
{
	volatile int i;

	/* arrange to catch SEGV */
	struct sigaction v;
	sigemptyset(&v.sa_mask);
	v.sa_flags = 0;
	v.sa_handler = signal_handler;
	SIGACTION(SIGSEGV, &v, NULL);

	char pat[PAGE_SIZE] = { 0 };
	char buf[PAGE_SIZE];

	if ((flags & CHECK_RO) == 0 && fd != -1) {
		/* write some pattern to the file */
		memset(pat, 0x5A, PAGE_SIZE);

		for (i = 0; i < len / PAGE_SIZE; i++) {
			LSEEK(fd, offset + PAGE_SIZE * i, SEEK_SET);
			WRITE(fd, pat, PAGE_SIZE);

			LSEEK(fd, offset + PAGE_SIZE * i, SEEK_SET);
			if (READ(fd, buf, PAGE_SIZE) == PAGE_SIZE) {
				if (memcmp(pat, buf, PAGE_SIZE))
					UT_FATAL("first %d bytes do not match",
							PAGE_SIZE);
			}
		}
	}

	check_access(addr, len, prot);

	munmap(addr, len);

	/* same memcpy from above should now fail */
	for (i = 0; i < len / PAGE_SIZE; i++) {
		if (!ut_sigsetjmp(Jmp)) {
			memcpy(addr + PAGE_SIZE * i, pat, PAGE_SIZE);
			UT_FATAL("unmap failed");
		}
	}

	if (fd != -1) {
		/* expected pattern */
		if ((flags & (CHECK_PRIV | CHECK_RO)) != 0 ||
		    (prot & PROT_WRITE) == 0)
			memset(pat, 0x5A, PAGE_SIZE);
		else
			memset(pat, 0xA5, PAGE_SIZE);

		for (i = 0; i < len / PAGE_SIZE; i++) {
			LSEEK(fd, offset + PAGE_SIZE * i, SEEK_SET);
			if (READ(fd, buf, PAGE_SIZE) == PAGE_SIZE) {
				if (memcmp(pat, buf, PAGE_SIZE))
					UT_FATAL("first %d bytes do not match",
							PAGE_SIZE);
			}
		}
	}
}
Пример #22
0
void
sendsig_sigcontext(const ksiginfo_t *ksi, const sigset_t *mask)
{
	struct lwp *l = curlwp;
	struct proc *p = l->l_proc;
	struct sigacts *ps = p->p_sigacts;
	int onstack, sig = ksi->ksi_signo;
	struct sigframe_sigcontext *fp, frame;
	struct trapframe *tf;
	sig_t catcher = SIGACTION(p, sig).sa_handler;

	tf = l->l_md.md_tf;
	fp = getframe(l, sig, &onstack), frame;
	fp--;

#ifdef DEBUG
	if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
		printf("sendsig_sigcontext(%d): sig %d ssp %p usp %p\n",
		       p->p_pid, sig, &onstack, fp);
#endif

	/* Build stack frame for signal trampoline. */
	frame.sf_sc.sc_pc = tf->tf_regs[FRAME_PC];
	frame.sf_sc.sc_ps = tf->tf_regs[FRAME_PS];

	/* Save register context. */
	frametoreg(tf, (struct reg *)frame.sf_sc.sc_regs);
	frame.sf_sc.sc_regs[R_ZERO] = 0xACEDBADE;	/* magic number */
	frame.sf_sc.sc_regs[R_SP] = alpha_pal_rdusp();

 	/* save the floating-point state, if necessary, then copy it. */
	if (l->l_addr->u_pcb.pcb_fpcpu != NULL)
		fpusave_proc(l, 1);
	frame.sf_sc.sc_ownedfp = l->l_md.md_flags & MDP_FPUSED;
	memcpy((struct fpreg *)frame.sf_sc.sc_fpregs, &l->l_addr->u_pcb.pcb_fp,
	    sizeof(struct fpreg));
	frame.sf_sc.sc_fp_control = alpha_read_fp_c(l);
	memset(frame.sf_sc.sc_reserved, 0, sizeof frame.sf_sc.sc_reserved);
	memset(frame.sf_sc.sc_xxx, 0, sizeof frame.sf_sc.sc_xxx); /* XXX */

	/* Save signal stack. */
	frame.sf_sc.sc_onstack = p->p_sigctx.ps_sigstk.ss_flags & SS_ONSTACK;

	/* Save signal mask. */
	frame.sf_sc.sc_mask = *mask;

#ifdef COMPAT_13
	/*
	 * XXX We always have to save an old style signal mask because
	 * XXX we might be delivering a signal to a process which will
	 * XXX escape from the signal in a non-standard way and invoke
	 * XXX sigreturn() directly.
	 */
	{
		/* Note: it's a long in the stack frame. */
		sigset13_t mask13;

		native_sigset_to_sigset13(mask, &mask13);
		frame.sf_sc.__sc_mask13 = mask13;
	}
#endif

#ifdef COMPAT_OSF1
	/*
	 * XXX Create an OSF/1-style sigcontext and associated goo.
	 */
#endif

	if (copyout(&frame, (caddr_t)fp, sizeof(frame)) != 0) {
		/*
		 * Process has trashed its stack; give it an illegal
		 * instruction to halt it in its tracks.
		 */
#ifdef DEBUG
		if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
			printf("sendsig_sigcontext(%d): copyout failed on sig %d\n",
			       p->p_pid, sig);
#endif
		sigexit(l, SIGILL);
		/* NOTREACHED */
	}
#ifdef DEBUG
	if (sigdebug & SDB_FOLLOW)
		printf("sendsig_sigcontext(%d): sig %d usp %p code %x\n",
		       p->p_pid, sig, fp, ksi->ksi_code);
#endif

	/*
	 * Set up the registers to directly invoke the signal handler.  The
	 * signal trampoline is then used to return from the signal.  Note
	 * the trampoline version numbers are coordinated with machine-
	 * dependent code in libc.
	 */
	switch (ps->sa_sigdesc[sig].sd_vers) {
	case 0:		/* legacy on-stack sigtramp */
		buildcontext(l,(void *)catcher,
			     (void *)p->p_sigctx.ps_sigcode,
			     (void *)fp);
		break;
	case 1:
		buildcontext(l,(void *)catcher,
			     (void *)ps->sa_sigdesc[sig].sd_tramp,
			     (void *)fp);
		break;

	default:
		/* Don't know what trampoline version; kill it. */
		sigexit(l, SIGILL);
	}

	/* sigcontext specific trap frame */
	tf->tf_regs[FRAME_A0] = sig;

	/* tf->tf_regs[FRAME_A1] = ksi->ksi_code; */
	tf->tf_regs[FRAME_A1] = KSI_TRAPCODE(ksi);
	tf->tf_regs[FRAME_A2] = (u_int64_t)&fp->sf_sc;

	/* Remember that we're now on the signal stack. */
	if (onstack)
		p->p_sigctx.ps_sigstk.ss_flags |= SS_ONSTACK;

#ifdef DEBUG
	if (sigdebug & SDB_FOLLOW)
		printf("sendsig(%d): pc %lx, catcher %lx\n", p->p_pid,
		    tf->tf_regs[FRAME_PC], tf->tf_regs[FRAME_A3]);
	if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
		printf("sendsig(%d): sig %d returns\n",
		    p->p_pid, sig);
#endif
}
Пример #23
0
/*
 * Send an interrupt to process.
 *
 */
void
sendsig(
	struct proc * p,
	user_addr_t catcher,
	int sig,
	int mask,
	__unused uint32_t code
)
{
	union {
		struct ts32 {
			arm_thread_state_t ss;
		} ts32;
#if defined(__arm64__)
		struct ts64 {
			arm_thread_state64_t ss;
		} ts64;
#endif
	} ts;
	union { 
		struct user_sigframe32 uf32;
#if defined(__arm64__)
		struct user_sigframe64 uf64;
#endif
	} user_frame;

	user_siginfo_t sinfo;
	user_addr_t 	sp = 0, trampact;
	struct sigacts *ps = p->p_sigacts;
	int             oonstack, infostyle;
	thread_t        th_act;
	struct uthread *ut;
	user_size_t	stack_size = 0;
	user_addr_t     p_uctx, token_uctx;
	kern_return_t   kr;

	th_act = current_thread();
	ut = get_bsdthread_info(th_act);

	bzero(&ts, sizeof(ts));
	bzero(&user_frame, sizeof(user_frame));

	if (p->p_sigacts->ps_siginfo & sigmask(sig))
		infostyle = UC_FLAVOR;
	else
		infostyle = UC_TRAD;

	trampact = ps->ps_trampact[sig];
	oonstack = ps->ps_sigstk.ss_flags & SA_ONSTACK;

	/*
	 * Get sundry thread state.
	 */
	if (proc_is64bit_data(p)) {
#ifdef __arm64__
		if (sendsig_get_state64(th_act, &ts.ts64.ss, &user_frame.uf64.mctx) != 0) {
			goto bad2;
		}
#else
	panic("Shouldn't have 64-bit thread states on a 32-bit kernel.");
#endif
	} else {
		if (sendsig_get_state32(th_act, &ts.ts32.ss, &user_frame.uf32.mctx) != 0) {
			goto bad2;
		}
	}

	/*
	 * Figure out where our new stack lives.
	 */
	if ((ps->ps_flags & SAS_ALTSTACK) && !oonstack &&
	    (ps->ps_sigonstack & sigmask(sig))) {
		sp = ps->ps_sigstk.ss_sp;
		sp += ps->ps_sigstk.ss_size;
		stack_size = ps->ps_sigstk.ss_size;
		ps->ps_sigstk.ss_flags |= SA_ONSTACK;
	} else {
		/*
		 * Get stack pointer, and allocate enough space
		 * for signal handler data.
		 */
		if (proc_is64bit_data(p)) {
#if defined(__arm64__)
			sp = CAST_USER_ADDR_T(ts.ts64.ss.sp);
			sp = (sp - sizeof(user_frame.uf64) - C_64_REDZONE_LEN) & ~0xf; /* Make sure to align to 16 bytes and respect red zone */
#else
			panic("Shouldn't have 64-bit thread states on a 32-bit kernel.");
#endif
		} else {
			sp = CAST_USER_ADDR_T(ts.ts32.ss.sp);
			sp -= sizeof(user_frame.uf32);
#if defined(__arm__) && (__BIGGEST_ALIGNMENT__ > 4)
			sp &= ~0xf; /* Make sure to align to 16 bytes for armv7k */
#endif
		}
	}

	proc_unlock(p);

	/*
	 * Fill in ucontext (points to mcontext, i.e. thread states).
	 */
	if (proc_is64bit_data(p)) {
#if defined(__arm64__)
		sendsig_fill_uctx64(&user_frame.uf64.uctx, oonstack, mask, sp, (user64_size_t)stack_size,
				(user64_addr_t)&((struct user_sigframe64*)sp)->mctx);
#else
		panic("Shouldn't have 64-bit thread states on a 32-bit kernel.");
#endif
	} else {
		sendsig_fill_uctx32(&user_frame.uf32.uctx, oonstack, mask, sp, (user32_size_t)stack_size, 
				(user32_addr_t)&((struct user_sigframe32*)sp)->mctx);
	}

	/*
	 * Setup siginfo.
	 */
	bzero((caddr_t) & sinfo, sizeof(sinfo));
	sinfo.si_signo = sig;

	if (proc_is64bit_data(p)) {
#if defined(__arm64__)
		sinfo.si_addr = ts.ts64.ss.pc;
		sinfo.pad[0] = ts.ts64.ss.sp;
#else
		panic("Shouldn't have 64-bit thread states on a 32-bit kernel.");
#endif
	} else {
		sinfo.si_addr = ts.ts32.ss.pc;
		sinfo.pad[0] = ts.ts32.ss.sp;
	}

	switch (sig) {
	case SIGILL:
#ifdef	BER_XXX
		if (mctx.ss.srr1 & (1 << (31 - SRR1_PRG_ILL_INS_BIT)))
			sinfo.si_code = ILL_ILLOPC;
		else if (mctx.ss.srr1 & (1 << (31 - SRR1_PRG_PRV_INS_BIT)))
			sinfo.si_code = ILL_PRVOPC;
		else if (mctx.ss.srr1 & (1 << (31 - SRR1_PRG_TRAP_BIT)))
			sinfo.si_code = ILL_ILLTRP;
		else
			sinfo.si_code = ILL_NOOP;
#else
		sinfo.si_code = ILL_ILLTRP;
#endif
		break;

	case SIGFPE:
		break;

	case SIGBUS:
		if (proc_is64bit_data(p)) {
#if defined(__arm64__)
			sinfo.si_addr = user_frame.uf64.mctx.es.far;
#else
			panic("Shouldn't have 64-bit thread states on a 32-bit kernel.");
#endif
		} else {
			sinfo.si_addr = user_frame.uf32.mctx.es.far;
		}

		sinfo.si_code = BUS_ADRALN;
		break;

	case SIGSEGV:
		if (proc_is64bit_data(p)) {
#if defined(__arm64__)
			sinfo.si_addr = user_frame.uf64.mctx.es.far;
#else
			panic("Shouldn't have 64-bit thread states on a 32-bit kernel.");
#endif
		} else {
			sinfo.si_addr = user_frame.uf32.mctx.es.far;
		}

#ifdef	BER_XXX
		/* First check in srr1 and then in dsisr */
		if (mctx.ss.srr1 & (1 << (31 - DSISR_PROT_BIT)))
			sinfo.si_code = SEGV_ACCERR;
		else if (mctx.es.dsisr & (1 << (31 - DSISR_PROT_BIT)))
			sinfo.si_code = SEGV_ACCERR;
		else
			sinfo.si_code = SEGV_MAPERR;
#else
		sinfo.si_code = SEGV_ACCERR;
#endif
		break;

	default:
	{
		int status_and_exitcode;

		/*
		 * All other signals need to fill out a minimum set of
		 * information for the siginfo structure passed into
		 * the signal handler, if SA_SIGINFO was specified.
		 *
		 * p->si_status actually contains both the status and
		 * the exit code; we save it off in its own variable
		 * for later breakdown.
		 */
		proc_lock(p);
		sinfo.si_pid = p->si_pid;
		p->si_pid = 0;
		status_and_exitcode = p->si_status;
		p->si_status = 0;
		sinfo.si_uid = p->si_uid;
		p->si_uid = 0;
		sinfo.si_code = p->si_code;
		p->si_code = 0;
		proc_unlock(p);
		if (sinfo.si_code == CLD_EXITED) {
			if (WIFEXITED(status_and_exitcode))
				sinfo.si_code = CLD_EXITED;
			else if (WIFSIGNALED(status_and_exitcode)) {
				if (WCOREDUMP(status_and_exitcode)) {
					sinfo.si_code = CLD_DUMPED;
					status_and_exitcode = W_EXITCODE(status_and_exitcode,status_and_exitcode);
				} else {
					sinfo.si_code = CLD_KILLED;
					status_and_exitcode = W_EXITCODE(status_and_exitcode,status_and_exitcode);
				}
			}
		}
		/*
		 * The recorded status contains the exit code and the
		 * signal information, but the information to be passed
		 * in the siginfo to the handler is supposed to only
		 * contain the status, so we have to shift it out.
		 */
		sinfo.si_status = (WEXITSTATUS(status_and_exitcode) & 0x00FFFFFF) | (((uint32_t)(p->p_xhighbits) << 24) & 0xFF000000);
		p->p_xhighbits = 0;
		break;
	}
	}

#if CONFIG_DTRACE	
	sendsig_do_dtrace(ut, &sinfo, sig, catcher);
#endif /* CONFIG_DTRACE */

	/* 
	 * Copy signal-handling frame out to user space, set thread state.
	 */
	if (proc_is64bit_data(p)) {
#if defined(__arm64__)
		user64_addr_t token;

		/*
		 * mctx filled in when we get state.  uctx filled in by 
		 * sendsig_fill_uctx64(). We fill in the sinfo now.
		 */
		siginfo_user_to_user64(&sinfo, &user_frame.uf64.sinfo);

		p_uctx = (user_addr_t)&((struct user_sigframe64*)sp)->uctx;
		/*
		 * Generate the validation token for sigreturn
		 */
		token_uctx = p_uctx;
		kr = machine_thread_siguctx_pointer_convert_to_user(th_act, &token_uctx);
		assert(kr == KERN_SUCCESS);
		token = (user64_addr_t)token_uctx ^ (user64_addr_t)ps->ps_sigreturn_token;

		if (copyout(&user_frame.uf64, sp, sizeof(user_frame.uf64)) != 0) {
			goto bad; 
		} 

		if (sendsig_set_thread_state64(&ts.ts64.ss,
			catcher, infostyle, sig, (user64_addr_t)&((struct user_sigframe64*)sp)->sinfo,
			(user64_addr_t)p_uctx, token, trampact, sp, th_act) != KERN_SUCCESS)
			goto bad;

#else
	panic("Shouldn't have 64-bit thread states on a 32-bit kernel.");
#endif
	} else {
		user32_addr_t token;

		/*
		 * mctx filled in when we get state.  uctx filled in by 
		 * sendsig_fill_uctx32(). We fill in the sinfo, *pointer*
		 * to uctx and token now.
		 */
		siginfo_user_to_user32(&sinfo, &user_frame.uf32.sinfo);

		p_uctx = (user_addr_t)&((struct user_sigframe32*)sp)->uctx;
		/*
		 * Generate the validation token for sigreturn
		 */
		token_uctx = (user_addr_t)p_uctx;
		kr = machine_thread_siguctx_pointer_convert_to_user(th_act, &token_uctx);
		assert(kr == KERN_SUCCESS);
		token = (user32_addr_t)token_uctx ^ (user32_addr_t)ps->ps_sigreturn_token;

		user_frame.uf32.puctx = (user32_addr_t)p_uctx;
		user_frame.uf32.token = token;

		if (copyout(&user_frame.uf32, sp, sizeof(user_frame.uf32)) != 0) {
			goto bad; 
		} 

		if (sendsig_set_thread_state32(&ts.ts32.ss,
			CAST_DOWN_EXPLICIT(user32_addr_t, catcher), infostyle, sig, (user32_addr_t)&((struct user_sigframe32*)sp)->sinfo,
			CAST_DOWN_EXPLICIT(user32_addr_t, trampact), CAST_DOWN_EXPLICIT(user32_addr_t, sp), th_act) != KERN_SUCCESS)
			goto bad;
	}

	proc_lock(p);
	return;

bad:
	proc_lock(p);
bad2:
	SIGACTION(p, SIGILL) = SIG_DFL;
	sig = sigmask(SIGILL);
	p->p_sigignore &= ~sig;
	p->p_sigcatch &= ~sig;
	ut->uu_sigmask &= ~sig;
	/* sendsig is called with signal lock held */
	proc_unlock(p);
	psignal_locked(p, SIGILL);
	proc_lock(p);
}
Пример #24
0
int
main(int argc, char *argv[])
{
	START(argc, argv, "vmem_delete");

	VMEM *vmp;
	void *ptr;

	if (argc < 2)
		FATAL("usage: %s op:h|f|m|c|r|a|s|d", argv[0]);

	/* allocate memory for function vmem_create_in_region() */
	void *mem_pool = MMAP_ANON_ALIGNED(VMEM_MIN_POOL, 4 << 20);

	vmp = vmem_create_in_region(mem_pool, VMEM_MIN_POOL);
	if (vmp == NULL)
		FATAL("!vmem_create_in_region");

	ptr = vmem_malloc(vmp, sizeof (long long int));
	if (ptr == NULL)
		ERR("!vmem_malloc");
	vmem_delete(vmp);

	/* arrange to catch SEGV */
	struct sigaction v;
	sigemptyset(&v.sa_mask);
	v.sa_flags = 0;
	v.sa_handler = signal_handler;
	SIGACTION(SIGSEGV, &v, NULL);
	SIGACTION(SIGABRT, &v, NULL);
	SIGACTION(SIGILL, &v, NULL);

	/* go through all arguments one by one */
	for (int arg = 1; arg < argc; arg++) {
		/* Scan the character of each argument. */
		if (strchr("hfmcrasd", argv[arg][0]) == NULL ||
				argv[arg][1] != '\0')
			FATAL("op must be one of: h, f, m, c, r, a, s, d");

		switch (argv[arg][0]) {
		case 'h':
			OUT("Testing vmem_check...");
			if (!sigsetjmp(Jmp, 1)) {
				OUT("\tvmem_check returned %i",
							vmem_check(vmp));
			}
			break;

		case 'f':
			OUT("Testing vmem_free...");
			if (!sigsetjmp(Jmp, 1)) {
				vmem_free(vmp, ptr);
				OUT("\tvmem_free succeeded");
			}
			break;

		case 'm':
			OUT("Testing vmem_malloc...");
			if (!sigsetjmp(Jmp, 1)) {
				ptr = vmem_malloc(vmp, sizeof (long long int));
				if (ptr != NULL)
					OUT("\tvmem_malloc succeeded");
				else
					OUT("\tvmem_malloc returned NULL");
			}
			break;

		case 'c':
			OUT("Testing vmem_calloc...");
			if (!sigsetjmp(Jmp, 1)) {
				ptr = vmem_calloc(vmp, 10, sizeof (int));
				if (ptr != NULL)
					OUT("\tvmem_calloc succeeded");
				else
					OUT("\tvmem_calloc returned NULL");
			}
			break;

		case 'r':
			OUT("Testing vmem_realloc...");
			if (!sigsetjmp(Jmp, 1)) {
				ptr = vmem_realloc(vmp, ptr, 128);
				if (ptr != NULL)
					OUT("\tvmem_realloc succeeded");
				else
					OUT("\tvmem_realloc returned NULL");
			}
			break;

		case 'a':
			OUT("Testing vmem_aligned_alloc...");
			if (!sigsetjmp(Jmp, 1)) {
				ptr = vmem_aligned_alloc(vmp, 128, 128);
				if (ptr != NULL)
					OUT("\tvmem_aligned_alloc succeeded");
				else
					OUT("\tvmem_aligned_alloc"
							" returned NULL");
			}
			break;

		case 's':
			OUT("Testing vmem_strdup...");
			if (!sigsetjmp(Jmp, 1)) {
				ptr = vmem_strdup(vmp, "Test string");
				if (ptr != NULL)
					OUT("\tvmem_strdup succeeded");
				else
					OUT("\tvmem_strdup returned NULL");
			}
			break;

		case 'd':
			OUT("Testing vmem_delete...");
			if (!sigsetjmp(Jmp, 1)) {
				vmem_delete(vmp);
				if (errno != 0)
					OUT("\tvmem_delete failed: %s",
						vmem_errormsg());
				else
					OUT("\tvmem_delete succeeded");
			}
			break;
		}
	}

	DONE(NULL);
}
/*
 * Send a signal to process.
 */
void
sendsig_sigcontext(const ksiginfo_t *ksi, const sigset_t *returnmask)
{
	int sig = ksi->ksi_signo;
	struct lwp * const l = curlwp;
	struct proc * const p = l->l_proc;
	struct sigacts * const ps = p->p_sigacts;
	struct pcb * const pcb = lwp_getpcb(l);
	int onstack, error;
	struct sigcontext *scp = getframe(l, sig, &onstack);
	struct sigcontext ksc;
	struct trapframe * const tf = l->l_md.md_utf;
	sig_t catcher = SIGACTION(p, sig).sa_handler;

#if !defined(__mips_o32)
	if (p->p_md.md_abi != _MIPS_BSD_API_O32)
		sigexit(l, SIGILL);
#endif

	scp--;

#ifdef DEBUG
	if ((sigdebug & SDB_FOLLOW) ||
	    ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid))
		printf("sendsig(%d): sig %d ssp %p scp %p\n",
		       p->p_pid, sig, &onstack, scp);
#endif

	/* Build stack frame for signal trampoline. */
	ksc.sc_pc = tf->tf_regs[_R_PC];
	ksc.mullo = tf->tf_regs[_R_MULLO];
	ksc.mulhi = tf->tf_regs[_R_MULHI];

	/* Save register context. */
	ksc.sc_regs[_R_ZERO] = 0xACEDBADE;		/* magic number */
#if defined(__mips_o32)
	memcpy(&ksc.sc_regs[1], &tf->tf_regs[1],
	    sizeof(ksc.sc_regs) - sizeof(ksc.sc_regs[0]));
#else
	for (size_t i = 1; i < 32; i++)
		ksc.sc_regs[i] = tf->tf_regs[i];
#endif

	/* Save the FP state, if necessary, then copy it. */
	ksc.sc_fpused = fpu_used_p();
#if !defined(NOFPU)
	if (ksc.sc_fpused) {
		/* if FPU has current state, save it first */
		fpu_save();
	}
#endif
	*(struct fpreg *)ksc.sc_fpregs = *(struct fpreg *)&pcb->pcb_fpregs;

	/* Save signal stack. */
	ksc.sc_onstack = l->l_sigstk.ss_flags & SS_ONSTACK;

	/* Save signal mask. */
	ksc.sc_mask = *returnmask;

#if defined(COMPAT_13) || defined(COMPAT_ULTRIX)
	/*
	 * XXX We always have to save an old style signal mask because
	 * XXX we might be delivering a signal to a process which will
	 * XXX escape from the signal in a non-standard way and invoke
	 * XXX sigreturn() directly.
	 */
	native_sigset_to_sigset13(returnmask, &ksc.__sc_mask13);
#endif

	sendsig_reset(l, sig);

	mutex_exit(p->p_lock);
	error = copyout(&ksc, (void *)scp, sizeof(ksc));
	mutex_enter(p->p_lock);

	if (error != 0) {
		/*
		 * Process has trashed its stack; give it an illegal
		 * instruction to halt it in its tracks.
		 */
#ifdef DEBUG
		if ((sigdebug & SDB_FOLLOW) ||
		    ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid))
			printf("sendsig(%d): copyout failed on sig %d\n",
			    p->p_pid, sig);
#endif
		sigexit(l, SIGILL);
		/* NOTREACHED */
	}

	/*
	 * Set up the registers to directly invoke the signal
	 * handler.  The return address will be set up to point
	 * to the signal trampoline to bounce us back.
	 */
	tf->tf_regs[_R_A0] = sig;
	tf->tf_regs[_R_A1] = ksi->ksi_trap;
	tf->tf_regs[_R_A2] = (intptr_t)scp;
	tf->tf_regs[_R_A3] = (intptr_t)catcher;		/* XXX ??? */

	tf->tf_regs[_R_PC] = (intptr_t)catcher;
	tf->tf_regs[_R_T9] = (intptr_t)catcher;
	tf->tf_regs[_R_SP] = (intptr_t)scp;

	switch (ps->sa_sigdesc[sig].sd_vers) {
	case 0:		/* legacy on-stack sigtramp */
		tf->tf_regs[_R_RA] = (intptr_t)p->p_sigctx.ps_sigcode;
		break;
#ifdef COMPAT_16
	case 1:
		tf->tf_regs[_R_RA] = (intptr_t)ps->sa_sigdesc[sig].sd_tramp;
		break;
#endif
	default:
		/* Don't know what trampoline version; kill it. */
		sigexit(l, SIGILL);
	}

	/* Remember that we're now on the signal stack. */
	if (onstack)
		l->l_sigstk.ss_flags |= SS_ONSTACK;

#ifdef DEBUG
	if ((sigdebug & SDB_FOLLOW) ||
	    ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid))
		printf("sendsig(%d): sig %d returns\n",
		       p->p_pid, sig);
#endif
}
Пример #26
0
/*ARGSUSED*/
void
trap(struct frame *fp, int type, unsigned code, unsigned v)
{
	extern char fubail[], subail[];
	struct lwp *l;
	struct proc *p;
	struct pcb *pcb;
	void *onfault;
	ksiginfo_t ksi;
	int s;
	int rv;
	u_quad_t sticks = 0 /* XXX initialiser works around compiler bug */;
	static int panicking __diagused;

	curcpu()->ci_data.cpu_ntrap++;
	l = curlwp;
	p = l->l_proc;
	pcb = lwp_getpcb(l);

	KSI_INIT_TRAP(&ksi);
	ksi.ksi_trap = type & ~T_USER;

	if (USERMODE(fp->f_sr)) {
		type |= T_USER;
		sticks = p->p_sticks;
		l->l_md.md_regs = fp->f_regs;
		LWP_CACHE_CREDS(l, p);
	}
	switch (type) {

	default:
	dopanic:
		/*
		 * Let the kernel debugger see the trap frame that
		 * caused us to panic.  This is a convenience so
		 * one can see registers at the point of failure.
		 */
		s = splhigh();
		panicking = 1;
		printf("trap type %d, code = 0x%x, v = 0x%x\n", type, code, v);
		printf("%s program counter = 0x%x\n",
		    (type & T_USER) ? "user" : "kernel", fp->f_pc);
#ifdef KGDB
		/* If connected, step or cont returns 1 */
		if (kgdb_trap(type, (db_regs_t *)fp))
			goto kgdb_cont;
#endif
#ifdef DDB
		(void)kdb_trap(type, (db_regs_t *)fp);
#endif
#ifdef KGDB
	kgdb_cont:
#endif
		splx(s);
		if (panicstr) {
			printf("trap during panic!\n");
#ifdef DEBUG
			/* XXX should be a machine-dependent hook */
			printf("(press a key)\n"); (void)cngetc();
#endif
		}
		regdump((struct trapframe *)fp, 128);
		type &= ~T_USER;
		if ((u_int)type < trap_types)
			panic(trap_type[type]);
		panic("trap");

	case T_BUSERR:		/* kernel bus error */
		onfault = pcb->pcb_onfault;
		if (onfault == NULL)
			goto dopanic;
		rv = EFAULT;
		/* FALLTHROUGH */

	copyfault:
		/*
		 * If we have arranged to catch this fault in any of the
		 * copy to/from user space routines, set PC to return to
		 * indicated location and set flag informing buserror code
		 * that it may need to clean up stack frame.
		 */
		fp->f_stackadj = exframesize[fp->f_format];
		fp->f_format = fp->f_vector = 0;
		fp->f_pc = (int)onfault;
		fp->f_regs[D0] = rv;
		return;

	case T_BUSERR|T_USER:	/* bus error */
	case T_ADDRERR|T_USER:	/* address error */
		ksi.ksi_addr = (void *)v;
		ksi.ksi_signo = SIGBUS;
		ksi.ksi_code = (type == (T_BUSERR|T_USER)) ?
			BUS_OBJERR : BUS_ADRERR;
		break;

	case T_COPERR:		/* kernel coprocessor violation */
	case T_FMTERR|T_USER:	/* do all RTE errors come in as T_USER? */
	case T_FMTERR:		/* ...just in case... */
	/*
	 * The user has most likely trashed the RTE or FP state info
	 * in the stack frame of a signal handler.
	 */
		printf("pid %d: kernel %s exception\n", p->p_pid,
		       type==T_COPERR ? "coprocessor" : "format");
		type |= T_USER;

		mutex_enter(p->p_lock);
		SIGACTION(p, SIGILL).sa_handler = SIG_DFL;
		sigdelset(&p->p_sigctx.ps_sigignore, SIGILL);
		sigdelset(&p->p_sigctx.ps_sigcatch, SIGILL);
		sigdelset(&l->l_sigmask, SIGILL);
		mutex_exit(p->p_lock);

		ksi.ksi_signo = SIGILL;
		ksi.ksi_addr = (void *)(int)fp->f_format;
				/* XXX was ILL_RESAD_FAULT */
		ksi.ksi_code = (type == T_COPERR) ?
			ILL_COPROC : ILL_ILLOPC;
		break;

	case T_COPERR|T_USER:	/* user coprocessor violation */
	/* What is a proper response here? */
		ksi.ksi_signo = SIGFPE;
		ksi.ksi_code = FPE_FLTINV;
		break;

	case T_FPERR|T_USER:	/* 68881 exceptions */
	/*
	 * We pass along the 68881 status register which locore stashed
	 * in code for us.
	 */
		ksi.ksi_signo = SIGFPE;
		ksi.ksi_code = fpsr2siginfocode(code);
		break;

#ifdef M68040
	case T_FPEMULI|T_USER:	/* unimplemented FP instruction */
	case T_FPEMULD|T_USER:	/* unimplemented FP data type */
		/* XXX need to FSAVE */
		printf("pid %d(%s): unimplemented FP %s at %x (EA %x)\n",
		       p->p_pid, p->p_comm,
		       fp->f_format == 2 ? "instruction" : "data type",
		       fp->f_pc, fp->f_fmt2.f_iaddr);
		/* XXX need to FRESTORE */
		ksi.ksi_signo = SIGFPE;
		ksi.ksi_code = FPE_FLTINV;
		break;
#endif

	case T_ILLINST|T_USER:	/* illegal instruction fault */
	case T_PRIVINST|T_USER:	/* privileged instruction fault */
		ksi.ksi_addr = (void *)(int)fp->f_format;
				/* XXX was ILL_PRIVIN_FAULT */
		ksi.ksi_signo = SIGILL;
		ksi.ksi_code = (type == (T_PRIVINST|T_USER)) ?
			ILL_PRVOPC : ILL_ILLOPC;
		break;

	case T_ZERODIV|T_USER:	/* Divide by zero */
		ksi.ksi_addr = (void *)(int)fp->f_format;
				/* XXX was FPE_INTDIV_TRAP */
		ksi.ksi_signo = SIGFPE;
		ksi.ksi_code = FPE_FLTDIV;
		break;

	case T_CHKINST|T_USER:	/* CHK instruction trap */
		ksi.ksi_addr = (void *)(int)fp->f_format;
				/* XXX was FPE_SUBRNG_TRAP */
		ksi.ksi_signo = SIGFPE;
		break;

	case T_TRAPVINST|T_USER:	/* TRAPV instruction trap */
		ksi.ksi_addr = (void *)(int)fp->f_format;
				/* XXX was FPE_INTOVF_TRAP */
		ksi.ksi_signo = SIGFPE;
		break;

	/*
	 * XXX: Trace traps are a nightmare.
	 *
	 *	HP-UX uses trap #1 for breakpoints,
	 *	NetBSD/m68k uses trap #2,
	 *	SUN 3.x uses trap #15,
	 *	DDB and KGDB uses trap #15 (for kernel breakpoints;
	 *	handled elsewhere).
	 *
	 * NetBSD and HP-UX traps both get mapped by locore.s into T_TRACE.
	 * SUN 3.x traps get passed through as T_TRAP15 and are not really
	 * supported yet.
	 *
	 * XXX: We should never get kernel-mode T_TRAP15
	 * XXX: because locore.s now gives them special treatment.
	 */
	case T_TRAP15:		/* kernel breakpoint */
#ifdef DEBUG
		printf("unexpected kernel trace trap, type = %d\n", type);
		printf("program counter = 0x%x\n", fp->f_pc);
#endif
		fp->f_sr &= ~PSL_T;
		return;

	case T_TRACE|T_USER:	/* user trace trap */
#ifdef COMPAT_SUNOS
		/*
		 * SunOS uses Trap #2 for a "CPU cache flush".
		 * Just flush the on-chip caches and return.
		 */
		if (p->p_emul == &emul_sunos) {
			ICIA();
			DCIU();
			return;
		}
#endif
		/* FALLTHROUGH */
	case T_TRACE:		/* tracing a trap instruction */
	case T_TRAP15|T_USER:	/* SUN user trace trap */
		fp->f_sr &= ~PSL_T;
		ksi.ksi_signo = SIGTRAP;
		break;

	case T_ASTFLT:		/* system async trap, cannot happen */
		goto dopanic;

	case T_ASTFLT|T_USER:	/* user async trap */
		astpending = 0;
		/*
		 * We check for software interrupts first.  This is because
		 * they are at a higher level than ASTs, and on a VAX would
		 * interrupt the AST.  We assume that if we are processing
		 * an AST that we must be at IPL0 so we don't bother to
		 * check.  Note that we ensure that we are at least at SIR
		 * IPL while processing the SIR.
		 */
		spl1();
		/* fall into... */

	case T_SSIR:		/* software interrupt */
	case T_SSIR|T_USER:
		/*
		 * If this was not an AST trap, we are all done.
		 */
		if (type != (T_ASTFLT|T_USER)) {
			curcpu()->ci_data.cpu_ntrap--;
			return;
		}
		spl0();
		if (l->l_pflag & LP_OWEUPC) {
			l->l_pflag &= ~LP_OWEUPC;
			ADDUPROF(l);
		}
		if (curcpu()->ci_want_resched)
			preempt();
		goto out;

	case T_MMUFLT:		/* kernel mode page fault */
		/*
		 * If we were doing profiling ticks or other user mode
		 * stuff from interrupt code, Just Say No.
		 */
		onfault = pcb->pcb_onfault;
		if (onfault == fubail || onfault == subail) {
			rv = EFAULT;
			goto copyfault;
		}
		/* fall into ... */

	case T_MMUFLT|T_USER:	/* page fault */
	    {
		vaddr_t va;
		struct vmspace *vm = p->p_vmspace;
		struct vm_map *map;
		vm_prot_t ftype;
		extern struct vm_map *kernel_map;

		onfault = pcb->pcb_onfault;

#ifdef DEBUG
		if ((mmudebug & MDB_WBFOLLOW) || MDB_ISPID(p->p_pid))
		printf("trap: T_MMUFLT pid=%d, code=%x, v=%x, pc=%x, sr=%x\n",
		       p->p_pid, code, v, fp->f_pc, fp->f_sr);
#endif
		/*
		 * It is only a kernel address space fault iff:
		 * 	1. (type & T_USER) == 0  and
		 * 	2. pcb_onfault not set or
		 *	3. pcb_onfault set but supervisor space data fault
		 * The last can occur during an exec() copyin where the
		 * argument space is lazy-allocated.
		 */
		if ((type & T_USER) == 0 && (onfault == NULL || KDFAULT(code)))
			map = kernel_map;
		else {
			map = vm ? &vm->vm_map : kernel_map;
		}

		if (WRFAULT(code))
			ftype = VM_PROT_WRITE;
		else
			ftype = VM_PROT_READ;

		va = trunc_page((vaddr_t)v);

		if (map == kernel_map && va == 0) {
			printf("trap: bad kernel %s access at 0x%x\n",
			    (ftype & VM_PROT_WRITE) ? "read/write" :
			    "read", v);
			goto dopanic;
		}

#ifdef DIAGNOSTIC
		if (interrupt_depth && !panicking) {
			printf("trap: calling uvm_fault() from interrupt!\n");
			goto dopanic;
		}
#endif
		
		pcb->pcb_onfault = NULL;
		rv = uvm_fault(map, va, ftype);
		pcb->pcb_onfault = onfault;
#ifdef DEBUG
		if (rv && MDB_ISPID(p->p_pid))
			printf("uvm_fault(%p, 0x%lx, 0x%x) -> 0x%x\n",
			    map, va, ftype, rv);
#endif
		/*
		 * If this was a stack access we keep track of the maximum
		 * accessed stack size.  Also, if vm_fault gets a protection
		 * failure it is due to accessing the stack region outside
		 * the current limit and we need to reflect that as an access
		 * error.
		 */
		if (rv == 0) {
			if (map != kernel_map && (void *)va >= vm->vm_maxsaddr)
				uvm_grow(p, va);

			if (type == T_MMUFLT) {
				if (ucas_ras_check(&fp->F_t)) {
					return;
				}
#ifdef M68040
				if (cputype == CPU_68040)
					(void) writeback(fp, 1);
#endif
				return;
			}
			goto out;
		}
		if (rv == EACCES) {
			ksi.ksi_code = SEGV_ACCERR;
			rv = EFAULT;
		} else
			ksi.ksi_code = SEGV_MAPERR;
		if (type == T_MMUFLT) {
			if (onfault)
				goto copyfault;
			printf("uvm_fault(%p, 0x%lx, 0x%x) -> 0x%x\n",
			    map, va, ftype, rv);
			printf("  type %x, code [mmu,,ssw]: %x\n",
			       type, code);
			goto dopanic;
		}
		ksi.ksi_addr = (void *)v;
		switch (rv) {
		case ENOMEM:
			printf("UVM: pid %d (%s), uid %d killed: out of swap\n",
			       p->p_pid, p->p_comm,
			       l->l_cred ?
			       kauth_cred_geteuid(l->l_cred) : -1);
			ksi.ksi_signo = SIGKILL;
			break;
		case EINVAL:
			ksi.ksi_signo = SIGBUS;
			ksi.ksi_code = BUS_ADRERR;
			break;
		case EACCES:
			ksi.ksi_signo = SIGSEGV;
			ksi.ksi_code = SEGV_ACCERR;
			break;
		default:
			ksi.ksi_signo = SIGSEGV;
			ksi.ksi_code = SEGV_MAPERR;
			break;
		}
		break;
	    }
	}
	trapsignal(l, &ksi);
	if ((type & T_USER) == 0)
		return;
out:
	userret(l, fp, sticks, v, 1);
}
Пример #27
0
/*
 *  General purpose routine for passing commands to gdb.  All gdb commands
 *  come through here, where they are passed to gdb_command_funnel().
 */
void 
gdb_interface(struct gnu_request *req)
{
	if (!(pc->flags & GDB_INIT)) 
		error(FATAL, "gdb_interface: gdb not initialized?\n"); 

	if (output_closed()) 
		restart(0);

	if (!req->fp) {
		req->fp = ((pc->flags & RUNTIME) || (pc->flags2 & ALLOW_FP)) ? 
			fp : CRASHDEBUG(1) ? fp : pc->nullfp;
	}

	pc->cur_req = req;
	pc->cur_gdb_cmd = req->command;

	if (req->flags & GNU_RETURN_ON_ERROR) {
		error_hook = gdb_error_hook;
        	if (setjmp(pc->gdb_interface_env)) {
			pc->last_gdb_cmd = pc->cur_gdb_cmd;
			pc->cur_gdb_cmd = 0;
			pc->cur_req = NULL;
			req->flags |= GNU_COMMAND_FAILED;
			pc->flags &= ~IN_GDB;
			return;
		}
	} else
		error_hook = NULL;

	if (CRASHDEBUG(2))
		dump_gnu_request(req, IN_GDB);

        if (!(pc->flags & DROP_CORE)) 
		SIGACTION(SIGSEGV, restart, &pc->sigaction, NULL);
        else 
		SIGACTION(SIGSEGV, SIG_DFL, &pc->sigaction, NULL);

	if (interruptible()) { 
		SIGACTION(SIGINT, pc->gdb_sigaction.sa_handler, 
			&pc->gdb_sigaction, NULL);
	} else {
		SIGACTION(SIGINT, SIG_IGN, &pc->sigaction, NULL);
		SIGACTION(SIGPIPE, SIG_IGN, &pc->sigaction, NULL);
	} 

	pc->flags |= IN_GDB;
	gdb_command_funnel(req);
	pc->flags &= ~IN_GDB;

	SIGACTION(SIGINT, restart, &pc->sigaction, NULL);
	SIGACTION(SIGSEGV, SIG_DFL, &pc->sigaction, NULL);

	if (CRASHDEBUG(2))
		dump_gnu_request(req, !IN_GDB);

	error_hook = NULL;
        pc->last_gdb_cmd = pc->cur_gdb_cmd;
        pc->cur_gdb_cmd = 0;
	pc->cur_req = NULL;
}
Пример #28
0
static void
netbsd32_sendsig_sigcontext(const ksiginfo_t *ksi, const sigset_t *mask)
{
	int sig = ksi->ksi_signo;
	struct lwp *l = curlwp;
	struct proc *p = l->l_proc;
	struct sparc32_sigframe *fp;
	struct trapframe64 *tf;
	int addr, onstack, error;
	struct rwindow32 *oldsp, *newsp;
	register32_t sp;
	sig_t catcher = SIGACTION(p, sig).sa_handler;
	struct sparc32_sigframe sf;
	extern char netbsd32_sigcode[], netbsd32_esigcode[];
#define	szsigcode	(netbsd32_esigcode - netbsd32_sigcode)

	tf = l->l_md.md_tf;
	/* Need to attempt to zero extend this 32-bit pointer */
	oldsp = (struct rwindow32 *)(u_long)(u_int)tf->tf_out[6];
	/* Do we need to jump onto the signal stack? */
	onstack =
	    (l->l_sigstk.ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 &&
	    (SIGACTION(p, sig).sa_flags & SA_ONSTACK) != 0;
	if (onstack) {
		fp = (struct sparc32_sigframe *)((char *)l->l_sigstk.ss_sp +
					l->l_sigstk.ss_size);
		l->l_sigstk.ss_flags |= SS_ONSTACK;
	} else
		fp = (struct sparc32_sigframe *)oldsp;
	fp = (struct sparc32_sigframe *)((u_long)(fp - 1) & ~7);

#ifdef DEBUG
	sigpid = p->p_pid;
	if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) {
		printf("sendsig: %s[%d] sig %d newusp %p scp %p oldsp %p\n",
		    p->p_comm, p->p_pid, sig, fp, &fp->sf_sc, oldsp);
		if (sigdebug & SDB_DDB) Debugger();
	}
#endif
	/*
	 * Now set up the signal frame.  We build it in kernel space
	 * and then copy it out.  We probably ought to just build it
	 * directly in user space....
	 */
	sf.sf_signo = sig;
	sf.sf_code = (u_int)ksi->ksi_trap;
#if defined(COMPAT_SUNOS) || defined(MODULAR)
	sf.sf_scp = (u_long)&fp->sf_sc;
#endif
	sf.sf_addr = 0;			/* XXX */

	/*
	 * Build the signal context to be used by sigreturn.
	 */
	sf.sf_sc.sc_onstack = onstack;
	sf.sf_sc.sc_mask = *mask;
	sf.sf_sc.sc_sp = (u_long)oldsp;
	sf.sf_sc.sc_pc = tf->tf_pc;
	sf.sf_sc.sc_npc = tf->tf_npc;
	sf.sf_sc.sc_psr = TSTATECCR_TO_PSR(tf->tf_tstate); /* XXX */
	sf.sf_sc.sc_g1 = tf->tf_global[1];
	sf.sf_sc.sc_o0 = tf->tf_out[0];

	/*
	 * Put the stack in a consistent state before we whack away
	 * at it.  Note that write_user_windows may just dump the
	 * registers into the pcb; we need them in the process's memory.
	 * We also need to make sure that when we start the signal handler,
	 * its %i6 (%fp), which is loaded from the newly allocated stack area,
	 * joins seamlessly with the frame it was in when the signal occurred,
	 * so that the debugger and _longjmp code can back up through it.
	 */
	sendsig_reset(l, sig);
	mutex_exit(p->p_lock);
	newsp = (struct rwindow32 *)((long)fp - sizeof(struct rwindow32));
	write_user_windows();
#ifdef DEBUG
	if ((sigdebug & SDB_KSTACK))
	    printf("sendsig: saving sf to %p, setting stack pointer %p to %p\n",
		   fp, &(((struct rwindow32 *)newsp)->rw_in[6]), oldsp);
#endif
	sp = NETBSD32PTR32I(oldsp);
	error = (rwindow_save(l) || 
	    copyout(&sf, fp, sizeof sf) || 
	    copyout(&sp, &(((struct rwindow32 *)newsp)->rw_in[6]),
	        sizeof(sp)));
	mutex_enter(p->p_lock);
	if (error) {
		/*
		 * Process has trashed its stack; give it an illegal
		 * instruction to halt it in its tracks.
		 */
#ifdef DEBUG
		mutex_exit(p->p_lock);
		if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
			printf("sendsig: window save or copyout error\n");
		printf("sendsig: stack was trashed trying to send sig %d, sending SIGILL\n", sig);
		if (sigdebug & SDB_DDB) Debugger();
		mutex_enter(p->p_lock);
#endif
		sigexit(l, SIGILL);
		/* NOTREACHED */
	}

#ifdef DEBUG
	if (sigdebug & SDB_FOLLOW) {
		printf("sendsig: %s[%d] sig %d scp %p\n",
		       p->p_comm, p->p_pid, sig, &fp->sf_sc);
	}
#endif
	/*
	 * Arrange to continue execution at the code copied out in exec().
	 * It needs the function to call in %g1, and a new stack pointer.
	 */
	addr = p->p_psstrp - szsigcode;
	tf->tf_global[1] = (long)catcher;
	tf->tf_pc = addr;
	tf->tf_npc = addr + 4;
	tf->tf_out[6] = (uint64_t)(u_int)(u_long)newsp;

	/* Remember that we're now on the signal stack. */
	if (onstack)
		l->l_sigstk.ss_flags |= SS_ONSTACK;

#ifdef DEBUG
	if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid) {
		mutex_exit(p->p_lock);
		printf("sendsig: about to return to catcher %p thru %p\n", 
		       catcher, addr);
		if (sigdebug & SDB_DDB) Debugger();
		mutex_enter(p->p_lock);
	}
#endif
}
Пример #29
0
void
linux_sendsig(const ksiginfo_t *ksi, const sigset_t *mask)
{
    const int sig = ksi->ksi_signo;
    struct lwp *l = curlwp;
    struct proc *p = l->l_proc;
    struct sigacts *ps = p->p_sigacts;
    struct linux_rt_sigframe *fp;
    struct frame *f;
    int i, onstack, error;
    struct linux_rt_sigframe sf;

#ifdef DEBUG_LINUX
    printf("linux_sendsig()\n");
#endif /* DEBUG_LINUX */
    f = (struct frame *)l->l_md.md_regs;

    /*
     * Do we need to jump onto the signal stack?
     */
    onstack =
        (l->l_sigstk.ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 &&
        (SIGACTION(p, sig).sa_flags & SA_ONSTACK) != 0;

    /*
     * Allocate space for the signal handler context.
     */
    if (onstack)
        panic("linux_sendsig: onstack notyet");
    else
        fp = (struct linux_rt_sigframe *)(u_int32_t)f->f_regs[_R_SP];

    /*
     * Build stack frame for signal trampoline.
     */
    memset(&sf, 0, sizeof sf);

#if LINUX_SYS_rt_sigreturn > 127
#error LINUX_SYS_rt_sigreturn does not fit in a 16-bit opcode.
#endif

    /*
     * This is the signal trampoline used by Linux, we don't use it,
     * but we set it up in case an application expects it to be there.
     *
     * 	mov	r8, LINUX_SYS_rt_sigreturn
     * 	scall
     */
    sf.lrs_code = (0x3008d733 | LINUX_SYS_rt_sigreturn << 20);

    /*
     * The user context.
     */
    native_to_linux_sigset(&sf.lrs_uc.luc_sigmask, mask);
    sf.lrs_uc.luc_flags = 0;
    sf.lrs_uc.luc_link = NULL;

    /* This is used regardless of SA_ONSTACK in Linux AVR32. */
    sf.lrs_uc.luc_stack.ss_sp = l->l_sigstk.ss_sp;
    sf.lrs_uc.luc_stack.ss_size = l->l_sigstk.ss_size;
    sf.lrs_uc.luc_stack.ss_flags = 0;
    if (l->l_sigstk.ss_flags & SS_ONSTACK)
        sf.lrs_uc.luc_stack.ss_flags |= LINUX_SS_ONSTACK;
    if (l->l_sigstk.ss_flags & SS_DISABLE)
        sf.lrs_uc.luc_stack.ss_flags |= LINUX_SS_DISABLE;
    memcpy(sf.lrs_uc.luc_mcontext.lsc_regs, f->f_regs,
           sizeof(sf.lrs_uc.luc_mcontext.lsc_regs));
    sendsig_reset(l, sig);

    /*
     * Install the sigframe onto the stack.
     */
    fp -= sizeof(struct linux_rt_sigframe);
    mutex_exit(p->p_lock);
    error = copyout(&sf, fp, sizeof(sf));
    mutex_enter(p->p_lock);

    if (error != 0) {
        /*
         * Process has trashed its stack; give it an illegal
         * instruction to halt it in its tracks.
         */
#ifdef DEBUG_LINUX
        printf("linux_sendsig: stack trashed\n");
#endif /* DEBUG_LINUX */
        sigexit(l, SIGILL);
        /* NOTREACHED */
    }

#ifdef DEBUG_LINUX
    printf("sigcontext is at %p\n", &fp->lrs_sc);
#endif /* DEBUG_LINUX */

    /* Set up the registers to return to sigcode. */
    f->f_regs[_R_SP] = (register_t)fp;
    f->f_regs[_R_R12] = native_to_linux_signo[sig];
    f->f_regs[_R_R11] = 0;
    f->f_regs[_R_R10] = (register_t)&fp->lrs_uc;
    f->f_regs[_R_PC] = (register_t)SIGACTION(p, sig).sa_handler;

#define RESTORER(p, sig) \
	(p->p_sigacts->sa_sigdesc[(sig)].sd_tramp)

    if (ps->sa_sigdesc[sig].sd_vers != 0)
        f->f_regs[_R_LR] = (register_t)RESTORER(p, sig);
    else
        panic("linux_sendsig: SA_RESTORER");

    /* Remember that we're now on the signal stack. */
    if (onstack)
        l->l_sigstk.ss_flags |= SS_ONSTACK;

    return;
}
Пример #30
0
void setup_linux_sigframe(struct trapframe *tf, const ksiginfo_t *ksi,
    const sigset_t *mask)
{
	struct lwp *l = curlwp;
	struct proc *p = l->l_proc;
	struct linux_sigframe *sfp, sigframe;
	int onstack, error;
	int fsize, rndfsize;
	int sig = ksi->ksi_signo;
	extern char linux_sigcode[], linux_esigcode[];

	/* Do we need to jump onto the signal stack? */
	onstack = (l->l_sigstk.ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 &&
		  (SIGACTION(p, sig).sa_flags & SA_ONSTACK) != 0;

	/* Allocate space for the signal handler context.  */
	fsize = sizeof(struct linux_sigframe);
	rndfsize = ((fsize + 15) / 16) * 16;

	if (onstack)
		sfp = (struct linux_sigframe *)
		    ((char *)l->l_sigstk.ss_sp + l->l_sigstk.ss_size);
	else
		sfp = (struct linux_sigframe *)(alpha_pal_rdusp());
	sfp = (struct linux_sigframe *)((char *)sfp - rndfsize);

#ifdef DEBUG
	if ((sigdebug & SDB_KSTACK) && (p->p_pid == sigpid))
		printf("linux_sendsig(%d): sig %d ssp %p usp %p\n", p->p_pid,
		    sig, &onstack, sfp);
#endif /* DEBUG */

	/*
	 * Build the signal context to be used by sigreturn.
	 */
	memset(&sigframe.sf_sc, 0, sizeof(struct linux_sigcontext));
	sigframe.sf_sc.sc_onstack = onstack;
	native_to_linux_old_sigset(&sigframe.sf_sc.sc_mask, mask);
	sigframe.sf_sc.sc_pc = tf->tf_regs[FRAME_PC];
	sigframe.sf_sc.sc_ps = ALPHA_PSL_USERMODE;
	frametoreg(tf, (struct reg *)sigframe.sf_sc.sc_regs);
	sigframe.sf_sc.sc_regs[R_SP] = alpha_pal_rdusp();

	if (l == fpcurlwp) {
		struct pcb *pcb = lwp_getpcb(l);

		alpha_pal_wrfen(1);
		savefpstate(&pcb->pcb_fp);
		alpha_pal_wrfen(0);
		sigframe.sf_sc.sc_fpcr = pcb->pcb_fp.fpr_cr;
		fpcurlwp = NULL;
	}
	/* XXX ownedfp ? etc...? */

	sigframe.sf_sc.sc_traparg_a0 = tf->tf_regs[FRAME_A0];
	sigframe.sf_sc.sc_traparg_a1 = tf->tf_regs[FRAME_A1];
	sigframe.sf_sc.sc_traparg_a2 = tf->tf_regs[FRAME_A2];

	sendsig_reset(l, sig);
	mutex_exit(p->p_lock);
	error = copyout((void *)&sigframe, (void *)sfp, fsize);
	mutex_enter(p->p_lock);

	if (error != 0) {
#ifdef DEBUG
		if ((sigdebug & SDB_KSTACK) && p->p_pid == sigpid)
			printf("sendsig(%d): copyout failed on sig %d\n",
			    p->p_pid, sig);
#endif
		/*
		 * Process has trashed its stack; give it an illegal
		 * instruction to halt it in its tracks.
		 */
		sigexit(l, SIGILL);
		/* NOTREACHED */
	}

	/* Pass pointers to sigcontext in the regs */
	tf->tf_regs[FRAME_A1] = 0;
	tf->tf_regs[FRAME_A2] = (unsigned long)&sfp->sf_sc;

	/* Address of trampoline code.  End up at this PC after mi_switch */
	tf->tf_regs[FRAME_PC] =
	    (u_int64_t)(p->p_psstrp - (linux_esigcode - linux_sigcode));

	/* Adjust the stack */
	alpha_pal_wrusp((unsigned long)sfp);

	/* Remember that we're now on the signal stack. */
	if (onstack)
		l->l_sigstk.ss_flags |= SS_ONSTACK;
}