From a5881ea55a2c554fd584cf985d99e92ad1db8737 Mon Sep 17 00:00:00 2001 From: John Baldwin Date: Thu, 13 Mar 2003 18:24:22 +0000 Subject: [PATCH] - Cache a reference to the credential of the thread that starts a ktrace in struct proc as p_tracecred alongside the current cache of the vnode in p_tracep. This credential is then used for all later ktrace operations on this file rather than using the credential of the current thread at the time of each ktrace event. - Now that we have multiple ktrace-related items in struct proc that are pointers, rename p_tracep to p_tracevp to make it less ambiguous. Requested by: rwatson (1) --- sys/kern/kern_exec.c | 11 +++++++--- sys/kern/kern_exit.c | 9 ++++++-- sys/kern/kern_fork.c | 10 ++++++--- sys/kern/kern_ktrace.c | 49 ++++++++++++++++++++++++++++++------------ sys/kern/kern_proc.c | 2 +- sys/sys/proc.h | 3 ++- 6 files changed, 60 insertions(+), 24 deletions(-) diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c index 2c5df1ccd410..a359b75d76a2 100644 --- a/sys/kern/kern_exec.c +++ b/sys/kern/kern_exec.c @@ -178,6 +178,7 @@ kern_execve(td, fname, argv, envv, mac_p) struct procsig *oldprocsig, *newprocsig; #ifdef KTRACE struct vnode *tracevp = NULL; + struct ucred *tracecred = NULL; #endif struct vnode *textvp = NULL; int credential_changing; @@ -489,11 +490,13 @@ interpret: */ setsugid(p); #ifdef KTRACE - if (p->p_tracep && suser_cred(oldcred, PRISON_ROOT)) { + if (p->p_tracevp != NULL && suser_cred(oldcred, PRISON_ROOT)) { mtx_lock(&ktrace_mtx); p->p_traceflag = 0; - tracevp = p->p_tracep; - p->p_tracep = NULL; + tracevp = p->p_tracevp; + p->p_tracevp = NULL; + tracecred = p->p_tracecred; + p->p_tracecred = NULL; mtx_unlock(&ktrace_mtx); } #endif @@ -626,6 +629,8 @@ done1: #ifdef KTRACE if (tracevp != NULL) vrele(tracevp); + if (tracecred != NULL) + crfree(tracecred); #endif if (oldargs != NULL) pargs_drop(oldargs); diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c index 22dba08c3ca7..168900f2305e 100644 --- a/sys/kern/kern_exit.c +++ b/sys/kern/kern_exit.c @@ -135,6 +135,7 @@ exit1(td, rv) struct vnode *vtmp; #ifdef KTRACE struct vnode *tracevp; + struct ucred *tracecred; #endif GIANT_REQUIRED; @@ -359,12 +360,16 @@ exit1(td, rv) PROC_LOCK(p); mtx_lock(&ktrace_mtx); p->p_traceflag = 0; /* don't trace the vrele() */ - tracevp = p->p_tracep; - p->p_tracep = NULL; + tracevp = p->p_tracevp; + p->p_tracevp = NULL; + tracecred = p->p_tracecred; + p->p_tracecred = NULL; mtx_unlock(&ktrace_mtx); PROC_UNLOCK(p); if (tracevp != NULL) vrele(tracevp); + if (tracecred != NULL) + crfree(tracecred); #endif /* * Release reference to text vnode diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c index 65a3360854ab..0c24cc6dad74 100644 --- a/sys/kern/kern_fork.c +++ b/sys/kern/kern_fork.c @@ -626,11 +626,15 @@ again: * Copy traceflag and tracefile if enabled. */ mtx_lock(&ktrace_mtx); - KASSERT(p2->p_tracep == NULL, ("new process has a ktrace vnode")); + KASSERT(p2->p_tracevp == NULL, ("new process has a ktrace vnode")); if (p1->p_traceflag & KTRFAC_INHERIT) { p2->p_traceflag = p1->p_traceflag; - if ((p2->p_tracep = p1->p_tracep) != NULL) - VREF(p2->p_tracep); + if ((p2->p_tracevp = p1->p_tracevp) != NULL) { + VREF(p2->p_tracevp); + KASSERT(p1->p_tracecred != NULL, + ("ktrace vnode with no cred")); + p2->p_tracecred = crhold(p1->p_tracecred); + } } mtx_unlock(&ktrace_mtx); #endif diff --git a/sys/kern/kern_ktrace.c b/sys/kern/kern_ktrace.c index bb4642c5acb3..8685eb1576ae 100644 --- a/sys/kern/kern_ktrace.c +++ b/sys/kern/kern_ktrace.c @@ -226,14 +226,15 @@ ktr_getrequest(int type) if (req != NULL) { STAILQ_REMOVE_HEAD(&ktr_free, ktr_list); req->ktr_header.ktr_type = type; - KASSERT(p->p_tracep != NULL, ("ktrace: no trace vnode")); - req->ktr_vp = p->p_tracep; - VREF(p->p_tracep); + KASSERT(p->p_tracevp != NULL, ("ktrace: no trace vnode")); + KASSERT(p->p_tracecred != NULL, ("ktrace: no trace cred")); + req->ktr_vp = p->p_tracevp; + VREF(p->p_tracevp); + req->ktr_cred = crhold(p->p_tracecred); mtx_unlock(&ktrace_mtx); microtime(&req->ktr_header.ktr_time); req->ktr_header.ktr_pid = p->p_pid; bcopy(p->p_comm, req->ktr_header.ktr_comm, MAXCOMLEN + 1); - req->ktr_cred = crhold(td->td_ucred); req->ktr_header.ktr_buffer = NULL; req->ktr_header.ktr_len = 0; } else { @@ -498,6 +499,7 @@ ktrace(td, uap) int ret = 0; int flags, error = 0; struct nameidata nd; + struct ucred *cred; td->td_inktrace = 1; if (ops != KTROP_CLEAR) { @@ -527,15 +529,18 @@ ktrace(td, uap) sx_slock(&allproc_lock); LIST_FOREACH(p, &allproc, p_list) { PROC_LOCK(p); - if (p->p_tracep == vp) { + if (p->p_tracevp == vp) { if (ktrcanset(td, p)) { mtx_lock(&ktrace_mtx); - p->p_tracep = NULL; + cred = p->p_tracecred; + p->p_tracecred = NULL; + p->p_tracevp = NULL; p->p_traceflag = 0; mtx_unlock(&ktrace_mtx); PROC_UNLOCK(p); (void) vn_close(vp, FREAD|FWRITE, - td->td_ucred, td); + cred, td); + crfree(cred); } else { PROC_UNLOCK(p); error = EPERM; @@ -654,6 +659,7 @@ ktrops(td, p, ops, facs, vp) struct vnode *vp; { struct vnode *tracevp = NULL; + struct ucred *tracecred = NULL; PROC_LOCK(p); if (!ktrcanset(td, p)) { @@ -662,13 +668,17 @@ ktrops(td, p, ops, facs, vp) } mtx_lock(&ktrace_mtx); if (ops == KTROP_SET) { - if (p->p_tracep != vp) { + if (p->p_tracevp != vp) { /* * if trace file already in use, relinquish below */ - tracevp = p->p_tracep; + tracevp = p->p_tracevp; VREF(vp); - p->p_tracep = vp; + p->p_tracevp = vp; + } + if (p->p_tracecred != td->td_ucred) { + tracecred = p->p_tracecred; + p->p_tracecred = crhold(td->td_ucred); } p->p_traceflag |= facs; if (td->td_ucred->cr_uid == 0) @@ -678,14 +688,18 @@ ktrops(td, p, ops, facs, vp) if (((p->p_traceflag &= ~facs) & KTRFAC_MASK) == 0) { /* no more tracing */ p->p_traceflag = 0; - tracevp = p->p_tracep; - p->p_tracep = NULL; + tracevp = p->p_tracevp; + p->p_tracevp = NULL; + tracecred = p->p_tracecred; + p->p_tracecred = NULL; } } mtx_unlock(&ktrace_mtx); PROC_UNLOCK(p); if (tracevp != NULL) vrele(tracevp); + if (tracecred != NULL) + crfree(tracecred); return (1); } @@ -804,17 +818,24 @@ ktr_writerequest(struct ktr_request *req) * we really do this? Other processes might have suitable * credentials for the operation. */ + cred = NULL; sx_slock(&allproc_lock); LIST_FOREACH(p, &allproc, p_list) { PROC_LOCK(p); - if (p->p_tracep == vp) { + if (p->p_tracevp == vp) { mtx_lock(&ktrace_mtx); - p->p_tracep = NULL; + p->p_tracevp = NULL; p->p_traceflag = 0; + cred = p->p_tracecred; + p->p_tracecred = NULL; mtx_unlock(&ktrace_mtx); vrele_count++; } PROC_UNLOCK(p); + if (cred != NULL) { + crfree(cred); + cred = NULL; + } } sx_sunlock(&allproc_lock); /* diff --git a/sys/kern/kern_proc.c b/sys/kern/kern_proc.c index 84b3fc180eb1..752fbf024e15 100644 --- a/sys/kern/kern_proc.c +++ b/sys/kern/kern_proc.c @@ -625,7 +625,7 @@ fill_kinfo_proc(p, kp) kp->ki_args = p->p_args; kp->ki_textvp = p->p_textvp; #ifdef KTRACE - kp->ki_tracep = p->p_tracep; + kp->ki_tracep = p->p_tracevp; mtx_lock(&ktrace_mtx); kp->ki_traceflag = p->p_traceflag; mtx_unlock(&ktrace_mtx); diff --git a/sys/sys/proc.h b/sys/sys/proc.h index 270b235a7f67..c34d4362d661 100644 --- a/sys/sys/proc.h +++ b/sys/sys/proc.h @@ -553,7 +553,8 @@ struct proc { int p_profthreads; /* (c) Num threads in addupc_task */ int p_maxthrwaits; /* (c) Max threads num waiters */ int p_traceflag; /* (o) Kernel trace points. */ - struct vnode *p_tracep; /* (c + o) Trace to vnode. */ + struct vnode *p_tracevp; /* (c + o) Trace to vnode. */ + struct ucred *p_tracecred; /* (o) Credentials to trace with. */ sigset_t p_siglist; /* (c) Sigs arrived, not delivered. */ struct vnode *p_textvp; /* (b) Vnode of executable. */ char p_lock; /* (c) Proclock (prevent swap) count. */