Module Name:    src
Committed By:   christos
Date:           Thu Aug 24 19:51:24 UTC 2023

Modified Files:
        src/sys/compat/linux/common: linux_inotify.c

Log Message:
fix a locking bug (Theodore Preduta)


To generate a diff of this commit:
cvs rdiff -u -r1.4 -r1.5 src/sys/compat/linux/common/linux_inotify.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/compat/linux/common/linux_inotify.c
diff -u src/sys/compat/linux/common/linux_inotify.c:1.4 src/sys/compat/linux/common/linux_inotify.c:1.5
--- src/sys/compat/linux/common/linux_inotify.c:1.4	Wed Aug 23 15:17:59 2023
+++ src/sys/compat/linux/common/linux_inotify.c	Thu Aug 24 15:51:24 2023
@@ -1,4 +1,4 @@
-/*	$NetBSD: linux_inotify.c,v 1.4 2023/08/23 19:17:59 christos Exp $	*/
+/*	$NetBSD: linux_inotify.c,v 1.5 2023/08/24 19:51:24 christos Exp $	*/
 
 /*-
  * Copyright (c) 2023 The NetBSD Foundation, Inc.
@@ -29,7 +29,7 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: linux_inotify.c,v 1.4 2023/08/23 19:17:59 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: linux_inotify.c,v 1.5 2023/08/24 19:51:24 christos Exp $");
 
 #include <sys/param.h>
 #include <sys/types.h>
@@ -790,9 +790,18 @@ inotify_readdir(file_t *fp, struct diren
 	/* XXX: should pass whether to lock or not */
 	if (needs_lock)
 		vn_lock(vp, LK_SHARED | LK_RETRY);
+	else
+		/*
+		 * XXX We need to temprarily drop v_interlock because
+		 * it may be temporarily acquired by biowait().
+		 */
+		mutex_exit(vp->v_interlock);
+	KASSERT(!mutex_owned(vp->v_interlock));
 	error = VOP_READDIR(vp, &uio, fp->f_cred, &eofflag, NULL, NULL);
 	if (needs_lock)
 		VOP_UNLOCK(vp);
+	else
+		mutex_enter(vp->v_interlock);
 
 	mutex_enter(&fp->f_lock);
 	fp->f_offset = uio.uio_offset;
@@ -1107,7 +1116,7 @@ inotify_filt_event(struct knote *kn, lon
 		cv_signal(&ifd->ifd_qcv);
 
 		mutex_enter(&ifd->ifd_lock);
-		selnotify(&ifd->ifd_sel, 0, 0);
+		selnotify(&ifd->ifd_sel, 0, NOTE_LOWAT);
 		mutex_exit(&ifd->ifd_lock);
 	} else
 		DPRINTF(("%s: hint=%lx resulted in 0 inotify events\n",
@@ -1295,14 +1304,17 @@ inotify_read_filt_detach(struct knote *k
 static int
 inotify_read_filt_event(struct knote *kn, long hint)
 {
-	int rv;
 	struct inotifyfd *ifd = ((file_t *)kn->kn_obj)->f_data;
 
-	mutex_enter(&ifd->ifd_qlock);
-	rv = (ifd->ifd_qcount > 0);
-	mutex_exit(&ifd->ifd_qlock);
+	if (hint != 0) {
+		KASSERT(mutex_owned(&ifd->ifd_lock));
+		KASSERT(mutex_owned(&ifd->ifd_qlock));
+		KASSERT(hint == NOTE_LOWAT);
+
+		kn->kn_data = ifd->ifd_qcount;
+	}
 
-	return rv;
+	return kn->kn_data > 0;
 }
 
 /*

Reply via email to