Commit fc8a8533 authored by Paolo \'Blaisorblade\' Giarrusso's avatar Paolo \'Blaisorblade\' Giarrusso Committed by Linus Torvalds

[PATCH] uml: use PTRACE_SYSEMU also for TT mode

From: Jeff Dike <jdike@addtoit.com>
      Paolo 'Blaisorblade' Giarrusso<blaisorblade_spam@yahoo.it>

As Jeff Dike noted, even if SYSEMU was originally written for use in SKAS
mode, there is nothing SKAS specific in SYSEMU, so use it for TT mode, too.

SYSEMU simply allows one to ptrace(PTRACE_SYSEMU) a process, that will stop
on the syscall entry path like with PTRACE_SYSCALL, but with the difference
that it makes sure that the syscall execution is totally skipped and that
the child will see the return value set by the ptracer when the child was
stopped.

We even hope that the SYSEMU patch can be merged in mainline sooner than
SKAS.
Signed-off-by: default avatarPaolo 'Blaisorblade' Giarrusso <blaisorblade_spam@yahoo.it>
Cc: Roland McGrath <roland@redhat.com>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent a328c343
......@@ -15,4 +15,15 @@ extern void arch_enter_kernel(void *task, int pid);
extern void arch_leave_kernel(void *task, int pid);
extern void ptrace_pokeuser(unsigned long addr, unsigned long data);
/* syscall emulation path in ptrace */
#ifndef PTRACE_SYSEMU
#define PTRACE_SYSEMU 31
#endif
void set_using_sysemu(int value);
int get_using_sysemu(void);
extern int sysemu_supported;
#endif
......@@ -242,9 +242,6 @@ 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);
......
......@@ -18,6 +18,7 @@
#include "linux/capability.h"
#include "linux/vmalloc.h"
#include "linux/spinlock.h"
#include "linux/proc_fs.h"
#include "asm/unistd.h"
#include "asm/mman.h"
#include "asm/segment.h"
......@@ -398,6 +399,61 @@ int cpu(void)
return(current_thread->cpu);
}
static atomic_t using_sysemu = ATOMIC_INIT(0);
int sysemu_supported;
void set_using_sysemu(int value)
{
atomic_set(&using_sysemu, sysemu_supported && value);
}
int get_using_sysemu(void)
{
return atomic_read(&using_sysemu);
}
static int proc_read_sysemu(char *buf, char **start, off_t offset, int size,int *eof, void *data)
{
if (snprintf(buf, size, "%d\n", get_using_sysemu()) < size) /*No overflow*/
*eof = 1;
return strlen(buf);
}
static int proc_write_sysemu(struct file *file,const char *buf, unsigned long count,void *data)
{
char tmp[2];
if (copy_from_user(tmp, buf, 1))
return -EFAULT;
if (tmp[0] == '0' || tmp[0] == '1')
set_using_sysemu(tmp[0] - '0');
return count; /*We use the first char, but pretend to write everything*/
}
int __init make_proc_sysemu(void)
{
struct proc_dir_entry *ent;
if (!sysemu_supported)
return 0;
ent = create_proc_entry("sysemu", 0600, &proc_root);
if (ent == NULL)
{
printk("Failed to register /proc/sysemu\n");
return(0);
}
ent->read_proc = proc_read_sysemu;
ent->write_proc = proc_write_sysemu;
return 0;
}
late_initcall(make_proc_sysemu);
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
* Emacs will notice this stuff at the end of the file and automatically
......
......@@ -10,16 +10,6 @@
#ifdef UML_CONFIG_MODE_SKAS
/* syscall emulation path in ptrace */
#ifndef PTRACE_SYSEMU
#define PTRACE_SYSEMU 31
#endif
void set_using_sysemu(int value);
int get_using_sysemu(void);
extern int sysemu_supported;
#include "skas_ptregs.h"
#define HOST_FRAME_SIZE 17
......
......@@ -139,17 +139,16 @@ void start_userspace(int cpu)
void userspace(union uml_pt_regs *regs)
{
int err, status, op, pid = userspace_pid[0];
int err, status, op, pt_syscall_parm, pid = userspace_pid[0];
int local_using_sysemu; /*To prevent races if using_sysemu changes under us.*/
restore_registers(regs);
local_using_sysemu = get_using_sysemu();
if (local_using_sysemu)
err = ptrace(PTRACE_SYSEMU, pid, 0, 0);
else
err = ptrace(PTRACE_SYSCALL, pid, 0, 0);
pt_syscall_parm = local_using_sysemu ? PTRACE_SYSEMU : PTRACE_SYSCALL;
err = ptrace(pt_syscall_parm, pid, 0, 0);
if(err)
panic("userspace - PTRACE_%s failed, errno = %d\n",
local_using_sysemu ? "SYSEMU" : "SYSCALL", errno);
......@@ -189,13 +188,10 @@ void userspace(union uml_pt_regs *regs)
/*Now we ended the syscall, so re-read local_using_sysemu.*/
local_using_sysemu = get_using_sysemu();
pt_syscall_parm = local_using_sysemu ? PTRACE_SYSEMU : PTRACE_SYSCALL;
if (local_using_sysemu)
op = singlestepping_skas() ? PTRACE_SINGLESTEP :
PTRACE_SYSEMU;
else
op = singlestepping_skas() ? PTRACE_SINGLESTEP :
PTRACE_SYSCALL;
op = singlestepping_skas() ? PTRACE_SINGLESTEP :
pt_syscall_parm;
err = ptrace(op, pid, 0, 0);
if(err)
......
......@@ -24,61 +24,6 @@
#include "mode.h"
#include "proc_mm.h"
static atomic_t using_sysemu = ATOMIC_INIT(0);
int sysemu_supported;
void set_using_sysemu(int value)
{
atomic_set(&using_sysemu, sysemu_supported && value);
}
int get_using_sysemu(void)
{
return atomic_read(&using_sysemu);
}
int proc_read_sysemu(char *buf, char **start, off_t offset, int size,int *eof, void *data)
{
if (snprintf(buf, size, "%d\n", get_using_sysemu()) < size) /*No overflow*/
*eof = 1;
return strlen(buf);
}
int proc_write_sysemu(struct file *file,const char *buf, unsigned long count,void *data)
{
char tmp[2];
if (copy_from_user(tmp, buf, 1))
return -EFAULT;
if (tmp[0] == '0' || tmp[0] == '1')
set_using_sysemu(tmp[0] - '0');
return count; /*We use the first char, but pretend to write everything*/
}
int __init make_proc_sysemu(void)
{
struct proc_dir_entry *ent;
if (mode_tt || !sysemu_supported)
return 0;
ent = create_proc_entry("sysemu", 0600, &proc_root);
if (ent == NULL)
{
printk("Failed to register /proc/sysemu\n");
return(0);
}
ent->read_proc = proc_read_sysemu;
ent->write_proc = proc_write_sysemu;
return 0;
}
late_initcall(make_proc_sysemu);
int singlestepping_skas(void)
{
int ret = current->ptrace & PT_DTRACE;
......
......@@ -28,7 +28,7 @@ extern int singlestepping_tt(void *t);
extern void clear_singlestep(void *t);
extern void syscall_handler(int sig, union uml_pt_regs *regs);
extern void exit_kernel(int pid, void *task);
extern int do_syscall(void *task, int pid);
extern int do_syscall(void *task, int pid, int local_using_sysemu);
extern int is_valid_pid(int pid);
extern void remap_data(void *segment_start, void *segment_end, int w);
......
......@@ -50,7 +50,7 @@ void syscall_handler_tt(int sig, union uml_pt_regs *regs)
record_syscall_end(index, result);
}
int do_syscall(void *task, int pid)
int do_syscall(void *task, int pid, int local_using_sysemu)
{
unsigned long proc_regs[FRAME_SIZE];
union uml_pt_regs *regs;
......@@ -70,6 +70,9 @@ int do_syscall(void *task, int pid)
((unsigned long *) PT_IP(proc_regs) <= &_etext))
tracer_panic("I'm tracing myself and I can't get out");
if(local_using_sysemu)
return(1);
if(ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_NR_OFFSET,
__NR_getpid) < 0)
tracer_panic("do_syscall : Nullifying syscall failed, "
......
......@@ -184,6 +184,7 @@ int tracer(int (*init_proc)(void *), void *sp)
unsigned long eip = 0;
int status, pid = 0, sig = 0, cont_type, tracing = 0, op = 0;
int last_index, proc_id = 0, n, err, old_tracing = 0, strace = 0;
int pt_syscall_parm, local_using_sysemu;
capture_signal_stack();
signal(SIGPIPE, SIG_IGN);
......@@ -297,6 +298,9 @@ int tracer(int (*init_proc)(void *), void *sp)
tracing = is_tracing(task);
old_tracing = tracing;
local_using_sysemu = get_using_sysemu();
pt_syscall_parm = local_using_sysemu ? PTRACE_SYSEMU : PTRACE_SYSCALL;
switch(sig){
case SIGUSR1:
sig = 0;
......@@ -330,7 +334,7 @@ int tracer(int (*init_proc)(void *), void *sp)
continue;
}
tracing = 0;
if(do_syscall(task, pid))
if(do_syscall(task, pid, local_using_sysemu))
sig = SIGUSR2;
else clear_singlestep(task);
break;
......@@ -349,6 +353,7 @@ int tracer(int (*init_proc)(void *), void *sp)
case SIGBUS:
case SIGILL:
case SIGWINCH:
default:
tracing = 0;
break;
......@@ -370,7 +375,7 @@ int tracer(int (*init_proc)(void *), void *sp)
if(tracing){
if(singlestepping_tt(task))
cont_type = PTRACE_SINGLESTEP;
else cont_type = PTRACE_SYSCALL;
else cont_type = pt_syscall_parm;
}
else cont_type = PTRACE_CONT;
......
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