summaryrefslogtreecommitdiffstats
path: root/sys/amd64/amd64/ptrace_machdep.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/amd64/amd64/ptrace_machdep.c')
-rw-r--r--sys/amd64/amd64/ptrace_machdep.c62
1 files changed, 62 insertions, 0 deletions
diff --git a/sys/amd64/amd64/ptrace_machdep.c b/sys/amd64/amd64/ptrace_machdep.c
index 4cd5bf2..dbb3f13 100644
--- a/sys/amd64/amd64/ptrace_machdep.c
+++ b/sys/amd64/amd64/ptrace_machdep.c
@@ -36,8 +36,12 @@ __FBSDID("$FreeBSD$");
#include <sys/proc.h>
#include <sys/ptrace.h>
#include <sys/sysent.h>
+#include <vm/vm.h>
+#include <vm/pmap.h>
#include <machine/md_var.h>
#include <machine/pcb.h>
+#include <machine/frame.h>
+#include <machine/vmparam.h>
static int
cpu_ptrace_xstate(struct thread *td, int req, void *addr, int data)
@@ -110,6 +114,20 @@ cpu_ptrace_xstate(struct thread *td, int req, void *addr, int data)
return (error);
}
+static void
+cpu_ptrace_setbase(struct thread *td, int req, register_t r)
+{
+
+ if (req == PT_SETFSBASE) {
+ td->td_pcb->pcb_fsbase = r;
+ td->td_frame->tf_fs = _ufssel;
+ } else {
+ td->td_pcb->pcb_gsbase = r;
+ td->td_frame->tf_gs = _ugssel;
+ }
+ set_pcb_flags(td->td_pcb, PCB_FULL_IRET);
+}
+
#ifdef COMPAT_FREEBSD32
#define PT_I386_GETXMMREGS (PT_FIRSTMACH + 0)
#define PT_I386_SETXMMREGS (PT_FIRSTMACH + 1)
@@ -118,6 +136,7 @@ static int
cpu32_ptrace(struct thread *td, int req, void *addr, int data)
{
struct savefpu *fpstate;
+ uint32_t r;
int error;
switch (req) {
@@ -142,6 +161,29 @@ cpu32_ptrace(struct thread *td, int req, void *addr, int data)
error = cpu_ptrace_xstate(td, req, addr, data);
break;
+ case PT_GETFSBASE:
+ case PT_GETGSBASE:
+ if (!SV_PROC_FLAG(td->td_proc, SV_ILP32)) {
+ error = EINVAL;
+ break;
+ }
+ r = req == PT_GETFSBASE ? td->td_pcb->pcb_fsbase :
+ td->td_pcb->pcb_gsbase;
+ error = copyout(&r, addr, sizeof(r));
+ break;
+
+ case PT_SETFSBASE:
+ case PT_SETGSBASE:
+ if (!SV_PROC_FLAG(td->td_proc, SV_ILP32)) {
+ error = EINVAL;
+ break;
+ }
+ error = copyin(addr, &r, sizeof(r));
+ if (error != 0)
+ break;
+ cpu_ptrace_setbase(td, req, r);
+ break;
+
default:
error = EINVAL;
break;
@@ -154,6 +196,7 @@ cpu32_ptrace(struct thread *td, int req, void *addr, int data)
int
cpu_ptrace(struct thread *td, int req, void *addr, int data)
{
+ register_t *r, rv;
int error;
#ifdef COMPAT_FREEBSD32
@@ -176,6 +219,25 @@ cpu_ptrace(struct thread *td, int req, void *addr, int data)
error = cpu_ptrace_xstate(td, req, addr, data);
break;
+ case PT_GETFSBASE:
+ case PT_GETGSBASE:
+ r = req == PT_GETFSBASE ? &td->td_pcb->pcb_fsbase :
+ &td->td_pcb->pcb_gsbase;
+ error = copyout(r, addr, sizeof(*r));
+ break;
+
+ case PT_SETFSBASE:
+ case PT_SETGSBASE:
+ error = copyin(addr, &rv, sizeof(rv));
+ if (error != 0)
+ break;
+ if (rv >= td->td_proc->p_sysent->sv_maxuser) {
+ error = EINVAL;
+ break;
+ }
+ cpu_ptrace_setbase(td, req, rv);
+ break;
+
default:
error = EINVAL;
break;
OpenPOWER on IntegriCloud