From 8764325d83b701c5629ead8a3cafcd054882f684 Mon Sep 17 00:00:00 2001 From: elad Date: Wed, 27 Dec 2006 10:02:46 +0000 Subject: [PATCH] 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. --- sys/kern/sys_process.c | 102 +++++++--------------- sys/secmodel/bsd44/secmodel_bsd44_suser.c | 64 +++++++++++++- 2 files changed, 94 insertions(+), 72 deletions(-) diff --git a/sys/kern/sys_process.c b/sys/kern/sys_process.c index da785d9317a7..a706a99032cf 100644 --- a/sys/kern/sys_process.c +++ b/sys/kern/sys_process.c @@ -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 -__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 #include @@ -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))); diff --git a/sys/secmodel/bsd44/secmodel_bsd44_suser.c b/sys/secmodel/bsd44/secmodel_bsd44_suser.c index 0294fd6a83e7..53cb7ef5b674 100644 --- a/sys/secmodel/bsd44/secmodel_bsd44_suser.c +++ b/sys/secmodel/bsd44/secmodel_bsd44_suser.c @@ -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 * All rights reserved. @@ -41,7 +41,7 @@ */ #include -__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 #include @@ -54,6 +54,7 @@ __KERNEL_RCSID(0, "$NetBSD: secmodel_bsd44_suser.c,v 1.22 2006/12/26 10:43:44 el #include #include #include +#include #include @@ -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;