summaryrefslogtreecommitdiffstats
path: root/sys/kern/kern_exit.c
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2016-06-27 21:52:17 +0000
committerkib <kib@FreeBSD.org>2016-06-27 21:52:17 +0000
commit15841a7afef498342a9cd565c145086ccf28d9f9 (patch)
tree1f2b0dc7608da9e7ac3822cc576909c7e7a41ff5 /sys/kern/kern_exit.c
parent05dea908a0038cf030676684bfb2e147aa42ae10 (diff)
downloadFreeBSD-src-15841a7afef498342a9cd565c145086ccf28d9f9.zip
FreeBSD-src-15841a7afef498342a9cd565c145086ccf28d9f9.tar.gz
When filt_proc() removes event from the knlist due to the process
exiting (NOTE_EXIT->knlist_remove_inevent()), two things happen: - knote kn_knlist pointer is reset - INFLUX knote is removed from the process knlist. And, there are two consequences: - KN_LIST_UNLOCK() on such knote is nop - there is nothing which would block exit1() from processing past the knlist_destroy() (and knlist_destroy() resets knlist lock pointers). Both consequences result either in leaked process lock, or dereferencing NULL function pointers for locking. Handle this by stopping embedding the process knlist into struct proc. Instead, the knlist is allocated together with struct proc, but marked as autodestroy on the zombie reap, by knlist_detach() function. The knlist is freed when last kevent is removed from the list, in particular, at the zombie reap time if the list is empty. As result, the knlist_remove_inevent() is no longer needed and removed. Other changes: In filt_procattach(), clear NOTE_EXEC and NOTE_FORK desired events from kn_sfflags for knote registered by kernel to only get NOTE_CHILD notifications. The flags leak resulted in excessive NOTE_EXEC/NOTE_FORK reports. Fix immediate note activation in filt_procattach(). Condition should be either the immediate CHILD_NOTE activation, or immediate NOTE_EXIT report for the exiting process. In knote_fork(), do not perform racy check for KN_INFLUX before kq lock is taken. Besides being racy, it did not accounted for notes just added by scan (KN_SCAN). Some minor and incomplete style fixes. Analyzed and tested by: Eric Badger <eric@badgerio.us> Reviewed by: jhb Sponsored by: The FreeBSD Foundation MFC after: 2 weeks Approved by: re (gjb) Differential revision: https://reviews.freebsd.org/D6859
Diffstat (limited to 'sys/kern/kern_exit.c')
-rw-r--r--sys/kern/kern_exit.c20
1 files changed, 6 insertions, 14 deletions
diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c
index 0a0659d..7b73236 100644
--- a/sys/kern/kern_exit.c
+++ b/sys/kern/kern_exit.c
@@ -512,7 +512,7 @@ exit1(struct thread *td, int rval, int signo)
/*
* Notify interested parties of our demise.
*/
- KNOTE_LOCKED(&p->p_klist, NOTE_EXIT);
+ KNOTE_LOCKED(p->p_klist, NOTE_EXIT);
#ifdef KDTRACE_HOOKS
int reason = CLD_EXITED;
@@ -524,13 +524,6 @@ exit1(struct thread *td, int rval, int signo)
#endif
/*
- * Just delete all entries in the p_klist. At this point we won't
- * report any more events, and there are nasty race conditions that
- * can beat us if we don't.
- */
- knlist_clear(&p->p_klist, 1);
-
- /*
* If this is a process with a descriptor, we may not need to deliver
* a signal to the parent. proctree_lock is held over
* procdesc_exit() to serialize concurrent calls to close() and
@@ -603,12 +596,6 @@ exit1(struct thread *td, int rval, int signo)
PROC_UNLOCK(p->p_pptr);
/*
- * Hopefully no one will try to deliver a signal to the process this
- * late in the game.
- */
- knlist_destroy(&p->p_klist);
-
- /*
* Save our children's rusage information in our exit rusage.
*/
PROC_STATLOCK(p);
@@ -853,6 +840,11 @@ proc_reap(struct thread *td, struct proc *p, int *status, int options)
procdesc_reap(p);
sx_xunlock(&proctree_lock);
+ PROC_LOCK(p);
+ knlist_detach(p->p_klist);
+ p->p_klist = NULL;
+ PROC_UNLOCK(p);
+
/*
* Removal from allproc list and process group list paired with
* PROC_LOCK which was executed during that time should guarantee
OpenPOWER on IntegriCloud