- 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)
This commit is contained in:
John Baldwin 2003-03-13 18:24:22 +00:00
parent c0796d1cb4
commit a5881ea55a
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=112198
6 changed files with 60 additions and 24 deletions

View File

@ -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 @@ kern_execve(td, fname, argv, envv, mac_p)
*/
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 @@ kern_execve(td, fname, argv, envv, mac_p)
#ifdef KTRACE
if (tracevp != NULL)
vrele(tracevp);
if (tracecred != NULL)
crfree(tracecred);
#endif
if (oldargs != NULL)
pargs_drop(oldargs);

View File

@ -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

View File

@ -626,11 +626,15 @@ fork1(td, flags, pages, procp)
* 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

View File

@ -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);
/*

View File

@ -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);

View File

@ -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. */