示例#1
0
文件: syscall.c 项目: AK101111/linux
void handle_syscall(struct uml_pt_regs *r)
{
	struct pt_regs *regs = container_of(r, struct pt_regs, regs);
	int syscall;

	/* Initialize the syscall number and default return value. */
	UPT_SYSCALL_NR(r) = PT_SYSCALL_NR(r->gp);
	PT_REGS_SET_SYSCALL_RETURN(regs, -ENOSYS);

	if (syscall_trace_enter(regs))
		return;

	/* Do the seccomp check after ptrace; failures should be fast. */
	if (secure_computing(NULL) == -1)
		return;

	/* Update the syscall number after orig_ax has potentially been updated
	 * with ptrace.
	 */
	UPT_SYSCALL_NR(r) = PT_SYSCALL_NR(r->gp);
	syscall = UPT_SYSCALL_NR(r);

	if (syscall >= 0 && syscall <= __NR_syscall_max)
		PT_REGS_SET_SYSCALL_RETURN(regs,
				EXECUTE_SYSCALL(syscall, regs));

	syscall_trace_leave(regs);
}
示例#2
0
/*To use the same value of using_sysemu as the caller, ask it that value (in local_using_sysemu)*/
static void handle_trap(int pid, union uml_pt_regs *regs, int local_using_sysemu)
{
	int err, status;

	/* Mark this as a syscall */
	UPT_SYSCALL_NR(regs) = PT_SYSCALL_NR(regs->skas.regs);

	if (!local_using_sysemu)
	{
		err = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET, __NR_getpid);
		if(err < 0)
			panic("handle_trap - nullifying syscall failed errno = %d\n",
			      errno);

		err = ptrace(PTRACE_SYSCALL, pid, 0, 0);
		if(err < 0)
			panic("handle_trap - continuing to end of syscall failed, "
			      "errno = %d\n", errno);

		CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED));
		if((err < 0) || !WIFSTOPPED(status) ||
		   (WSTOPSIG(status) != SIGTRAP + 0x80))
			panic("handle_trap - failed to wait at end of syscall, "
			      "errno = %d, status = %d\n", errno, status);
	}

	handle_syscall(regs);
}
示例#3
0
static void handle_trap(int pid, union uml_pt_regs *regs)
{
	int err, syscall_nr, status;

	syscall_nr = PT_SYSCALL_NR(regs->skas.regs);
	UPT_SYSCALL_NR(regs) = syscall_nr;
	if(syscall_nr < 1){
		relay_signal(SIGTRAP, regs);
		return;
	}

	err = ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_NR_OFFSET, __NR_getpid);
	if(err < 0)
	        panic("handle_trap - nullifying syscall failed errno = %d\n", 
		      errno);

	err = ptrace(PTRACE_SYSCALL, pid, 0, 0);
	if(err < 0)
	        panic("handle_trap - continuing to end of syscall failed, "
		      "errno = %d\n", errno);

	CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED));
	if((err < 0) || !WIFSTOPPED(status) || (WSTOPSIG(status) != SIGTRAP))
		panic("handle_trap - failed to wait at end of syscall, "
		      "errno = %d, status = %d\n", errno, status);

	handle_syscall(regs);
}
示例#4
0
void userspace(union uml_pt_regs *regs)
{
	int err, status, op, pid = userspace_pid[0];
	int local_using_sysemu; /*To prevent races if using_sysemu changes under us.*/

	while(1){
		restore_registers(pid, regs);

		/* Now we set local_using_sysemu to be used for one loop */
		local_using_sysemu = get_using_sysemu();

		op = SELECT_PTRACE_OPERATION(local_using_sysemu, singlestepping(NULL));

		err = ptrace(op, pid, 0, 0);
		if(err)
			panic("userspace - could not resume userspace process, "
			      "pid=%d, ptrace operation = %d, errno = %d\n",
			      op, errno);

		CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED));
		if(err < 0)
			panic("userspace - waitpid failed, errno = %d\n", 
			      errno);

		regs->skas.is_user = 1;
		save_registers(pid, regs);
		UPT_SYSCALL_NR(regs) = -1; /* Assume: It's not a syscall */

		if(WIFSTOPPED(status)){
		  	switch(WSTOPSIG(status)){
			case SIGSEGV:
                                handle_segv(pid, regs);
				break;
			case SIGTRAP + 0x80:
			        handle_trap(pid, regs, local_using_sysemu);
				break;
			case SIGTRAP:
				relay_signal(SIGTRAP, regs);
				break;
			case SIGIO:
			case SIGVTALRM:
			case SIGILL:
			case SIGBUS:
			case SIGFPE:
			case SIGWINCH:
                                user_signal(WSTOPSIG(status), regs, pid);
				break;
			default:
			        printk("userspace - child stopped with signal "
				       "%d\n", WSTOPSIG(status));
			}
			interrupt_end();

			/* Avoid -ERESTARTSYS handling in host */
			PT_SYSCALL_NR(regs->skas.regs) = -1;
		}
	}
}
示例#5
0
文件: start_up.c 项目: ubante/linux
static void __init check_sysemu(void)
{
	unsigned long regs[MAX_REG_NR];
	int pid, n, status, count=0;

	non_fatal("Checking syscall emulation patch for ptrace...");
	sysemu_supported = 0;
	pid = start_ptraced_child();

	if (ptrace(PTRACE_SYSEMU, pid, 0, 0) < 0)
		goto fail;

	CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED));
	if (n < 0)
		fatal_perror("check_sysemu : wait failed");
	if (!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGTRAP))
		fatal("check_sysemu : expected SIGTRAP, got status = %d\n",
		      status);

	if (ptrace(PTRACE_GETREGS, pid, 0, regs) < 0)
		fatal_perror("check_sysemu : PTRACE_GETREGS failed");
	if (PT_SYSCALL_NR(regs) != __NR_getpid) {
		non_fatal("check_sysemu got system call number %d, "
			  "expected %d...", PT_SYSCALL_NR(regs), __NR_getpid);
		goto fail;
	}

	n = ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_RET_OFFSET, os_getpid());
	if (n < 0) {
		non_fatal("check_sysemu : failed to modify system call "
			  "return");
		goto fail;
	}

	if (stop_ptraced_child(pid, 0, 0) < 0)
		goto fail_stopped;

	sysemu_supported = 1;
	non_fatal("OK\n");
	set_using_sysemu(!force_sysemu_disabled);

	non_fatal("Checking advanced syscall emulation patch for ptrace...");
	pid = start_ptraced_child();

	if ((ptrace(PTRACE_OLDSETOPTIONS, pid, 0,
		   (void *) PTRACE_O_TRACESYSGOOD) < 0))
		fatal_perror("check_sysemu: PTRACE_OLDSETOPTIONS failed");

	while (1) {
		count++;
		if (ptrace(PTRACE_SYSEMU_SINGLESTEP, pid, 0, 0) < 0)
			goto fail;
		CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED));
		if (n < 0)
			fatal_perror("check_sysemu: wait failed");

		if (WIFSTOPPED(status) &&
		    (WSTOPSIG(status) == (SIGTRAP|0x80))) {
			if (!count) {
				non_fatal("check_sysemu: SYSEMU_SINGLESTEP "
					  "doesn't singlestep");
				goto fail;
			}
			n = ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_RET_OFFSET,
				   os_getpid());
			if (n < 0)
				fatal_perror("check_sysemu : failed to modify "
					     "system call return");
			break;
		}
		else if (WIFSTOPPED(status) && (WSTOPSIG(status) == SIGTRAP))
			count++;
		else {
			non_fatal("check_sysemu: expected SIGTRAP or "
				  "(SIGTRAP | 0x80), got status = %d\n",
				  status);
			goto fail;
		}
	}
	if (stop_ptraced_child(pid, 0, 0) < 0)
		goto fail_stopped;

	sysemu_supported = 2;
	non_fatal("OK\n");

	if (!force_sysemu_disabled)
		set_using_sysemu(sysemu_supported);
	return;

fail:
	stop_ptraced_child(pid, 1, 0);
fail_stopped:
	non_fatal("missing\n");
}