Commit acc70885 authored by Daniel Jacobowitz's avatar Daniel Jacobowitz

Factor out common ptrace code and PTRACE_SETOPTIONS

Support PTRACE_O_TRACESYSGOOD on all platforms
parent 1ab068b3
......@@ -383,7 +383,7 @@ sys_ptrace(long request, long pid, long addr, long data,
goto out;
default:
ret = -EIO;
ret = ptrace_request(child, request, addr, data);
goto out;
}
out:
......@@ -400,7 +400,8 @@ syscall_trace(void)
return;
if (!(current->ptrace & PT_PTRACED))
return;
current->exit_code = SIGTRAP;
current->exit_code = SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
? 0x80 : 0);
current->state = TASK_STOPPED;
notify_parent(current, SIGCHLD);
schedule();
......
......@@ -629,16 +629,8 @@ static int do_ptrace(int request, struct task_struct *child, long addr, long dat
ret = ptrace_setfpregs(child, (void *)data);
break;
case PTRACE_SETOPTIONS:
if (data & PTRACE_O_TRACESYSGOOD)
child->ptrace |= PT_TRACESYSGOOD;
else
child->ptrace &= ~PT_TRACESYSGOOD;
ret = 0;
break;
default:
ret = -EIO;
ret = ptrace_request(child, request, addr, data);
break;
}
......
......@@ -292,7 +292,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
}
default:
ret = -EIO;
ret = ptrace_request(child, request, addr, data);
break;
}
out_tsk:
......@@ -307,10 +307,8 @@ asmlinkage void syscall_trace(void)
if ((current->ptrace & (PT_PTRACED | PT_TRACESYS)) !=
(PT_PTRACED | PT_TRACESYS))
return;
/* TODO: make a way to distinguish between a syscall stop and SIGTRAP
* delivery like in the i386 port ?
*/
current->exit_code = SIGTRAP;
current->exit_code = SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
? 0x80 : 0);
current->state = TASK_STOPPED;
notify_parent(current, SIGCHLD);
schedule();
......
......@@ -425,17 +425,8 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
break;
}
case PTRACE_SETOPTIONS: {
if (data & PTRACE_O_TRACESYSGOOD)
child->ptrace |= PT_TRACESYSGOOD;
else
child->ptrace &= ~PT_TRACESYSGOOD;
ret = 0;
break;
}
default:
ret = -EIO;
ret = ptrace_request(child, request, addr, data);
break;
}
out_tsk:
......
......@@ -3084,7 +3084,7 @@ sys32_ptrace (int request, pid_t pid, unsigned int addr, unsigned int data,
break;
default:
ret = -EIO;
ret = ptrace_request(child, request, addr, data);
break;
}
......
......@@ -1268,16 +1268,8 @@ sys_ptrace (long request, pid_t pid, unsigned long addr, unsigned long data,
ret = ptrace_setregs(child, (struct pt_all_user_regs*) data);
goto out_tsk;
case PTRACE_SETOPTIONS:
if (data & PTRACE_O_TRACESYSGOOD)
child->ptrace |= PT_TRACESYSGOOD;
else
child->ptrace &= ~PT_TRACESYSGOOD;
ret = 0;
break;
default:
ret = -EIO;
ret = ptrace_request(child, request, addr, data);
goto out_tsk;
}
out_tsk:
......
......@@ -355,7 +355,7 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
}
default:
ret = -EIO;
ret = ptrace_request(child, request, addr, data);
break;
}
out_tsk:
......@@ -370,7 +370,8 @@ asmlinkage void syscall_trace(void)
if (!current->thread.work.delayed_trace &&
!current->thread.work.syscall_trace)
return;
current->exit_code = SIGTRAP;
current->exit_code = SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
? 0x80 : 0);
current->state = TASK_STOPPED;
notify_parent(current, SIGCHLD);
schedule();
......
......@@ -304,16 +304,8 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
res = ptrace_detach(child, data);
break;
case PTRACE_SETOPTIONS:
if (data & PTRACE_O_TRACESYSGOOD)
child->ptrace |= PT_TRACESYSGOOD;
else
child->ptrace &= ~PT_TRACESYSGOOD;
res = 0;
break;
default:
res = -EIO;
res = ptrace_request(child, request, addr, data);
goto out;
}
out_tsk:
......
......@@ -275,17 +275,8 @@ asmlinkage int sys32_ptrace(int request, int pid, int addr, int data)
ret = ptrace_detach(child, data);
break;
case PTRACE_SETOPTIONS: {
if (data & PTRACE_O_TRACESYSGOOD)
child->ptrace |= PT_TRACESYSGOOD;
else
child->ptrace &= ~PT_TRACESYSGOOD;
ret = 0;
break;
}
default:
ret = -EIO;
ret = ptrace_request(child, request, addr, data);
break;
}
......@@ -535,17 +526,8 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
ret = ptrace_detach(child, data);
break;
case PTRACE_SETOPTIONS: {
if (data & PTRACE_O_TRACESYSGOOD)
child->ptrace |= PT_TRACESYSGOOD;
else
child->ptrace &= ~PT_TRACESYSGOOD;
ret = 0;
break;
}
default:
ret = -EIO;
ret = ptrace_request(child, request, addr, data);
break;
}
......
......@@ -244,7 +244,7 @@ long sys_ptrace(long request, pid_t pid, long addr, long data)
goto out_tsk;
default:
ret = -EIO;
ret = ptrace_request(child, request, addr, data);
goto out_tsk;
}
......@@ -269,7 +269,8 @@ void syscall_trace(void)
if ((current->ptrace & (PT_PTRACED|PT_TRACESYS)) !=
(PT_PTRACED|PT_TRACESYS))
return;
current->exit_code = SIGTRAP;
current->exit_code = SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
? 0x80 : 0);
current->state = TASK_STOPPED;
notify_parent(current, SIGCHLD);
schedule();
......
......@@ -342,7 +342,7 @@ int sys_ptrace(long request, long pid, long addr, long data)
#endif
default:
ret = -EIO;
ret = ptrace_request(child, request, addr, data);
break;
}
out_tsk:
......@@ -357,7 +357,8 @@ void do_syscall_trace(void)
if (!test_thread_flag(TIF_SYSCALL_TRACE)
|| !(current->ptrace & PT_PTRACED))
return;
current->exit_code = SIGTRAP;
current->exit_code = SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
? 0x80 : 0);
current->state = TASK_STOPPED;
notify_parent(current, SIGCHLD);
schedule();
......
......@@ -258,7 +258,7 @@ int sys_ptrace(long request, long pid, long addr, long data)
}
default:
ret = -EIO;
ret = ptrace_request(child, request, addr, data);
break;
}
out_tsk:
......@@ -274,7 +274,8 @@ void do_syscall_trace(void)
return;
if (!(current->ptrace & PT_PTRACED))
return;
current->exit_code = SIGTRAP;
current->exit_code = SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
? 0x80 : 0);
current->state = TASK_STOPPED;
notify_parent(current, SIGCHLD);
schedule();
......
......@@ -345,7 +345,7 @@ int sys32_ptrace(long request, long pid, unsigned long addr, unsigned long data)
break;
default:
ret = -EIO;
ret = ptrace_request(child, request, addr, data);
break;
}
out_tsk:
......
......@@ -346,16 +346,8 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
ret=copy_user(child,parea.kernel_addr,parea.process_addr,
parea.len,1,(request==PTRACE_POKEUSR_AREA));
break;
case PTRACE_SETOPTIONS: {
if (data & PTRACE_O_TRACESYSGOOD)
child->ptrace |= PT_TRACESYSGOOD;
else
child->ptrace &= ~PT_TRACESYSGOOD;
ret = 0;
break;
}
default:
ret = -EIO;
ret = ptrace_request(child, request, addr, data);
break;
}
out_tsk:
......
......@@ -576,16 +576,8 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
parea.len,1,(request==PTRACE_POKEUSR_AREA));
}
break;
case PTRACE_SETOPTIONS: {
if (data & PTRACE_O_TRACESYSGOOD)
child->ptrace |= PT_TRACESYSGOOD;
else
child->ptrace &= ~PT_TRACESYSGOOD;
ret = 0;
break;
}
default:
ret = -EIO;
ret = ptrace_request(child, request, addr, data);
break;
}
out_tsk:
......
......@@ -356,17 +356,8 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
ret = ptrace_detach(child, data);
break;
case PTRACE_SETOPTIONS: {
if (data & PTRACE_O_TRACESYSGOOD)
child->ptrace |= PT_TRACESYSGOOD;
else
child->ptrace &= ~PT_TRACESYSGOOD;
ret = 0;
break;
}
default:
ret = -EIO;
ret = ptrace_request(child, request, addr, data);
break;
}
out_tsk:
......
......@@ -584,10 +584,15 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
/* PTRACE_DUMPCORE unsupported... */
default:
pt_error_return(regs, EIO);
default: {
int err = ptrace_request(child, request, addr, data);
if (err)
pt_error_return(regs, -err);
else
pt_succ_return(regs, 0);
goto out_tsk;
}
}
out_tsk:
if (child)
put_task_struct(child);
......@@ -604,7 +609,8 @@ asmlinkage void syscall_trace(void)
return;
if (!(current->ptrace & PT_PTRACED))
return;
current->exit_code = SIGTRAP;
current->exit_code = SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
? 0x80 : 0);
current->state = TASK_STOPPED;
current->thread.flags ^= MAGIC_CONSTANT;
notify_parent(current, SIGCHLD);
......
......@@ -571,10 +571,15 @@ asmlinkage void do_ptrace(struct pt_regs *regs)
/* PTRACE_DUMPCORE unsupported... */
default:
pt_error_return(regs, EIO);
default: {
int err = ptrace_request(child, request, addr, data);
if (err)
pt_error_return(regs, -err);
else
pt_succ_return(regs, 0);
goto out_tsk;
}
}
flush_and_out:
{
unsigned long va;
......@@ -612,7 +617,8 @@ asmlinkage void syscall_trace(void)
return;
if (!(current->ptrace & PT_PTRACED))
return;
current->exit_code = SIGTRAP;
current->exit_code = SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
? 0x80 : 0);
current->state = TASK_STOPPED;
notify_parent(current, SIGCHLD);
schedule();
......
......@@ -172,17 +172,6 @@ asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data)
__u32 val;
switch (request) {
case PTRACE_TRACEME:
case PTRACE_ATTACH:
case PTRACE_SYSCALL:
case PTRACE_CONT:
case PTRACE_KILL:
case PTRACE_SINGLESTEP:
case PTRACE_DETACH:
case PTRACE_SETOPTIONS:
ret = sys_ptrace(request, pid, addr, data);
return ret;
case PTRACE_PEEKTEXT:
case PTRACE_PEEKDATA:
case PTRACE_POKEDATA:
......@@ -198,7 +187,8 @@ asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data)
break;
default:
return -EIO;
ret = sys_ptrace(request, pid, addr, data);
return ret;
}
child = find_target(request, pid, &ret);
......
......@@ -396,17 +396,8 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data)
break;
}
case PTRACE_SETOPTIONS: {
if (data & PTRACE_O_TRACESYSGOOD)
child->ptrace |= PT_TRACESYSGOOD;
else
child->ptrace &= ~PT_TRACESYSGOOD;
ret = 0;
break;
}
default:
ret = -EIO;
ret = ptrace_request(child, request, addr, data);
break;
}
out_tsk:
......
......@@ -6,10 +6,7 @@
#define PTRACE_GETFPREGS 14
#define PTRACE_SETFPREGS 15
#define PTRACE_SETOPTIONS 21
/* options set using PTRACE_SETOPTIONS */
#define PTRACE_O_TRACESYSGOOD 0x00000001
#define PTRACE_OLDSETOPTIONS 21
#include <asm/proc/ptrace.h>
......
......@@ -49,10 +49,7 @@ struct pt_regs {
#define PTRACE_GETFPXREGS 18
#define PTRACE_SETFPXREGS 19
#define PTRACE_SETOPTIONS 21
/* options set using PTRACE_SETOPTIONS */
#define PTRACE_O_TRACESYSGOOD 0x00000001
#define PTRACE_OLDSETOPTIONS 21
#ifdef __KERNEL__
#define user_mode(regs) ((VM_MASK & (regs)->eflags) || (3 & (regs)->xcs))
......
......@@ -287,9 +287,6 @@ struct pt_all_user_regs {
#define PTRACE_GETREGS 18 /* get all registers (pt_all_user_regs) in one shot */
#define PTRACE_SETREGS 19 /* set all registers (pt_all_user_regs) in one shot */
#define PTRACE_SETOPTIONS 21
/* options set using PTRACE_SETOPTIONS */
#define PTRACE_O_TRACESYSGOOD 0x00000001
#define PTRACE_OLDSETOPTIONS 21
#endif /* _ASM_IA64_PTRACE_H */
......@@ -59,10 +59,7 @@ struct pt_regs {
/* #define PTRACE_GETFPXREGS 18 */
/* #define PTRACE_SETFPXREGS 19 */
#define PTRACE_SETOPTIONS 21
/* options set using PTRACE_SETOPTIONS */
#define PTRACE_O_TRACESYSGOOD 0x00000001
#define PTRACE_OLDSETOPTIONS 21
#ifdef _LANGUAGE_ASSEMBLY
#include <asm/offset.h>
......
......@@ -64,10 +64,7 @@ struct pt_regs {
/* #define PTRACE_GETFPXREGS 18 */
/* #define PTRACE_SETFPXREGS 19 */
#define PTRACE_SETOPTIONS 21
/* options set using PTRACE_SETOPTIONS */
#define PTRACE_O_TRACESYSGOOD 0x00000001
#define PTRACE_OLDSETOPTIONS 21
#ifdef _LANGUAGE_ASSEMBLY
#include <asm/offset.h>
......
......@@ -105,10 +105,7 @@
#define STACK_FRAME_OVERHEAD 96 /* size of minimum stack frame */
#define PTRACE_SETOPTIONS 21
/* options set using PTRACE_SETOPTIONS */
#define PTRACE_O_TRACESYSGOOD 0x00000001
#define PTRACE_OLDSETOPTIONS 21
#ifndef __ASSEMBLY__
#include <linux/config.h>
......
......@@ -85,10 +85,7 @@
#define STACK_FRAME_OVERHEAD 160 /* size of minimum stack frame */
#define PTRACE_SETOPTIONS 21
/* options set using PTRACE_SETOPTIONS */
#define PTRACE_O_TRACESYSGOOD 0x00000001
#define PTRACE_OLDSETOPTIONS 21
#ifndef __ASSEMBLY__
#include <linux/config.h>
......
......@@ -44,10 +44,7 @@
#define REG_XDREG14 47
#define REG_FPSCR 48
#define PTRACE_SETOPTIONS 21
/* options set using PTRACE_SETOPTIONS */
#define PTRACE_O_TRACESYSGOOD 0x00000001
#define PTRACE_OLDSETOPTIONS 21
/*
* This struct defines the way the registers are stored on the
......
......@@ -32,10 +32,7 @@
/* top of stack page */
#define FRAME_SIZE 168
#define PTRACE_SETOPTIONS 21
/* options set using PTRACE_SETOPTIONS */
#define PTRACE_O_TRACESYSGOOD 0x00000001
#define PTRACE_OLDSETOPTIONS 21
/* Dummy values for ptrace */
#define FS 1000
......
......@@ -23,6 +23,12 @@
#define PTRACE_SYSCALL 24
/* 0x4200-0x4300 are reserved for architecture-independent additions. */
#define PTRACE_SETOPTIONS 0x4200
/* options set using PTRACE_SETOPTIONS */
#define PTRACE_O_TRACESYSGOOD 0x00000001
#include <asm/ptrace.h>
#include <linux/sched.h>
......@@ -32,6 +38,7 @@ extern int ptrace_attach(struct task_struct *tsk);
extern int ptrace_detach(struct task_struct *, unsigned int);
extern void ptrace_disable(struct task_struct *);
extern int ptrace_check_attach(struct task_struct *task, int kill);
extern int ptrace_request(struct task_struct *child, long request, long addr, long data);
extern void __ptrace_link(struct task_struct *child,
struct task_struct *new_parent);
extern void __ptrace_unlink(struct task_struct *child);
......
......@@ -248,3 +248,35 @@ int ptrace_writedata(struct task_struct *tsk, char * src, unsigned long dst, int
}
return copied;
}
int ptrace_setoptions(struct task_struct *child, long data)
{
if (data & PTRACE_O_TRACESYSGOOD)
child->ptrace |= PT_TRACESYSGOOD;
else
child->ptrace &= ~PT_TRACESYSGOOD;
if ((data & PTRACE_O_TRACESYSGOOD) != data)
return -EINVAL;
return 0;
}
int ptrace_request(struct task_struct *child, long request,
long addr, long data)
{
int ret = -EIO;
switch (request) {
#ifdef PTRACE_OLDSETOPTIONS
case PTRACE_OLDSETOPTIONS:
#endif
case PTRACE_SETOPTIONS:
ret = ptrace_setoptions(child, data);
break;
default:
break;
}
return ret;
}
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