Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F151772739
D9406.id25201.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
24 KB
Referenced Files
None
Subscribers
None
D9406.id25201.diff
View Options
Index: sys/amd64/linux/linux_dummy.c
===================================================================
--- sys/amd64/linux/linux_dummy.c
+++ sys/amd64/linux/linux_dummy.c
@@ -45,7 +45,6 @@
DUMMY(mincore);
DUMMY(sendfile);
-DUMMY(ptrace);
DUMMY(syslog);
DUMMY(setfsuid);
DUMMY(setfsgid);
Index: sys/amd64/linux/linux_ptrace.c
===================================================================
--- sys/amd64/linux/linux_ptrace.c
+++ sys/amd64/linux/linux_ptrace.c
@@ -1,483 +1,417 @@
/*-
- * Copyright (c) 2001 Alexander Kabaev
+ * Copyright (c) 2017 Edward Tomasz Napierala <trasz@FreeBSD.org>
* All rights reserved.
*
+ * This software was developed by SRI International and the University of
+ * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
+ * ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer
- * in this position and unchanged.
+ * notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
*
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/i386/linux/linux_ptrace.c 302921 2016-07-16 00:54:46Z jhb $");
-
-#include "opt_cpu.h"
+__FBSDID("$FreeBSD$");
#include <sys/param.h>
-#include <sys/lock.h>
-#include <sys/mutex.h>
#include <sys/proc.h>
#include <sys/ptrace.h>
#include <sys/syscallsubr.h>
-#include <sys/systm.h>
-
-#include <machine/md_var.h>
#include <machine/pcb.h>
#include <machine/reg.h>
-
-#include <i386/linux/linux.h>
-#include <i386/linux/linux_proto.h>
+#include <security/audit/audit.h>
+#include <amd64/linux/linux.h>
+#include <amd64/linux/linux_proto.h>
#include <compat/linux/linux_signal.h>
-#if !defined(CPU_DISABLE_SSE) && defined(I686_CPU)
-#define CPU_ENABLE_SSE
-#endif
+#define LINUX_PTRACE_TRACEME 0
+#define LINUX_PTRACE_PEEKTEXT 1
+#define LINUX_PTRACE_PEEKDATA 2
+#define LINUX_PTRACE_PEEKUSER 3
+#define LINUX_PTRACE_POKETEXT 4
+#define LINUX_PTRACE_POKEDATA 5
+#define LINUX_PTRACE_POKEUSER 6
+#define LINUX_PTRACE_CONT 7
+#define LINUX_PTRACE_KILL 8
+#define LINUX_PTRACE_SINGLESTEP 9
+#define LINUX_PTRACE_GETREGS 12
+#define LINUX_PTRACE_SETREGS 13
+#define LINUX_PTRACE_GETFPREGS 14
+#define LINUX_PTRACE_SETFPREGS 15
+#define LINUX_PTRACE_ATTACH 16
+#define LINUX_PTRACE_DETACH 17
+#define LINUX_PTRACE_SYSCALL 24
+#define LINUX_PTRACE_SETOPTIONS 0x4200
+#define LINUX_PTRACE_GETREGSET 0x4204
+#define LINUX_PTRACE_SEIZE 0x4206
+
+#define LINUX_PTRACE_O_TRACESYSGOOD 1
+#define LINUX_PTRACE_O_TRACEFORK 2
+#define LINUX_PTRACE_O_TRACEVFORK 4
+#define LINUX_PTRACE_O_TRACECLONE 8
+#define LINUX_PTRACE_O_TRACEEXEC 16
+#define LINUX_PTRACE_O_TRACEVFORKDONE 32
+#define LINUX_PTRACE_O_TRACEEXIT 64
+#define LINUX_PTRACE_O_TRACESECCOMP 128
+#define LINUX_PTRACE_O_EXITKILL 1048576
+#define LINUX_PTRACE_O_SUSPEND_SECCOMP 2097152
+
+#define LINUX_NT_PRSTATUS 1
+
+#define LINUX_PTRACE_O_MASK (LINUX_PTRACE_O_TRACESYSGOOD | \
+ LINUX_PTRACE_O_TRACEFORK | LINUX_PTRACE_O_TRACEVFORK | \
+ LINUX_PTRACE_O_TRACECLONE | LINUX_PTRACE_O_TRACEEXEC | \
+ LINUX_PTRACE_O_TRACEVFORKDONE | LINUX_PTRACE_O_TRACEEXIT | \
+ LINUX_PTRACE_O_TRACESECCOMP | LINUX_PTRACE_O_EXITKILL | \
+ LINUX_PTRACE_O_SUSPEND_SECCOMP)
-/*
- * Linux ptrace requests numbers. Mostly identical to FreeBSD,
- * except for MD ones and PT_ATTACH/PT_DETACH.
- */
-#define PTRACE_TRACEME 0
-#define PTRACE_PEEKTEXT 1
-#define PTRACE_PEEKDATA 2
-#define PTRACE_PEEKUSR 3
-#define PTRACE_POKETEXT 4
-#define PTRACE_POKEDATA 5
-#define PTRACE_POKEUSR 6
-#define PTRACE_CONT 7
-#define PTRACE_KILL 8
-#define PTRACE_SINGLESTEP 9
-
-#define PTRACE_ATTACH 16
-#define PTRACE_DETACH 17
-
-#define LINUX_PTRACE_SYSCALL 24
-
-#define PTRACE_GETREGS 12
-#define PTRACE_SETREGS 13
-#define PTRACE_GETFPREGS 14
-#define PTRACE_SETFPREGS 15
-#define PTRACE_GETFPXREGS 18
-#define PTRACE_SETFPXREGS 19
+struct linux_pt_reg {
+ l_ulong r15;
+ l_ulong r14;
+ l_ulong r13;
+ l_ulong r12;
+ l_ulong rbp;
+ l_ulong rbx;
+ l_ulong r11;
+ l_ulong r10;
+ l_ulong r9;
+ l_ulong r8;
+ l_ulong rax;
+ l_ulong rcx;
+ l_ulong rdx;
+ l_ulong rsi;
+ l_ulong rdi;
+ l_ulong orig_rax;
+ l_ulong rip;
+ l_ulong cs;
+ l_ulong eflags;
+ l_ulong rsp;
+ l_ulong ss;
+};
-#define PTRACE_SETOPTIONS 21
+static int
+map_signum(int lsig, int *bsigp)
+{
+ int bsig;
-/*
- * Linux keeps debug registers at the following
- * offset in the user struct
- */
-#define LINUX_DBREG_OFFSET 252
-#define LINUX_DBREG_SIZE (8*sizeof(l_int))
+ if (lsig == 0) {
+ *bsigp = 0;
+ return (0);
+ }
-static __inline int
-map_signum(int signum)
-{
+ if (lsig < 0 || lsig > LINUX_SIGRTMAX)
+ return (EINVAL);
- signum = linux_to_bsd_signal(signum);
- return ((signum == SIGSTOP)? 0 : signum);
-}
+ bsig = linux_to_bsd_signal(lsig);
+ if (bsig == SIGSTOP)
+ bsig = 0;
-struct linux_pt_reg {
- l_long ebx;
- l_long ecx;
- l_long edx;
- l_long esi;
- l_long edi;
- l_long ebp;
- l_long eax;
- l_int xds;
- l_int xes;
- l_int xfs;
- l_int xgs;
- l_long orig_eax;
- l_long eip;
- l_int xcs;
- l_long eflags;
- l_long esp;
- l_int xss;
-};
+ *bsigp = bsig;
+ return (0);
+}
/*
- * Translate i386 ptrace registers between Linux and FreeBSD formats.
- * The translation is pretty straighforward, for all registers, but
- * orig_eax on Linux side and r_trapno and r_err in FreeBSD
+ * Translate amd64 ptrace registers between Linux and FreeBSD formats.
+ * The translation is pretty straighforward, for all registers but
+ * orig_rax on Linux side and r_trapno and r_err in FreeBSD.
*/
static void
-map_regs_to_linux(struct reg *bsd_r, struct linux_pt_reg *linux_r)
+map_regs_to_linux(struct reg *b_reg, struct linux_pt_reg *l_reg)
{
- linux_r->ebx = bsd_r->r_ebx;
- linux_r->ecx = bsd_r->r_ecx;
- linux_r->edx = bsd_r->r_edx;
- linux_r->esi = bsd_r->r_esi;
- linux_r->edi = bsd_r->r_edi;
- linux_r->ebp = bsd_r->r_ebp;
- linux_r->eax = bsd_r->r_eax;
- linux_r->xds = bsd_r->r_ds;
- linux_r->xes = bsd_r->r_es;
- linux_r->xfs = bsd_r->r_fs;
- linux_r->xgs = bsd_r->r_gs;
- linux_r->orig_eax = bsd_r->r_eax;
- linux_r->eip = bsd_r->r_eip;
- linux_r->xcs = bsd_r->r_cs;
- linux_r->eflags = bsd_r->r_eflags;
- linux_r->esp = bsd_r->r_esp;
- linux_r->xss = bsd_r->r_ss;
+
+ l_reg->r15 = b_reg->r_r15;
+ l_reg->r14 = b_reg->r_r14;
+ l_reg->r13 = b_reg->r_r13;
+ l_reg->r12 = b_reg->r_r12;
+ l_reg->rbp = b_reg->r_rbp;
+ l_reg->rbx = b_reg->r_rbx;
+ l_reg->r11 = b_reg->r_r11;
+ l_reg->r10 = b_reg->r_r10;
+ l_reg->r9 = b_reg->r_r9;
+ l_reg->r8 = b_reg->r_r8;
+ l_reg->rax = b_reg->r_rax;
+ l_reg->rcx = b_reg->r_rcx;
+ l_reg->rdx = b_reg->r_rdx;
+ l_reg->rsi = b_reg->r_rsi;
+ l_reg->rdi = b_reg->r_rdi;
+ l_reg->orig_rax = b_reg->r_rax;
+ l_reg->rip = b_reg->r_rip;
+ l_reg->cs = b_reg->r_cs;
+ l_reg->eflags = b_reg->r_rflags;
+ l_reg->rsp = b_reg->r_rsp;
+ l_reg->ss = b_reg->r_ss;
}
static void
-map_regs_from_linux(struct reg *bsd_r, struct linux_pt_reg *linux_r)
+map_regs_from_linux(struct reg *b_reg, struct linux_pt_reg *l_reg)
{
- bsd_r->r_ebx = linux_r->ebx;
- bsd_r->r_ecx = linux_r->ecx;
- bsd_r->r_edx = linux_r->edx;
- bsd_r->r_esi = linux_r->esi;
- bsd_r->r_edi = linux_r->edi;
- bsd_r->r_ebp = linux_r->ebp;
- bsd_r->r_eax = linux_r->eax;
- bsd_r->r_ds = linux_r->xds;
- bsd_r->r_es = linux_r->xes;
- bsd_r->r_fs = linux_r->xfs;
- bsd_r->r_gs = linux_r->xgs;
- bsd_r->r_eip = linux_r->eip;
- bsd_r->r_cs = linux_r->xcs;
- bsd_r->r_eflags = linux_r->eflags;
- bsd_r->r_esp = linux_r->esp;
- bsd_r->r_ss = linux_r->xss;
+ b_reg->r_r15 = l_reg->r15;
+ b_reg->r_r14 = l_reg->r14;
+ b_reg->r_r13 = l_reg->r13;
+ b_reg->r_r12 = l_reg->r12;
+ b_reg->r_r11 = l_reg->r11;
+ b_reg->r_r10 = l_reg->r10;
+ b_reg->r_r9 = l_reg->r9;
+ b_reg->r_r8 = l_reg->r8;
+ b_reg->r_rdi = l_reg->rdi;
+ b_reg->r_rsi = l_reg->rsi;
+ b_reg->r_rbp = l_reg->rbp;
+ b_reg->r_rbx = l_reg->rbx;
+ b_reg->r_rdx = l_reg->rdx;
+ b_reg->r_rcx = l_reg->rcx;
+ b_reg->r_rax = l_reg->rax;
+
+ /*
+ * XXX: Are zeroes the right thing to put here?
+ */
+ b_reg->r_trapno = 0;
+ b_reg->r_fs = 0;
+ b_reg->r_gs = 0;
+ b_reg->r_err = 0;
+ b_reg->r_es = 0;
+ b_reg->r_ds = 0;
+
+ b_reg->r_rip = l_reg->rip;
+ b_reg->r_cs = l_reg->cs;
+ b_reg->r_rflags = l_reg->eflags;
+ b_reg->r_rsp = l_reg->rsp;
+ b_reg->r_ss = l_reg->ss;
}
-struct linux_pt_fpreg {
- l_long cwd;
- l_long swd;
- l_long twd;
- l_long fip;
- l_long fcs;
- l_long foo;
- l_long fos;
- l_long st_space[2*10];
-};
+static int
+linux_ptrace_peek(struct thread *td, pid_t pid, void *addr, void *data)
+{
+ int error;
-static void
-map_fpregs_to_linux(struct fpreg *bsd_r, struct linux_pt_fpreg *linux_r)
+ error = kern_ptrace(td, PT_READ_I, pid, addr, 0);
+ if (error == 0)
+ error = copyout(td->td_retval, data, sizeof(l_int));
+ td->td_retval[0] = error;
+
+ return (error);
+}
+
+static int
+linux_ptrace_setoptions(struct thread *td, pid_t pid, l_ulong data)
{
- linux_r->cwd = bsd_r->fpr_env[0];
- linux_r->swd = bsd_r->fpr_env[1];
- linux_r->twd = bsd_r->fpr_env[2];
- linux_r->fip = bsd_r->fpr_env[3];
- linux_r->fcs = bsd_r->fpr_env[4];
- linux_r->foo = bsd_r->fpr_env[5];
- linux_r->fos = bsd_r->fpr_env[6];
- bcopy(bsd_r->fpr_acc, linux_r->st_space, sizeof(linux_r->st_space));
+ int mask;
+
+ mask = 0;
+
+ if (data & ~LINUX_PTRACE_O_MASK) {
+ printf("%s: unknown ptrace option %lx set; "
+ "returning EINVAL\n",
+ __func__, data & ~LINUX_PTRACE_O_MASK);
+ return (EINVAL);
+ }
+
+ /*
+ * PTRACE_O_EXITKILL is ignored, we do that by default.
+ */
+
+ if (data & LINUX_PTRACE_O_TRACESYSGOOD) {
+ printf("%s: PTRACE_O_TRACESYSGOOD not implemented; "
+ "returning EINVAL\n", __func__);
+ return (EINVAL);
+ }
+
+ if (data & LINUX_PTRACE_O_TRACEFORK)
+ mask |= PTRACE_FORK;
+
+ if (data & LINUX_PTRACE_O_TRACEVFORK)
+ mask |= PTRACE_VFORK;
+
+ if (data & LINUX_PTRACE_O_TRACECLONE)
+ mask |= PTRACE_VFORK;
+
+ if (data & LINUX_PTRACE_O_TRACEEXEC)
+ mask |= PTRACE_EXEC;
+
+ if (data & LINUX_PTRACE_O_TRACEVFORKDONE)
+ mask |= PTRACE_VFORK; /* XXX: Close enough? */
+
+ if (data & LINUX_PTRACE_O_TRACEEXIT) {
+ printf("%s: PTRACE_O_TRACESYSGOOD not implemented; "
+ "returning EINVAL\n", __func__);
+ return (EINVAL);
+ }
+
+ return (kern_ptrace(td, PT_SET_EVENT_MASK, pid, &mask, sizeof(mask)));
}
-static void
-map_fpregs_from_linux(struct fpreg *bsd_r, struct linux_pt_fpreg *linux_r)
+static int
+linux_ptrace_getregs(struct thread *td, pid_t pid, void *data)
{
- bsd_r->fpr_env[0] = linux_r->cwd;
- bsd_r->fpr_env[1] = linux_r->swd;
- bsd_r->fpr_env[2] = linux_r->twd;
- bsd_r->fpr_env[3] = linux_r->fip;
- bsd_r->fpr_env[4] = linux_r->fcs;
- bsd_r->fpr_env[5] = linux_r->foo;
- bsd_r->fpr_env[6] = linux_r->fos;
- bcopy(bsd_r->fpr_acc, linux_r->st_space, sizeof(bsd_r->fpr_acc));
+ struct ptrace_lwpinfo lwpinfo;
+ struct reg b_reg;
+ struct linux_pt_reg l_reg;
+ int error;
+
+ error = kern_ptrace(td, PT_GETREGS, pid, &b_reg, 0);
+ if (error != 0)
+ return (error);
+
+ map_regs_to_linux(&b_reg, &l_reg);
+
+ /*
+ * The strace(1) utility depends on RAX being set to -ENOSYS
+ * on syscall entry.
+ */
+ error = kern_ptrace(td, PT_LWPINFO, pid, &lwpinfo, sizeof(lwpinfo));
+ if (error != 0) {
+ printf("%s: PT_LWPINFO failed with error %d\n",
+ __func__, error);
+ return (error);
+ }
+ if (lwpinfo.pl_flags & PL_FLAG_SCE)
+ l_reg.rax = -38; // XXX: This should be #defined somewhere.
+
+ error = copyout(&l_reg, (void *)data, sizeof(l_reg));
+ return (error);
}
-struct linux_pt_fpxreg {
- l_ushort cwd;
- l_ushort swd;
- l_ushort twd;
- l_ushort fop;
- l_long fip;
- l_long fcs;
- l_long foo;
- l_long fos;
- l_long mxcsr;
- l_long reserved;
- l_long st_space[32];
- l_long xmm_space[32];
- l_long padding[56];
-};
+static int
+linux_ptrace_setregs(struct thread *td, pid_t pid, void *data)
+{
+ struct reg b_reg;
+ struct linux_pt_reg l_reg;
+ int error;
+
+ error = copyin(data, &l_reg, sizeof(l_reg));
+ if (error != 0)
+ return (error);
+ map_regs_from_linux(&b_reg, &l_reg);
+ error = kern_ptrace(td, PT_SETREGS, pid, &b_reg, 0);
+ return (error);
+}
-#ifdef CPU_ENABLE_SSE
static int
-linux_proc_read_fpxregs(struct thread *td, struct linux_pt_fpxreg *fpxregs)
+linux_ptrace_getregset(struct thread *td, pid_t pid,
+ l_ulong addr, l_ulong data)
{
- PROC_LOCK_ASSERT(td->td_proc, MA_OWNED);
- if (cpu_fxsr == 0 || (td->td_proc->p_flag & P_INMEM) == 0)
- return (EIO);
- bcopy(&get_pcb_user_save_td(td)->sv_xmm, fpxregs, sizeof(*fpxregs));
- return (0);
+ switch (addr) {
+ case LINUX_NT_PRSTATUS:
+ printf("%s: NT_PRSTATUS not implemented; returning EINVAL\n",
+ __func__);
+ return (EINVAL);
+ default:
+ printf("%s: PTRACE_GETREGSET request %ld not implemented; "
+ "returning EINVAL\n", __func__, addr);
+ return (EINVAL);
+ }
}
static int
-linux_proc_write_fpxregs(struct thread *td, struct linux_pt_fpxreg *fpxregs)
+linux_ptrace_seize(struct thread *td, pid_t pid, l_ulong addr, l_ulong data)
{
- PROC_LOCK_ASSERT(td->td_proc, MA_OWNED);
- if (cpu_fxsr == 0 || (td->td_proc->p_flag & P_INMEM) == 0)
- return (EIO);
- bcopy(fpxregs, &get_pcb_user_save_td(td)->sv_xmm, sizeof(*fpxregs));
- return (0);
+ printf("%s: PTRACE_SEIZE not implemented; returning EINVAL\n",
+ __func__);
+ return (EINVAL);
}
-#endif
int
linux_ptrace(struct thread *td, struct linux_ptrace_args *uap)
{
- union {
- struct linux_pt_reg reg;
- struct linux_pt_fpreg fpreg;
- struct linux_pt_fpxreg fpxreg;
- } r;
- union {
- struct reg bsd_reg;
- struct fpreg bsd_fpreg;
- struct dbreg bsd_dbreg;
- } u;
void *addr;
pid_t pid;
- int error, req;
+ int error, sig;
- error = 0;
+ AUDIT_ARG_PID(uap->pid);
+ AUDIT_ARG_CMD(uap->req);
+ AUDIT_ARG_VALUE(uap->data);
- /* by default, just copy data intact */
- req = uap->req;
pid = (pid_t)uap->pid;
addr = (void *)uap->addr;
- switch (req) {
- case PTRACE_TRACEME:
- case PTRACE_POKETEXT:
- case PTRACE_POKEDATA:
- case PTRACE_KILL:
- error = kern_ptrace(td, req, pid, addr, uap->data);
- break;
- case PTRACE_PEEKTEXT:
- case PTRACE_PEEKDATA: {
- /* need to preserve return value */
- int rval = td->td_retval[0];
- error = kern_ptrace(td, req, pid, addr, 0);
- if (error == 0)
- error = copyout(td->td_retval, (void *)uap->data,
- sizeof(l_int));
- td->td_retval[0] = rval;
+ switch (uap->req) {
+ case LINUX_PTRACE_TRACEME:
+ error = kern_ptrace(td, PT_TRACE_ME, 0, 0, 0);
+ break;
+ case LINUX_PTRACE_PEEKTEXT:
+ case LINUX_PTRACE_PEEKDATA:
+ error = linux_ptrace_peek(td, pid, addr, (void *)uap->data);
+ if (error != 0)
+ return (error);
+ /*
+ * Linux expects this syscall to read 64 bits, not 32.
+ */
+ error = linux_ptrace_peek(td, pid,
+ (void *)(uap->addr + 4), (void *)(uap->data + 4));
break;
- }
- case PTRACE_DETACH:
- error = kern_ptrace(td, PT_DETACH, pid, (void *)1,
- map_signum(uap->data));
- break;
- case PTRACE_SINGLESTEP:
- case PTRACE_CONT:
- error = kern_ptrace(td, req, pid, (void *)1,
- map_signum(uap->data));
+ case LINUX_PTRACE_POKETEXT:
+ error = kern_ptrace(td, PT_WRITE_I, pid, addr, uap->data);
break;
- case PTRACE_ATTACH:
- error = kern_ptrace(td, PT_ATTACH, pid, addr, uap->data);
+ case LINUX_PTRACE_POKEDATA:
+ error = kern_ptrace(td, PT_WRITE_D, pid, addr, uap->data);
break;
- case PTRACE_GETREGS:
- /* Linux is using data where FreeBSD is using addr */
- error = kern_ptrace(td, PT_GETREGS, pid, &u.bsd_reg, 0);
- if (error == 0) {
- map_regs_to_linux(&u.bsd_reg, &r.reg);
- error = copyout(&r.reg, (void *)uap->data,
- sizeof(r.reg));
- }
- break;
- case PTRACE_SETREGS:
- /* Linux is using data where FreeBSD is using addr */
- error = copyin((void *)uap->data, &r.reg, sizeof(r.reg));
- if (error == 0) {
- map_regs_from_linux(&u.bsd_reg, &r.reg);
- error = kern_ptrace(td, PT_SETREGS, pid, &u.bsd_reg, 0);
- }
- break;
- case PTRACE_GETFPREGS:
- /* Linux is using data where FreeBSD is using addr */
- error = kern_ptrace(td, PT_GETFPREGS, pid, &u.bsd_fpreg, 0);
- if (error == 0) {
- map_fpregs_to_linux(&u.bsd_fpreg, &r.fpreg);
- error = copyout(&r.fpreg, (void *)uap->data,
- sizeof(r.fpreg));
- }
- break;
- case PTRACE_SETFPREGS:
- /* Linux is using data where FreeBSD is using addr */
- error = copyin((void *)uap->data, &r.fpreg, sizeof(r.fpreg));
- if (error == 0) {
- map_fpregs_from_linux(&u.bsd_fpreg, &r.fpreg);
- error = kern_ptrace(td, PT_SETFPREGS, pid,
- &u.bsd_fpreg, 0);
- }
- break;
- case PTRACE_SETFPXREGS:
-#ifdef CPU_ENABLE_SSE
- error = copyin((void *)uap->data, &r.fpxreg, sizeof(r.fpxreg));
- if (error)
- break;
-#endif
- /* FALL THROUGH */
- case PTRACE_GETFPXREGS: {
-#ifdef CPU_ENABLE_SSE
- struct proc *p;
- struct thread *td2;
-
- if (sizeof(struct linux_pt_fpxreg) != sizeof(struct savexmm)) {
- static int once = 0;
- if (!once) {
- printf("linux: savexmm != linux_pt_fpxreg\n");
- once = 1;
- }
- error = EIO;
+ case LINUX_PTRACE_CONT:
+ error = map_signum(uap->data, &sig);
+ if (error != 0)
break;
- }
-
- if ((p = pfind(uap->pid)) == NULL) {
- error = ESRCH;
+ error = kern_ptrace(td, PT_CONTINUE, pid, (void *)1, sig);
+ break;
+ case LINUX_PTRACE_KILL:
+ error = kern_ptrace(td, PT_KILL, pid, addr, uap->data);
+ break;
+ case LINUX_PTRACE_SINGLESTEP:
+ error = map_signum(uap->data, &sig);
+ if (error != 0)
break;
- }
-
- /* Exiting processes can't be debugged. */
- if ((p->p_flag & P_WEXIT) != 0) {
- error = ESRCH;
- goto fail;
- }
-
- if ((error = p_candebug(td, p)) != 0)
- goto fail;
-
- /* System processes can't be debugged. */
- if ((p->p_flag & P_SYSTEM) != 0) {
- error = EINVAL;
- goto fail;
- }
-
- /* not being traced... */
- if ((p->p_flag & P_TRACED) == 0) {
- error = EPERM;
- goto fail;
- }
-
- /* not being traced by YOU */
- if (p->p_pptr != td->td_proc) {
- error = EBUSY;
- goto fail;
- }
-
- /* not currently stopped */
- if (!P_SHOULDSTOP(p) || (p->p_flag & P_WAITED) == 0) {
- error = EBUSY;
- goto fail;
- }
-
- if (req == PTRACE_GETFPXREGS) {
- _PHOLD(p); /* may block */
- td2 = FIRST_THREAD_IN_PROC(p);
- error = linux_proc_read_fpxregs(td2, &r.fpxreg);
- _PRELE(p);
- PROC_UNLOCK(p);
- if (error == 0)
- error = copyout(&r.fpxreg, (void *)uap->data,
- sizeof(r.fpxreg));
- } else {
- /* clear dangerous bits exactly as Linux does*/
- r.fpxreg.mxcsr &= 0xffbf;
- _PHOLD(p); /* may block */
- td2 = FIRST_THREAD_IN_PROC(p);
- error = linux_proc_write_fpxregs(td2, &r.fpxreg);
- _PRELE(p);
- PROC_UNLOCK(p);
- }
- break;
-
- fail:
- PROC_UNLOCK(p);
-#else
- error = EIO;
-#endif
+ error = kern_ptrace(td, PT_STEP, pid, (void *)1, sig);
break;
- }
- case PTRACE_PEEKUSR:
- case PTRACE_POKEUSR: {
- error = EIO;
-
- /* check addr for alignment */
- if (uap->addr < 0 || uap->addr & (sizeof(l_int) - 1))
+ case LINUX_PTRACE_GETREGS:
+ error = linux_ptrace_getregs(td, pid, (void *)uap->data);
+ break;
+ case LINUX_PTRACE_SETREGS:
+ error = linux_ptrace_setregs(td, pid, (void *)uap->data);
+ break;
+ case LINUX_PTRACE_ATTACH:
+ error = kern_ptrace(td, PT_ATTACH, pid, addr, uap->data);
+ break;
+ case LINUX_PTRACE_DETACH:
+ error = map_signum(uap->data, &sig);
+ if (error != 0)
break;
- /*
- * Allow linux programs to access register values in
- * user struct. We simulate this through PT_GET/SETREGS
- * as necessary.
- */
- if (uap->addr < sizeof(struct linux_pt_reg)) {
- error = kern_ptrace(td, PT_GETREGS, pid, &u.bsd_reg, 0);
- if (error != 0)
- break;
-
- map_regs_to_linux(&u.bsd_reg, &r.reg);
- if (req == PTRACE_PEEKUSR) {
- error = copyout((char *)&r.reg + uap->addr,
- (void *)uap->data, sizeof(l_int));
- break;
- }
-
- *(l_int *)((char *)&r.reg + uap->addr) =
- (l_int)uap->data;
-
- map_regs_from_linux(&u.bsd_reg, &r.reg);
- error = kern_ptrace(td, PT_SETREGS, pid, &u.bsd_reg, 0);
- }
-
- /*
- * Simulate debug registers access
- */
- if (uap->addr >= LINUX_DBREG_OFFSET &&
- uap->addr <= LINUX_DBREG_OFFSET + LINUX_DBREG_SIZE) {
- error = kern_ptrace(td, PT_GETDBREGS, pid, &u.bsd_dbreg,
- 0);
- if (error != 0)
- break;
-
- uap->addr -= LINUX_DBREG_OFFSET;
- if (req == PTRACE_PEEKUSR) {
- error = copyout((char *)&u.bsd_dbreg +
- uap->addr, (void *)uap->data,
- sizeof(l_int));
- break;
- }
-
- *(l_int *)((char *)&u.bsd_dbreg + uap->addr) =
- uap->data;
- error = kern_ptrace(td, PT_SETDBREGS, pid,
- &u.bsd_dbreg, 0);
- }
-
+ error = kern_ptrace(td, PT_DETACH, pid, (void *)1, sig);
break;
- }
case LINUX_PTRACE_SYSCALL:
- /* fall through */
+ error = map_signum(uap->data, &sig);
+ if (error != 0)
+ break;
+ error = kern_ptrace(td, PT_SYSCALL, pid, (void *)1, sig);
+ break;
+ case LINUX_PTRACE_SETOPTIONS:
+ error = linux_ptrace_setoptions(td, pid, uap->data);
+ break;
+ case LINUX_PTRACE_GETREGSET:
+ error = linux_ptrace_getregset(td, pid, uap->addr, uap->data);
+ break;
+ case LINUX_PTRACE_SEIZE:
+ error = linux_ptrace_seize(td, pid, uap->addr, uap->data);
+ break;
default:
- printf("linux: ptrace(%u, ...) not implemented\n",
- (unsigned int)uap->req);
+ printf("%s: ptrace(%ld, ...) not implemented; "
+ "returning EINVAL\n", __func__, uap->req);
error = EINVAL;
break;
}
Index: sys/amd64/linux/syscalls.master
===================================================================
--- sys/amd64/linux/syscalls.master
+++ sys/amd64/linux/syscalls.master
@@ -219,7 +219,7 @@
99 AUE_NULL STD { int linux_sysinfo(struct l_sysinfo *info); }
100 AUE_NULL STD { int linux_times(struct l_times_argv *buf); }
101 AUE_PTRACE STD { int linux_ptrace(l_long req, l_long pid, \
- l_long addr, l_long data); }
+ l_ulong addr, l_ulong data); }
102 AUE_GETUID STD { int linux_getuid(void); }
103 AUE_NULL STD { int linux_syslog(l_int type, char *buf, \
l_int len); }
Index: sys/modules/linux64/Makefile
===================================================================
--- sys/modules/linux64/Makefile
+++ sys/modules/linux64/Makefile
@@ -7,7 +7,7 @@
KMOD= linux64
SRCS= linux_fork.c linux_dummy.c linux_file.c linux_event.c \
linux_futex.c linux_getcwd.c linux_ioctl.c linux_ipc.c \
- linux_machdep.c linux_misc.c linux_signal.c \
+ linux_machdep.c linux_misc.c linux_ptrace.c linux_signal.c \
linux_socket.c linux_stats.c linux_sysctl.c linux_sysent.c \
linux_sysvec.c linux_time.c linux_vdso.c linux_timer.c \
opt_inet6.h opt_compat.h opt_posix.h opt_usb.h \
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Apr 11, 1:56 PM (15 h, 32 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
31294429
Default Alt Text
D9406.id25201.diff (24 KB)
Attached To
Mode
D9406: Implement linux64 version of ptrace.
Attached
Detach File
Event Timeline
Log In to Comment