1*57718be8SEnji Cooper /* $NetBSD: t_kevent.c,v 1.6 2012/11/29 09:13:44 martin Exp $ */ 2*57718be8SEnji Cooper 3*57718be8SEnji Cooper /*- 4*57718be8SEnji Cooper * Copyright (c) 2011 The NetBSD Foundation, Inc. 5*57718be8SEnji Cooper * All rights reserved. 6*57718be8SEnji Cooper * 7*57718be8SEnji Cooper * This code is derived from software contributed to The NetBSD Foundatiom 8*57718be8SEnji Cooper * by Christos Zoulas. 9*57718be8SEnji Cooper * 10*57718be8SEnji Cooper * Redistribution and use in source and binary forms, with or without 11*57718be8SEnji Cooper * modification, are permitted provided that the following conditions 12*57718be8SEnji Cooper * are met: 13*57718be8SEnji Cooper * 1. Redistributions of source code must retain the above copyright 14*57718be8SEnji Cooper * notice, this list of conditions and the following disclaimer. 15*57718be8SEnji Cooper * 2. Redistributions in binary form must reproduce the above copyright 16*57718be8SEnji Cooper * notice, this list of conditions and the following disclaimer in the 17*57718be8SEnji Cooper * documentation and/or other materials provided with the distribution. 18*57718be8SEnji Cooper * 19*57718be8SEnji Cooper * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20*57718be8SEnji Cooper * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21*57718be8SEnji Cooper * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22*57718be8SEnji Cooper * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23*57718be8SEnji Cooper * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24*57718be8SEnji Cooper * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25*57718be8SEnji Cooper * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26*57718be8SEnji Cooper * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27*57718be8SEnji Cooper * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28*57718be8SEnji Cooper * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29*57718be8SEnji Cooper * POSSIBILITY OF SUCH DAMAGE. 30*57718be8SEnji Cooper */ 31*57718be8SEnji Cooper #include <sys/cdefs.h> 32*57718be8SEnji Cooper __RCSID("$NetBSD: t_kevent.c,v 1.6 2012/11/29 09:13:44 martin Exp $"); 33*57718be8SEnji Cooper 34*57718be8SEnji Cooper #include <sys/types.h> 35*57718be8SEnji Cooper #include <sys/event.h> 36*57718be8SEnji Cooper 37*57718be8SEnji Cooper #include <atf-c.h> 38*57718be8SEnji Cooper #include <errno.h> 39*57718be8SEnji Cooper #include <time.h> 40*57718be8SEnji Cooper #include <stdio.h> 41*57718be8SEnji Cooper #include <stdlib.h> 42*57718be8SEnji Cooper #include <string.h> 43*57718be8SEnji Cooper #include <unistd.h> 44*57718be8SEnji Cooper #include <fcntl.h> 45*57718be8SEnji Cooper #include <err.h> 46*57718be8SEnji Cooper #include <sys/drvctlio.h> 47*57718be8SEnji Cooper #include <sys/event.h> 48*57718be8SEnji Cooper #include <sys/time.h> 49*57718be8SEnji Cooper #include <sys/socket.h> 50*57718be8SEnji Cooper #include <sys/wait.h> 51*57718be8SEnji Cooper 52*57718be8SEnji Cooper ATF_TC(kevent_zerotimer); 53*57718be8SEnji Cooper ATF_TC_HEAD(kevent_zerotimer, tc) 54*57718be8SEnji Cooper { 55*57718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Checks that kevent with a 0 timer " 56*57718be8SEnji Cooper "does not crash the system (PR lib/45618)"); 57*57718be8SEnji Cooper } 58*57718be8SEnji Cooper 59*57718be8SEnji Cooper ATF_TC_BODY(kevent_zerotimer, tc) 60*57718be8SEnji Cooper { 61*57718be8SEnji Cooper struct kevent ev; 62*57718be8SEnji Cooper int kq; 63*57718be8SEnji Cooper 64*57718be8SEnji Cooper ATF_REQUIRE((kq = kqueue()) != -1); 65*57718be8SEnji Cooper EV_SET(&ev, 1, EVFILT_TIMER, EV_ADD|EV_ENABLE, 0, 1, 0); 66*57718be8SEnji Cooper ATF_REQUIRE(kevent(kq, &ev, 1, NULL, 0, NULL) != -1); 67*57718be8SEnji Cooper ATF_REQUIRE(kevent(kq, NULL, 0, &ev, 1, NULL) == 1); 68*57718be8SEnji Cooper } 69*57718be8SEnji Cooper 70*57718be8SEnji Cooper ATF_TC(kqueue_desc_passing); 71*57718be8SEnji Cooper ATF_TC_HEAD(kqueue_desc_passing, tc) 72*57718be8SEnji Cooper { 73*57718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Checks that passing a kqueue to " 74*57718be8SEnji Cooper "another process does not crash the kernel (PR 46463)"); 75*57718be8SEnji Cooper } 76*57718be8SEnji Cooper 77*57718be8SEnji Cooper ATF_TC_BODY(kqueue_desc_passing, tc) 78*57718be8SEnji Cooper { 79*57718be8SEnji Cooper pid_t child; 80*57718be8SEnji Cooper int s[2], storage, status, kq; 81*57718be8SEnji Cooper struct cmsghdr *msg; 82*57718be8SEnji Cooper struct iovec iov; 83*57718be8SEnji Cooper struct msghdr m; 84*57718be8SEnji Cooper struct kevent ev; 85*57718be8SEnji Cooper 86*57718be8SEnji Cooper ATF_REQUIRE((kq = kqueue()) != -1); 87*57718be8SEnji Cooper 88*57718be8SEnji Cooper // atf_tc_skip("crashes kernel (PR 46463)"); 89*57718be8SEnji Cooper 90*57718be8SEnji Cooper ATF_REQUIRE(socketpair(AF_LOCAL, SOCK_STREAM, 0, s) != -1); 91*57718be8SEnji Cooper msg = malloc(CMSG_SPACE(sizeof(int))); 92*57718be8SEnji Cooper m.msg_iov = &iov; 93*57718be8SEnji Cooper m.msg_iovlen = 1; 94*57718be8SEnji Cooper m.msg_name = NULL; 95*57718be8SEnji Cooper m.msg_namelen = 0; 96*57718be8SEnji Cooper m.msg_control = msg; 97*57718be8SEnji Cooper m.msg_controllen = CMSG_SPACE(sizeof(int)); 98*57718be8SEnji Cooper 99*57718be8SEnji Cooper child = fork(); 100*57718be8SEnji Cooper if (child == 0) { 101*57718be8SEnji Cooper close(s[0]); 102*57718be8SEnji Cooper 103*57718be8SEnji Cooper iov.iov_base = &storage; 104*57718be8SEnji Cooper iov.iov_len = sizeof(int); 105*57718be8SEnji Cooper m.msg_iov = &iov; 106*57718be8SEnji Cooper m.msg_iovlen = 1; 107*57718be8SEnji Cooper 108*57718be8SEnji Cooper if (recvmsg(s[1], &m, 0) == -1) 109*57718be8SEnji Cooper err(1, "child: could not recvmsg"); 110*57718be8SEnji Cooper 111*57718be8SEnji Cooper kq = *(int *)CMSG_DATA(msg); 112*57718be8SEnji Cooper printf("child (pid %d): received kq fd %d\n", getpid(), kq); 113*57718be8SEnji Cooper exit(0); 114*57718be8SEnji Cooper } 115*57718be8SEnji Cooper 116*57718be8SEnji Cooper close(s[1]); 117*57718be8SEnji Cooper 118*57718be8SEnji Cooper iov.iov_base = &storage; 119*57718be8SEnji Cooper iov.iov_len = sizeof(int); 120*57718be8SEnji Cooper 121*57718be8SEnji Cooper msg->cmsg_level = SOL_SOCKET; 122*57718be8SEnji Cooper msg->cmsg_type = SCM_RIGHTS; 123*57718be8SEnji Cooper msg->cmsg_len = CMSG_LEN(sizeof(int)); 124*57718be8SEnji Cooper 125*57718be8SEnji Cooper *(int *)CMSG_DATA(msg) = kq; 126*57718be8SEnji Cooper 127*57718be8SEnji Cooper EV_SET(&ev, 1, EVFILT_TIMER, EV_ADD|EV_ENABLE, 0, 1, 0); 128*57718be8SEnji Cooper ATF_CHECK(kevent(kq, &ev, 1, NULL, 0, NULL) != -1); 129*57718be8SEnji Cooper 130*57718be8SEnji Cooper printf("parent (pid %d): sending kq fd %d\n", getpid(), kq); 131*57718be8SEnji Cooper if (sendmsg(s[0], &m, 0) == -1) { 132*57718be8SEnji Cooper ATF_REQUIRE_EQ_MSG(errno, EBADF, "errno is %d", errno); 133*57718be8SEnji Cooper atf_tc_skip("PR kern/46523"); 134*57718be8SEnji Cooper } 135*57718be8SEnji Cooper 136*57718be8SEnji Cooper close(kq); 137*57718be8SEnji Cooper 138*57718be8SEnji Cooper waitpid(child, &status, 0); 139*57718be8SEnji Cooper ATF_CHECK(WIFEXITED(status) && WEXITSTATUS(status)==0); 140*57718be8SEnji Cooper } 141*57718be8SEnji Cooper 142*57718be8SEnji Cooper ATF_TC(kqueue_unsupported_fd); 143*57718be8SEnji Cooper ATF_TC_HEAD(kqueue_unsupported_fd, tc) 144*57718be8SEnji Cooper { 145*57718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Checks that watching an fd whose" 146*57718be8SEnji Cooper " type is not supported does not crash the kernel"); 147*57718be8SEnji Cooper } 148*57718be8SEnji Cooper 149*57718be8SEnji Cooper ATF_TC_BODY(kqueue_unsupported_fd, tc) 150*57718be8SEnji Cooper { 151*57718be8SEnji Cooper /* mqueue and semaphore use fnullop_kqueue also */ 152*57718be8SEnji Cooper int fd, kq; 153*57718be8SEnji Cooper struct kevent ev; 154*57718be8SEnji Cooper 155*57718be8SEnji Cooper fd = open(DRVCTLDEV, O_RDONLY); 156*57718be8SEnji Cooper if (fd == -1 && errno == ENOENT) 157*57718be8SEnji Cooper atf_tc_skip("no " DRVCTLDEV " available for testing"); 158*57718be8SEnji Cooper ATF_REQUIRE(fd != -1); 159*57718be8SEnji Cooper ATF_REQUIRE((kq = kqueue()) != -1); 160*57718be8SEnji Cooper 161*57718be8SEnji Cooper EV_SET(&ev, fd, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_CLEAR, 162*57718be8SEnji Cooper NOTE_DELETE|NOTE_WRITE|NOTE_EXTEND|NOTE_ATTRIB|NOTE_LINK| 163*57718be8SEnji Cooper NOTE_RENAME|NOTE_REVOKE, 0, 0); 164*57718be8SEnji Cooper 165*57718be8SEnji Cooper ATF_REQUIRE(kevent(kq, &ev, 1, NULL, 0, NULL) == -1); 166*57718be8SEnji Cooper ATF_REQUIRE_ERRNO(EOPNOTSUPP, true); 167*57718be8SEnji Cooper 168*57718be8SEnji Cooper (void)close(fd); 169*57718be8SEnji Cooper } 170*57718be8SEnji Cooper 171*57718be8SEnji Cooper 172*57718be8SEnji Cooper ATF_TP_ADD_TCS(tp) 173*57718be8SEnji Cooper { 174*57718be8SEnji Cooper 175*57718be8SEnji Cooper ATF_TP_ADD_TC(tp, kevent_zerotimer); 176*57718be8SEnji Cooper ATF_TP_ADD_TC(tp, kqueue_desc_passing); 177*57718be8SEnji Cooper ATF_TP_ADD_TC(tp, kqueue_unsupported_fd); 178*57718be8SEnji Cooper 179*57718be8SEnji Cooper return atf_no_error(); 180*57718be8SEnji Cooper } 181