diff options
author | Philip Guenthe <guenther@cvs.openbsd.org> | 2010-08-02 19:54:08 +0000 |
---|---|---|
committer | Philip Guenthe <guenther@cvs.openbsd.org> | 2010-08-02 19:54:08 +0000 |
commit | a625e136b7a7dffe00dec15e6a7e483df3fd33be (patch) | |
tree | 3c907bffd1eac9154218208e7c253ffddf50e85f /sys/kern | |
parent | d5946e6e400083e7d659a2e414a328cd2582df92 (diff) |
Fix knote handling for exiting processes: when triggering a NOTE_EXIT
knote, remove it from the process's klist; after handling those,
remove and drop any remaining knotes from the process's klist. Ban
attaching knotes to processes that have started exiting or attaching
them via the pid of a thread other than the main thread.
ok tedu@, deraadt@
Diffstat (limited to 'sys/kern')
-rw-r--r-- | sys/kern/kern_event.c | 25 | ||||
-rw-r--r-- | sys/kern/kern_exit.c | 6 |
2 files changed, 26 insertions, 5 deletions
diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c index 6538129fa1f..19c250de2fc 100644 --- a/sys/kern/kern_event.c +++ b/sys/kern/kern_event.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_event.c,v 1.37 2010/07/28 21:44:41 nicm Exp $ */ +/* $OpenBSD: kern_event.c,v 1.38 2010/08/02 19:54:07 guenther Exp $ */ /*- * Copyright (c) 1999,2000,2001 Jonathan Lemon <jlemon@FreeBSD.org> @@ -198,6 +198,10 @@ filt_procattach(struct knote *kn) if (p == NULL) return (ESRCH); + /* threads and exiting processes can't be specified */ + if (p->p_flag & (P_THREAD|P_WEXIT)) + return (ESRCH); + /* * Fail if it's not owned by you, or the last exec gave us * setuid/setgid privs (unless you're root). @@ -262,11 +266,15 @@ filt_proc(struct knote *kn, long hint) kn->kn_fflags |= event; /* - * process is gone, so flag the event as finished. + * process is gone, so flag the event as finished and remove it + * from the process's klist */ if (event == NOTE_EXIT) { + struct process *pr = kn->kn_ptr.p_proc->p_p; + kn->kn_status |= KN_DETACHED; kn->kn_flags |= (EV_EOF | EV_ONESHOT); + SLIST_REMOVE(&pr->ps_klist, kn, knote, kn_selnext); return (1); } @@ -938,6 +946,19 @@ knote_fdclose(struct proc *p, int fd) knote_remove(p, list); } +/* + * handle a process exiting, including the triggering of NOTE_EXIT notes + * XXX this could be more efficient, doing a single pass down the klist + */ +void +knote_processexit(struct process *pr) +{ + KNOTE(&pr->ps_klist, NOTE_EXIT); + + /* remove other knotes hanging off the process */ + knote_remove(pr->ps_mainproc, &pr->ps_klist); +} + void knote_attach(struct knote *kn, struct filedesc *fdp) { diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c index 3302bc6eb00..792f8391340 100644 --- a/sys/kern/kern_exit.c +++ b/sys/kern/kern_exit.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_exit.c,v 1.96 2010/07/26 01:56:27 guenther Exp $ */ +/* $OpenBSD: kern_exit.c,v 1.97 2010/08/02 19:54:07 guenther Exp $ */ /* $NetBSD: kern_exit.c,v 1.39 1996/04/22 01:38:25 christos Exp $ */ /* @@ -298,8 +298,8 @@ exit1(struct proc *p, int rv, int flags) p->p_pctcpu = 0; if ((p->p_flag & P_THREAD) == 0) { - /* notify interested parties of our demise */ - KNOTE(&pr->ps_klist, NOTE_EXIT); + /* notify interested parties of our demise and clean up */ + knote_processexit(pr); /* * Notify parent that we're gone. If we have P_NOZOMBIE |