mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-26 21:54:11 +08:00
[PATCH] uml: x86_64 ptrace fixes
This patch fixes some missing ptrace bits on x86_64. PTRACE_ARCH_PRCTL is hooked up and implemented. This required generalizing arch_prctl_skas slightly to take a task_struct to modify. Previously, it always operated on current. Reading and writing the debug registers is also enabled by un-ifdefing the code that implements that. It turns out that x86_64 is identical to i386, so the same code can be used. Signed-off-by: Jeff Dike <jdike@addtoit.com> Cc: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
f355559cf7
commit
6e6d74cfac
@ -18,6 +18,7 @@
|
|||||||
#include "kern_util.h"
|
#include "kern_util.h"
|
||||||
#include "skas_ptrace.h"
|
#include "skas_ptrace.h"
|
||||||
#include "sysdep/ptrace.h"
|
#include "sysdep/ptrace.h"
|
||||||
|
#include "os.h"
|
||||||
|
|
||||||
static inline void set_singlestepping(struct task_struct *child, int on)
|
static inline void set_singlestepping(struct task_struct *child, int on)
|
||||||
{
|
{
|
||||||
@ -240,6 +241,12 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
|
|||||||
ret = 0;
|
ret = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef PTRACE_ARCH_PRCTL
|
||||||
|
case PTRACE_ARCH_PRCTL:
|
||||||
|
/* XXX Calls ptrace on the host - needs some SMP thinking */
|
||||||
|
ret = arch_prctl_skas(child, data, (void *) addr);
|
||||||
|
break;
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
ret = ptrace_request(child, request, addr, data);
|
ret = ptrace_request(child, request, addr, data);
|
||||||
|
@ -71,8 +71,6 @@ int poke_user(struct task_struct *child, long addr, long data)
|
|||||||
|
|
||||||
if (addr < MAX_REG_OFFSET)
|
if (addr < MAX_REG_OFFSET)
|
||||||
return putreg(child, addr, data);
|
return putreg(child, addr, data);
|
||||||
|
|
||||||
#if 0 /* Need x86_64 debugregs handling */
|
|
||||||
else if((addr >= offsetof(struct user, u_debugreg[0])) &&
|
else if((addr >= offsetof(struct user, u_debugreg[0])) &&
|
||||||
(addr <= offsetof(struct user, u_debugreg[7]))){
|
(addr <= offsetof(struct user, u_debugreg[7]))){
|
||||||
addr -= offsetof(struct user, u_debugreg[0]);
|
addr -= offsetof(struct user, u_debugreg[0]);
|
||||||
@ -81,7 +79,6 @@ int poke_user(struct task_struct *child, long addr, long data)
|
|||||||
child->thread.arch.debugregs[addr] = data;
|
child->thread.arch.debugregs[addr] = data;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -119,14 +116,12 @@ int peek_user(struct task_struct *child, long addr, long data)
|
|||||||
if(addr < MAX_REG_OFFSET){
|
if(addr < MAX_REG_OFFSET){
|
||||||
tmp = getreg(child, addr);
|
tmp = getreg(child, addr);
|
||||||
}
|
}
|
||||||
#if 0 /* Need x86_64 debugregs handling */
|
|
||||||
else if((addr >= offsetof(struct user, u_debugreg[0])) &&
|
else if((addr >= offsetof(struct user, u_debugreg[0])) &&
|
||||||
(addr <= offsetof(struct user, u_debugreg[7]))){
|
(addr <= offsetof(struct user, u_debugreg[7]))){
|
||||||
addr -= offsetof(struct user, u_debugreg[0]);
|
addr -= offsetof(struct user, u_debugreg[0]);
|
||||||
addr = addr >> 2;
|
addr = addr >> 2;
|
||||||
tmp = child->thread.arch.debugregs[addr];
|
tmp = child->thread.arch.debugregs[addr];
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
return put_user(tmp, (unsigned long *) data);
|
return put_user(tmp, (unsigned long *) data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,18 +59,20 @@ static long arch_prctl_tt(int code, unsigned long addr)
|
|||||||
|
|
||||||
#ifdef CONFIG_MODE_SKAS
|
#ifdef CONFIG_MODE_SKAS
|
||||||
|
|
||||||
static long arch_prctl_skas(int code, unsigned long __user *addr)
|
long arch_prctl_skas(struct task_struct *task, int code,
|
||||||
|
unsigned long __user *addr)
|
||||||
{
|
{
|
||||||
unsigned long *ptr = addr, tmp;
|
unsigned long *ptr = addr, tmp;
|
||||||
long ret;
|
long ret;
|
||||||
int pid = current->mm->context.skas.id.u.pid;
|
int pid = task->mm->context.skas.id.u.pid;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* With ARCH_SET_FS (and ARCH_SET_GS is treated similarly to
|
* With ARCH_SET_FS (and ARCH_SET_GS is treated similarly to
|
||||||
* be safe), we need to call arch_prctl on the host because
|
* be safe), we need to call arch_prctl on the host because
|
||||||
* setting %fs may result in something else happening (like a
|
* setting %fs may result in something else happening (like a
|
||||||
* GDT being set instead). So, we let the host fiddle the
|
* GDT or thread.fs being set instead). So, we let the host
|
||||||
* registers and restore them afterwards.
|
* fiddle the registers and thread struct and restore the
|
||||||
|
* registers afterwards.
|
||||||
*
|
*
|
||||||
* So, the saved registers are stored to the process (this
|
* So, the saved registers are stored to the process (this
|
||||||
* needed because a stub may have been the last thing to run),
|
* needed because a stub may have been the last thing to run),
|
||||||
@ -118,7 +120,7 @@ static long arch_prctl_skas(int code, unsigned long __user *addr)
|
|||||||
|
|
||||||
long sys_arch_prctl(int code, unsigned long addr)
|
long sys_arch_prctl(int code, unsigned long addr)
|
||||||
{
|
{
|
||||||
return CHOOSE_MODE_PROC(arch_prctl_tt, arch_prctl_skas, code,
|
return CHOOSE_MODE_PROC(arch_prctl_tt, arch_prctl_skas, current, code,
|
||||||
(unsigned long __user *) addr);
|
(unsigned long __user *) addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -141,6 +143,6 @@ void arch_switch_to_skas(struct task_struct *from, struct task_struct *to)
|
|||||||
if(to->thread.arch.fs == 0)
|
if(to->thread.arch.fs == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
arch_prctl_skas(ARCH_SET_FS, (void __user *) to->thread.arch.fs);
|
arch_prctl_skas(to, ARCH_SET_FS, (void __user *) to->thread.arch.fs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,4 +84,7 @@ static inline void arch_switch_to_tt(struct task_struct *from,
|
|||||||
extern void arch_switch_to_skas(struct task_struct *from,
|
extern void arch_switch_to_skas(struct task_struct *from,
|
||||||
struct task_struct *to);
|
struct task_struct *to);
|
||||||
|
|
||||||
|
extern long arch_prctl_skas(struct task_struct *task, int code,
|
||||||
|
unsigned long __user *addr);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user