Beispiel #1
0
static int
save_fpu_state_to_user_stack(
	struct sigcontext __user *	sc,
	struct _fpstate __user *	fpstate
)
{
	if (__put_user(fpstate, &sc->fpstate))
		return -EFAULT;

	return save_i387(fpstate);
}
Beispiel #2
0
static int
setup_sigcontext(struct sigcontext __user *sc, struct _fpstate __user *fpstate,
		 struct pt_regs *regs, unsigned long mask)
{
	int tmp, err = 0;

	tmp = 0;
	savesegment(gs, tmp);
	err |= __put_user(tmp, (unsigned int __user *)&sc->gs);
	savesegment(fs, tmp);
	err |= __put_user(tmp, (unsigned int __user *)&sc->fs);

	err |= __put_user(regs->xes, (unsigned int __user *)&sc->es);
	err |= __put_user(regs->xds, (unsigned int __user *)&sc->ds);
	err |= __put_user(regs->edi, &sc->edi);
	err |= __put_user(regs->esi, &sc->esi);
	err |= __put_user(regs->ebp, &sc->ebp);
	err |= __put_user(regs->esp, &sc->esp);
	err |= __put_user(regs->ebx, &sc->ebx);
	err |= __put_user(regs->edx, &sc->edx);
	err |= __put_user(regs->ecx, &sc->ecx);
	err |= __put_user(regs->eax, &sc->eax);
	err |= __put_user(current->thread.trap_no, &sc->trapno);
	err |= __put_user(current->thread.error_code, &sc->err);
	err |= __put_user(regs->eip, &sc->eip);
	err |= __put_user(regs->xcs, (unsigned int __user *)&sc->cs);
	err |= __put_user(regs->eflags, &sc->eflags);
	err |= __put_user(regs->esp, &sc->esp_at_signal);
	err |= __put_user(regs->xss, (unsigned int __user *)&sc->ss);

	tmp = save_i387(fpstate);
	if (tmp < 0)
	  err = 1;
	else
	  err |= __put_user(tmp ? fpstate : NULL, &sc->fpstate);

	/* non-iBCS2 extensions.. */
	err |= __put_user(mask, &sc->oldmask);
	err |= __put_user(current->thread.cr2, &sc->cr2);

	return err;
}
Beispiel #3
0
static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
			   sigset_t *set, struct pt_regs * regs)
{
	struct rt_sigframe __user *frame;
	struct _fpstate __user *fp = NULL; 
	int err = 0;
	struct task_struct *me = current;

	if (used_math()) {
		fp = get_stack(ka, regs, sizeof(struct _fpstate)); 
		frame = (void __user *)round_down(
			(unsigned long)fp - sizeof(struct rt_sigframe), 16) - 8;

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

		if (save_i387(fp) < 0) 
			err |= -1; 
	} else
		frame = get_stack(ka, regs, sizeof(struct rt_sigframe)) - 8;

	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
		goto give_sigsegv;

	if (ka->sa.sa_flags & SA_SIGINFO) { 
		err |= copy_siginfo_to_user(&frame->info, info);
		if (err)
			goto give_sigsegv;
	}
		
	/* 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(regs->rsp),
			  &frame->uc.uc_stack.ss_flags);
	err |= __put_user(me->sas_ss_size, &frame->uc.uc_stack.ss_size);
	err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, set->sig[0], me);
	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 give_sigsegv; 
	}

	if (err)
		goto give_sigsegv;

#ifdef DEBUG_SIG
	printk("%d old rip %lx old rsp %lx old rax %lx\n", current->pid,regs->rip,regs->rsp,regs->rax);
#endif

	/* Set up registers for signal handler */
	regs->rdi = sig;
	/* In case the signal handler was declared without prototypes */ 
	regs->rax = 0;	

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

	regs->rsp = (unsigned long)frame;

	/* Set up the CS register to run signal handlers in 64-bit mode,
	   even if the handler happens to be interrupting 32-bit code. */
	regs->cs = __USER_CS;

	/* This, by contrast, has nothing to do with segment registers -
	   see include/asm-x86_64/uaccess.h for details. */
	set_fs(USER_DS);

	regs->eflags &= ~TF_MASK;
	if (test_thread_flag(TIF_SINGLESTEP))
		ptrace_notify(SIGTRAP);
#ifdef DEBUG_SIG
	printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n",
		current->comm, current->pid, frame, regs->rip, frame->pretcode);
#endif

	return 0;

give_sigsegv:
	force_sigsegv(sig, current);
	return -EFAULT;
}
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);
}
Beispiel #5
0
SCOPE void
injector_entry(struct syscall_regs r,
		uint32_t old_vdso_ventry,
		uint32_t main_addr)
{
	int err;

	/* build STDOUT_FILENO_INJ and STDERR_FILENO_INJ */
	/* all INJ_XXXX messages are wrote to console through
	 * STDOUT_FILENO_INJ and STDERR_FILENO_INJ, not the original
	 * 1 and 2. This is for some targets which close 1 and 2, like
	 * lighttpd.
	 * STDOUT_FILENO_INJ and STDERR_FILENO_INJ are defined in injector_debug.h */
	if (STDOUT_FILENO != STDOUT_FILENO_INJ)
		INTERNAL_SYSCALL(dup2, 2, STDOUT_FILENO, STDOUT_FILENO_INJ);
	if (STDERR_FILENO != STDERR_FILENO_INJ)
		INTERNAL_SYSCALL(dup2, 2, STDERR_FILENO, STDERR_FILENO_INJ);


	INJ_TRACE("Here! we come to injector!!!\n");
	INJ_TRACE("wrapped_sigreturn=%p\n", wrapped_sigreturn);
	INJ_TRACE("wrapped_rt_sigreturn=%p\n", wrapped_rt_sigreturn);

	ASSERT(injector_opts.logger_threshold >= 4096, &r, "logger threshold %d is strange\n",
			injector_opts.logger_threshold);

	old_self_pid = self_pid = INTERNAL_SYSCALL(getpid, 0);

	if (injector_opts.untraced) {
		/* We need to restore sighandler's restorer here */
		tracing = 0;
		unhook_sighandlers();
		return;
	}

	tracing = 1;

	snprintf(logger_filename, 128, LOGGER_DIRECTORY"/%d.log", self_pid);
	INJ_TRACE("logger fn: %s\n", logger_filename);

	snprintf(ckpt_filename, 128, LOGGER_DIRECTORY"/%d.ckpt", self_pid);
	INJ_TRACE("ckpt fn: %s\n", ckpt_filename);

	int fd = INTERNAL_SYSCALL(open, 3, logger_filename, O_WRONLY|O_APPEND, 0664);
	INJ_TRACE("logger fd = %d\n", fd);
	ASSERT(fd > 0, &r, "open logger failed: %d\n", fd);

	/* dup the fd to LOGGER_FD */
	err = INTERNAL_SYSCALL(dup2, 2, fd, LOGGER_FD);
	ASSERT(err == LOGGER_FD, &r, "dup2 failed: %d\n", err);
	INJ_TRACE("dup fd to %d\n", err);

	err = INTERNAL_SYSCALL(close, 1, fd);
	ASSERT(err == 0, &r, "close failed: %d\n", err);
	INJ_TRACE("close %d\n", fd);

	logger_fd = LOGGER_FD;

	/* save the sigprocmask */
	INTERNAL_SYSCALL(rt_sigprocmask, 4,
			0, NULL, &state_vector.sigmask, sizeof(state_vector.sigmask));

	/* :NOTICE: */
	/* We MUST adjust esp here. when loader call injector, it pushs
	 * 2 int32_t onto stack, so the esp in 'r' cannot be used directly.
	 */
	save_i387(&fpustate_struct);
	r.esp += 8;
	make_checkpoint(ckpt_filename, &r, &fpustate_struct, NULL);
	r.esp -= 8;

	err = INTERNAL_SYSCALL(ftruncate, 2, logger_fd, 0);
	ASSERT(err == 0, &r, "ftruncate failed: %d\n", err);
	INJ_TRACE("main ip=0x%x:0x%x\n", main_addr, r.eip);
	INJ_TRACE("eax=%d\n", r.eax);
}
Beispiel #6
0
SCOPE void
wrapped_syscall(const struct syscall_regs r)
{
	/* if we don't trace fork and clone, the
	 * child process can set tracing to 0 */
	if (!tracing) {
		uint32_t retval;
		call_syscall(r, retval);
		return;
	}

	/* we must set signal_regs very early. if we set it
	 * inside ENTER/EXIT_SYSCALL, a signal may happen before this assignment. */
	/* don't check IS_BREAK_SYSCALL. we allow embeded signal handler. */
	/* if a signal raise, we will use signal_regs immediately. so don't worry about
	 * override. (the signal handler will save this regs before any new syscall, and
	 * the restorer needn't it). */
	signal_regs = &r;
	
	/* if a signal raise outside a syscall, those 2 values should same. if not, thay are
	 * different. */
	__syscall_reenter_base = __syscall_reenter_counter;

	/* if a signal happened after this gate and before EXIT_SYSCALL,
	 * we know this syscall is disturbed, when sigprocess making ckpts,
	 * it needs to adjust registers. */


	/* don't allow signal inside before_syscall.
	 * if signal happened inside it, the logger may be disturbed. */
	/* disable dignal before enter_syscall make sure the sysall's header
	 * is written into log when potential signal raise */
	DISABLE_SIGNAL();
	ENTER_SYSCALL();

	if (!replay) {
		uint32_t syscall_nr = r.orig_eax;
		INJ_SILENT("wrapped_syscall: %d\n", syscall_nr);

		before_syscall(&r);
		ENABLE_SIGNAL();

		uint32_t retval;

		call_syscall(r, retval);

		DISABLE_SIGNAL();

		/* write a flag to indicate syscall not be disturbed */
		/* if this syscall disturbed, the next data in logger
		 * may be a syscall_nr (if signal processing use syscall) or a -2
		 * (write by wrapped_(rt_)sigreturn). when replay, if see this -1,
		 * we know this syscall ends normally. */
		int16_t f = -1;
		if (!(is_fork_syscall(syscall_nr) && (retval == 0))) {
			int err;
			err = INTERNAL_SYSCALL(write, 3, logger_fd, &f, sizeof(f));
			ASSERT(err == sizeof(f), &r, "write signal tag failed: %d\n", err);
			logger_sz += err;
		}
		/* don't allow signal in after_syscall. if signal happens
		 * in it, the syscall handler may only write a part of log into
		 * log file. when ckpt is made and resume, it will write the left,
		 * makes the log file inconsistent. */
		after_syscall(&r);

		INJ_SILENT("wrapped_syscall: %d over, retval=%d\n", syscall_nr, r.eax);

		/* in the assembly code, we have modify the 'eax'. */

		/* check the logger sz */
		INJ_SILENT("logger_sz = %d\n", logger_sz);
		/* don't switch when signal processing */
		if ((logger_sz > injector_opts.logger_threshold) &&
				(!IS_REENTER_SYSCALL())) {
			int err;

			/* we need to remake ckpt */
			INJ_TRACE("make ckpt: eip=0x%x\n", r.eip);
			/* we still need to adjust esp:
			 * when we come here, r.esp hold an 'ret' address for
			 * coming 'ret'. */
			((struct syscall_regs*)(&r))->esp += 4;
			/* save fpustate */
			save_i387(&fpustate_struct);
			make_checkpoint(ckpt_filename, (struct syscall_regs *)(&r),
					&fpustate_struct, NULL);
			((struct syscall_regs*)(&r))->esp -= 4;

			/* truncate logger file */
			err = INTERNAL_SYSCALL(ftruncate, 2, logger_fd, 0);
			ASSERT(err == 0, &r, "ftruncate failed: %d\n", err);

			/* reset logger_sz */
			/* logger_sz have been reset in do_make_checkpoint */
			/* logger_sz = 0; */
		}
		EXIT_SYSCALL();
		ENABLE_SIGNAL();
	} else {
		/* this gate is useless in replay */
		EXIT_SYSCALL();
		ENABLE_SIGNAL();
		INJ_SILENT("replay syscall, eax=%d\n", r.eax);
		uint32_t retval;
		retval = replay_syscall(&r);
		INJ_SILENT("syscall, eax=%d, replayed: %d\n", r.eax, retval);
		/* here we force to reset the eax */
		(((volatile struct syscall_regs *)&r)->eax) = retval;
	}
}
Beispiel #7
0
static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
               sigset_t *set, struct pt_regs * regs)
{
    struct rt_sigframe __user *frame;
    struct _fpstate __user *fp = NULL; 
    int err = 0;
    struct task_struct *me = current;

    if (used_math()) {
        fp = get_stack(ka, regs, sizeof(struct _fpstate)); 
        frame = (void __user *)round_down(
            (unsigned long)fp - sizeof(struct rt_sigframe), 16) - 8;

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

        if (save_i387(fp) < 0) 
            err |= -1; 
    } else
        frame = get_stack(ka, regs, sizeof(struct rt_sigframe)) - 8;

    if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
        goto give_sigsegv;

    if (ka->sa.sa_flags & SA_SIGINFO) { 
        err |= copy_siginfo_to_user(&frame->info, info);
        if (err)
            goto give_sigsegv;
    }
        
    /* 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(regs->sp),
              &frame->uc.uc_stack.ss_flags);
    err |= __put_user(me->sas_ss_size, &frame->uc.uc_stack.ss_size);
    err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, set->sig[0], me);
    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 give_sigsegv; 
    }

    if (err)
        goto give_sigsegv;

    /* Set up registers for signal handler */
    regs->di = sig;
    /* In case the signal handler was declared without prototypes */ 
    regs->ax = 0;

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

    regs->sp = (unsigned long)frame;

    /* Set up the CS register to run signal handlers in 64-bit mode,
       even if the handler happens to be interrupting 32-bit code. */
    regs->cs = __USER_CS;

    return 0;

give_sigsegv:
    force_sigsegv(sig, current);
    return -EFAULT;
}