void syscall_handler_tt(int sig, struct pt_regs *regs)
{
	void *sc;
	long result;
	int syscall;
#ifdef CONFIG_SYSCALL_DEBUG
	int index;
  	index = record_syscall_start(syscall);
#endif
	sc = UPT_SC(&regs->regs);
	SC_START_SYSCALL(sc);

	syscall_trace(&regs->regs, 0);

	current->thread.nsyscalls++;
	nsyscalls++;
	syscall = UPT_SYSCALL_NR(&regs->regs);

	if((syscall >= NR_syscalls) || (syscall < 0))
		result = -ENOSYS;
	else result = EXECUTE_SYSCALL(syscall, regs);

	/* regs->sc may have changed while the system call ran (there may
	 * have been an interrupt or segfault), so it needs to be refreshed.
	 */
	UPT_SC(&regs->regs) = sc;

	SC_SET_SYSCALL_RETURN(sc, result);

	syscall_trace(&regs->regs, 1);
#ifdef CONFIG_SYSCALL_DEBUG
  	record_syscall_end(index, result);
#endif
}
void handle_syscall(struct uml_pt_regs *r)
{
	struct pt_regs *regs = container_of(r, struct pt_regs, regs);
	long result;
	int syscall;

	syscall_trace(r, 0);

	/*
	 * This should go in the declaration of syscall, but when I do that,
	 * strace -f -c bash -c 'ls ; ls' breaks, sometimes not tracing
	 * children at all, sometimes hanging when bash doesn't see the first
	 * ls exit.
	 * The assembly looks functionally the same to me.  This is
	 *     gcc version 4.0.1 20050727 (Red Hat 4.0.1-5)
	 * in case it's a compiler bug.
	 */
	syscall = UPT_SYSCALL_NR(r);
	if ((syscall >= NR_SYSCALLS) || (syscall < 0))
		result = -ENOSYS;
	else result = EXECUTE_SYSCALL(syscall, regs);

	REGS_SET_SYSCALL_RETURN(r->gp, result);

	syscall_trace(r, 1);
}
Exemple #3
0
void handle_syscall(union uml_pt_regs *regs)
{
	long result;
	int index;

	index = record_syscall_start(UPT_SYSCALL_NR(regs));

	syscall_trace();
	result = execute_syscall(regs);

	REGS_SET_SYSCALL_RETURN(regs->skas.regs, result);
	if((result == -ERESTARTNOHAND) || (result == -ERESTARTSYS) || 
	   (result == -ERESTARTNOINTR))
		do_signal(result);

	syscall_trace();
	record_syscall_end(index, result);
}
Exemple #4
0
void handle_syscall(union uml_pt_regs *regs)
{
	long result;
#ifdef UML_CONFIG_SYSCALL_DEBUG
  	int index;

  	index = record_syscall_start(UPT_SYSCALL_NR(regs));
#endif

	syscall_trace(regs, 0);
	result = execute_syscall_skas(regs);

	REGS_SET_SYSCALL_RETURN(regs->skas.regs, result);

	syscall_trace(regs, 1);
#ifdef UML_CONFIG_SYSCALL_DEBUG
  	record_syscall_end(index, result);
#endif
}
Exemple #5
0
void do_sys(struct pt_regs *regs)
{
	unsigned long syscallnr, usp;
	syscall_t syscall;
	int errno, narg;

	/*
	 * Compute the return address;
	 */
	if (regs->cp0_cause & CAUSEF_BD)
	{
		/*
		 * This syscall is in a branch delay slot.  Since we don't do
		 * branch delay slot handling we would get a process trying
		 * to do syscalls ever and ever again.  So better zap it.
		 */
		printk("%s: syscall in branch delay slot.\n", current->comm);
		current->sig->action[SIGILL-1].sa_handler = NULL;
		current->blocked &= ~(1<<(SIGILL-1));
		send_sig(SIGILL, current, 1);
		return;
	}
	regs->cp0_epc += 4;

	syscallnr = regs->reg2;
	if (syscallnr > (__NR_Linux + __NR_Linux_syscalls))
		goto illegal_syscall;

	syscall = sys_call_table[syscallnr];
	if (syscall == NULL)
		goto illegal_syscall;

	narg = sys_narg_table[syscallnr];
	if (narg > 4)
	{
		/*
		 * Verify that we can safely get the additional parameters
		 * from the user stack.  Of course I could read the params
		 * from unaligned addresses ...  Consider this a programming
		 * course caliber .45.
		 */
		usp = regs->reg29;
		if (usp & 3)
		{
			printk("unaligned usp\n");
			send_sig(SIGSEGV, current, 1);
			regs->reg2 = EFAULT;
			regs->reg7 = 1;
			return;
		}
		errno = verify_area(VERIFY_READ, (void *) (usp + 16),
		                    (narg - 4) * sizeof(unsigned long));
		if (errno < 0)
			goto bad_syscall;
	}

	if ((current->flags & PF_TRACESYS) == 0)
	{
		errno = do_syscalls(regs, syscall, narg);
		if (errno < 0 || current->errno)
			goto bad_syscall;

		regs->reg2 = errno;
		regs->reg7 = 0;
	}
	else
	{
		syscall_trace();

		errno = do_syscalls(regs, syscall, narg);
		if (errno < 0 || current->errno)
		{
			regs->reg2 = -errno;
			regs->reg7 = 1;
		}
		else
		{
			regs->reg2 = errno;
			regs->reg7 = 0;
		}

		syscall_trace();
	}
	return;

bad_syscall:
	regs->reg2 = -errno;
	regs->reg7 = 1;
	return;
illegal_syscall:
	regs->reg2 = ENOSYS;
	regs->reg7 = 1;
	return;
}
Exemple #6
0
asmlinkage void
irix_sigreturn(struct pt_regs *regs)
{
	struct sigctx_irix5 *context, *magic;
	unsigned long umask, mask;
	u64 *fregs;
	int sig, i, base = 0;
	sigset_t blocked;

	if(regs->regs[2] == 1000)
		base = 1;

	context = (struct sigctx_irix5 *) regs->regs[base + 4];
	magic = (struct sigctx_irix5 *) regs->regs[base + 5];
	sig = (int) regs->regs[base + 6];
#ifdef DEBUG_SIG
	printk("[%s:%d] IRIX sigreturn(scp[%p],ucp[%p],sig[%d])\n",
	       current->comm, current->pid, context, magic, sig);
#endif
	if (!context)
		context = magic;
	if (!access_ok(VERIFY_READ, context, sizeof(struct sigctx_irix5)))
		goto badframe;

#ifdef DEBUG_SIG
	dump_irix5_sigctx(context);
#endif

	__get_user(regs->cp0_epc, &context->pc);
	umask = context->rmask; mask = 2;
	for (i = 1; i < 32; i++, mask <<= 1) {
		if(umask & mask)
			__get_user(regs->regs[i], &context->regs[i]);
	}
	__get_user(regs->hi, &context->hi);
	__get_user(regs->lo, &context->lo);

	if ((umask & 1) && context->usedfp) {
		fregs = (u64 *) &current->thread.fpu;
		for(i = 0; i < 32; i++)
			fregs[i] = (u64) context->fpregs[i];
		__get_user(current->thread.fpu.hard.control, &context->fpcsr);
	}

	/* XXX do sigstack crapola here... XXX */

	if (__copy_from_user(&blocked, &context->sigset, sizeof(blocked)))
		goto badframe;

	sigdelsetmask(&blocked, ~_BLOCKABLE);
	spin_lock_irq(&current->sigmask_lock);
	current->blocked = blocked;
	recalc_sigpending(current);
	spin_unlock_irq(&current->sigmask_lock);

	/*
	 * Don't let your children do this ...
	 */
	if (current->ptrace & PT_TRACESYS)
		syscall_trace();
	__asm__ __volatile__(
		"move\t$29,%0\n\t"
		"j\tret_from_sys_call"
		:/* no outputs */
		:"r" (&regs));
		/* Unreached */

badframe:
	force_sig(SIGSEGV, current);
}