Skip to content
Permalink
Browse files

compat32: Translate userland PT_* request values into kernel codes

Currently, the compat32 passes PT_* request values to kernel functions
without translation.  This works fine for low PT_* requests that happen
to have the same values both on i386 and amd64.  However, for requests
higher than PT_SETFPREGS, the value passed from userland (matching i386
const) does not match the correct kernel (amd64) request.  As a result,
e.g. when compat32 process calls PT_GETDBREGS, kernel actually processes
it as PT_SETSTEP.

To resolve this, introduce support for compat32 PT_* request
translation.  The interface is based on PTRACE_TRANSLATE_REQUEST32 macro
that is defined to a mapping function on architectures needing it.
In case of amd64, this function maps userland i386 PT_* values into
appropriate amd64 PT_* values.

For the time being, the two additional PT_GETXMMREGS and PT_SETXMMREGS
requests are unsupported due to lack of matching free amd64 constant.
  • Loading branch information...
mgorny committed Jun 4, 2019
1 parent 04aa365 commit cd7d01a76ac4287c73be09dbca245e2864ac3948
@@ -1,4 +1,4 @@
/* $NetBSD: netbsd32_machdep.c,v 1.121 2019/05/19 08:46:15 maxv Exp $ */
/* $NetBSD: netbsd32_machdep.c,v 1.122 2019/06/04 16:29:53 mgorny Exp $ */

/*
* Copyright (c) 2001 Wasabi Systems, Inc.
@@ -36,7 +36,7 @@
*/

#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: netbsd32_machdep.c,v 1.121 2019/05/19 08:46:15 maxv Exp $");
__KERNEL_RCSID(0, "$NetBSD: netbsd32_machdep.c,v 1.122 2019/06/04 16:29:53 mgorny Exp $");

#ifdef _KERNEL_OPT
#include "opt_compat_netbsd.h"
@@ -335,6 +335,28 @@ cpu_coredump32(struct lwp *l, struct coredump_iostate *iocookie,
}
#endif

int
netbsd32_ptrace_translate_request(int req)
{

switch (req)
{
case 0 ... PT_FIRSTMACH - 1: return req;
case PT32_STEP: return PT_STEP;
case PT32_GETREGS: return PT_GETREGS;
case PT32_SETREGS: return PT_SETREGS;
case PT32_GETFPREGS: return PT_GETFPREGS;
case PT32_SETFPREGS: return PT_SETFPREGS;
case PT32_GETXMMREGS: return -1;
case PT32_SETXMMREGS: return -1;
case PT32_GETDBREGS: return PT_GETDBREGS;
case PT32_SETDBREGS: return PT_SETDBREGS;
case PT32_SETSTEP: return PT_SETSTEP;
case PT32_CLEARSTEP: return PT_CLEARSTEP;
default: return -1;
}
}

int
netbsd32_process_read_regs(struct lwp *l, struct reg32 *regs)
{
@@ -1,4 +1,4 @@
/* $NetBSD: netbsd32_machdep.h,v 1.22 2017/02/23 03:34:22 kamil Exp $ */
/* $NetBSD: netbsd32_machdep.h,v 1.23 2019/06/04 16:29:53 mgorny Exp $ */

#ifndef _MACHINE_NETBSD32_H_
#define _MACHINE_NETBSD32_H_
@@ -7,6 +7,22 @@
#include <compat/sys/ucontext.h>
#include <compat/sys/siginfo.h>

/*
* i386 ptrace constants
* Please keep in sync with sys/arch/i386/include/ptrace.h.
*/
#define PT32_STEP (PT_FIRSTMACH + 0)
#define PT32_GETREGS (PT_FIRSTMACH + 1)
#define PT32_SETREGS (PT_FIRSTMACH + 2)
#define PT32_GETFPREGS (PT_FIRSTMACH + 3)
#define PT32_SETFPREGS (PT_FIRSTMACH + 4)
#define PT32_GETXMMREGS (PT_FIRSTMACH + 5)
#define PT32_SETXMMREGS (PT_FIRSTMACH + 6)
#define PT32_GETDBREGS (PT_FIRSTMACH + 7)
#define PT32_SETDBREGS (PT_FIRSTMACH + 8)
#define PT32_SETSTEP (PT_FIRSTMACH + 9)
#define PT32_CLEARSTEP (PT_FIRSTMACH + 10)

#define NETBSD32_POINTER_TYPE uint32_t
typedef struct { NETBSD32_POINTER_TYPE i32; } netbsd32_pointer_t;

@@ -151,6 +167,9 @@ struct x86_64_set_mtrr_args32 {

#define NETBSD32_MID_MACHINE MID_I386

/* Translate ptrace() PT_* request from 32-bit userland to kernel. */
int netbsd32_ptrace_translate_request(int);

int netbsd32_process_read_regs(struct lwp *, struct reg32 *);
int netbsd32_process_read_fpregs(struct lwp *, struct fpreg32 *, size_t *);
int netbsd32_process_read_dbregs(struct lwp *, struct dbreg32 *, size_t *);
@@ -1,4 +1,4 @@
/* $NetBSD: ptrace.h,v 1.13 2019/02/07 00:19:54 kamil Exp $ */
/* $NetBSD: ptrace.h,v 1.14 2019/06/04 16:29:53 mgorny Exp $ */

/*
* Copyright (c) 1993 Christopher G. Demetriou
@@ -87,6 +87,8 @@
#define process_reg32 struct reg32
#define process_fpreg32 struct fpreg32
#define process_dbreg32 struct dbreg32

#define PTRACE_TRANSLATE_REQUEST32(x) netbsd32_ptrace_translate_request(x)
#endif /* COMPAT_NETBSD32 */
#endif /* _KERNEL_OPT */

@@ -1,4 +1,4 @@
/* $NetBSD: netbsd32_ptrace.c,v 1.6 2019/01/27 02:08:40 pgoyette Exp $ */
/* $NetBSD: netbsd32_ptrace.c,v 1.7 2019/06/04 16:29:53 mgorny Exp $ */

/*
* Copyright (c) 2016 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
*/

#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: netbsd32_ptrace.c,v 1.6 2019/01/27 02:08:40 pgoyette Exp $");
__KERNEL_RCSID(0, "$NetBSD: netbsd32_ptrace.c,v 1.7 2019/06/04 16:29:53 mgorny Exp $");

#if defined(_KERNEL_OPT)
#include "opt_ptrace.h"
@@ -47,6 +47,10 @@ __KERNEL_RCSID(0, "$NetBSD: netbsd32_ptrace.c,v 1.6 2019/01/27 02:08:40 pgoyette
#include <compat/netbsd32/netbsd32_syscallargs.h>
#include <compat/netbsd32/netbsd32_conv.h>

#ifndef PTRACE_TRANSLATE_REQUEST32
#define PTRACE_TRANSLATE_REQUEST32(x) x
#endif

/*
* PTRACE methods
*/
@@ -243,14 +247,20 @@ int
netbsd32_ptrace(struct lwp *l, const struct netbsd32_ptrace_args *uap,
register_t *retval)
{
int req;

/* {
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),
req = PTRACE_TRANSLATE_REQUEST32(SCARG(uap, req));
if (req == -1)
return EOPNOTSUPP;

return do_ptrace(&netbsd32_ptm, l, req, SCARG(uap, pid),
SCARG_P32(uap, addr), SCARG(uap, data), retval);
}

0 comments on commit cd7d01a

Please sign in to comment.
You can’t perform that action at this time.