Module Name:    src
Committed By:   jdc
Date:           Sat Nov 24 21:40:03 UTC 2012

Modified Files:
        src/lib/libc/sys [netbsd-6]: kqueue.2
        src/sys/kern [netbsd-6]: kern_descrip.c kern_event.c
        src/tests/lib/libc/sys [netbsd-6]: t_kevent.c

Log Message:
Pull up revisions:
  src/sys/kern/kern_event.c revision 1.79
  src/sys/kern/kern_descrip.c revision 1.219
  src/lib/libc/sys/kqueue.2 revision 1.33
  src/tests/lib/libc/sys/t_kevent.c revision 1.2-1.5
(requested by christos in ticket #716).

- initialize kn_id
- in close, invalidate f_data and f_type early to prevent accidental re-use
- add a DIAGNOSTIC for when we use unsupported fd's and a KASSERT for f_event
  being NULL.

Return EOPNOTSUPP for fnullop_kqfilter to prevent registration of unsupported
fds. XXX: We should really fix the fd's to be supported in the future.
Unsupported fd's have a NULL f_event, so registering crashes the kernel with
a NULL function dereference of f_event.

mention that kevent returns now EOPNOTSUPP.

Move the references to PRs from code comments to the test description. Once
ATF has the ability to output the metadata in the HTML reports, it should be
easy to traverse between releng and gnats -reports via links.

Add a (skipped for now) test case for PR 46463

adapt to new reality

Add a test for adding an event to an unsupported fd.


To generate a diff of this commit:
cvs rdiff -u -r1.32 -r1.32.2.1 src/lib/libc/sys/kqueue.2
cvs rdiff -u -r1.218 -r1.218.2.1 src/sys/kern/kern_descrip.c
cvs rdiff -u -r1.75 -r1.75.2.1 src/sys/kern/kern_event.c
cvs rdiff -u -r1.1 -r1.1.2.1 src/tests/lib/libc/sys/t_kevent.c

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

Modified files:

Index: src/lib/libc/sys/kqueue.2
diff -u src/lib/libc/sys/kqueue.2:1.32 src/lib/libc/sys/kqueue.2:1.32.2.1
--- src/lib/libc/sys/kqueue.2:1.32	Wed Jan 25 00:28:35 2012
+++ src/lib/libc/sys/kqueue.2	Sat Nov 24 21:40:03 2012
@@ -1,4 +1,4 @@
-.\"	$NetBSD: kqueue.2,v 1.32 2012/01/25 00:28:35 christos Exp $
+.\"	$NetBSD: kqueue.2,v 1.32.2.1 2012/11/24 21:40:03 jdc Exp $
 .\"
 .\" Copyright (c) 2000 Jonathan Lemon
 .\" All rights reserved.
@@ -32,7 +32,7 @@
 .\"
 .\" $FreeBSD: src/lib/libc/sys/kqueue.2,v 1.22 2001/06/27 19:55:57 dd Exp $
 .\"
-.Dd January 23, 2012
+.Dd November 24, 2012
 .Dt KQUEUE 2
 .Os
 .Sh NAME
@@ -604,6 +604,10 @@ The specified time limit or filter is in
 The event could not be found to be modified or deleted.
 .It Bq Er ENOMEM
 No memory was available to register the event.
+.It Bq Er EOPNOTSUPP
+This type of file descriptor is not supported for
+.Fn kevent
+operations.
 .It Bq Er ESRCH
 The specified process to attach to does not exist.
 .El

Index: src/sys/kern/kern_descrip.c
diff -u src/sys/kern/kern_descrip.c:1.218 src/sys/kern/kern_descrip.c:1.218.2.1
--- src/sys/kern/kern_descrip.c:1.218	Wed Jan 25 00:28:35 2012
+++ src/sys/kern/kern_descrip.c	Sat Nov 24 21:40:02 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: kern_descrip.c,v 1.218 2012/01/25 00:28:35 christos Exp $	*/
+/*	$NetBSD: kern_descrip.c,v 1.218.2.1 2012/11/24 21:40:02 jdc Exp $	*/
 
 /*-
  * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
@@ -70,7 +70,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_descrip.c,v 1.218 2012/01/25 00:28:35 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_descrip.c,v 1.218.2.1 2012/11/24 21:40:02 jdc Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -1885,7 +1885,7 @@ int
 fnullop_kqfilter(file_t *fp, struct knote *kn)
 {
 
-	return 0;
+	return EOPNOTSUPP;
 }
 
 void

Index: src/sys/kern/kern_event.c
diff -u src/sys/kern/kern_event.c:1.75 src/sys/kern/kern_event.c:1.75.2.1
--- src/sys/kern/kern_event.c:1.75	Wed Jan 25 00:28:35 2012
+++ src/sys/kern/kern_event.c	Sat Nov 24 21:40:02 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: kern_event.c,v 1.75 2012/01/25 00:28:35 christos Exp $	*/
+/*	$NetBSD: kern_event.c,v 1.75.2.1 2012/11/24 21:40:02 jdc 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.75 2012/01/25 00:28:35 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_event.c,v 1.75.2.1 2012/11/24 21:40:02 jdc Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -961,6 +961,7 @@ kqueue_register(struct kqueue *kq, struc
 			kn = newkn;
 			newkn = NULL;
 			kn->kn_obj = fp;
+			kn->kn_id = kev->ident;
 			kn->kn_kq = kq;
 			kn->kn_fop = kfilter->filtops;
 			kn->kn_kfilter = kfilter;
@@ -1002,6 +1003,10 @@ kqueue_register(struct kqueue *kq, struc
 			error = (*kfilter->filtops->f_attach)(kn);
 			KERNEL_UNLOCK_ONE(NULL);	/* XXXSMP */
 			if (error != 0) {
+#ifdef DIAGNOSTIC
+				printf("%s: event not supported for file type"
+				    " %d\n", __func__, fp ? fp->f_type : -1);
+#endif
 				/* knote_detach() drops fdp->fd_lock */
 				knote_detach(kn, fdp, false);
 				goto done;
@@ -1017,6 +1022,13 @@ kqueue_register(struct kqueue *kq, struc
 			kn->kn_sdata = kev->data;
 			kn->kn_kevent.udata = kev->udata;
 		}
+		/*
+		 * We can get here if we are trying to attach
+		 * an event to a file descriptor that does not
+		 * support events, and the attach routine is
+		 * broken and does not return an error.
+		 */
+		KASSERT(kn->kn_fop->f_event != NULL);
 		KERNEL_LOCK(1, NULL);			/* XXXSMP */
 		rv = (*kn->kn_fop->f_event)(kn, 0);
 		KERNEL_UNLOCK_ONE(NULL);		/* XXXSMP */
@@ -1421,6 +1433,8 @@ kqueue_close(file_t *fp)
 	int i;
 
 	kq = fp->f_data;
+	fp->f_data = NULL;
+	fp->f_type = 0;
 	fdp = curlwp->l_fd;
 
 	mutex_enter(&fdp->fd_lock);
@@ -1441,7 +1455,6 @@ kqueue_close(file_t *fp)
 	cv_destroy(&kq->kq_cv);
 	seldestroy(&kq->kq_sel);
 	kmem_free(kq, sizeof(*kq));
-	fp->f_data = NULL;
 
 	return (0);
 }

Index: src/tests/lib/libc/sys/t_kevent.c
diff -u src/tests/lib/libc/sys/t_kevent.c:1.1 src/tests/lib/libc/sys/t_kevent.c:1.1.2.1
--- src/tests/lib/libc/sys/t_kevent.c:1.1	Thu Nov 17 01:14:12 2011
+++ src/tests/lib/libc/sys/t_kevent.c	Sat Nov 24 21:40:03 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: t_kevent.c,v 1.1 2011/11/17 01:14:12 christos Exp $ */
+/*	$NetBSD: t_kevent.c,v 1.1.2.1 2012/11/24 21:40:03 jdc Exp $ */
 
 /*-
  * Copyright (c) 2011 The NetBSD Foundation, Inc.
@@ -29,40 +29,149 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: t_kevent.c,v 1.1 2011/11/17 01:14:12 christos Exp $");
-
-#include <time.h>
-#include <stdio.h>
+__RCSID("$NetBSD: t_kevent.c,v 1.1.2.1 2012/11/24 21:40:03 jdc Exp $");
 
 #include <sys/types.h>
 #include <sys/event.h>
 
 #include <atf-c.h>
+#include <errno.h>
+#include <time.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <err.h>
+#include <sys/event.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <sys/wait.h>
 
 ATF_TC(kevent_zerotimer);
 ATF_TC_HEAD(kevent_zerotimer, tc)
 {
-
-	/* Cf. PR lib/45618. */
 	atf_tc_set_md_var(tc, "descr", "Checks that kevent with a 0 timer "
-	    "does not crash the system");
+	    "does not crash the system (PR lib/45618)");
 }
 
 ATF_TC_BODY(kevent_zerotimer, tc)
 {
 	struct kevent ev;
 	int kq;
-	
+
 	ATF_REQUIRE((kq = kqueue()) != -1);
 	EV_SET(&ev, 1, EVFILT_TIMER, EV_ADD|EV_ENABLE, 0, 1, 0);
 	ATF_REQUIRE(kevent(kq, &ev, 1, NULL, 0, NULL) != -1);
 	ATF_REQUIRE(kevent(kq, NULL, 0, &ev, 1, NULL) == 1);
 }
 
+ATF_TC(kqueue_desc_passing);
+ATF_TC_HEAD(kqueue_desc_passing, tc)
+{
+	atf_tc_set_md_var(tc, "descr", "Checks that passing a kqueue to "
+		"another process does not crash the kernel (PR 46463)");
+}
+
+ATF_TC_BODY(kqueue_desc_passing, tc)
+{
+	pid_t child;
+	int s[2], storage, status, kq;
+	struct cmsghdr *msg;
+	struct iovec iov;
+	struct msghdr m;
+	struct kevent ev;
+
+	ATF_REQUIRE((kq = kqueue()) != -1);
+
+	// atf_tc_skip("crashes kernel (PR 46463)");
+
+	ATF_REQUIRE(socketpair(AF_LOCAL, SOCK_STREAM, 0, s) != -1);
+	msg = malloc(CMSG_SPACE(sizeof(int)));
+	m.msg_iov = &iov;
+	m.msg_iovlen = 1;
+	m.msg_name = NULL;
+	m.msg_namelen = 0;
+	m.msg_control = msg;
+	m.msg_controllen = CMSG_SPACE(sizeof(int));
+
+	child = fork();
+	if (child == 0) {
+		close(s[0]);
+
+		iov.iov_base = &storage;
+		iov.iov_len = sizeof(int);
+		m.msg_iov = &iov;
+		m.msg_iovlen = 1;
+
+		if (recvmsg(s[1], &m, 0) == -1)
+			err(1, "child: could not recvmsg");
+
+		kq = *(int *)CMSG_DATA(msg);
+		printf("child (pid %d): received kq fd %d\n", getpid(), kq);
+		exit(0);
+	}
+
+	close(s[1]);
+
+	iov.iov_base = &storage;
+	iov.iov_len = sizeof(int);
+
+	msg->cmsg_level = SOL_SOCKET;
+	msg->cmsg_type = SCM_RIGHTS;
+	msg->cmsg_len = CMSG_LEN(sizeof(int));
+
+	*(int *)CMSG_DATA(msg) = kq;
+
+	EV_SET(&ev, 1, EVFILT_TIMER, EV_ADD|EV_ENABLE, 0, 1, 0);
+	ATF_CHECK(kevent(kq, &ev, 1, NULL, 0, NULL) != -1);
+
+	printf("parent (pid %d): sending kq fd %d\n", getpid(), kq);
+	if (sendmsg(s[0], &m, 0) == -1) {
+		ATF_REQUIRE_EQ_MSG(errno, EBADF, "errno is %d", errno);
+		atf_tc_skip("PR kern/46523");
+	}
+
+	close(kq);
+
+	waitpid(child, &status, 0);
+	ATF_CHECK(WIFEXITED(status) && WEXITSTATUS(status)==0);
+}
+
+ATF_TC(kqueue_unsupported_fd);
+ATF_TC_HEAD(kqueue_unsupported_fd, tc)
+{
+	atf_tc_set_md_var(tc, "descr", "Checks that watching an fd whose"
+	    " type is not supported does not crash the kernel");
+}
+
+ATF_TC_BODY(kqueue_unsupported_fd, tc)
+{
+	/* mqueue and semaphore use fnullop_kqueue also */
+	static const char drvctl[] = "/dev/drvctl";
+	int fd, kq;
+	struct kevent ev;
+
+	ATF_REQUIRE((fd = open(drvctl, O_RDONLY)) != -1);
+	ATF_REQUIRE((kq = kqueue()) != -1);
+
+	EV_SET(&ev, fd, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_CLEAR,
+	   NOTE_DELETE|NOTE_WRITE|NOTE_EXTEND|NOTE_ATTRIB|NOTE_LINK|
+	   NOTE_RENAME|NOTE_REVOKE, 0, 0);
+
+	ATF_REQUIRE(kevent(kq, &ev, 1, NULL, 0, NULL) == -1);
+	ATF_REQUIRE_ERRNO(EOPNOTSUPP, true);
+
+	(void)close(fd);
+}
+
+
 ATF_TP_ADD_TCS(tp)
 {
 
 	ATF_TP_ADD_TC(tp, kevent_zerotimer);
+	ATF_TP_ADD_TC(tp, kqueue_desc_passing);
+	ATF_TP_ADD_TC(tp, kqueue_unsupported_fd);
 
 	return atf_no_error();
 }

Reply via email to