Author: markj
Date: Wed Nov 28 18:06:16 2018
New Revision: 341159
URL: https://svnweb.freebsd.org/changeset/base/341159

Log:
  MFstable/12 r341082:
  Ensure that knotes do not get registered when KQ_CLOSING is set.
  
  PR:           228858
  Approved by:  re (gjb)

Modified:
  releng/12.0/sys/kern/kern_event.c
Directory Properties:
  releng/12.0/   (props changed)

Modified: releng/12.0/sys/kern/kern_event.c
==============================================================================
--- releng/12.0/sys/kern/kern_event.c   Wed Nov 28 18:02:59 2018        
(r341158)
+++ releng/12.0/sys/kern/kern_event.c   Wed Nov 28 18:06:16 2018        
(r341159)
@@ -1463,8 +1463,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);
 
@@ -1700,12 +1703,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;
@@ -1717,9 +1720,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,
@@ -1740,9 +1745,12 @@ kqueue_expand(struct kqueue *kq, struct filterops *fop
                        tmp_knhash = hashinit(KN_HASHSIZE, M_KQUEUE,
                            &tmp_knhashmask);
                        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 {
@@ -1754,7 +1762,7 @@ kqueue_expand(struct kqueue *kq, struct filterops *fop
        free(to_free, M_KQUEUE);
 
        KQ_NOTOWNED(kq);
-       return 0;
+       return (error);
 }
 
 static void
@@ -2605,6 +2613,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);
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to