Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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: Jeff Dike <jdike@linux.intel.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Jeff Dike and committed by
Linus Torvalds
cf6acedb da90fa8f

+16 -8
+16 -8
arch/um/os-Linux/start_up.c
··· 144 144 int exit_with = WEXITSTATUS(status); 145 145 if (exit_with == 2) 146 146 non_fatal("check_ptrace : child exited with status 2. " 147 - "Serious trouble happening! Try updating " 148 - "your host skas patch!\nDisabling SYSEMU " 149 - "support."); 147 + "\nDisabling SYSEMU support.\n"); 150 148 non_fatal("check_ptrace : child exited with exitcode %d, while " 151 149 "expecting %d; status 0x%x\n", exit_with, 152 150 exitcode, status); ··· 207 209 static void __init check_sysemu(void) 208 210 { 209 211 void *stack; 212 + unsigned long regs[MAX_REG_NR]; 210 213 int pid, n, status, count=0; 211 214 212 215 non_fatal("Checking syscall emulation patch for ptrace..."); ··· 224 225 fatal("check_sysemu : expected SIGTRAP, got status = %d", 225 226 status); 226 227 227 - n = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_RET_OFFSET, 228 - os_getpid()); 229 - if(n < 0) 230 - fatal_perror("check_sysemu : failed to modify system call " 231 - "return"); 228 + if(ptrace(PTRACE_GETREGS, pid, 0, regs) < 0) 229 + fatal_perror("check_sysemu : PTRACE_GETREGS failed"); 230 + if(PT_SYSCALL_NR(regs) != __NR_getpid){ 231 + non_fatal("check_sysemu got system call number %d, " 232 + "expected %d...", PT_SYSCALL_NR(regs), __NR_getpid); 233 + goto fail; 234 + } 235 + 236 + n = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_RET_OFFSET, os_getpid()); 237 + if(n < 0){ 238 + non_fatal("check_sysemu : failed to modify system call " 239 + "return"); 240 + goto fail; 241 + } 232 242 233 243 if (stop_ptraced_child(pid, stack, 0, 0) < 0) 234 244 goto fail_stopped;