From 458bf05c8809c4e815fe1c53afb84eec1ec811a6 Mon Sep 17 00:00:00 2001 From: guenther Date: Mon, 2 Aug 2010 19:54:07 +0000 Subject: [PATCH] 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@ --- sys/kern/kern_event.c | 25 +++++++++++++++++++++++-- sys/kern/kern_exit.c | 6 +++--- sys/sys/event.h | 3 ++- 3 files changed, 28 insertions(+), 6 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 @@ -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 diff --git a/sys/sys/event.h b/sys/sys/event.h index c528d669e8f..89fa08b20f8 100644 --- a/sys/sys/event.h +++ b/sys/sys/event.h @@ -1,4 +1,4 @@ -/* $OpenBSD: event.h,v 1.14 2010/07/28 21:44:41 nicm Exp $ */ +/* $OpenBSD: event.h,v 1.15 2010/08/02 19:54:07 guenther Exp $ */ /*- * Copyright (c) 1999,2000,2001 Jonathan Lemon @@ -169,6 +169,7 @@ struct proc; extern void knote(struct klist *list, long hint); extern void knote_remove(struct proc *p, struct klist *list); extern void knote_fdclose(struct proc *p, int fd); +extern void knote_processexit(struct process *); extern int kqueue_register(struct kqueue *kq, struct kevent *kev, struct proc *p); extern int filt_seltrue(struct knote *kn, long hint); -- 2.20.1