Commit 77ddaa4b authored by Jeff Dike's avatar Jeff Dike Committed by Linus Torvalds

[PATCH] uml: Add TRACESYSGOOD support

From: Bodo Stroesser

Patch 1/3 to implement usage of PTRACE_O_TRACESYSGOOD
This is necessary, to fix UMLs bad behavior when a process does
a systemcall with syscall-number less than 0.

Insert a check for availability and function of
ptrace(PTRACE_SETOPTIONS,,,PTRACE_O_TRACESYSGOOD)
into the normal ptrace checks at startup.

Patch 2/3 to implement usage of PTRACE_O_TRACESYSGOOD
This is necessary, to fix UMLs bad behavior when a process does
a systemcall with syscall-number less than 0.

This patch makes SKAS-mode use PTRACE_O_TRACESYSGOOD and fixes
the problems in SKAS.

Patch 3/3 to implement usage of PTRACE_O_TRACESYSGOOD
This is necessary, to fix UMLs bad behavior when a process does
a systemcall with syscall-number less than 0.

This patch makes TT-mode use PTRACE_O_TRACESYSGOOD and fixes
the problems in TT.
I'm not quite sure, that this patch doesn't cause problems with
debugger usage. It should be testet by someone, who has more
know how about TT-mode debugger.
Signed-off-by: default avatarBodo Stroesser <bstroesser@fujitsu-siemens.com>
Signed-off-by: default avatarJeff Dike <jdike@addtoit.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent f9ce1060
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include <setjmp.h> #include <setjmp.h>
#include <sys/time.h> #include <sys/time.h>
#include <sys/ptrace.h> #include <sys/ptrace.h>
#include <linux/ptrace.h>
#include <sys/wait.h> #include <sys/wait.h>
#include <sys/mman.h> #include <sys/mman.h>
#include <asm/ptrace.h> #include <asm/ptrace.h>
...@@ -285,6 +286,9 @@ void __init check_ptrace(void) ...@@ -285,6 +286,9 @@ void __init check_ptrace(void)
printk("Checking that ptrace can change system call numbers..."); printk("Checking that ptrace can change system call numbers...");
pid = start_ptraced_child(&stack); pid = start_ptraced_child(&stack);
if(ptrace(PTRACE_SETOPTIONS, pid, 0, (void *)PTRACE_O_TRACESYSGOOD) < 0)
panic("check_ptrace: PTRACE_SETOPTIONS failed, errno = %d", errno);
while(1){ while(1){
if(ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) if(ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0)
panic("check_ptrace : ptrace failed, errno = %d", panic("check_ptrace : ptrace failed, errno = %d",
...@@ -292,8 +296,8 @@ void __init check_ptrace(void) ...@@ -292,8 +296,8 @@ void __init check_ptrace(void)
CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED));
if(n < 0) if(n < 0)
panic("check_ptrace : wait failed, errno = %d", errno); panic("check_ptrace : wait failed, errno = %d", errno);
if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGTRAP)) if(!WIFSTOPPED(status) || (WSTOPSIG(status) != (SIGTRAP + 0x80)))
panic("check_ptrace : expected SIGTRAP, " panic("check_ptrace : expected SIGTRAP + 0x80, "
"got status = %d", status); "got status = %d", status);
syscall = ptrace(PTRACE_PEEKUSER, pid, PT_SYSCALL_NR_OFFSET, syscall = ptrace(PTRACE_PEEKUSER, pid, PT_SYSCALL_NR_OFFSET,
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include <sched.h> #include <sched.h>
#include <sys/wait.h> #include <sys/wait.h>
#include <sys/ptrace.h> #include <sys/ptrace.h>
#include <linux/ptrace.h>
#include <sys/mman.h> #include <sys/mman.h>
#include <sys/user.h> #include <sys/user.h>
#include <asm/unistd.h> #include <asm/unistd.h>
...@@ -60,14 +61,9 @@ static void handle_segv(int pid) ...@@ -60,14 +61,9 @@ static void handle_segv(int pid)
/*To use the same value of using_sysemu as the caller, ask it that value (in local_using_sysemu)*/ /*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) static void handle_trap(int pid, union uml_pt_regs *regs, int local_using_sysemu)
{ {
int err, syscall_nr, status; int err, status;
syscall_nr = PT_SYSCALL_NR(regs->skas.regs); UPT_SYSCALL_NR(regs) = PT_SYSCALL_NR(regs->skas.regs);
UPT_SYSCALL_NR(regs) = syscall_nr;
if(syscall_nr < 0){
relay_signal(SIGTRAP, regs);
return;
}
if (!local_using_sysemu) if (!local_using_sysemu)
{ {
...@@ -82,7 +78,7 @@ static void handle_trap(int pid, union uml_pt_regs *regs, int local_using_sysemu ...@@ -82,7 +78,7 @@ static void handle_trap(int pid, union uml_pt_regs *regs, int local_using_sysemu
"errno = %d\n", errno); "errno = %d\n", errno);
CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED)); CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED));
if((err < 0) || !WIFSTOPPED(status) || (WSTOPSIG(status) != SIGTRAP)) if((err < 0) || !WIFSTOPPED(status) || (WSTOPSIG(status) != (SIGTRAP + 0x80)))
panic("handle_trap - failed to wait at end of syscall, " panic("handle_trap - failed to wait at end of syscall, "
"errno = %d, status = %d\n", errno, status); "errno = %d, status = %d\n", errno, status);
} }
...@@ -131,6 +127,10 @@ void start_userspace(int cpu) ...@@ -131,6 +127,10 @@ void start_userspace(int cpu)
panic("start_userspace : expected SIGSTOP, got status = %d", panic("start_userspace : expected SIGSTOP, got status = %d",
status); status);
if (ptrace(PTRACE_SETOPTIONS, pid, NULL, (void *)PTRACE_O_TRACESYSGOOD) < 0)
panic("start_userspace : PTRACE_SETOPTIONS failed, errno=%d\n",
errno);
if(munmap(stack, PAGE_SIZE) < 0) if(munmap(stack, PAGE_SIZE) < 0)
panic("start_userspace : munmap failed, errno = %d\n", errno); panic("start_userspace : munmap failed, errno = %d\n", errno);
...@@ -166,9 +166,13 @@ void userspace(union uml_pt_regs *regs) ...@@ -166,9 +166,13 @@ void userspace(union uml_pt_regs *regs)
case SIGSEGV: case SIGSEGV:
handle_segv(pid); handle_segv(pid);
break; break;
case SIGTRAP: case SIGTRAP + 0x80:
handle_trap(pid, regs, local_using_sysemu); handle_trap(pid, regs, local_using_sysemu);
break; break;
case SIGTRAP:
UPT_SYSCALL_NR(regs) = -1;
relay_signal(SIGTRAP, regs);
break;
case SIGIO: case SIGIO:
case SIGVTALRM: case SIGVTALRM:
case SIGILL: case SIGILL:
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include <errno.h> #include <errno.h>
#include <sys/wait.h> #include <sys/wait.h>
#include <sys/ptrace.h> #include <sys/ptrace.h>
#include <linux/ptrace.h>
#include <signal.h> #include <signal.h>
#include "user_util.h" #include "user_util.h"
#include "kern_util.h" #include "kern_util.h"
...@@ -37,6 +38,9 @@ void do_exec(int old_pid, int new_pid) ...@@ -37,6 +38,9 @@ void do_exec(int old_pid, int new_pid)
kill(old_pid, SIGKILL); kill(old_pid, SIGKILL);
if (ptrace(PTRACE_SETOPTIONS, new_pid, 0, (void *)PTRACE_O_TRACESYSGOOD) < 0)
tracer_panic("do_exec: PTRACE_SETOPTIONS failed, errno = %d", errno);
if(ptrace_setregs(new_pid, regs) < 0) if(ptrace_setregs(new_pid, regs) < 0)
tracer_panic("do_exec failed to start new proc - errno = %d", tracer_panic("do_exec failed to start new proc - errno = %d",
errno); errno);
......
...@@ -27,6 +27,7 @@ extern int is_tracing(void *task); ...@@ -27,6 +27,7 @@ extern int is_tracing(void *task);
extern void syscall_handler(int sig, union uml_pt_regs *regs); extern void syscall_handler(int sig, union uml_pt_regs *regs);
extern void exit_kernel(int pid, void *task); extern void exit_kernel(int pid, void *task);
extern int do_syscall(void *task, int pid, int local_using_sysemu); extern int do_syscall(void *task, int pid, int local_using_sysemu);
extern void do_sigtrap(void *task);
extern int is_valid_pid(int pid); extern int is_valid_pid(int pid);
extern void remap_data(void *segment_start, void *segment_end, int w); extern void remap_data(void *segment_start, void *segment_end, int w);
......
...@@ -43,21 +43,19 @@ void syscall_handler_tt(int sig, union uml_pt_regs *regs) ...@@ -43,21 +43,19 @@ void syscall_handler_tt(int sig, union uml_pt_regs *regs)
record_syscall_end(index, result); record_syscall_end(index, result);
} }
void do_sigtrap(void *task)
{
UPT_SYSCALL_NR(TASK_REGS(task)) = -1;
}
int do_syscall(void *task, int pid, int local_using_sysemu) int do_syscall(void *task, int pid, int local_using_sysemu)
{ {
unsigned long proc_regs[FRAME_SIZE]; unsigned long proc_regs[FRAME_SIZE];
union uml_pt_regs *regs;
int syscall;
if(ptrace_getregs(pid, proc_regs) < 0) if(ptrace_getregs(pid, proc_regs) < 0)
tracer_panic("Couldn't read registers"); tracer_panic("Couldn't read registers");
syscall = PT_SYSCALL_NR(proc_regs);
regs = TASK_REGS(task);
UPT_SYSCALL_NR(regs) = syscall;
if(syscall < 0) UPT_SYSCALL_NR(TASK_REGS(task)) = PT_SYSCALL_NR(proc_regs);
return(0);
if((syscall != __NR_sigreturn) && if((syscall != __NR_sigreturn) &&
((unsigned long *) PT_IP(proc_regs) >= &_stext) && ((unsigned long *) PT_IP(proc_regs) >= &_stext) &&
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include <string.h> #include <string.h>
#include <sys/mman.h> #include <sys/mman.h>
#include <sys/ptrace.h> #include <sys/ptrace.h>
#include <linux/ptrace.h>
#include <sys/time.h> #include <sys/time.h>
#include <sys/wait.h> #include <sys/wait.h>
#include "user.h" #include "user.h"
...@@ -71,6 +72,8 @@ void attach_process(int pid) ...@@ -71,6 +72,8 @@ void attach_process(int pid)
(ptrace(PTRACE_CONT, pid, 0, 0) < 0)) (ptrace(PTRACE_CONT, pid, 0, 0) < 0))
tracer_panic("OP_FORK failed to attach pid"); tracer_panic("OP_FORK failed to attach pid");
wait_for_stop(pid, SIGSTOP, PTRACE_CONT, NULL); wait_for_stop(pid, SIGSTOP, PTRACE_CONT, NULL);
if (ptrace(PTRACE_SETOPTIONS, pid, 0, (void *)PTRACE_O_TRACESYSGOOD) < 0)
tracer_panic("OP_FORK: PTRACE_SETOPTIONS failed, errno = %d", errno);
if(ptrace(PTRACE_CONT, pid, 0, 0) < 0) if(ptrace(PTRACE_CONT, pid, 0, 0) < 0)
tracer_panic("OP_FORK failed to continue process"); tracer_panic("OP_FORK failed to continue process");
} }
...@@ -140,7 +143,7 @@ static void sleeping_process_signal(int pid, int sig) ...@@ -140,7 +143,7 @@ static void sleeping_process_signal(int pid, int sig)
* any more, the trace of those will land here. So, we need to just * any more, the trace of those will land here. So, we need to just
* PTRACE_SYSCALL it. * PTRACE_SYSCALL it.
*/ */
case SIGTRAP: case (SIGTRAP + 0x80):
if(ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0) if(ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0)
tracer_panic("sleeping_process_signal : Failed to " tracer_panic("sleeping_process_signal : Failed to "
"PTRACE_SYSCALL pid %d, errno = %d\n", "PTRACE_SYSCALL pid %d, errno = %d\n",
...@@ -196,6 +199,10 @@ int tracer(int (*init_proc)(void *), void *sp) ...@@ -196,6 +199,10 @@ int tracer(int (*init_proc)(void *), void *sp)
printf("waitpid on idle thread failed, errno = %d\n", errno); printf("waitpid on idle thread failed, errno = %d\n", errno);
exit(1); exit(1);
} }
if (ptrace(PTRACE_SETOPTIONS, pid, 0, (void *)PTRACE_O_TRACESYSGOOD) < 0) {
printf("Failed to PTRACE_SETOPTIONS for idle thread, errno = %d\n", errno);
exit(1);
}
if((ptrace(PTRACE_CONT, pid, 0, 0) < 0)){ if((ptrace(PTRACE_CONT, pid, 0, 0) < 0)){
printf("Failed to continue idle thread, errno = %d\n", errno); printf("Failed to continue idle thread, errno = %d\n", errno);
exit(1); exit(1);
...@@ -326,14 +333,22 @@ int tracer(int (*init_proc)(void *), void *sp) ...@@ -326,14 +333,22 @@ int tracer(int (*init_proc)(void *), void *sp)
*/ */
pid = cpu_tasks[proc_id].pid; pid = cpu_tasks[proc_id].pid;
break; break;
case (SIGTRAP + 0x80):
if(!tracing && (debugger_pid != -1)){
child_signal(pid, status & 0x7fff);
continue;
}
tracing = 0;
do_syscall(task, pid, local_using_sysemu);
sig = SIGUSR2;
break;
case SIGTRAP: case SIGTRAP:
if(!tracing && (debugger_pid != -1)){ if(!tracing && (debugger_pid != -1)){
child_signal(pid, status); child_signal(pid, status);
continue; continue;
} }
tracing = 0; tracing = 0;
if(do_syscall(task, pid, local_using_sysemu)) do_sigtrap(task);
sig = SIGUSR2;
break; break;
case SIGPROF: case SIGPROF:
if(tracing) sig = 0; if(tracing) sig = 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment