Date: Sat, 24 Nov 2018 16:58:34 +0000 (UTC) From: Mark Johnston <markj@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r340898 - head/sys/kern Message-ID: <201811241658.wAOGwYdY002451@repo.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: markj Date: Sat Nov 24 16:58:34 2018 New Revision: 340898 URL: https://svnweb.freebsd.org/changeset/base/340898 Log: Ensure that knotes do not get registered when KQ_CLOSING is set. KQ_CLOSING is set before draining the knotes associated with a kqueue, so we must ensure that new knotes are not added after that point. In particular, some kernel facilities may register for events on behalf of a userspace process and race with a close of the kqueue. PR: 228858 Reviewed by: kib Tested by: pho MFC after: 3 days Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D18316 Modified: head/sys/kern/kern_event.c Modified: head/sys/kern/kern_event.c ============================================================================== --- head/sys/kern/kern_event.c Sat Nov 24 16:41:29 2018 (r340897) +++ head/sys/kern/kern_event.c Sat Nov 24 16:58:34 2018 (r340898) @@ -1460,8 +1460,11 @@ findkn: break; } } else { - if ((kev->flags & EV_ADD) == EV_ADD) - kqueue_expand(kq, fops, kev->ident, waitok); + if ((kev->flags & EV_ADD) == EV_ADD) { + error = kqueue_expand(kq, fops, kev->ident, waitok); + if (error != 0) + goto done; + } KQ_LOCK(kq); @@ -1693,12 +1696,12 @@ kqueue_expand(struct kqueue *kq, struct filterops *fop { struct klist *list, *tmp_knhash, *to_free; u_long tmp_knhashmask; - int size; - int fd; + int error, fd, size; int mflag = waitok ? M_WAITOK : M_NOWAIT; KQ_NOTOWNED(kq); + error = 0; to_free = NULL; if (fops->f_isfd) { fd = ident; @@ -1710,9 +1713,11 @@ kqueue_expand(struct kqueue *kq, struct filterops *fop if (list == NULL) return ENOMEM; KQ_LOCK(kq); - if (kq->kq_knlistsize > fd) { + if ((kq->kq_state & KQ_CLOSING) != 0) { to_free = list; - list = NULL; + error = EBADF; + } else if (kq->kq_knlistsize > fd) { + to_free = list; } else { if (kq->kq_knlist != NULL) { bcopy(kq->kq_knlist, list, @@ -1734,9 +1739,12 @@ kqueue_expand(struct kqueue *kq, struct filterops *fop &tmp_knhashmask, waitok ? HASH_WAITOK : HASH_NOWAIT); if (tmp_knhash == NULL) - return ENOMEM; + return (ENOMEM); KQ_LOCK(kq); - if (kq->kq_knhashmask == 0) { + if ((kq->kq_state & KQ_CLOSING) != 0) { + to_free = tmp_knhash; + error = EBADF; + } else if (kq->kq_knhashmask == 0) { kq->kq_knhash = tmp_knhash; kq->kq_knhashmask = tmp_knhashmask; } else { @@ -1748,7 +1756,7 @@ kqueue_expand(struct kqueue *kq, struct filterops *fop free(to_free, M_KQUEUE); KQ_NOTOWNED(kq); - return 0; + return (error); } static void @@ -2597,6 +2605,8 @@ knote_attach(struct knote *kn, struct kqueue *kq) KASSERT(kn_in_flux(kn), ("knote %p not marked influx", kn)); KQ_OWNED(kq); + if ((kq->kq_state & KQ_CLOSING) != 0) + return (EBADF); if (kn->kn_fop->f_isfd) { if (kn->kn_id >= kq->kq_knlistsize) return (ENOMEM);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201811241658.wAOGwYdY002451>