PR# kern/45312: ptrace: PT_SETREGS can't alter system calls

Add a new PT_SYSCALLEMU request that cancels the current syscall, for
use with PT_SYSCALL.
This commit is contained in:
jmcneill 2011-08-31 22:58:39 +00:00
parent 0479426ceb
commit 1904b2b8db
4 changed files with 29 additions and 8 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: kern_subr.c,v 1.209 2011/07/27 14:35:34 uebayasi Exp $ */
/* $NetBSD: kern_subr.c,v 1.210 2011/08/31 22:58:39 jmcneill Exp $ */
/*-
* Copyright (c) 1997, 1998, 1999, 2002, 2007, 2008 The NetBSD Foundation, Inc.
@ -79,7 +79,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: kern_subr.c,v 1.209 2011/07/27 14:35:34 uebayasi Exp $");
__KERNEL_RCSID(0, "$NetBSD: kern_subr.c,v 1.210 2011/08/31 22:58:39 jmcneill Exp $");
#include "opt_ddb.h"
#include "opt_md.h"
@ -686,6 +686,8 @@ trace_is_enabled(struct proc *p)
int
trace_enter(register_t code, const register_t *args, int narg)
{
int error = 0;
#ifdef SYSCALL_DEBUG
scdebug_call(code, args);
#endif /* SYSCALL_DEBUG */
@ -694,10 +696,16 @@ trace_enter(register_t code, const register_t *args, int narg)
#ifdef PTRACE
if ((curlwp->l_proc->p_slflag & (PSL_SYSCALL|PSL_TRACED)) ==
(PSL_SYSCALL|PSL_TRACED))
(PSL_SYSCALL|PSL_TRACED)) {
process_stoptrace();
if (curlwp->l_proc->p_slflag & PSL_SYSCALLEMU) {
/* tracer will emulate syscall for us */
error = EJUSTRETURN;
CLR(curlwp->l_proc->p_slflag, PSL_SYSCALLEMU);
}
}
#endif
return 0;
return error;
}
/*

View File

@ -1,4 +1,4 @@
/* $NetBSD: sys_process.c,v 1.159 2011/08/30 22:45:55 christos Exp $ */
/* $NetBSD: sys_process.c,v 1.160 2011/08/31 22:58:39 jmcneill Exp $ */
/*-
* Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
@ -118,7 +118,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: sys_process.c,v 1.159 2011/08/30 22:45:55 christos Exp $");
__KERNEL_RCSID(0, "$NetBSD: sys_process.c,v 1.160 2011/08/31 22:58:39 jmcneill Exp $");
#include "opt_ptrace.h"
#include "opt_ktrace.h"
@ -195,6 +195,7 @@ ptrace_listener_cb(kauth_cred_t cred, kauth_action_t action, void *cookie,
case PT_DETACH:
case PT_LWPINFO:
case PT_SYSCALL:
case PT_SYSCALLEMU:
case PT_DUMPCORE:
result = KAUTH_RESULT_ALLOW;
break;
@ -370,6 +371,7 @@ sys_ptrace(struct lwp *l, const struct sys_ptrace_args *uap, register_t *retval)
case PT_DETACH:
case PT_LWPINFO:
case PT_SYSCALL:
case PT_SYSCALLEMU:
case PT_DUMPCORE:
#ifdef PT_STEP
case PT_STEP:
@ -453,6 +455,7 @@ sys_ptrace(struct lwp *l, const struct sys_ptrace_args *uap, register_t *retval)
case PT_DETACH:
case PT_KILL:
case PT_SYSCALL:
case PT_SYSCALLEMU:
case PT_ATTACH:
case PT_TRACE_ME:
pheld = 1;
@ -714,6 +717,14 @@ sys_ptrace(struct lwp *l, const struct sys_ptrace_args *uap, register_t *retval)
}
break;
case PT_SYSCALLEMU:
if (!ISSET(t->p_slflag, PSL_SYSCALL) || t->p_stat != SSTOP) {
error = EINVAL;
break;
}
SET(t->p_slflag, PSL_SYSCALLEMU);
break;
case PT_KILL:
/* just send the process a KILL signal. */
signo = SIGKILL;

View File

@ -1,4 +1,4 @@
/* $NetBSD: proc.h,v 1.308 2011/07/27 13:20:07 uebayasi Exp $ */
/* $NetBSD: proc.h,v 1.309 2011/08/31 22:58:39 jmcneill Exp $ */
/*-
* Copyright (c) 2006, 2007, 2008 The NetBSD Foundation, Inc.
@ -378,6 +378,7 @@ struct proc {
#define PSL_FSTRACE 0x00010000 /* Debugger process being traced by procfs */
#define PSL_CHTRACED 0x00400000 /* Child has been traced & reparented */
#define PSL_SYSCALL 0x04000000 /* process has PT_SYSCALL enabled */
#define PSL_SYSCALLEMU 0x08000000 /* cancel in-progress syscall */
/*
* Kept in p_stflag and protected by p_stmutex.

View File

@ -1,4 +1,4 @@
/* $NetBSD: ptrace.h,v 1.42 2009/12/14 00:48:35 matt Exp $ */
/* $NetBSD: ptrace.h,v 1.43 2011/08/31 22:58:39 jmcneill Exp $ */
/*-
* Copyright (c) 1984, 1993
@ -47,6 +47,7 @@
#define PT_DUMPCORE 12 /* make the child generate a core dump */
#define PT_LWPINFO 13 /* get info about the LWP */
#define PT_SYSCALL 14 /* stop on syscall entry/exit */
#define PT_SYSCALLEMU 15 /* cancel syscall, tracer will emulate it */
#define PT_FIRSTMACH 32 /* for machine-specific requests */
#include <machine/ptrace.h> /* machine-specific requests, if any */