Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cf6acedb authored by Jeff Dike's avatar Jeff Dike Committed by Linus Torvalds
Browse files

uml: improve PTRACE_SYSEMU checking



Make the PTRACE_SYSEMU checking more robust.  It will make sure that system
call numbers are reported correctly.  If there is a problem, it will disable
PTRACE_SYSEMU use and use PTRACE_SYSCALL instead.

Thanks to Balaji G for helping reproduce this problem.

Signed-off-by: default avatarJeff Dike <jdike@linux.intel.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent da90fa8f
Loading
Loading
Loading
Loading
+16 −8
Original line number Original line Diff line number Diff line
@@ -144,9 +144,7 @@ static int stop_ptraced_child(int pid, void *stack, int exitcode,
		int exit_with = WEXITSTATUS(status);
		int exit_with = WEXITSTATUS(status);
		if (exit_with == 2)
		if (exit_with == 2)
			non_fatal("check_ptrace : child exited with status 2. "
			non_fatal("check_ptrace : child exited with status 2. "
				  "Serious trouble happening! Try updating "
				  "\nDisabling SYSEMU support.\n");
				  "your host skas patch!\nDisabling SYSEMU "
				  "support.");
		non_fatal("check_ptrace : child exited with exitcode %d, while "
		non_fatal("check_ptrace : child exited with exitcode %d, while "
			  "expecting %d; status 0x%x\n", exit_with,
			  "expecting %d; status 0x%x\n", exit_with,
			  exitcode, status);
			  exitcode, status);
@@ -209,6 +207,7 @@ __uml_setup("nosysemu", nosysemu_cmd_param,
static void __init check_sysemu(void)
static void __init check_sysemu(void)
{
{
	void *stack;
	void *stack;
	unsigned long regs[MAX_REG_NR];
	int pid, n, status, count=0;
	int pid, n, status, count=0;


	non_fatal("Checking syscall emulation patch for ptrace...");
	non_fatal("Checking syscall emulation patch for ptrace...");
@@ -225,11 +224,20 @@ static void __init check_sysemu(void)
		fatal("check_sysemu : expected SIGTRAP, got status = %d",
		fatal("check_sysemu : expected SIGTRAP, got status = %d",
		      status);
		      status);


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

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


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