Refactor a bit the ptrace(2) code: first make the keep-kernel-stable

decisions, then have a kauth(9) call for security policy enforcement,
and only then proceed to processing each request.

Add a KAUTH_PROCESS_CANSEE call right after pfind(). This should really
be done differently, so mark it with XXX.
This commit is contained in:
elad 2006-12-27 10:02:46 +00:00
parent a8552e41ca
commit 8764325d83
2 changed files with 94 additions and 72 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: sys_process.c,v 1.118 2006/12/06 18:54:02 christos Exp $ */
/* $NetBSD: sys_process.c,v 1.119 2006/12/27 10:02:46 elad Exp $ */
/*-
* Copyright (c) 1982, 1986, 1989, 1993
@ -93,7 +93,7 @@
#include "opt_ktrace.h"
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: sys_process.c,v 1.118 2006/12/06 18:54:02 christos Exp $");
__KERNEL_RCSID(0, "$NetBSD: sys_process.c,v 1.119 2006/12/27 10:02:46 elad Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@ -148,6 +148,12 @@ sys_ptrace(struct lwp *l, void *v, register_t *retval)
/* Find the process we're supposed to be operating on. */
if ((t = pfind(SCARG(uap, pid))) == NULL)
return (ESRCH);
/* XXX elad - this should be in pfind(). */
error = kauth_authorize_process(l->l_cred, KAUTH_PROCESS_CANSEE,
t, NULL, NULL, NULL);
if (error)
return (ESRCH);
}
/* Can't trace a process that's currently exec'ing. */
@ -181,16 +187,7 @@ sys_ptrace(struct lwp *l, void *v, register_t *retval)
return (EBUSY);
/*
* (4) the security model prevents it, or
*/
error = kauth_authorize_process(l->l_cred,
KAUTH_PROCESS_CANPTRACE, t, KAUTH_ARG(SCARG(uap, req)),
NULL, NULL);
if (error)
return (error);
/*
* (5) the tracer is chrooted, and its root directory is
* (4) the tracer is chrooted, and its root directory is
* not at or above the root directory of the tracee
*/
if (!proc_isunder(t, l))
@ -201,18 +198,7 @@ sys_ptrace(struct lwp *l, void *v, register_t *retval)
case PT_READ_D:
case PT_WRITE_I:
case PT_WRITE_D:
case PT_CONTINUE:
case PT_IO:
case PT_KILL:
case PT_DETACH:
case PT_LWPINFO:
case PT_SYSCALL:
#ifdef COREDUMP
case PT_DUMPCORE:
#endif
#ifdef PT_STEP
case PT_STEP:
#endif
#ifdef PT_GETREGS
case PT_GETREGS:
#endif
@ -225,11 +211,29 @@ sys_ptrace(struct lwp *l, void *v, register_t *retval)
#ifdef PT_SETFPREGS
case PT_SETFPREGS:
#endif
#ifdef __HAVE_PTRACE_MACHDEP
PTRACE_MACHDEP_REQUEST_CASES
#endif
/*
* You can't read/write the memory or registers of a process
* if the tracer is chrooted, and its root directory is not at
* or above the root directory of the tracee.
*/
if (!proc_isunder(t, l))
return (EPERM);
/*FALLTHROUGH*/
case PT_CONTINUE:
case PT_KILL:
case PT_DETACH:
case PT_LWPINFO:
case PT_SYSCALL:
#ifdef COREDUMP
case PT_DUMPCORE:
#endif
#ifdef PT_STEP
case PT_STEP:
#endif
/*
* You can't do what you want to the process if:
* (1) It's not being traced at all,
@ -268,6 +272,11 @@ sys_ptrace(struct lwp *l, void *v, register_t *retval)
return (EINVAL);
}
error = kauth_authorize_process(l->l_cred, KAUTH_PROCESS_CANPTRACE,
t, KAUTH_ARG(SCARG(uap, req)), NULL, NULL);
if (error)
return (error);
/* Do single-step fixup if needed. */
FIX_SSTEP(t);
@ -319,15 +328,6 @@ sys_ptrace(struct lwp *l, void *v, register_t *retval)
uio.uio_rw = write ? UIO_WRITE : UIO_READ;
UIO_SETUP_SYSSPACE(&uio);
error = kauth_authorize_process(l->l_cred,
KAUTH_PROCESS_CANPTRACE, t, KAUTH_ARG(SCARG(uap, req)),
NULL, NULL);
if (error)
return (error);
if (!proc_isunder(t, l))
return (EPERM);
error = process_domem(l, lt, &uio);
if (!write)
*retval = tmp;
@ -370,15 +370,6 @@ sys_ptrace(struct lwp *l, void *v, register_t *retval)
uio.uio_resid = piod.piod_len;
uio.uio_vmspace = vm;
error = kauth_authorize_process(l->l_cred,
KAUTH_PROCESS_CANPTRACE, t, KAUTH_ARG(SCARG(uap, req)),
NULL, NULL);
if (error)
return (error);
if (!proc_isunder(t, l))
return (EPERM);
error = process_domem(l, lt, &uio);
piod.piod_len -= uio.uio_resid;
(void) copyout(&piod, SCARG(uap, addr), sizeof(piod));
@ -592,15 +583,6 @@ sys_ptrace(struct lwp *l, void *v, register_t *retval)
uio.uio_rw = write ? UIO_WRITE : UIO_READ;
uio.uio_vmspace = vm;
error = kauth_authorize_process(l->l_cred,
KAUTH_PROCESS_CANPTRACE, t,
KAUTH_ARG(SCARG(uap, req)), NULL, NULL);
if (error)
return (error);
if (!proc_isunder(t, l))
return (EPERM);
error = process_doregs(l, lt, &uio);
uvmspace_free(vm);
return error;
@ -640,15 +622,6 @@ sys_ptrace(struct lwp *l, void *v, register_t *retval)
uio.uio_rw = write ? UIO_WRITE : UIO_READ;
uio.uio_vmspace = vm;
error = kauth_authorize_process(l->l_cred,
KAUTH_PROCESS_CANPTRACE, t,
KAUTH_ARG(SCARG(uap, req)), NULL, NULL);
if (error)
return (error);
if (!proc_isunder(t, l))
return (EPERM);
error = process_dofpregs(l, lt, &uio);
uvmspace_free(vm);
return error;
@ -657,15 +630,6 @@ sys_ptrace(struct lwp *l, void *v, register_t *retval)
#ifdef __HAVE_PTRACE_MACHDEP
PTRACE_MACHDEP_REQUEST_CASES
error = kauth_authorize_process(l->l_cred,
KAUTH_PROCESS_CANPTRACE, t, KAUTH_ARG(SCARG(uap, req)),
NULL, NULL);
if (error)
return (error);
if (!proc_isunder(t, l))
return (EPERM);
return (ptrace_machdep_dorequest(l, lt,
SCARG(uap, req), SCARG(uap, addr),
SCARG(uap, data)));

View File

@ -1,4 +1,4 @@
/* $NetBSD: secmodel_bsd44_suser.c,v 1.22 2006/12/26 10:43:44 elad Exp $ */
/* $NetBSD: secmodel_bsd44_suser.c,v 1.23 2006/12/27 10:02:46 elad Exp $ */
/*-
* Copyright (c) 2006 Elad Efrat <elad@NetBSD.org>
* All rights reserved.
@ -41,7 +41,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: secmodel_bsd44_suser.c,v 1.22 2006/12/26 10:43:44 elad Exp $");
__KERNEL_RCSID(0, "$NetBSD: secmodel_bsd44_suser.c,v 1.23 2006/12/27 10:02:46 elad Exp $");
#include <sys/types.h>
#include <sys/param.h>
@ -54,6 +54,7 @@ __KERNEL_RCSID(0, "$NetBSD: secmodel_bsd44_suser.c,v 1.22 2006/12/26 10:43:44 el
#include <sys/sysctl.h>
#include <sys/tty.h>
#include <net/route.h>
#include <sys/ptrace.h>
#include <miscfs/procfs/procfs.h>
@ -305,7 +306,64 @@ secmodel_bsd44_suser_process_cb(kauth_cred_t cred, kauth_action_t action,
break;
}
case KAUTH_PROCESS_CANPTRACE:
case KAUTH_PROCESS_CANPTRACE: {
switch ((u_long)arg1) {
case PT_ATTACH:
case PT_WRITE_I:
case PT_WRITE_D:
case PT_READ_I:
case PT_READ_D:
case PT_IO:
#ifdef PT_GETREGS
case PT_GETREGS:
#endif
#ifdef PT_SETREGS
case PT_SETREGS:
#endif
#ifdef PT_GETFPREGS
case PT_GETFPREGS:
#endif
#ifdef PT_SETFPREGS
case PT_SETFPREGS:
#endif
#ifdef __HAVE_PTRACE_MACHDEP
PTRACE_MACHDEP_REQUEST_CASES
#endif
if (isroot) {
result = KAUTH_RESULT_ALLOW;
break;
}
if (kauth_cred_getuid(cred) !=
kauth_cred_getuid(p->p_cred) ||
ISSET(p->p_flag, P_SUGID)) {
result = KAUTH_RESULT_DENY;
break;
}
result = KAUTH_RESULT_ALLOW;
break;
#ifdef PT_STEP
case PT_STEP:
#endif
case PT_CONTINUE:
case PT_KILL:
case PT_DETACH:
case PT_LWPINFO:
case PT_SYSCALL:
case PT_DUMPCORE:
result = KAUTH_RESULT_ALLOW;
break;
default:
result = KAUTH_RESULT_DEFER;
break;
}
break;
}
case KAUTH_PROCESS_CANSYSTRACE:
if (isroot) {
result = KAUTH_RESULT_ALLOW;