1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-12-20 11:11:24 +00:00

Partially reworked r219042.

The reason for this is a bug at ktrops() where process dereferenced
without having a lock. This might cause a panic if ktrace was runned
with -p flag and the specified process exited between the dropping
a lock and writing sv_flags.

Since it is impossible to acquire sx lock while holding mtx switch
to use asynchronous enqueuerequest() instead of writerequest().

Rename ktr_getrequest_ne() to more understandable name [1].

Requested by:	jhb [1]

MFC after:	1 Week
This commit is contained in:
Dmitry Chagin 2011-03-05 20:36:42 +00:00
parent adb67a1ac0
commit 22ec040605
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=219311

View File

@ -138,9 +138,8 @@ static struct sx ktrace_sx;
static void ktrace_init(void *dummy);
static int sysctl_kern_ktrace_request_pool(SYSCTL_HANDLER_ARGS);
static u_int ktrace_resize_pool(u_int oldsize, u_int newsize);
static struct ktr_request *ktr_getrequest_ne(struct thread *, int type);
static struct ktr_request *ktr_getrequest_entered(struct thread *td, int type);
static struct ktr_request *ktr_getrequest(int type);
static void ktr_submitrequest_ne(struct thread *td, struct ktr_request *req);
static void ktr_submitrequest(struct thread *td, struct ktr_request *req);
static void ktr_freeproc(struct proc *p, struct ucred **uc,
struct vnode **vp);
@ -150,7 +149,7 @@ static void ktr_writerequest(struct thread *td, struct ktr_request *req);
static int ktrcanset(struct thread *,struct proc *);
static int ktrsetchildren(struct thread *,struct proc *,int,int,struct vnode *);
static int ktrops(struct thread *,struct proc *,int,int,struct vnode *);
static void ktrprocctor_ne(struct thread *, struct proc *p);
static void ktrprocctor_entered(struct thread *, struct proc *);
/*
* ktrace itself generates events, such as context switches, which we do not
@ -272,7 +271,7 @@ CTASSERT(sizeof(((struct ktr_header *)NULL)->ktr_comm) ==
(sizeof((struct thread *)NULL)->td_name));
static struct ktr_request *
ktr_getrequest_ne(struct thread *td, int type)
ktr_getrequest_entered(struct thread *td, int type)
{
struct ktr_request *req;
struct proc *p = td->td_proc;
@ -317,7 +316,7 @@ ktr_getrequest(int type)
struct ktr_request *req;
ktrace_enter(td);
req = ktr_getrequest_ne(td, type);
req = ktr_getrequest_entered(td, type);
if (req == NULL)
ktrace_exit(td);
@ -337,7 +336,6 @@ ktr_enqueuerequest(struct thread *td, struct ktr_request *req)
mtx_lock(&ktrace_mtx);
STAILQ_INSERT_TAIL(&td->td_proc->p_ktr, req, ktr_list);
mtx_unlock(&ktrace_mtx);
ktrace_exit(td);
}
/*
@ -377,7 +375,7 @@ ktr_drain(struct thread *td)
* been cached in the thread.
*/
static void
ktr_submitrequest_ne(struct thread *td, struct ktr_request *req)
ktr_submitrequest(struct thread *td, struct ktr_request *req)
{
ktrace_assert(td);
@ -387,14 +385,6 @@ ktr_submitrequest_ne(struct thread *td, struct ktr_request *req)
ktr_writerequest(td, req);
ktr_freerequest(req);
sx_xunlock(&ktrace_sx);
}
static void
ktr_submitrequest(struct thread *td, struct ktr_request *req)
{
ktrace_assert(td);
ktr_submitrequest_ne(td, req);
ktrace_exit(td);
}
@ -523,12 +513,12 @@ ktrprocexit(struct thread *td)
return;
ktrace_enter(td);
req = ktr_getrequest_entered(td, KTR_PROCDTOR);
if (req != NULL)
ktr_enqueuerequest(td, req);
sx_xlock(&ktrace_sx);
ktr_drain(td);
sx_xunlock(&ktrace_sx);
req = ktr_getrequest_ne(td, KTR_PROCDTOR);
if (req != NULL)
ktr_submitrequest_ne(td, req);
PROC_LOCK(p);
mtx_lock(&ktrace_mtx);
ktr_freeproc(p, &cred, &vp);
@ -545,21 +535,20 @@ ktrprocexit(struct thread *td)
}
static void
ktrprocctor_ne(struct thread *td, struct proc *p)
ktrprocctor_entered(struct thread *td, struct proc *p)
{
struct ktr_proc_ctor *ktp;
struct ktr_request *req;
struct thread *td2;
struct thread *td2;;
ktrace_assert(td);
td2 = FIRST_THREAD_IN_PROC(p);
req = ktr_getrequest_ne(td2, KTR_PROCCTOR);
req = ktr_getrequest_entered(td2, KTR_PROCCTOR);
if (req == NULL)
return;
ktp = &req->ktr_data.ktr_proc_ctor;
ktp->sv_flags = p->p_sysent->sv_flags;
ktr_submitrequest_ne(td, req);
ktr_enqueuerequest(td2, req);
}
void
@ -571,7 +560,7 @@ ktrprocctor(struct proc *p)
return;
ktrace_enter(td);
ktrprocctor_ne(td, p);
ktrprocctor_entered(td, p);
ktrace_exit(td);
}
@ -721,6 +710,7 @@ ktrpsig(sig, action, mask, code)
sigset_t *mask;
int code;
{
struct thread *td = curthread;
struct ktr_request *req;
struct ktr_psig *kp;
@ -732,13 +722,15 @@ ktrpsig(sig, action, mask, code)
kp->action = action;
kp->mask = *mask;
kp->code = code;
ktr_enqueuerequest(curthread, req);
ktr_enqueuerequest(td, req);
ktrace_exit(td);
}
void
ktrcsw(out, user)
int out, user;
{
struct thread *td = curthread;
struct ktr_request *req;
struct ktr_csw *kc;
@ -748,7 +740,8 @@ ktrcsw(out, user)
kc = &req->ktr_data.ktr_csw;
kc->out = out;
kc->user = user;
ktr_enqueuerequest(curthread, req);
ktr_enqueuerequest(td, req);
ktrace_exit(td);
}
void
@ -1021,6 +1014,8 @@ ktrops(td, p, ops, facs, vp)
ktr_freeproc(p, &tracecred, &tracevp);
}
mtx_unlock(&ktrace_mtx);
if ((p->p_traceflag & KTRFAC_MASK) != 0)
ktrprocctor_entered(td, p);
PROC_UNLOCK(p);
if (tracevp != NULL) {
int vfslocked;
@ -1032,9 +1027,6 @@ ktrops(td, p, ops, facs, vp)
if (tracecred != NULL)
crfree(tracecred);
if ((p->p_traceflag & KTRFAC_MASK) != 0)
ktrprocctor_ne(td, p);
return (1);
}