{
int flags = altstack ? SA_ONSTACK : 0;
- set_handler(SIGSEGV, (__sighandler_t) sig_handler, flags,
+ set_handler(SIGSEGV, (__sighandler_t) sig_handler, flags,
SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
set_handler(SIGTRAP, (__sighandler_t) sig_handler, flags,
SIGUSR1, SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, -1);
static int ptrace_child(void *arg)
{
- int ret;
- int pid = os_getpid(), ppid = getppid();
- int sc_result;
+ int pid = os_getpid();
if(ptrace(PTRACE_TRACEME, 0, 0, 0) < 0){
perror("ptrace");
os_kill_process(pid, 0);
}
os_stop_process(pid);
-
- /*This syscall will be intercepted by the parent. Don't call more than
- * once, please.*/
- sc_result = os_getpid();
-
- if (sc_result == pid)
- ret = 1; /*Nothing modified by the parent, we are running
- normally.*/
- else if (sc_result == ppid)
- ret = 0; /*Expected in check_ptrace and check_sysemu when they
- succeed in modifying the stack frame*/
- else
- ret = 2; /*Serious trouble! This could be caused by a bug in
- host 2.6 SKAS3/2.6 patch before release -V6, together
- with a bug in the UML code itself.*/
- _exit(ret);
+ _exit(os_getpid() == pid);
}
static int start_ptraced_child(void **stack_out)
return(pid);
}
-/* When testing for SYSEMU support, if it is one of the broken versions, we must
- * just avoid using sysemu, not panic, but only if SYSEMU features are broken.
- * So only for SYSEMU features we test mustpanic, while normal host features
- * must work anyway!*/
-static int stop_ptraced_child(int pid, void *stack, int exitcode, int mustpanic)
+static void stop_ptraced_child(int pid, void *stack, int exitcode)
{
- int status, n, ret = 0;
+ int status, n;
if(ptrace(PTRACE_CONT, pid, 0, 0) < 0)
panic("check_ptrace : ptrace failed, errno = %d", errno);
CATCH_EINTR(n = waitpid(pid, &status, 0));
- if(!WIFEXITED(status) || (WEXITSTATUS(status) != exitcode)) {
- int exit_with = WEXITSTATUS(status);
- if (exit_with == 2)
- printk("check_ptrace : child exited with status 2. "
- "Serious trouble happening! Try updating your "
- "host skas patch!\nDisabling SYSEMU support.");
- printk("check_ptrace : child exited with exitcode %d, while "
- "expecting %d; status 0x%x", exit_with,
- exitcode, status);
- if (mustpanic)
- panic("\n");
- else
- printk("\n");
- ret = -1;
- }
+ if(!WIFEXITED(status) || (WEXITSTATUS(status) != exitcode))
+ panic("check_ptrace : child exited with status 0x%x", status);
if(munmap(stack, PAGE_SIZE) < 0)
panic("check_ptrace : munmap failed, errno = %d", errno);
- return ret;
}
static int force_sysemu_disabled = 0;
" SYSEMU is a performance-patch introduced by Laurent Vivier. It changes\n"
" behaviour of ptrace() and helps reducing host context switch rate.\n"
" To make it working, you need a kernel patch for your host, too.\n"
- " See http://perso.wanadoo.fr/laurent.vivier/UML/ for further information.\n\n");
+ " See http://perso.wanadoo.fr/laurent.vivier/UML/ for further information.\n");
static void __init check_sysemu(void)
{
void *stack;
int pid, n, status;
+ if (mode_tt)
+ return;
+
printk("Checking syscall emulation patch for ptrace...");
sysemu_supported = 0;
pid = start_ptraced_child(&stack);
+ if(ptrace(PTRACE_SYSEMU, pid, 0, 0) >= 0) {
+ struct user_regs_struct regs;
- if(ptrace(PTRACE_SYSEMU, pid, 0, 0) < 0)
- goto fail;
+ CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED));
+ if (n < 0)
+ panic("check_ptrace : wait failed, errno = %d", errno);
+ if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGTRAP))
+ panic("check_ptrace : expected SIGTRAP, "
+ "got status = %d", status);
- CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED));
- if (n < 0)
- panic("check_sysemu : wait failed, errno = %d", errno);
- if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGTRAP))
- panic("check_sysemu : expected SIGTRAP, "
- "got status = %d", status);
-
- n = ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_RET_OFFSET,
- os_getpid());
- if(n < 0)
- panic("check_sysemu : failed to modify system "
- "call return, errno = %d", errno);
+ if (ptrace(PTRACE_GETREGS, pid, 0, ®s) < 0)
+ panic("check_ptrace : failed to read child "
+ "registers, errno = %d", errno);
+ regs.orig_eax = pid;
+ if (ptrace(PTRACE_SETREGS, pid, 0, ®s) < 0)
+ panic("check_ptrace : failed to modify child "
+ "registers, errno = %d", errno);
- if (stop_ptraced_child(pid, stack, 0, 0) < 0)
- goto fail_stopped;
+ stop_ptraced_child(pid, stack, 0);
- sysemu_supported = 1;
- printk("OK\n");
- set_using_sysemu(!force_sysemu_disabled);
- return;
+ sysemu_supported = 1;
+ printk("found\n");
+ }
+ else
+ {
+ stop_ptraced_child(pid, stack, 1);
+ sysemu_supported = 0;
+ printk("missing\n");
+ }
-fail:
- stop_ptraced_child(pid, stack, 1, 0);
-fail_stopped:
- sysemu_supported = 0;
- printk("missing\n");
+ set_using_sysemu(!force_sysemu_disabled);
}
void __init check_ptrace(void)
break;
}
}
- stop_ptraced_child(pid, stack, 0, 1);
+ stop_ptraced_child(pid, stack, 0);
printk("OK\n");
check_sysemu();
}
else printf("found\n");
init_registers(pid);
- stop_ptraced_child(pid, stack, 1, 1);
+ stop_ptraced_child(pid, stack, 1);
printf("Checking for /proc/mm...");
if(os_access("/proc/mm", OS_ACC_W_OK) < 0){