Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys fix file descriptor locking (from joerg).



details:   https://anonhg.NetBSD.org/src/rev/ff03c2da2900
branches:  trunk
changeset: 825152:ff03c2da2900
user:      christos <christos%NetBSD.org@localhost>
date:      Sat Jul 01 20:08:56 2017 +0000

description:
fix file descriptor locking (from joerg).
fixes kernel crashes by running go
XXX: pullup-7

diffstat:

 sys/kern/kern_event.c |  31 +++++++++++++++++++++++--------
 sys/sys/event.h       |  13 +++++++------
 2 files changed, 30 insertions(+), 14 deletions(-)

diffs (138 lines):

diff -r b45517758a3c -r ff03c2da2900 sys/kern/kern_event.c
--- a/sys/kern/kern_event.c     Sat Jul 01 20:07:00 2017 +0000
+++ b/sys/kern/kern_event.c     Sat Jul 01 20:08:56 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: kern_event.c,v 1.91 2017/05/11 23:50:17 christos Exp $ */
+/*     $NetBSD: kern_event.c,v 1.92 2017/07/01 20:08:56 christos Exp $ */
 
 /*-
  * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
@@ -58,7 +58,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_event.c,v 1.91 2017/05/11 23:50:17 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_event.c,v 1.92 2017/07/01 20:08:56 christos Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -1021,8 +1021,9 @@
                        if (error != 0) {
 #ifdef DIAGNOSTIC
                                
-                               printf("%s: event not supported for file type"
-                                   " %d (error %d)\n", __func__, kn->kn_obj ?
+                               printf("%s: event type %d not supported for "
+                                   "file type %d (error %d)\n", __func__,
+                                   kn->kn_filter, kn->kn_obj ?
                                    ((file_t *)kn->kn_obj)->f_type : -1, error);
 #endif
                                /* knote_detach() drops fdp->fd_lock */
@@ -1204,10 +1205,19 @@
                                        error = 0;
                        }
                }
+               mutex_spin_exit(&kq->kq_lock);
        } else {
                /* mark end of knote list */
                TAILQ_INSERT_TAIL(&kq->kq_head, marker, kn_tqe);
 
+               /*
+                * Acquire the fdp->fd_lock interlock to avoid races with
+                * file creation/destruction from other threads.
+                */
+               mutex_spin_exit(&kq->kq_lock);
+               mutex_enter(&fdp->fd_lock);
+               mutex_spin_enter(&kq->kq_lock);
+
                while (count != 0) {
                        kn = TAILQ_FIRST(&kq->kq_head); /* get next knote */
                        while ((kn->kn_status & KN_MARKER) != 0) {
@@ -1218,6 +1228,7 @@
                                            (timeout = gettimeleft(&ats,
                                            &sleepts)) <= 0))
                                                goto done;
+                                       mutex_exit(&fdp->fd_lock);
                                        goto retry;
                                }
                                /* someone else's marker. */
@@ -1239,6 +1250,7 @@
                                KASSERT(kn->kn_fop != NULL);
                                KASSERT(kn->kn_fop->f_event != NULL);
                                KERNEL_LOCK(1, NULL);           /* XXXSMP */
+                               KASSERT(mutex_owned(&fdp->fd_lock));
                                rv = (*kn->kn_fop->f_event)(kn, 0);
                                KERNEL_UNLOCK_ONE(NULL);        /* XXXSMP */
                                mutex_spin_enter(&kq->kq_lock);
@@ -1261,10 +1273,10 @@
                        nkev++;
                        if (kn->kn_flags & EV_ONESHOT) {
                                /* delete ONESHOT events after retrieval */
+                               kn->kn_status &= ~KN_BUSY;
                                mutex_spin_exit(&kq->kq_lock);
+                               knote_detach(kn, fdp, true);
                                mutex_enter(&fdp->fd_lock);
-                               kn->kn_status &= ~KN_BUSY;
-                               knote_detach(kn, fdp, true);
                                mutex_spin_enter(&kq->kq_lock);
                        } else if (kn->kn_flags & EV_CLEAR) {
                                /* clear state after retrieval */
@@ -1286,9 +1298,11 @@
                        if (nkev == kevcnt) {
                                /* do copyouts in kevcnt chunks */
                                mutex_spin_exit(&kq->kq_lock);
+                               mutex_exit(&fdp->fd_lock);
                                error = (*keops->keo_put_events)
                                    (keops->keo_private,
                                    kevbuf, ulistp, nevents, nkev);
+                               mutex_enter(&fdp->fd_lock);
                                mutex_spin_enter(&kq->kq_lock);
                                nevents += nkev;
                                nkev = 0;
@@ -1301,9 +1315,10 @@
                                break;
                        }
                }
+ done:
+               mutex_spin_exit(&kq->kq_lock);
+               mutex_exit(&fdp->fd_lock);
        }
- done:
-       mutex_spin_exit(&kq->kq_lock);
        if (nkev != 0) {
                /* copyout remaining events */
                error = (*keops->keo_put_events)(keops->keo_private,
diff -r b45517758a3c -r ff03c2da2900 sys/sys/event.h
--- a/sys/sys/event.h   Sat Jul 01 20:07:00 2017 +0000
+++ b/sys/sys/event.h   Sat Jul 01 20:08:56 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: event.h,v 1.29 2017/06/14 16:37:05 christos Exp $      */
+/*     $NetBSD: event.h,v 1.30 2017/07/01 20:08:56 christos Exp $      */
 
 /*-
  * Copyright (c) 1999,2000,2001 Jonathan Lemon <jlemon%FreeBSD.org@localhost>
@@ -188,10 +188,10 @@
        TAILQ_ENTRY(knote)      kn_tqe;         /* q: for struct kqueue */
        struct kqueue           *kn_kq;         /* q: which queue we are on */
        struct kevent           kn_kevent;
-       uint32_t                kn_status;
-       uint32_t                kn_sfflags;     /*   saved filter flags */
-       uintptr_t               kn_sdata;       /*   saved data field */
-       void                    *kn_obj;        /*   pointer to monitored obj */
+       uint32_t                kn_status;      /* q: flags below */
+       uint32_t                kn_sfflags;     /*    saved filter flags */
+       uintptr_t               kn_sdata;       /*    saved data field */
+       void                    *kn_obj;        /*    monitored obj */
        const struct filterops  *kn_fop;
        struct kfilter          *kn_kfilter;
        void                    *kn_hook;
@@ -201,7 +201,8 @@
 #define        KN_DISABLED     0x04U                   /* event is disabled */
 #define        KN_DETACHED     0x08U                   /* knote is detached */
 #define        KN_MARKER       0x10U                   /* is a marker */
-#define KN_BUSY                0x20U                   /* is being scanned */
+#define        KN_BUSY         0x20U                   /* is being scanned */
+/* Toggling KN_BUSY also requires kn_kq->kq_fdp->fd_lock. */
 
 #define        kn_id           kn_kevent.ident
 #define        kn_filter       kn_kevent.filter



Home | Main Index | Thread Index | Old Index