Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/kern untangle the mess:
details: https://anonhg.NetBSD.org/src/rev/625e56dd4617
branches: trunk
changeset: 828507:625e56dd4617
user: christos <christos%NetBSD.org@localhost>
date: Sun Dec 17 04:35:21 2017 +0000
description:
untangle the mess:
- factor out common code
- break each ptrace subcall to its own sub-function
... more to come ...
diffstat:
sys/kern/sys_ptrace_common.c | 959 +++++++++++++++++++++---------------------
1 files changed, 487 insertions(+), 472 deletions(-)
diffs (truncated from 1127 to 300 lines):
diff -r 62f0a41cda61 -r 625e56dd4617 sys/kern/sys_ptrace_common.c
--- a/sys/kern/sys_ptrace_common.c Sun Dec 17 04:06:03 2017 +0000
+++ b/sys/kern/sys_ptrace_common.c Sun Dec 17 04:35:21 2017 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: sys_ptrace_common.c,v 1.26 2017/12/09 05:18:45 christos Exp $ */
+/* $NetBSD: sys_ptrace_common.c,v 1.27 2017/12/17 04:35:21 christos Exp $ */
/*-
* Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
@@ -118,7 +118,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sys_ptrace_common.c,v 1.26 2017/12/09 05:18:45 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sys_ptrace_common.c,v 1.27 2017/12/17 04:35:21 christos Exp $");
#ifdef _KERNEL_OPT
#include "opt_ptrace.h"
@@ -299,113 +299,80 @@
return 0;
}
-int
-do_ptrace(struct ptrace_methods *ptm, struct lwp *l, int req, pid_t pid,
- void *addr, int data, register_t *retval)
+static struct proc *
+ptrace_find(struct lwp *l, int req, pid_t pid)
{
- struct proc *p = l->l_proc;
- struct lwp *lt;
- struct lwp *lt2;
- struct proc *t; /* target process */
- struct uio uio;
- struct iovec iov;
- struct ptrace_io_desc piod;
- struct ptrace_event pe;
- struct ptrace_state ps;
- struct ptrace_lwpinfo pl;
- struct ptrace_siginfo psi;
- struct vmspace *vm;
- int error, write, tmp, pheld;
- int signo = 0;
- int resume_all;
- ksiginfo_t ksi;
- char *path;
- int len = 0;
- error = 0;
-
- /*
- * If attaching or detaching, we need to get a write hold on the
- * proclist lock so that we can re-parent the target process.
- */
- mutex_enter(proc_lock);
+ struct proc *t;
/* "A foolish consistency..." XXX */
if (req == PT_TRACE_ME) {
- t = p;
+ t = l->l_proc;
mutex_enter(t->p_lock);
- } else {
- /* Find the process we're supposed to be operating on. */
- t = proc_find(pid);
- if (t == NULL) {
- mutex_exit(proc_lock);
- return ESRCH;
- }
-
- /* XXX-elad */
- mutex_enter(t->p_lock);
- error = kauth_authorize_process(l->l_cred, KAUTH_PROCESS_CANSEE,
- t, KAUTH_ARG(KAUTH_REQ_PROCESS_CANSEE_ENTRY), NULL, NULL);
- if (error) {
- mutex_exit(proc_lock);
- mutex_exit(t->p_lock);
- return ESRCH;
- }
+ return t;
}
+ /* Find the process we're supposed to be operating on. */
+ t = proc_find(pid);
+ if (t == NULL)
+ return NULL;
+
+ /* XXX-elad */
+ mutex_enter(t->p_lock);
+ int error = kauth_authorize_process(l->l_cred, KAUTH_PROCESS_CANSEE,
+ t, KAUTH_ARG(KAUTH_REQ_PROCESS_CANSEE_ENTRY), NULL, NULL);
+ if (error) {
+ mutex_exit(t->p_lock);
+ return NULL;
+ }
+ return t;
+}
+
+static int
+ptrace_allowed(struct lwp *l, int req, struct proc *t, struct proc *p)
+{
/*
* Grab a reference on the process to prevent it from execing or
* exiting.
*/
- if (!rw_tryenter(&t->p_reflock, RW_READER)) {
- mutex_exit(proc_lock);
- mutex_exit(t->p_lock);
+ if (!rw_tryenter(&t->p_reflock, RW_READER))
return EBUSY;
- }
/* Make sure we can operate on it. */
switch (req) {
case PT_TRACE_ME:
/* Saying that you're being traced is always legal. */
- break;
+ return 0;
case PT_ATTACH:
/*
* You can't attach to a process if:
* (1) it's the process that's doing the attaching,
*/
- if (t->p_pid == p->p_pid) {
- error = EINVAL;
- break;
- }
+ if (t->p_pid == p->p_pid)
+ return EINVAL;
/*
* (2) it's a system process
*/
- if (t->p_flag & PK_SYSTEM) {
- error = EPERM;
- break;
- }
+ if (t->p_flag & PK_SYSTEM)
+ return EPERM;
/*
* (3) it's already being traced, or
*/
- if (ISSET(t->p_slflag, PSL_TRACED)) {
- error = EBUSY;
- break;
- }
+ if (ISSET(t->p_slflag, PSL_TRACED))
+ return EBUSY;
/*
* (4) the tracer is chrooted, and its root directory is
* not at or above the root directory of the tracee
*/
mutex_exit(t->p_lock); /* XXXSMP */
- tmp = proc_isunder(t, l);
+ int tmp = proc_isunder(t, l);
mutex_enter(t->p_lock); /* XXXSMP */
- if (!tmp) {
- error = EPERM;
- break;
- }
- break;
+ if (!tmp)
+ return EPERM;
+ return 0;
case PT_READ_I:
case PT_READ_D:
@@ -445,10 +412,8 @@
mutex_exit(t->p_lock); /* XXXSMP */
tmp = proc_isunder(t, l);
mutex_enter(t->p_lock); /* XXXSMP */
- if (!tmp) {
- error = EPERM;
- break;
- }
+ if (!tmp)
+ return EPERM;
/*FALLTHROUGH*/
case PT_CONTINUE:
@@ -472,10 +437,8 @@
* You can't do what you want to the process if:
* (1) It's not being traced at all,
*/
- if (!ISSET(t->p_slflag, PSL_TRACED)) {
- error = EPERM;
- break;
- }
+ if (!ISSET(t->p_slflag, PSL_TRACED))
+ return EPERM;
/*
* (2) it's not being traced by _you_, or
@@ -483,8 +446,7 @@
if (t->p_pptr != p) {
DPRINTF(("parent %d != %d\n", t->p_pptr->p_pid,
p->p_pid));
- error = EBUSY;
- break;
+ return EBUSY;
}
/*
@@ -493,42 +455,18 @@
if (t->p_stat != SSTOP || !t->p_waited /* XXXSMP */) {
DPRINTF(("stat %d flag %d\n", t->p_stat,
!t->p_waited));
- error = EBUSY;
- break;
+ return EBUSY;
}
- break;
+ return 0;
default: /* It was not a legal request. */
- error = EINVAL;
- break;
+ return EINVAL;
}
-
- if (error == 0) {
- error = kauth_authorize_process(l->l_cred,
- KAUTH_PROCESS_PTRACE, t, KAUTH_ARG(req),
- NULL, NULL);
- }
- if (error == 0) {
- lt = lwp_find_first(t);
- if (lt == NULL)
- error = ESRCH;
- }
+}
- if (error != 0) {
- mutex_exit(proc_lock);
- mutex_exit(t->p_lock);
- rw_exit(&t->p_reflock);
- return error;
- }
-
- /* Do single-step fixup if needed. */
- FIX_SSTEP(t);
- KASSERT(lt != NULL);
- lwp_addref(lt);
-
- /*
- * Which locks do we need held? XXX Ugly.
- */
+static int
+ptrace_needs_hold(int req)
+{
switch (req) {
#ifdef PT_STEP
case PT_STEP:
@@ -540,13 +478,431 @@
case PT_SYSCALLEMU:
case PT_ATTACH:
case PT_TRACE_ME:
- pheld = 1;
+ case PT_GET_SIGINFO:
+ case PT_SET_SIGINFO:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+static int
+ptrace_update_lwp(struct proc *t, struct lwp **lt, lwpid_t lid)
+{
+ if (lid == 0 || lid == (*lt)->l_lid || t->p_nlwps == 1)
+ return 0;
+
+ lwp_delref(*lt);
+
+ mutex_enter(t->p_lock);
+ *lt = lwp_find(t, lid);
+ if (*lt == NULL) {
+ mutex_exit(t->p_lock);
+ return ESRCH;
+ }
+
+ if ((*lt)->l_flag & LW_SYSTEM) {
+ *lt = NULL;
+ return EINVAL;
+ }
+
+ lwp_addref(*lt);
+ mutex_exit(t->p_lock);
+
+ return 0;
+}
+
+static int
+ptrace_get_siginfo(struct proc *t, void *addr, size_t data)
+{
+ struct ptrace_siginfo psi;
+
+ if (data != sizeof(psi)) {
+ DPRINTF(("%s: %zu != %zu\n", __func__, data, sizeof(psi)));
Home |
Main Index |
Thread Index |
Old Index