NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: kern/51514: ptrace(2) fails for 32-bit process on 64-bit kernel
The following reply was made to PR kern/51514; it has been noted by GNATS.
From: Nick Hudson <skrll%netbsd.org@localhost>
To: gnats-bugs%NetBSD.org@localhost, gnats-admin%netbsd.org@localhost, netbsd-bugs%netbsd.org@localhost,
rokuyama%rk.phys.keio.ac.jp@localhost
Cc:
Subject: Re: kern/51514: ptrace(2) fails for 32-bit process on 64-bit kernel
Date: Sun, 16 Oct 2016 09:09:10 +0100
This is a multi-part message in MIME format.
--------------050409000904030005020102
Content-Type: text/plain; charset=utf-8; format=flowed
Content-Transfer-Encoding: 7bit
On 09/29/16 14:30, Nick Hudson wrote:
> The following reply was made to PR kern/51514; it has been noted by GNATS.
> > > the problem with your patch is that invades the main kernel with
> > > comaptibility code that currently mostly works as a module. it
> > > really would be best to do this in compat/netbsd32 sources.
> >
> > I agree with you. But it is difficult, at least for me, to separate
> > compatibility code from kern/sys_process.c.
> >
> > For sys_ptrace(9), the situation is similar to the case of
> > copy_procargs(9) in kern/kern_proc.c, which has also compatibility
> > code in it:
> >
> >https://nxr.netbsd.org/source/xref/src/sys/kern/kern_proc.c#2086
> >
> > The procedure is almost common for native and 32-bit processes, but
> > just small parts are different. How do we separate compat code from
> > functions like this?
> >
> > For process_{,fp}regs(9), the situation is more complicated as they
> > are used not only by ptrace(2), but also by procfs.
> >
> > I do not, of course, stick to my patch. My hope is just to implement
> > COMPAT_NETBSD32 support to ptrace(2); without it, we cannot use GDB
> > on mips64 at the moment. I would greatly appreciate it if you kindly
> > give me any suggestions.
>
> I'm working on this. Hopefully the rabbit hole isn't too deep.
Here's what I've got... Some things to nodes are
- New compat_netbsd32_ptrace modules is created, but a ptrace module isn't
- Should more be moved into compat32, e.g. PROC_{PTR,REG,FPREG}SZ and
the netbsd32_process_{read,write}_{,fp}regs?
-
--------------050409000904030005020102
Content-Type: text/x-patch;
name="ptrace32.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
filename="ptrace32.diff"
Index: sys/arch/amd64/amd64/netbsd32_machdep.c
===================================================================
RCS file: /cvsroot/src/sys/arch/amd64/amd64/netbsd32_machdep.c,v
retrieving revision 1.96
diff -u -p -r1.96 netbsd32_machdep.c
--- sys/arch/amd64/amd64/netbsd32_machdep.c 2 Sep 2016 07:51:05 -0000 1.96
+++ sys/arch/amd64/amd64/netbsd32_machdep.c 15 Oct 2016 12:40:13 -0000
@@ -487,12 +487,12 @@ netbsd32_process_read_regs(struct lwp *l
{
struct trapframe *tf = l->l_md.md_regs;
- regs->r_gs = LSEL(LUCODE32_SEL, SEL_UPL);
- regs->r_fs = LSEL(LUCODE32_SEL, SEL_UPL);
- regs->r_es = LSEL(LUCODE32_SEL, SEL_UPL);
- regs->r_ds = LSEL(LUCODE32_SEL, SEL_UPL);
- regs->r_eflags = tf->tf_rflags;
/* XXX avoid sign extension problems with unknown upper bits? */
+ regs->r_gs = tf->tf_gs & 0xffff;
+ regs->r_fs = tf->tf_fs & 0xffff;
+ regs->r_es = tf->tf_es & 0xffff;
+ regs->r_ds = tf->tf_ds & 0xffff;
+ regs->r_eflags = tf->tf_rflags;
regs->r_edi = tf->tf_rdi & 0xffffffff;
regs->r_esi = tf->tf_rsi & 0xffffffff;
regs->r_ebp = tf->tf_rbp & 0xffffffff;
@@ -501,9 +501,9 @@ netbsd32_process_read_regs(struct lwp *l
regs->r_ecx = tf->tf_rcx & 0xffffffff;
regs->r_eax = tf->tf_rax & 0xffffffff;
regs->r_eip = tf->tf_rip & 0xffffffff;
- regs->r_cs = tf->tf_cs;
+ regs->r_cs = tf->tf_cs & 0xffff;
regs->r_esp = tf->tf_rsp & 0xffffffff;
- regs->r_ss = tf->tf_ss;
+ regs->r_ss = tf->tf_ss & 0xffff;
return (0);
}
@@ -511,22 +511,52 @@ netbsd32_process_read_regs(struct lwp *l
int
netbsd32_process_read_fpregs(struct lwp *l, struct fpreg32 *regs, size_t *sz)
{
- struct fpreg regs64;
- int error;
- size_t fp_size;
+
+ __CTASSERT(sizeof *regs == sizeof (struct save87));
+ process_read_fpregs_s87(l, (struct save87 *)regs);
+ return 0;
+}
+
+int
+netbsd32_process_write_regs(struct lwp *l, const struct reg32 *regs)
+{
+ struct trapframe *tf = l->l_md.md_regs;
/*
- * All that stuff makes no sense in i386 code :(
+ * Check for security violations. Taken from i386/process_machdep.c.
*/
+ if (((regs->r_eflags ^ tf->tf_rflags) & PSL_USERSTATIC) != 0 ||
+ !VALID_USER_CSEL32(regs->r_cs))
+ return EINVAL;
- fp_size = sizeof regs64;
- error = process_read_fpregs(l, ®s64, &fp_size);
- if (error)
- return error;
- __CTASSERT(sizeof *regs == sizeof (struct save87));
- process_xmm_to_s87(®s64.fxstate, (struct save87 *)regs);
+ tf->tf_rax = regs->r_eax;
+ tf->tf_rcx = regs->r_ecx;
+ tf->tf_rdx = regs->r_edx;
+ tf->tf_rbx = regs->r_ebx;
+ tf->tf_rsp = regs->r_esp;
+ tf->tf_rbp = regs->r_ebp;
+ tf->tf_rsi = regs->r_esi;
+ tf->tf_rdi = regs->r_edi;
+ tf->tf_rip = regs->r_eip;
+ tf->tf_rflags = regs->r_eflags;
+ tf->tf_cs = regs->r_cs;
+ tf->tf_ss = regs->r_ss;
+ tf->tf_ds = regs->r_ds;
+ tf->tf_es = regs->r_es;
+ tf->tf_fs = regs->r_fs;
+ tf->tf_gs = regs->r_gs;
- return (0);
+ return 0;
+}
+
+int
+netbsd32_process_write_fpregs(struct lwp *l, const struct fpreg32 *regs,
+ size_t sz)
+{
+
+ __CTASSERT(sizeof *regs == sizeof (struct save87));
+ process_write_fpregs_s87(l, (const struct save87 *)regs);
+ return 0;
}
int
Index: sys/arch/amd64/include/netbsd32_machdep.h
===================================================================
RCS file: /cvsroot/src/sys/arch/amd64/include/netbsd32_machdep.h,v
retrieving revision 1.19
diff -u -p -r1.19 netbsd32_machdep.h
--- sys/arch/amd64/include/netbsd32_machdep.h 7 Feb 2014 22:40:22 -0000 1.19
+++ sys/arch/amd64/include/netbsd32_machdep.h 15 Oct 2016 12:40:13 -0000
@@ -138,4 +138,7 @@ struct x86_64_set_mtrr_args32 {
int netbsd32_process_read_regs(struct lwp *, struct reg32 *);
int netbsd32_process_read_fpregs(struct lwp *, struct fpreg32 *, size_t *);
+int netbsd32_process_write_regs(struct lwp *, const struct reg32 *);
+int netbsd32_process_write_fpregs(struct lwp *, const struct fpreg32 *, size_t);
+
#endif /* _MACHINE_NETBSD32_H_ */
Index: sys/arch/amd64/include/ptrace.h
===================================================================
RCS file: /cvsroot/src/sys/arch/amd64/include/ptrace.h,v
retrieving revision 1.6
diff -u -p -r1.6 ptrace.h
--- sys/arch/amd64/include/ptrace.h 25 Sep 2015 16:05:17 -0000 1.6
+++ sys/arch/amd64/include/ptrace.h 15 Oct 2016 12:40:13 -0000
@@ -68,6 +68,9 @@
#define process_read_regs32 netbsd32_process_read_regs
#define process_read_fpregs32 netbsd32_process_read_fpregs
+#define process_write_regs32 netbsd32_process_write_regs
+#define process_write_fpregs32 netbsd32_process_write_fpregs
+
#define process_reg32 struct reg32
#define process_fpreg32 struct fpreg32
#endif /* COMPAT_NETBSD32 */
Index: sys/arch/sparc64/include/netbsd32_machdep.h
===================================================================
RCS file: /cvsroot/src/sys/arch/sparc64/include/netbsd32_machdep.h,v
retrieving revision 1.28
diff -u -p -r1.28 netbsd32_machdep.h
--- sys/arch/sparc64/include/netbsd32_machdep.h 4 Jan 2014 00:10:03 -0000 1.28
+++ sys/arch/sparc64/include/netbsd32_machdep.h 15 Oct 2016 12:40:13 -0000
@@ -79,4 +79,7 @@ int netbsd32_md_ioctl(struct file *, net
int netbsd32_process_read_regs(struct lwp *, struct reg32 *);
int netbsd32_process_read_fpregs(struct lwp *, struct fpreg32 *, size_t *);
+int netbsd32_process_write_regs(struct lwp *, const struct reg32 *);
+int netbsd32_process_write_fpregs(struct lwp *, const struct fpreg32 *, size_t);
+
#endif /* _MACHINE_NETBSD32_H_ */
Index: sys/arch/sparc64/include/ptrace.h
===================================================================
RCS file: /cvsroot/src/sys/arch/sparc64/include/ptrace.h,v
retrieving revision 1.4
diff -u -p -r1.4 ptrace.h
--- sys/arch/sparc64/include/ptrace.h 28 Sep 2016 11:44:16 -0000 1.4
+++ sys/arch/sparc64/include/ptrace.h 15 Oct 2016 12:40:13 -0000
@@ -11,6 +11,9 @@
#define process_read_regs32 netbsd32_process_read_regs
#define process_read_fpregs32 netbsd32_process_read_fpregs
+#define process_write_regs32 netbsd32_process_write_regs
+#define process_write_fpregs32 netbsd32_process_write_fpregs
+
#define process_reg32 struct reg32
#define process_fpreg32 struct fpreg32
#endif
Index: sys/arch/sparc64/sparc64/netbsd32_machdep.c
===================================================================
RCS file: /cvsroot/src/sys/arch/sparc64/sparc64/netbsd32_machdep.c,v
retrieving revision 1.109
diff -u -p -r1.109 netbsd32_machdep.c
--- sys/arch/sparc64/sparc64/netbsd32_machdep.c 26 Nov 2015 13:15:34 -0000 1.109
+++ sys/arch/sparc64/sparc64/netbsd32_machdep.c 15 Oct 2016 12:40:14 -0000
@@ -624,16 +624,15 @@ netbsd32_process_read_regs(struct lwp *l
return (0);
}
-#if 0
int
netbsd32_process_write_regs(struct lwp *l, const struct reg32 *regs)
{
- struct trapframe64* tf = p->p_md.md_tf;
+ struct trapframe64* tf = l->l_md.md_tf;
int i;
tf->tf_pc = regs->r_pc;
tf->tf_npc = regs->r_npc;
- tf->tf_y = regs->r_pc;
+ tf->tf_y = regs->r_y;
for (i = 0; i < 8; i++) {
tf->tf_global[i] = regs->r_global[i];
tf->tf_out[i] = regs->r_out[i];
@@ -643,7 +642,6 @@ netbsd32_process_write_regs(struct lwp *
PSRCC_TO_TSTATE(regs->r_psr);
return (0);
}
-#endif
int
netbsd32_process_read_fpregs(struct lwp *l, struct fpreg32 *regs, size_t *sz)
@@ -661,9 +659,9 @@ netbsd32_process_read_fpregs(struct lwp
return 0;
}
-#if 0
int
-netbsd32_process_write_fpregs(struct lwp *l, const struct fpreg32 *regs)
+netbsd32_process_write_fpregs(struct lwp *l, const struct fpreg32 *regs,
+ size_t sz)
{
struct fpstate64 *statep;
int i;
@@ -678,7 +676,6 @@ netbsd32_process_write_fpregs(struct lwp
return 0;
}
-#endif
/*
* 32-bit version of cpu_coredump.
Index: sys/compat/netbsd32/files.netbsd32
===================================================================
RCS file: /cvsroot/src/sys/compat/netbsd32/files.netbsd32,v
retrieving revision 1.38
diff -u -p -r1.38 files.netbsd32
--- sys/compat/netbsd32/files.netbsd32 3 Dec 2015 11:25:45 -0000 1.38
+++ sys/compat/netbsd32/files.netbsd32 15 Oct 2016 12:40:14 -0000
@@ -21,6 +21,7 @@ file compat/netbsd32/netbsd32_module.c c
file compat/netbsd32/netbsd32_mod.c compat_netbsd32
file compat/netbsd32/netbsd32_mqueue.c compat_netbsd32 & mqueue
file compat/netbsd32/netbsd32_nfssvc.c compat_netbsd32 & nfsserver
+file compat/netbsd32/netbsd32_ptrace.c compat_netbsd32 & ptrace
file compat/netbsd32/netbsd32_select.c compat_netbsd32
file compat/netbsd32/netbsd32_sem.c compat_netbsd32
file compat/netbsd32/netbsd32_signal.c compat_netbsd32
Index: sys/compat/netbsd32/netbsd32.h
===================================================================
RCS file: /cvsroot/src/sys/compat/netbsd32/netbsd32.h,v
retrieving revision 1.112
diff -u -p -r1.112 netbsd32.h
--- sys/compat/netbsd32/netbsd32.h 23 Sep 2016 14:16:32 -0000 1.112
+++ sys/compat/netbsd32/netbsd32.h 15 Oct 2016 12:40:17 -0000
@@ -282,6 +282,16 @@ struct netbsd32_export_args30 {
/* from <sys/poll.h> */
typedef netbsd32_pointer_t netbsd32_pollfdp_t;
+/* from <sys/ptrace.h> */
+typedef netbsd32_pointer_t netbsd32_ptrace_io_descp_t;
+struct netbsd32_ptrace_io_desc {
+ int piod_op; /* I/O operation */
+ netbsd32_voidp piod_offs; /* child offset */
+ netbsd32_voidp piod_addr; /* parent offset */
+ netbsd32_size_t piod_len; /* request length (in) /
+ actual count (out) */
+};
+
/* from <sys/quotactl.h> */
typedef netbsd32_pointer_t netbsd32_quotactlargsp_t;
struct netbsd32_quotactlargs {
Index: sys/compat/netbsd32/netbsd32_netbsd.c
===================================================================
RCS file: /cvsroot/src/sys/compat/netbsd32/netbsd32_netbsd.c,v
retrieving revision 1.204
diff -u -p -r1.204 netbsd32_netbsd.c
--- sys/compat/netbsd32/netbsd32_netbsd.c 17 Sep 2016 02:44:38 -0000 1.204
+++ sys/compat/netbsd32/netbsd32_netbsd.c 15 Oct 2016 12:40:17 -0000
@@ -406,25 +406,6 @@ netbsd32_setuid(struct lwp *l, const str
}
int
-netbsd32_ptrace(struct lwp *l, const struct netbsd32_ptrace_args *uap, register_t *retval)
-{
- /* {
- syscallarg(int) req;
- syscallarg(pid_t) pid;
- syscallarg(netbsd32_voidp) addr;
- syscallarg(int) data;
- } */
- struct sys_ptrace_args ua;
-
- NETBSD32TO64_UAP(req);
- NETBSD32TO64_UAP(pid);
- NETBSD32TOP_UAP(addr, void *);
- NETBSD32TO64_UAP(data);
-
- return (*sysent[SYS_ptrace].sy_call)(l, &ua, retval);
-}
-
-int
netbsd32_accept(struct lwp *l, const struct netbsd32_accept_args *uap, register_t *retval)
{
/* {
Index: sys/compat/netbsd32/netbsd32_ptrace.c
===================================================================
RCS file: sys/compat/netbsd32/netbsd32_ptrace.c
diff -N sys/compat/netbsd32/netbsd32_ptrace.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ sys/compat/netbsd32/netbsd32_ptrace.c 15 Oct 2016 12:40:17 -0000
@@ -0,0 +1,217 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (c) 2016 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Nick Hudson
+ *
+ * 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.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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>
+__KERNEL_RCSID(0, "$NetBSD$");
+
+#if defined(_KERNEL_OPT)
+#include "opt_ptrace.h"
+#include "opt_compat_netbsd.h"
+#endif
+
+#include <sys/param.h>
+#include <sys/module.h>
+#include <sys/ptrace.h>
+#include <sys/syscallvar.h>
+
+#include <compat/netbsd32/netbsd32.h>
+#include <compat/netbsd32/netbsd32_syscall.h>
+#include <compat/netbsd32/netbsd32_syscallargs.h>
+#include <compat/netbsd32/netbsd32_conv.h>
+
+extern struct emul emul_netbsd32;
+
+
+/*
+ * PTRACE methods
+ */
+
+static int netbsd32_copyinpiod(struct ptrace_io_desc *, const void *);
+static void netbsd32_copyoutpiod(const struct ptrace_io_desc *, void *);
+static int netbsd32_doregs(struct lwp *, struct lwp *, struct uio *);
+static int netbsd32_dofpregs(struct lwp *, struct lwp *, struct uio *);
+
+
+static int
+netbsd32_copyinpiod(struct ptrace_io_desc *piod, const void *addr)
+{
+ struct netbsd32_ptrace_io_desc piod32;
+
+ int error = copyin(addr, &piod32, sizeof(piod32));
+ if (error)
+ return error;
+ piod->piod_op = piod32.piod_op;
+ piod->piod_offs = NETBSD32PTR64(piod32.piod_offs);
+ piod->piod_addr = NETBSD32PTR64(piod32.piod_addr);
+ piod->piod_len = (size_t)piod32.piod_len;
+
+ return 0;
+}
+
+static void
+netbsd32_copyoutpiod(const struct ptrace_io_desc *piod, void *addr)
+{
+ struct netbsd32_ptrace_io_desc piod32;
+
+ piod32.piod_op = piod->piod_op;
+ NETBSD32PTR32(piod32.piod_offs, piod->piod_offs);
+ NETBSD32PTR32(piod32.piod_addr, piod->piod_addr);
+ piod32.piod_len = (netbsd32_size_t)piod->piod_len;
+ (void) copyout(&piod32, addr, sizeof(piod32));
+}
+
+
+static int
+netbsd32_doregs(struct lwp *curl /*tracer*/,
+ struct lwp *l /*traced*/,
+ struct uio *uio)
+{
+#if defined(PT_GETREGS) || defined(PT_SETREGS)
+ process_reg32 r32;
+ int error;
+ char *kv;
+ int kl;
+
+ if (uio->uio_offset < 0 || uio->uio_offset > (off_t)sizeof(r32))
+ return EINVAL;
+
+ kl = sizeof(r32);
+ kv = (char *)&r32;
+
+ kv += uio->uio_offset;
+ kl -= uio->uio_offset;
+ if ((size_t)kl > uio->uio_resid)
+ kl = uio->uio_resid;
+ error = process_read_regs32(l, &r32);
+ if (error == 0)
+ error = uiomove(kv, kl, uio);
+ if (error == 0 && uio->uio_rw == UIO_WRITE) {
+ if (l->l_stat != LSSTOP)
+ error = EBUSY;
+ else
+ error = process_write_regs32(l, &r32);
+ }
+
+ uio->uio_offset = 0;
+ return error;
+#else
+ return EINVAL;
+#endif
+}
+
+static int
+netbsd32_dofpregs(struct lwp *curl /*tracer*/,
+ struct lwp *l /*traced*/,
+ struct uio *uio)
+{
+#if defined(PT_GETFPREGS) || defined(PT_SETFPREGS)
+ process_fpreg32 r32;
+ int error;
+ char *kv;
+ size_t kl;
+
+ KASSERT(l->l_proc->p_flag & PK_32);
+ if (uio->uio_offset < 0 || uio->uio_offset > (off_t)sizeof(r32))
+ return EINVAL;
+ kl = sizeof(r32);
+ kv = (char *)&r32;
+
+ kv += uio->uio_offset;
+ kl -= uio->uio_offset;
+ if (kl > uio->uio_resid)
+ kl = uio->uio_resid;
+
+ error = process_read_fpregs32(l, &r32, &kl);
+ if (error == 0)
+ error = uiomove(kv, kl, uio);
+ if (error == 0 && uio->uio_rw == UIO_WRITE) {
+ if (l->l_stat != LSSTOP)
+ error = EBUSY;
+ else
+ error = process_write_fpregs32(l, &r32, kl);
+ }
+ uio->uio_offset = 0;
+ return error;
+#else
+ return EINVAL;
+#endif
+}
+
+static struct ptrace_methods netbsd32_ptm = {
+ .ptm_copyinpiod = netbsd32_copyinpiod,
+ .ptm_copyoutpiod = netbsd32_copyoutpiod,
+ .ptm_doregs = netbsd32_doregs,
+ .ptm_dofpregs = netbsd32_dofpregs
+};
+
+
+int
+netbsd32_ptrace(struct lwp *l, const struct netbsd32_ptrace_args *uap,
+ register_t *retval)
+{
+ /* {
+ syscallarg(int) req;
+ syscallarg(pid_t) pid;
+ syscallarg(netbsd32_voidp *) addr;
+ syscallarg(int) data;
+ } */
+
+ return do_ptrace(&netbsd32_ptm, l, SCARG(uap, req), SCARG(uap, pid),
+ SCARG_P32(uap, addr), SCARG(uap, data), retval);
+}
+
+static const struct syscall_package compat_ptrace_syscalls[] = {
+ { NETBSD32_SYS_netbsd32_ptrace, 0, (sy_call_t *)netbsd32_ptrace },
+ { 0, 0, NULL },
+};
+
+MODULE(MODULE_CLASS_EXEC, compat_netbsd32_ptrace, "compat_netbsd32");
+
+static int
+compat_netbsd32_ptrace_modcmd(modcmd_t cmd, void *arg)
+{
+ int error;
+
+ switch (cmd) {
+ case MODULE_CMD_INIT:
+ error = syscall_establish(&emul_netbsd32,
+ compat_ptrace_syscalls);
+ break;
+ case MODULE_CMD_FINI:
+ error = syscall_disestablish(&emul_netbsd32,
+ compat_ptrace_syscalls);
+ break;
+ default:
+ error = ENOTTY;
+ break;
+ }
+ return error;
+}
Index: sys/compat/netbsd32/netbsd32_syscalls_autoload.c
===================================================================
RCS file: /cvsroot/src/sys/compat/netbsd32/netbsd32_syscalls_autoload.c,v
retrieving revision 1.6
diff -u -p -r1.6 netbsd32_syscalls_autoload.c
--- sys/compat/netbsd32/netbsd32_syscalls_autoload.c 23 Sep 2016 14:12:25 -0000 1.6
+++ sys/compat/netbsd32/netbsd32_syscalls_autoload.c 15 Oct 2016 12:40:18 -0000
@@ -1,4 +1,4 @@
-/* $NetBSD: netbsd32_syscalls_autoload.c,v 1.6 2016/09/23 14:12:25 skrll Exp $ */
+/* $NetBSD$ */
/*
* System call autoload table.
@@ -8,10 +8,11 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: netbsd32_syscalls_autoload.c,v 1.6 2016/09/23 14:12:25 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD$");
#include <sys/proc.h>
static struct sc_autoload netbsd32_syscalls_autoload[] = {
+ { NETBSD32_SYS_netbsd32_ptrace, "compat_netbsd32_ptrace" },
{ NETBSD32_SYS_netbsd32_nfssvc, "compat_netbsd32_nfssrv" },
{ NETBSD32_SYS_compat_10_osemsys, "compat_netbsd32_sysvipc" },
{ NETBSD32_SYS_compat_10_omsgsys, "compat_netbsd32_sysvipc" },
Index: sys/compat/netbsd32/netbsd32_sysent.c
===================================================================
RCS file: /cvsroot/src/sys/compat/netbsd32/netbsd32_sysent.c,v
retrieving revision 1.123
diff -u -p -r1.123 netbsd32_sysent.c
--- sys/compat/netbsd32/netbsd32_sysent.c 23 Sep 2016 14:12:25 -0000 1.123
+++ sys/compat/netbsd32/netbsd32_sysent.c 15 Oct 2016 12:40:18 -0000
@@ -1,4 +1,4 @@
-/* $NetBSD: netbsd32_sysent.c,v 1.123 2016/09/23 14:12:25 skrll Exp $ */
+/* $NetBSD$ */
/*
* System call switch table.
@@ -8,7 +8,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: netbsd32_sysent.c,v 1.123 2016/09/23 14:12:25 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD$");
#if defined(_KERNEL_OPT)
#include "opt_compat_netbsd.h"
@@ -220,7 +220,7 @@ struct sysent netbsd32_sysent[] = {
}, /* 25 = geteuid */
{
ns(struct netbsd32_ptrace_args),
- .sy_call = (sy_call_t *)netbsd32_ptrace
+ .sy_call = (sy_call_t *)sys_nomodule
}, /* 26 = netbsd32_ptrace */
{
ns(struct netbsd32_recvmsg_args),
Index: sys/compat/netbsd32/netbsd32_systrace_args.c
===================================================================
RCS file: /cvsroot/src/sys/compat/netbsd32/netbsd32_systrace_args.c,v
retrieving revision 1.14
diff -u -p -r1.14 netbsd32_systrace_args.c
--- sys/compat/netbsd32/netbsd32_systrace_args.c 23 Sep 2016 14:12:25 -0000 1.14
+++ sys/compat/netbsd32/netbsd32_systrace_args.c 15 Oct 2016 12:40:21 -0000
@@ -1,4 +1,4 @@
-/* $NetBSD: netbsd32_systrace_args.c,v 1.14 2016/09/23 14:12:25 skrll Exp $ */
+/* $NetBSD$ */
/*
* System call argument to DTrace register array converstion.
Index: sys/compat/netbsd32/syscalls.master
===================================================================
RCS file: /cvsroot/src/sys/compat/netbsd32/syscalls.master,v
retrieving revision 1.114
diff -u -p -r1.114 syscalls.master
--- sys/compat/netbsd32/syscalls.master 23 Sep 2016 14:10:28 -0000 1.114
+++ sys/compat/netbsd32/syscalls.master 15 Oct 2016 12:40:21 -0000
@@ -99,7 +99,8 @@
23 STD { int|netbsd32||setuid(uid_t uid); }
24 NOARGS { uid_t|sys||getuid(void); }
25 NOARGS { uid_t|sys||geteuid(void); }
-26 STD { int|netbsd32||ptrace(int req, pid_t pid, \
+26 STD MODULAR compat_netbsd32_ptrace \
+ { int|netbsd32||ptrace(int req, pid_t pid, \
netbsd32_voidp addr, int data); }
27 STD { netbsd32_ssize_t|netbsd32||recvmsg(int s, \
netbsd32_msghdrp_t msg, int flags); }
Index: sys/kern/sys_process.c
===================================================================
RCS file: /cvsroot/src/sys/kern/sys_process.c,v
retrieving revision 1.173
diff -u -p -r1.173 sys_process.c
--- sys/kern/sys_process.c 15 Oct 2016 09:09:55 -0000 1.173
+++ sys/kern/sys_process.c 15 Oct 2016 12:40:21 -0000
@@ -120,9 +120,11 @@
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: sys_process.c,v 1.173 2016/10/15 09:09:55 skrll Exp $");
+#ifdef _KERNEL_OPT
#include "opt_ptrace.h"
#include "opt_ktrace.h"
#include "opt_pax.h"
+#endif
#include <sys/param.h>
#include <sys/systm.h>
@@ -231,6 +233,26 @@ ptrace_init(void)
ptrace_listener_cb, NULL);
}
+static int
+ptrace_copyinpiod(struct ptrace_io_desc *piod, const void *addr)
+{
+ return copyin(addr, piod, sizeof(*piod));
+}
+
+static void
+ptrace_copyoutpiod(const struct ptrace_io_desc *piod, void *addr)
+{
+ (void) copyout(piod, addr, sizeof(*piod));
+}
+
+
+static struct ptrace_methods native_ptm = {
+ .ptm_copyinpiod = ptrace_copyinpiod,
+ .ptm_copyoutpiod = ptrace_copyoutpiod,
+ .ptm_doregs = process_doregs,
+ .ptm_dofpregs = process_dofpregs,
+};
+
/*
* Process debugging system call.
*/
@@ -243,6 +265,15 @@ sys_ptrace(struct lwp *l, const struct s
syscallarg(void *) addr;
syscallarg(int) data;
} */
+
+ return do_ptrace(&native_ptm, l, SCARG(uap, req), SCARG(uap, pid),
+ SCARG(uap, addr), SCARG(uap, data), retval);
+}
+
+int
+do_ptrace(struct ptrace_methods *ptm, struct lwp *l, int req, pid_t pid,
+ void *addr, int data, register_t *retval)
+{
struct proc *p = l->l_proc;
struct lwp *lt;
#ifdef PT_STEP
@@ -256,15 +287,13 @@ sys_ptrace(struct lwp *l, const struct s
struct ptrace_state ps;
struct ptrace_lwpinfo pl;
struct vmspace *vm;
- int error, write, tmp, req, pheld;
+ int error, write, tmp, pheld;
int signo = 0;
int resume_all;
ksiginfo_t ksi;
char *path;
int len = 0;
-
error = 0;
- req = SCARG(uap, req);
/*
* If attaching or detaching, we need to get a write hold on the
@@ -278,7 +307,7 @@ sys_ptrace(struct lwp *l, const struct s
mutex_enter(t->p_lock);
} else {
/* Find the process we're supposed to be operating on. */
- t = proc_find(SCARG(uap, pid));
+ t = proc_find(pid);
if (t == NULL) {
mutex_exit(proc_lock);
return ESRCH;
@@ -507,13 +536,13 @@ sys_ptrace(struct lwp *l, const struct s
/*
* Can't write to a RAS
*/
- if (ras_lookup(t, SCARG(uap, addr)) != (void *)-1) {
+ if (ras_lookup(t, addr) != (void *)-1) {
error = EACCES;
break;
}
#endif
write = 1;
- tmp = SCARG(uap, data);
+ tmp = data;
/* FALLTHROUGH */
case PT_READ_I: /* XXX no separate I and D spaces */
@@ -523,7 +552,7 @@ sys_ptrace(struct lwp *l, const struct s
iov.iov_len = sizeof(tmp);
uio.uio_iov = &iov;
uio.uio_iovcnt = 1;
- uio.uio_offset = (off_t)(unsigned long)SCARG(uap, addr);
+ uio.uio_offset = (off_t)(unsigned long)addr;
uio.uio_resid = sizeof(tmp);
uio.uio_rw = write ? UIO_WRITE : UIO_READ;
UIO_SETUP_SYSSPACE(&uio);
@@ -534,7 +563,7 @@ sys_ptrace(struct lwp *l, const struct s
break;
case PT_IO:
- error = copyin(SCARG(uap, addr), &piod, sizeof(piod));
+ error = ptm->ptm_copyinpiod(&piod, addr);
if (error)
break;
@@ -555,7 +584,7 @@ sys_ptrace(struct lwp *l, const struct s
/*
* Can't write to a RAS
*/
- if (ras_lookup(t, SCARG(uap, addr)) != (void *)-1) {
+ if (ras_lookup(t, addr) != (void *)-1) {
return EACCES;
}
uio.uio_rw = UIO_WRITE;
@@ -586,14 +615,15 @@ sys_ptrace(struct lwp *l, const struct s
error = process_domem(l, lt, &uio);
piod.piod_len -= uio.uio_resid;
- (void) copyout(&piod, SCARG(uap, addr), sizeof(piod));
+ (void) ptm->ptm_copyoutpiod(&piod, addr);
+
uvmspace_free(vm);
break;
case PT_DUMPCORE:
- if ((path = SCARG(uap, addr)) != NULL) {
+ if ((path = addr) != NULL) {
char *dst;
- len = SCARG(uap, data);
+ len = data;
if (len < 0 || len >= MAXPATHLEN) {
error = EINVAL;
@@ -648,7 +678,7 @@ sys_ptrace(struct lwp *l, const struct s
* For operations other than PT_STEP, data > 0 means
* data is the signo to deliver to the process.
*/
- tmp = SCARG(uap, data);
+ tmp = data;
if (tmp >= 0) {
#ifdef PT_STEP
if (req == PT_STEP)
@@ -697,8 +727,8 @@ sys_ptrace(struct lwp *l, const struct s
}
/* If the address parameter is not (int *)1, set the pc. */
- if ((int *)SCARG(uap, addr) != (int *)1) {
- error = process_set_pc(lt, SCARG(uap, addr));
+ if ((int *)addr != (int *)1) {
+ error = process_set_pc(lt, addr);
if (error != 0)
break;
}
@@ -797,26 +827,26 @@ sys_ptrace(struct lwp *l, const struct s
goto sendsig;
case PT_GET_EVENT_MASK:
- if (SCARG(uap, data) != sizeof(pe)) {
+ if (data != sizeof(pe)) {
DPRINTF(("ptrace(%d): %d != %zu\n", req,
- SCARG(uap, data), sizeof(pe)));
+ data, sizeof(pe)));
error = EINVAL;
break;
}
memset(&pe, 0, sizeof(pe));
pe.pe_set_event = ISSET(t->p_slflag, PSL_TRACEFORK) ?
PTRACE_FORK : 0;
- error = copyout(&pe, SCARG(uap, addr), sizeof(pe));
+ error = copyout(&pe, addr, sizeof(pe));
break;
case PT_SET_EVENT_MASK:
- if (SCARG(uap, data) != sizeof(pe)) {
- DPRINTF(("ptrace(%d): %d != %zu\n", req,
- SCARG(uap, data), sizeof(pe)));
+ if (data != sizeof(pe)) {
+ DPRINTF(("ptrace(%d): %d != %zu\n", req, data,
+ sizeof(pe)));
error = EINVAL;
break;
}
- if ((error = copyin(SCARG(uap, addr), &pe, sizeof(pe))) != 0)
+ if ((error = copyin(addr, &pe, sizeof(pe))) != 0)
return error;
if (pe.pe_set_event & PTRACE_FORK)
SET(t->p_slflag, PSL_TRACEFORK);
@@ -825,9 +855,9 @@ sys_ptrace(struct lwp *l, const struct s
break;
case PT_GET_PROCESS_STATE:
- if (SCARG(uap, data) != sizeof(ps)) {
- DPRINTF(("ptrace(%d): %d != %zu\n", req,
- SCARG(uap, data), sizeof(ps)));
+ if (data != sizeof(ps)) {
+ DPRINTF(("ptrace(%d): %d != %zu\n", req, data,
+ sizeof(ps)));
error = EINVAL;
break;
}
@@ -836,17 +866,17 @@ sys_ptrace(struct lwp *l, const struct s
ps.pe_report_event = PTRACE_FORK;
ps.pe_other_pid = t->p_fpid;
}
- error = copyout(&ps, SCARG(uap, addr), sizeof(ps));
+ error = copyout(&ps, addr, sizeof(ps));
break;
case PT_LWPINFO:
- if (SCARG(uap, data) != sizeof(pl)) {
- DPRINTF(("ptrace(%d): %d != %zu\n", req,
- SCARG(uap, data), sizeof(pl)));
+ if (data != sizeof(pl)) {
+ DPRINTF(("ptrace(%d): %d != %zu\n", req, data,
+ sizeof(pl)));
error = EINVAL;
break;
}
- error = copyin(SCARG(uap, addr), &pl, sizeof(pl));
+ error = copyin(addr, &pl, sizeof(pl));
if (error)
break;
tmp = pl.pl_lwpid;
@@ -875,7 +905,7 @@ sys_ptrace(struct lwp *l, const struct s
}
mutex_exit(t->p_lock);
- error = copyout(&pl, SCARG(uap, addr), sizeof(pl));
+ error = copyout(&pl, addr, sizeof(pl));
break;
#ifdef PT_SETREGS
@@ -887,7 +917,7 @@ sys_ptrace(struct lwp *l, const struct s
/* write = 0 done above. */
#endif
#if defined(PT_SETREGS) || defined(PT_GETREGS)
- tmp = SCARG(uap, data);
+ tmp = data;
if (tmp != 0 && t->p_nlwps > 1) {
lwp_delref(lt);
mutex_enter(t->p_lock);
@@ -903,19 +933,19 @@ sys_ptrace(struct lwp *l, const struct s
if (!process_validregs(lt))
error = EINVAL;
else {
- error = proc_vmspace_getref(l->l_proc, &vm);
+ error = proc_vmspace_getref(p, &vm);
if (error)
break;
- iov.iov_base = SCARG(uap, addr);
- iov.iov_len = sizeof(struct reg);
+ iov.iov_base = addr;
+ iov.iov_len = PROC_REGSZ(p);
uio.uio_iov = &iov;
uio.uio_iovcnt = 1;
uio.uio_offset = 0;
- uio.uio_resid = sizeof(struct reg);
+ uio.uio_resid = iov.iov_len;
uio.uio_rw = write ? UIO_WRITE : UIO_READ;
uio.uio_vmspace = vm;
- error = process_doregs(l, lt, &uio);
+ error = ptm->ptm_doregs(l, lt, &uio);
uvmspace_free(vm);
}
break;
@@ -930,7 +960,7 @@ sys_ptrace(struct lwp *l, const struct s
/* write = 0 done above. */
#endif
#if defined(PT_SETFPREGS) || defined(PT_GETFPREGS)
- tmp = SCARG(uap, data);
+ tmp = data;
if (tmp != 0 && t->p_nlwps > 1) {
lwp_delref(lt);
mutex_enter(t->p_lock);
@@ -946,19 +976,19 @@ sys_ptrace(struct lwp *l, const struct s
if (!process_validfpregs(lt))
error = EINVAL;
else {
- error = proc_vmspace_getref(l->l_proc, &vm);
+ error = proc_vmspace_getref(p, &vm);
if (error)
break;
- iov.iov_base = SCARG(uap, addr);
- iov.iov_len = sizeof(struct fpreg);
+ iov.iov_base = addr;
+ iov.iov_len = PROC_FPREGSZ(p);
uio.uio_iov = &iov;
uio.uio_iovcnt = 1;
uio.uio_offset = 0;
- uio.uio_resid = sizeof(struct fpreg);
+ uio.uio_resid = iov.iov_len;
uio.uio_rw = write ? UIO_WRITE : UIO_READ;
uio.uio_vmspace = vm;
- error = process_dofpregs(l, lt, &uio);
+ error = ptm->ptm_dofpregs(l, lt, &uio);
uvmspace_free(vm);
}
break;
@@ -966,8 +996,7 @@ sys_ptrace(struct lwp *l, const struct s
#ifdef __HAVE_PTRACE_MACHDEP
PTRACE_MACHDEP_REQUEST_CASES
- error = ptrace_machdep_dorequest(l, lt,
- req, SCARG(uap, addr), SCARG(uap, data));
+ error = ptrace_machdep_dorequest(l, lt, req, addr, data);
break;
#endif
}
Index: sys/modules/Makefile
===================================================================
RCS file: /cvsroot/src/sys/modules/Makefile,v
retrieving revision 1.180
diff -u -p -r1.180 Makefile
--- sys/modules/Makefile 15 Oct 2016 12:38:03 -0000 1.180
+++ sys/modules/Makefile 15 Oct 2016 12:40:21 -0000
@@ -236,6 +236,7 @@ SUBDIR+= wmimsi
SUBDIR+= compat_netbsd32
SUBDIR+= compat_netbsd32_mqueue
SUBDIR+= compat_netbsd32_nfssrv
+SUBDIR+= compat_netbsd32_ptrace
SUBDIR+= compat_netbsd32_sysvipc
.endif
@@ -244,6 +245,7 @@ SUBDIR+= compat_linux32
SUBDIR+= compat_netbsd32
SUBDIR+= compat_netbsd32_mqueue
SUBDIR+= compat_netbsd32_nfssrv
+SUBDIR+= compat_netbsd32_ptrace
SUBDIR+= compat_netbsd32_sysvipc
.endif
Index: sys/sys/proc.h
===================================================================
RCS file: /cvsroot/src/sys/sys/proc.h,v
retrieving revision 1.334
diff -u -p -r1.334 proc.h
--- sys/sys/proc.h 29 Sep 2016 20:40:53 -0000 1.334
+++ sys/sys/proc.h 15 Oct 2016 12:40:22 -0000
@@ -557,6 +557,10 @@ _proclist_skipmarker(struct proc *p0)
}
#define PROC_PTRSZ(p) (((p)->p_flag & PK_32) ? sizeof(int) : sizeof(void *))
+#define PROC_REGSZ(p) (((p)->p_flag & PK_32) ? \
+ sizeof(process_reg32) : sizeof(struct reg))
+#define PROC_FPREGSZ(p) (((p)->p_flag & PK_32) ? \
+ sizeof(process_fpreg32) : sizeof(struct fpreg))
/*
* PROCLIST_FOREACH: iterate on the given proclist, skipping PK_MARKER ones.
Index: sys/sys/ptrace.h
===================================================================
RCS file: /cvsroot/src/sys/sys/ptrace.h,v
retrieving revision 1.46
diff -u -p -r1.46 ptrace.h
--- sys/sys/ptrace.h 2 Jul 2015 03:47:54 -0000 1.46
+++ sys/sys/ptrace.h 15 Oct 2016 12:40:22 -0000
@@ -139,6 +139,13 @@ struct fpreg;
#endif
#endif
+struct ptrace_methods {
+ int (*ptm_copyinpiod)(struct ptrace_io_desc *, const void *);
+ void (*ptm_copyoutpiod)(const struct ptrace_io_desc *, void *);
+ int (*ptm_doregs)(struct lwp *, struct lwp *, struct uio *);
+ int (*ptm_dofpregs)(struct lwp *, struct lwp *, struct uio *);
+};
+
void ptrace_init(void);
int process_doregs(struct lwp *, struct lwp *, struct uio *);
@@ -153,6 +160,10 @@ void process_stoptrace(void);
void proc_reparent(struct proc *, struct proc *);
+
+int do_ptrace(struct ptrace_methods *, struct lwp *, int, pid_t, void *,
+ int, register_t *);
+
/*
* 64bit architectures that support 32bit emulation (amd64 and sparc64)
* will #define process_read_regs32 to netbsd32_process_read_regs (etc).
@@ -180,9 +191,21 @@ int process_set_pc(struct lwp *, void *)
int process_sstep(struct lwp *, int);
#ifdef PT_SETFPREGS
int process_write_fpregs(struct lwp *, const struct fpreg *, size_t);
+#ifndef process_write_fpregs32
+#define process_write_fpregs32 process_write_fpregs
+#endif
+#ifndef process_write_fpregs64
+#define process_write_fpregs64 process_write_fpregs
+#endif
#endif
#ifdef PT_SETREGS
int process_write_regs(struct lwp *, const struct reg *);
+#ifndef process_write_regs32
+#define process_write_regs32 process_write_regs
+#endif
+#ifndef process_write_regs64
+#define process_write_regs64 process_write_regs
+#endif
#endif
#ifdef __HAVE_PROCFS_MACHDEP
--------------050409000904030005020102
Content-Type: text/plain; charset=UTF-8;
name="Makefile"
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
filename="Makefile"
IwkkTmV0QlNEJAoKLmluY2x1ZGUgIi4uL01ha2VmaWxlLmluYyIKLmluY2x1ZGUgIi4uL01h
a2VmaWxlLmFzc3ltIgoKS01PRD0JY29tcGF0X25ldGJzZDMyX3B0cmFjZQoKQ1BQRkxBR1Mr
PQktRENPTVBBVF9ORVRCU0QzMgpDUFBGTEFHUys9CS1EUFRSQUNFCkNQUEZMQUdTKz0JLURQ
VF9TRVRSRUdTIC1EUFRfR0VUUkVHUwoKLlBBVEg6CSR7U30vY29tcGF0L25ldGJzZDMyClNS
Q1MrPQluZXRic2QzMl9wdHJhY2UuYwoKLmluY2x1ZGUgPGJzZC5rbW9kdWxlLm1rPgoK
--------------050409000904030005020102--
Home |
Main Index |
Thread Index |
Old Index