Subject: sys_ptrace() changes
To: YAMAMOTO Takashi <yamt@mwd.biglobe.ne.jp>
From: Elad Efrat <elad@NetBSD.org>
List: tech-kern
Date: 12/26/2006 13:27:20
This is a multi-part message in MIME format.
--------------080504000609000203050305
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit
hi,
attached diff does the following:
- reorganize the code: first, switch statement to check if it's
possible to do the request as far as kernel stability etc. goes.
then a kauth(9) check to enforce security semantics (this replaces
several kauth(9) calls in the second switch. last, the second
switch statement to dispatch the request, after all aspects have
been checked.
- add kauth(9) KAUTH_PROCESS_CANSEE call right after the pfind()
to enforce curtain policy. with XXX comment because these should
not be sprinkled all around the code.
comments?
-e.
--------------080504000609000203050305
Content-Type: text/plain;
name="1.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="1.diff"
Index: secmodel/bsd44/secmodel_bsd44_suser.c
===================================================================
RCS file: /usr/cvs/src/sys/secmodel/bsd44/secmodel_bsd44_suser.c,v
retrieving revision 1.22
diff -u -p -r1.22 secmodel_bsd44_suser.c
--- secmodel/bsd44/secmodel_bsd44_suser.c 26 Dec 2006 10:43:44 -0000 1.22
+++ secmodel/bsd44/secmodel_bsd44_suser.c 24 Dec 2006 16:19:06 -0000
@@ -305,7 +305,42 @@ secmodel_bsd44_suser_process_cb(kauth_cr
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:
+ case PT_GETREGS:
+ case PT_SETREGS:
+ case PT_GETFPREGS:
+ case PT_SETFPREGS:
+ PTRACE_MACHDEP_REQUEST_CASES
+ 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;
+
+ default:
+ result = KAUTH_RESULT_ALLOW;
+ break;
+ }
+
+ break;
+ }
+
case KAUTH_PROCESS_CANSYSTRACE:
if (isroot) {
result = KAUTH_RESULT_ALLOW;
Index: kern/sys_process.c
===================================================================
RCS file: /usr/cvs/src/sys/kern/sys_process.c,v
retrieving revision 1.118
diff -u -p -r1.118 sys_process.c
--- kern/sys_process.c 6 Dec 2006 18:54:02 -0000 1.118
+++ kern/sys_process.c 24 Dec 2006 16:38:46 -0000
@@ -148,6 +148,12 @@ sys_ptrace(struct lwp *l, void *v, regis
/* 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, regis
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, regis
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, regis
#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, regis
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, regis
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, regis
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, regis
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, regis
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, regis
#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)));
--------------080504000609000203050305--