- 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:
parent
c0796d1cb4
commit
a5881ea55a
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
/*
|
||||
|
@ -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);
|
||||
|
@ -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. */
|
||||
|
Loading…
x
Reference in New Issue
Block a user