Source-Changes-HG archive

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

[src/netbsd-6]: src Pull up revisions:



details:   https://anonhg.NetBSD.org/src/rev/a302f44e98da
branches:  netbsd-6
changeset: 775532:a302f44e98da
user:      jdc <jdc%NetBSD.org@localhost>
date:      Sat Nov 24 21:40:02 2012 +0000

description:
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.

diffstat:

 lib/libc/sys/kqueue.2         |    8 +-
 sys/kern/kern_descrip.c       |    6 +-
 sys/kern/kern_event.c         |   19 +++++-
 tests/lib/libc/sys/t_kevent.c |  127 +++++++++++++++++++++++++++++++++++++++--
 4 files changed, 143 insertions(+), 17 deletions(-)

diffs (291 lines):

diff -r cfcd9efd0120 -r a302f44e98da lib/libc/sys/kqueue.2
--- a/lib/libc/sys/kqueue.2     Sat Nov 24 21:08:46 2012 +0000
+++ b/lib/libc/sys/kqueue.2     Sat Nov 24 21:40:02 2012 +0000
@@ -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 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
diff -r cfcd9efd0120 -r a302f44e98da sys/kern/kern_descrip.c
--- a/sys/kern/kern_descrip.c   Sat Nov 24 21:08:46 2012 +0000
+++ b/sys/kern/kern_descrip.c   Sat Nov 24 21:40:02 2012 +0000
@@ -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 @@
 fnullop_kqfilter(file_t *fp, struct knote *kn)
 {
 
-       return 0;
+       return EOPNOTSUPP;
 }
 
 void
diff -r cfcd9efd0120 -r a302f44e98da sys/kern/kern_event.c
--- a/sys/kern/kern_event.c     Sat Nov 24 21:08:46 2012 +0000
+++ b/sys/kern/kern_event.c     Sat Nov 24 21:40:02 2012 +0000
@@ -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 @@
                        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 @@
                        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 @@
                        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 @@
        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 @@
        cv_destroy(&kq->kq_cv);
        seldestroy(&kq->kq_sel);
        kmem_free(kq, sizeof(*kq));
-       fp->f_data = NULL;
 
        return (0);
 }
diff -r cfcd9efd0120 -r a302f44e98da tests/lib/libc/sys/t_kevent.c
--- a/tests/lib/libc/sys/t_kevent.c     Sat Nov 24 21:08:46 2012 +0000
+++ b/tests/lib/libc/sys/t_kevent.c     Sat Nov 24 21:40:02 2012 +0000
@@ -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();
 }



Home | Main Index | Thread Index | Old Index