NetBSD Problem Report #51514
From www@NetBSD.org Wed Sep 28 10:04:14 2016
Return-Path: <www@NetBSD.org>
Received: from mail.netbsd.org (mail.netbsd.org [199.233.217.200])
(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))
(Client CN "mail.netbsd.org", Issuer "Postmaster NetBSD.org" (verified OK))
by mollari.NetBSD.org (Postfix) with ESMTPS id 082337A26F
for <gnats-bugs@gnats.NetBSD.org>; Wed, 28 Sep 2016 10:04:14 +0000 (UTC)
Message-Id: <20160928100412.380097A2C2@mollari.NetBSD.org>
Date: Wed, 28 Sep 2016 10:04:12 +0000 (UTC)
From: rokuyama@rk.phys.keio.ac.jp
Reply-To: rokuyama@rk.phys.keio.ac.jp
To: gnats-bugs@NetBSD.org
Subject: ptrace(2) fails for 32-bit process on 64-bit kernel
X-Send-Pr-Version: www-1.0
>Number: 51514
>Category: kern
>Synopsis: ptrace(2) fails for 32-bit process on 64-bit kernel
>Confidential: no
>Severity: serious
>Priority: high
>Responsible: skrll
>State: closed
>Class: change-request
>Submitter-Id: net
>Arrival-Date: Wed Sep 28 10:05:00 +0000 2016
>Closed-Date: Sat Nov 05 08:14:59 +0000 2016
>Last-Modified: Sat Nov 05 08:14:59 +0000 2016
>Originator: Rin Okuyama
>Release: 7.99.39
>Organization:
Faculty of Science and Technology, Keio University
>Environment:
NetBSD erlite 7.99.39 NetBSD 7.99.39 (ERLITE_RO) #5: Wed Sep 28 06:43:08 JST 2016 rin@XXX:XXX evbmips
>Description:
ptrace(2) does not work properly for 32-bit process on 64-bit kernel with
COMPAT_NETBSD32 option. As a result, GDB (both 64-bit and 32-bit version)
fails for 32-bit binaries. For example, on sparc64 machine with base.tgz
and comp.tgz from sparc extracted into /emul/netbsd32:
% /emul/netbsd32/usr/bin/cc -g -O0 hello.c
% /emul/netbsd32/usr/bin/gdb ./a.out
GNU gdb (GDB) 7.10.1
...snip...
(gdb) r
Starting program: /home/rin/a.out
Hello, World!
Then, it hangs indefinitely with a.out being a zombie. I observed similar
results on amd64 and mips64. ( For mips64, I reported the problem here:
http://mail-index.netbsd.org/port-mips/2016/09/11/msg000759.html )
This is especially problematic for mips64, for which the default userland
ABI is N32.
>How-To-Repeat:
described above
>Fix:
I added COMPAT_NETBSD32 support to kern/sys_process.c (In my opinion,
it is easier to implement it to kern/sys_process.c, rather than to
netbsd32_ptrace(9) in compat/netbsd32/netbsd32_netbsd.c). This requires
new functions, process_write_regs32 and process_write_fpregs32 for archs
in which "struct reg" and "struct reg32" ("fpreg" and "fpreg32") are not
equivalent. I added them to sys/ptrace.h, and implemented for amd64 and
sparc64. Then, 32-bit version of GDB works fine for 32-bit binaries, and
64-bit version fails but terminates properly. I tested the patch on
amd64, sparc64, and mips64 (with N32 userland).
--- src/sys/arch/amd64/amd64/netbsd32_machdep.c.orig 2016-09-27 23:02:35.595062549 +0900
+++ src/sys/arch/amd64/amd64/netbsd32_machdep.c 2016-09-28 06:40:34.097335905 +0900
@@ -487,12 +487,12 @@
{
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 @@
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 @@
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
--- src/sys/arch/amd64/include/ptrace.h.orig 2016-09-27 23:03:04.247552840 +0900
+++ src/sys/arch/amd64/include/ptrace.h 2016-09-27 23:03:44.910371215 +0900
@@ -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 */
--- src/sys/arch/amd64/include/netbsd32_machdep.h.orig 2016-09-27 23:07:53.849813992 +0900
+++ src/sys/arch/amd64/include/netbsd32_machdep.h 2016-09-28 00:01:52.104719432 +0900
@@ -138,4 +138,7 @@
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_ */
--- src/sys/arch/sparc64/include/ptrace.h.orig 2016-09-28 07:27:12.604872351 +0900
+++ src/sys/arch/sparc64/include/ptrace.h 2016-09-28 07:27:51.489447290 +0900
@@ -8,9 +8,12 @@
#ifdef COMPAT_NETBSD32
#include <compat/netbsd32/netbsd32.h>
-#define process_read_regs32 netbsd32_process_read_regs
+#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
--- src/sys/arch/sparc64/include/netbsd32_machdep.h.orig 2016-09-28 07:28:21.564773071 +0900
+++ src/sys/arch/sparc64/include/netbsd32_machdep.h 2016-09-28 07:28:56.497298977 +0900
@@ -79,4 +79,7 @@
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_ */
--- src/sys/arch/sparc64/sparc64/netbsd32_machdep.c.orig 2016-09-28 07:29:43.583860712 +0900
+++ src/sys/arch/sparc64/sparc64/netbsd32_machdep.c 2016-09-28 11:56:11.368274396 +0900
@@ -624,16 +624,15 @@
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 @@
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 @@
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 @@
return 0;
}
-#endif
/*
* 32-bit version of cpu_coredump.
--- src/sys/compat/netbsd32/netbsd32.h.orig 2016-09-27 13:11:26.515967512 +0900
+++ src/sys/compat/netbsd32/netbsd32.h 2016-09-27 14:07:52.164728060 +0900
@@ -282,6 +282,16 @@
/* 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 {
--- src/sys/kern/sys_process.c.orig 2016-09-27 11:57:58.429775526 +0900
+++ src/sys/kern/sys_process.c 2016-09-28 07:38:53.092742755 +0900
@@ -120,9 +120,12 @@
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: sys_process.c,v 1.169 2016/05/25 17:43:58 christos Exp $");
+#ifdef _KERNEL_OPT
#include "opt_ptrace.h"
#include "opt_ktrace.h"
#include "opt_pax.h"
+#include "opt_compat_netbsd32.h"
+#endif
#include <sys/param.h>
#include <sys/systm.h>
@@ -142,6 +145,10 @@
#include <machine/reg.h>
+#ifdef COMPAT_NETBSD32
+#include <compat/netbsd32/netbsd32.h>
+#endif
+
#ifdef PTRACE
# ifdef DEBUG
@@ -262,6 +269,10 @@
ksiginfo_t ksi;
char *path;
int len = 0;
+#ifdef COMPAT_NETBSD32
+ struct netbsd32_ptrace_io_desc piod32;
+ int p32 = p->p_flag & PK_32;
+#endif
error = 0;
req = SCARG(uap, req);
@@ -295,6 +306,18 @@
}
}
+#ifdef COMPAT_NETBSD32
+ /* The tracer and traced processes must have the same ABI. */
+ if (p32 != (t->p_flag & PK_32)) {
+ /* XXX for GDB to terminate processes of wrong ABI */
+ if (req != PT_KILL) {
+ mutex_exit(proc_lock);
+ mutex_exit(t->p_lock);
+ return EINVAL;
+ }
+ }
+#endif
+
/*
* Grab a reference on the process to prevent it from execing or
* exiting.
@@ -534,9 +557,23 @@
break;
case PT_IO:
- error = copyin(SCARG(uap, addr), &piod, sizeof(piod));
- if (error)
- break;
+#ifdef COMPAT_NETBSD32
+ if (p32) {
+ error = copyin(SCARG(uap, addr), &piod32,
+ sizeof(piod32));
+ if (error)
+ break;
+ 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;
+ } else
+#endif
+ {
+ error = copyin(SCARG(uap, addr), &piod, sizeof(piod));
+ if (error)
+ break;
+ }
iov.iov_base = piod.piod_addr;
iov.iov_len = piod.piod_len;
@@ -563,7 +600,15 @@
case PIOD_READ_AUXV:
req = PT_READ_D;
uio.uio_rw = UIO_READ;
- tmp = t->p_execsw->es_arglen * sizeof(char *);
+ tmp = t->p_execsw->es_arglen;
+#ifdef COMPAT_NETBSD32
+ if (p32) {
+ tmp *= sizeof(netbsd32_pointer_t);
+ } else
+#endif
+ {
+ tmp *= sizeof(char *);
+ }
if (uio.uio_offset > tmp)
return EIO;
if (uio.uio_resid > tmp - uio.uio_offset)
@@ -586,7 +631,19 @@
error = process_domem(l, lt, &uio);
piod.piod_len -= uio.uio_resid;
- (void) copyout(&piod, SCARG(uap, addr), sizeof(piod));
+#ifdef COMPAT_NETBSD32
+ if (p32) {
+ 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, SCARG(uap, addr),
+ sizeof(piod32));
+ } else
+#endif
+ {
+ (void) copyout(&piod, SCARG(uap, addr), sizeof(piod));
+ }
uvmspace_free(vm);
break;
@@ -909,11 +966,18 @@
if (error)
break;
iov.iov_base = SCARG(uap, addr);
- iov.iov_len = sizeof(struct reg);
+#ifdef COMPAT_NETBSD32
+ if (p32) {
+ iov.iov_len = sizeof(process_reg32);
+ } else
+#endif
+ {
+ iov.iov_len = sizeof(struct reg);
+ }
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;
@@ -952,11 +1016,18 @@
if (error)
break;
iov.iov_base = SCARG(uap, addr);
- iov.iov_len = sizeof(struct fpreg);
+#ifdef COMPAT_NETBSD32
+ if (p32) {
+ iov.iov_len = sizeof(process_fpreg32);
+ } else
+#endif
+ {
+ iov.iov_len = sizeof(struct fpreg);
+ }
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;
@@ -995,26 +1066,54 @@
struct reg r;
char *kv;
int kl;
-
- if (uio->uio_offset < 0 || uio->uio_offset > (off_t)sizeof(r))
- return EINVAL;
-
- kl = sizeof(r);
- kv = (char *)&r;
+#ifdef COMPAT_NETBSD32
+ process_reg32 r32;
+ int p32 = l->l_proc->p_flag & PK_32; /* traced */
+#endif
+
+#ifdef COMPAT_NETBSD32
+ if (p32) {
+ if (uio->uio_offset < 0 || uio->uio_offset > (off_t)sizeof(r32))
+ return EINVAL;
+ kl = sizeof(r32);
+ kv = (char *)&r32;
+ } else
+#endif
+ {
+ if (uio->uio_offset < 0 || uio->uio_offset > (off_t)sizeof(r))
+ return EINVAL;
+ kl = sizeof(r);
+ kv = (char *)&r;
+ }
kv += uio->uio_offset;
kl -= uio->uio_offset;
if ((size_t)kl > uio->uio_resid)
kl = uio->uio_resid;
- error = process_read_regs(l, &r);
+#ifdef COMPAT_NETBSD32
+ if (p32) {
+ error = process_read_regs32(l, &r32);
+ } else
+#endif
+ {
+ error = process_read_regs(l, &r);
+ }
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_regs(l, &r);
+ else {
+#ifdef COMPAT_NETBSD32
+ if (p32) {
+ error = process_write_regs32(l, &r32);
+ } else
+#endif
+ {
+ error = process_write_regs(l, &r);
+ }
+ }
}
uio->uio_offset = 0;
@@ -1045,26 +1144,54 @@
struct fpreg r;
char *kv;
size_t kl;
-
- if (uio->uio_offset < 0 || uio->uio_offset > (off_t)sizeof(r))
- return EINVAL;
-
- kl = sizeof(r);
- kv = (char *)&r;
+#ifdef COMPAT_NETBSD32
+ process_fpreg32 r32;
+ int p32 = l->l_proc->p_flag & PK_32; /* traced */
+#endif
+
+#ifdef COMPAT_NETBSD32
+ if (p32) {
+ if (uio->uio_offset < 0 || uio->uio_offset > (off_t)sizeof(r32))
+ return EINVAL;
+ kl = sizeof(r32);
+ kv = (char *)&r32;
+ } else
+#endif
+ {
+ if (uio->uio_offset < 0 || uio->uio_offset > (off_t)sizeof(r))
+ return EINVAL;
+ kl = sizeof(r);
+ kv = (char *)&r;
+ }
kv += uio->uio_offset;
kl -= uio->uio_offset;
if (kl > uio->uio_resid)
kl = uio->uio_resid;
- error = process_read_fpregs(l, &r, &kl);
+#ifdef COMPAT_NETBSD32
+ if (p32) {
+ error = process_read_fpregs32(l, &r32, &kl);
+ } else
+#endif
+ {
+ error = process_read_fpregs(l, &r, &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_fpregs(l, &r, kl);
+ else {
+#ifdef COMPAT_NETBSD32
+ if (p32) {
+ error = process_write_fpregs32(l, &r32, kl);
+ } else
+#endif
+ {
+ error = process_write_fpregs(l, &r, kl);
+ }
+ }
}
uio->uio_offset = 0;
return (error);
--- src/sys/sys/ptrace.h.orig 2016-09-27 22:59:47.862486891 +0900
+++ src/sys/sys/ptrace.h 2016-09-28 05:46:26.502778292 +0900
@@ -180,9 +180,21 @@
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
>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: kern-bug-people->skrll
Responsible-Changed-By: skrll@NetBSD.org
Responsible-Changed-When: Wed, 28 Sep 2016 10:28:03 +0000
Responsible-Changed-Why:
take
From: matthew green <mrg@eterna.com.au>
To: gnats-bugs@NetBSD.org
Cc: kern-bug-people@netbsd.org, gnats-admin@netbsd.org,
netbsd-bugs@netbsd.org
Subject: re: kern/51514: ptrace(2) fails for 32-bit process on 64-bit kernel
Date: Thu, 29 Sep 2016 03:49:24 +1000
FWIW, you shouldn't ever have to extract things into /emul/netbsd32
anymore. if you find issues that require it, please file PRs about
them. eg, binaries should work in any location.
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.
thanks.
.mrg.
From: Rin Okuyama <rokuyama@rk.phys.keio.ac.jp>
To: matthew green <mrg@eterna.com.au>, gnats-bugs@NetBSD.org
Cc:
Subject: Re: kern/51514: ptrace(2) fails for 32-bit process on 64-bit kernel
Date: Thu, 29 Sep 2016 22:18:47 +0900
Thank you very much for your comment.
On 2016/09/29 2:49, matthew green wrote:
> FWIW, you shouldn't ever have to extract things into /emul/netbsd32
> anymore. if you find issues that require it, please file PRs about
> them. eg, binaries should work in any location.
Yes, I understand. My example was, somewhat, misleading. The location
of 32-bit version of GDB, etc., is irrelevant to the problem.
> 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.
Thanks,
Rin
From: Nick Hudson <skrll@netbsd.org>
To: gnats-bugs@NetBSD.org, gnats-admin@netbsd.org, netbsd-bugs@netbsd.org,
rokuyama@rk.phys.keio.ac.jp
Cc:
Subject: Re: kern/51514: ptrace(2) fails for 32-bit process on 64-bit kernel
Date: Thu, 29 Sep 2016 14:24:23 +0100
On 09/29/16 14:20, Rin Okuyama wrote:
> The following reply was made to PR kern/51514; it has been noted by GNATS.
>
> From: Rin Okuyama <rokuyama@rk.phys.keio.ac.jp>
> To: matthew green <mrg@eterna.com.au>, gnats-bugs@NetBSD.org
> Cc:
> Subject: Re: kern/51514: ptrace(2) fails for 32-bit process on 64-bit kernel
> Date: Thu, 29 Sep 2016 22:18:47 +0900
>
> Thank you very much for your comment.
>
> On 2016/09/29 2:49, matthew green wrote:
> > FWIW, you shouldn't ever have to extract things into /emul/netbsd32
> > anymore. if you find issues that require it, please file PRs about
> > them. eg, binaries should work in any location.
>
> Yes, I understand. My example was, somewhat, misleading. The location
> of 32-bit version of GDB, etc., is irrelevant to the problem.
>
> > 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.
Nick
From: Rin Okuyama <rokuyama@rk.phys.keio.ac.jp>
To: Nick Hudson <skrll@netbsd.org>, gnats-bugs@NetBSD.org
Cc:
Subject: Re: kern/51514: ptrace(2) fails for 32-bit process on 64-bit kernel
Date: Thu, 29 Sep 2016 22:36:59 +0900
On 2016/09/29 22:24, Nick Hudson wrote:
> I'm working on this. Hopefully the rabbit hole isn't too deep.
Thank you always for your kind support :-).
Rin
From: Nick Hudson <skrll@netbsd.org>
To: gnats-bugs@NetBSD.org, gnats-admin@netbsd.org, netbsd-bugs@netbsd.org,
rokuyama@rk.phys.keio.ac.jp
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--
From: matthew green <mrg@eterna.com.au>
To: Nick Hudson <skrll@netbsd.org>
Cc: gnats-bugs@NetBSD.org, gnats-admin@netbsd.org,
netbsd-bugs@netbsd.org, rokuyama@rk.phys.keio.ac.jp
Subject: re: kern/51514: ptrace(2) fails for 32-bit process on 64-bit kernel
Date: Mon, 17 Oct 2016 05:33:39 +1100
> /* 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;
> @@ -501,9 +501,9 @@ netbsd32_process_read_regs(struct lwp *l
> - 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;
i wonder if there should be ASSERT()s that they're not set. there
really should never be anything set here. x86-heads?
> - tf->tf_y = regs->r_pc;
> + tf->tf_y = regs->r_y;
well spotted.
rest LGTM and what i was envisioning. thanks!
.mrg.
From: David Holland <dholland-bugs@netbsd.org>
To: gnats-bugs@NetBSD.org
Cc:
Subject: Re: kern/51514: ptrace(2) fails for 32-bit process on 64-bit kernel
Date: Sun, 16 Oct 2016 19:14:21 +0000
On Sun, Oct 16, 2016 at 06:35:00PM +0000, matthew green wrote:
> > /* 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;
> > @@ -501,9 +501,9 @@ netbsd32_process_read_regs(struct lwp *l
> > - 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;
>
> i wonder if there should be ASSERT()s that they're not set. there
> really should never be anything set here. x86-heads?
The way the amd64 trapframe structure is built (via cpp abuse) causes
the segment register fields to be uint64_t. Therefore as long as they
have i386 segment selector values in them, which are 16 bits wide,
everything should be ok... unless they're sign-extended 16-bit values.
I have no idea if they manifest that way in hardware (I would think it
unlikely) or if there's a way for them to get sign-extended in the
trapframe before they get here (also seems unlikely) but masking them
is cheap.
It shouldn't be possible for a 32-bit process to get a 64-bit segment
register value and it might be a good idea to assert that. Maybe
something like
assert(regs->r_gs == tf->tf_gs ||
regs->r_gs == ((uint64_t)(int64_t)(int16_t)tf->tf_gs))
The problem is that i386 segment selectors that are negative 16-bit
values only happen if you have that many segments ( >= 4096, i think,
but I can't remember for sure) and that is going to be rare even with
large programs in Wine. So it's probably a good idea to be paranoid
about it as getting it wrong will lead to lurking problems later.
--
David A. Holland
dholland@netbsd.org
From: Rin Okuyama <rokuyama@rk.phys.keio.ac.jp>
To: Nick Hudson <skrll@netbsd.org>, gnats-bugs@NetBSD.org
Cc:
Subject: Re: kern/51514: ptrace(2) fails for 32-bit process on 64-bit kernel
Date: Tue, 18 Oct 2016 08:37:55 +0900
On 2016/10/16 17:09, Nick Hudson wrote:
> Here's what I've got... Some things to nodes are
>
> - New compat_netbsd32_ptrace modules is created, but a ptrace module isn't
Thank you so much for your efforts to modularize 32-bit version of
ptrace. It's also been a good education for me. I've confirmed that
32-bit version of GDB works well with your patch on amd64, sparc64,
andevbmips64-eb.
> - Should more be moved into compat32, e.g. PROC_{PTR,REG,FPREG}SZ and
> the netbsd32_process_{read,write}_{,fp}regs?
Yes, it should be for the latter. Otherwise, on non-COMPAT_NETBSD32
kernel, process_{read,write}_{,fp}regs32 are replaced by their 64-bit
counterparts:
https://nxr.netbsd.org/source/xref/src/sys/sys/ptrace.h#156
And therefore compat_netbsd32_ptrace module may not work properly.
On the other hand, it seems to be harmless for me to have
PROC_{PTR,REG,FPREG}SZ in the main kernel. Or would it be better to
protect them by _LP64 like this?
#ifdef _LP64
#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))
#else
#define PROC_PTRSZ(p) sizeof(void *)
#define PROC_REGSZ(p) sizeof(struct reg)
#define PROC_FPREGSZ(p) sizeof(struct fpreg)
#endif
For registers of x86, I have no ideas. Sorry but I do not have a
thorough knowledge of x86 architecture...
Thanks,
Rin
From: "Nick Hudson" <skrll@netbsd.org>
To: gnats-bugs@gnats.NetBSD.org
Cc:
Subject: PR/51514 CVS commit: src
Date: Wed, 19 Oct 2016 09:44:01 +0000
Module Name: src
Committed By: skrll
Date: Wed Oct 19 09:44:01 UTC 2016
Modified Files:
src/distrib/sets/lists/modules: ad.arm ad.mips md.amd64
src/sys/arch/amd64/amd64: netbsd32_machdep.c
src/sys/arch/amd64/include: netbsd32_machdep.h ptrace.h
src/sys/arch/sparc64/include: netbsd32_machdep.h ptrace.h
src/sys/arch/sparc64/sparc64: netbsd32_machdep.c
src/sys/compat/netbsd32: files.netbsd32 netbsd32.h netbsd32_fs.c
netbsd32_netbsd.c syscalls.master
src/sys/kern: sys_process.c
src/sys/modules: Makefile
src/sys/sys: proc.h ptrace.h
Added Files:
src/sys/compat/netbsd32: netbsd32_ptrace.c
src/sys/modules/compat_netbsd32_ptrace: Makefile
Log Message:
PR kern/51514: ptrace(2) fails for 32-bit process on 64-bit kernel
Updated from the original patch in the PR by me.
To generate a diff of this commit:
cvs rdiff -u -r1.8 -r1.9 src/distrib/sets/lists/modules/ad.arm \
src/distrib/sets/lists/modules/ad.mips
cvs rdiff -u -r1.69 -r1.70 src/distrib/sets/lists/modules/md.amd64
cvs rdiff -u -r1.96 -r1.97 src/sys/arch/amd64/amd64/netbsd32_machdep.c
cvs rdiff -u -r1.19 -r1.20 src/sys/arch/amd64/include/netbsd32_machdep.h
cvs rdiff -u -r1.6 -r1.7 src/sys/arch/amd64/include/ptrace.h
cvs rdiff -u -r1.28 -r1.29 src/sys/arch/sparc64/include/netbsd32_machdep.h
cvs rdiff -u -r1.4 -r1.5 src/sys/arch/sparc64/include/ptrace.h
cvs rdiff -u -r1.109 -r1.110 src/sys/arch/sparc64/sparc64/netbsd32_machdep.c
cvs rdiff -u -r1.38 -r1.39 src/sys/compat/netbsd32/files.netbsd32
cvs rdiff -u -r1.112 -r1.113 src/sys/compat/netbsd32/netbsd32.h
cvs rdiff -u -r1.75 -r1.76 src/sys/compat/netbsd32/netbsd32_fs.c
cvs rdiff -u -r1.204 -r1.205 src/sys/compat/netbsd32/netbsd32_netbsd.c
cvs rdiff -u -r0 -r1.1 src/sys/compat/netbsd32/netbsd32_ptrace.c
cvs rdiff -u -r1.114 -r1.115 src/sys/compat/netbsd32/syscalls.master
cvs rdiff -u -r1.173 -r1.174 src/sys/kern/sys_process.c
cvs rdiff -u -r1.180 -r1.181 src/sys/modules/Makefile
cvs rdiff -u -r0 -r1.1 src/sys/modules/compat_netbsd32_ptrace/Makefile
cvs rdiff -u -r1.334 -r1.335 src/sys/sys/proc.h
cvs rdiff -u -r1.46 -r1.47 src/sys/sys/ptrace.h
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
State-Changed-From-To: open->closed
State-Changed-By: skrll@NetBSD.org
State-Changed-When: Sat, 05 Nov 2016 08:14:59 +0000
State-Changed-Why:
Change committed
>Unformatted:
(Contact us)
$NetBSD: query-full-pr,v 1.39 2013/11/01 18:47:49 spz Exp $
$NetBSD: gnats_config.sh,v 1.8 2006/05/07 09:23:38 tsutsui Exp $
Copyright © 1994-2014
The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.