1276ffe2dSPeter Holm /*- 2af7b51e6SPeter Holm * Copyright (c) 2014 EMC Corp. 3276ffe2dSPeter Holm * All rights reserved. 4276ffe2dSPeter Holm * 5276ffe2dSPeter Holm * Redistribution and use in source and binary forms, with or without 6276ffe2dSPeter Holm * modification, are permitted provided that the following conditions 7276ffe2dSPeter Holm * are met: 8276ffe2dSPeter Holm * 1. Redistributions of source code must retain the above copyright 9276ffe2dSPeter Holm * notice, this list of conditions and the following disclaimer. 10276ffe2dSPeter Holm * 2. Redistributions in binary form must reproduce the above copyright 11276ffe2dSPeter Holm * notice, this list of conditions and the following disclaimer in the 12276ffe2dSPeter Holm * documentation and/or other materials provided with the distribution. 13276ffe2dSPeter Holm * 14276ffe2dSPeter Holm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15276ffe2dSPeter Holm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16276ffe2dSPeter Holm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17276ffe2dSPeter Holm * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18276ffe2dSPeter Holm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19276ffe2dSPeter Holm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20276ffe2dSPeter Holm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21276ffe2dSPeter Holm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22276ffe2dSPeter Holm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23276ffe2dSPeter Holm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24276ffe2dSPeter Holm * SUCH DAMAGE. 25276ffe2dSPeter Holm */ 26276ffe2dSPeter Holm 27276ffe2dSPeter Holm #include <sys/cdefs.h> 28276ffe2dSPeter Holm __FBSDID("$FreeBSD$"); 29276ffe2dSPeter Holm 30276ffe2dSPeter Holm #include <errno.h> 31276ffe2dSPeter Holm #include <fcntl.h> 32*a31faec3SPeter Holm #include <signal.h> 33276ffe2dSPeter Holm #include <stdio.h> 34276ffe2dSPeter Holm #include <stdlib.h> 35276ffe2dSPeter Holm #include <strings.h> 36276ffe2dSPeter Holm #include <sys/limits.h> 37276ffe2dSPeter Holm #include <sys/stat.h> 38*a31faec3SPeter Holm #include <sys/sysctl.h> 39276ffe2dSPeter Holm #include <unistd.h> 40276ffe2dSPeter Holm #include <atf-c.h> 41276ffe2dSPeter Holm 42*a31faec3SPeter Holm static volatile sig_atomic_t done; 43*a31faec3SPeter Holm 44*a31faec3SPeter Holm #define AFILE "afile" 45*a31faec3SPeter Holm #define EXPANDBY 1000 46*a31faec3SPeter Holm #define PARALLEL 4 47*a31faec3SPeter Holm #define RENDEZVOUS "rendezvous" 48*a31faec3SPeter Holm #define VALUE "value" 49*a31faec3SPeter Holm 50f8eccd0aSPeter Holm ATF_TC_WITHOUT_HEAD(dup2__simple); 51f8eccd0aSPeter Holm ATF_TC_BODY(dup2__simple, tc) 52276ffe2dSPeter Holm { 53276ffe2dSPeter Holm int fd1, fd2; 54276ffe2dSPeter Holm struct stat sb1, sb2; 55276ffe2dSPeter Holm 56*a31faec3SPeter Holm ATF_REQUIRE((fd1 = open(AFILE, O_CREAT, 0644)) != -1); 57276ffe2dSPeter Holm fd2 = 27; 58276ffe2dSPeter Holm ATF_REQUIRE(dup2(fd1, fd2) != -1); 59276ffe2dSPeter Holm ATF_REQUIRE(fstat(fd1, &sb1) != -1); 60276ffe2dSPeter Holm ATF_REQUIRE(fstat(fd2, &sb2) != -1); 61276ffe2dSPeter Holm ATF_REQUIRE(bcmp(&sb1, &sb2, sizeof(sb1)) == 0); 62276ffe2dSPeter Holm } 63276ffe2dSPeter Holm 64af7b51e6SPeter Holm ATF_TC(dup2__ebadf_when_2nd_arg_out_of_range); 65af7b51e6SPeter Holm ATF_TC_HEAD(dup2__ebadf_when_2nd_arg_out_of_range, tc) 66af7b51e6SPeter Holm { 67af7b51e6SPeter Holm atf_tc_set_md_var(tc, "descr", "Regression test for r234131"); 68af7b51e6SPeter Holm } 69*a31faec3SPeter Holm 70af7b51e6SPeter Holm ATF_TC_BODY(dup2__ebadf_when_2nd_arg_out_of_range, tc) 71276ffe2dSPeter Holm { 72276ffe2dSPeter Holm int fd1, fd2, ret; 73276ffe2dSPeter Holm 74*a31faec3SPeter Holm ATF_REQUIRE((fd1 = open(AFILE, O_CREAT, 0644)) != -1); 75276ffe2dSPeter Holm fd2 = INT_MAX; 76276ffe2dSPeter Holm ret = dup2(fd1, fd2); 77276ffe2dSPeter Holm ATF_CHECK_EQ(-1, ret); 78276ffe2dSPeter Holm ATF_CHECK_EQ(EBADF, errno); 79276ffe2dSPeter Holm } 80276ffe2dSPeter Holm 81*a31faec3SPeter Holm static void 82*a31faec3SPeter Holm handler(int s __unused) 83*a31faec3SPeter Holm { 84*a31faec3SPeter Holm done++; 85*a31faec3SPeter Holm } 86*a31faec3SPeter Holm 87*a31faec3SPeter Holm static void 88*a31faec3SPeter Holm openfiles2(size_t n) 89*a31faec3SPeter Holm { 90*a31faec3SPeter Holm size_t i; 91*a31faec3SPeter Holm int r; 92*a31faec3SPeter Holm 93*a31faec3SPeter Holm errno = 0; 94*a31faec3SPeter Holm for (i = 0; i < n; i++) 95*a31faec3SPeter Holm ATF_REQUIRE((r = open(AFILE, O_RDONLY)) != -1); 96*a31faec3SPeter Holm kill(getppid(), SIGUSR1); 97*a31faec3SPeter Holm 98*a31faec3SPeter Holm for (;;) { 99*a31faec3SPeter Holm if (access(RENDEZVOUS, R_OK) != 0) 100*a31faec3SPeter Holm break; 101*a31faec3SPeter Holm usleep(1000); 102*a31faec3SPeter Holm } 103*a31faec3SPeter Holm _exit(0); 104*a31faec3SPeter Holm } 105*a31faec3SPeter Holm 106*a31faec3SPeter Holm static void 107*a31faec3SPeter Holm openfiles(size_t n) 108*a31faec3SPeter Holm { 109*a31faec3SPeter Holm int i, fd; 110*a31faec3SPeter Holm 111*a31faec3SPeter Holm signal(SIGUSR1, handler); 112*a31faec3SPeter Holm ATF_REQUIRE((fd = open(AFILE, O_CREAT, 0644)) != -1); 113*a31faec3SPeter Holm close(fd); 114*a31faec3SPeter Holm ATF_REQUIRE((fd = open(RENDEZVOUS, O_CREAT, 0644)) != -1); 115*a31faec3SPeter Holm close(fd); 116*a31faec3SPeter Holm done = 0; 117*a31faec3SPeter Holm for (i = 0; i < PARALLEL; i++) 118*a31faec3SPeter Holm if (fork() == 0) 119*a31faec3SPeter Holm openfiles2(n / PARALLEL); 120*a31faec3SPeter Holm while (done != PARALLEL) 121*a31faec3SPeter Holm usleep(1000); 122*a31faec3SPeter Holm unlink(RENDEZVOUS); 123*a31faec3SPeter Holm usleep(40000); 124*a31faec3SPeter Holm } 125*a31faec3SPeter Holm 126*a31faec3SPeter Holm ATF_TC_WITH_CLEANUP(kern_maxfiles__increase); 127*a31faec3SPeter Holm ATF_TC_HEAD(kern_maxfiles__increase, tc) 128*a31faec3SPeter Holm { 129*a31faec3SPeter Holm atf_tc_set_md_var(tc, "require.user", "root"); 130*a31faec3SPeter Holm atf_tc_set_md_var(tc, "require.config", "allow_sysctl_side_effects"); 131*a31faec3SPeter Holm atf_tc_set_md_var(tc, "descr", 132*a31faec3SPeter Holm "Check kern.maxfiles expansion"); 133*a31faec3SPeter Holm } 134*a31faec3SPeter Holm 135*a31faec3SPeter Holm ATF_TC_BODY(kern_maxfiles__increase, tc) 136*a31faec3SPeter Holm { 137*a31faec3SPeter Holm size_t oldlen; 138*a31faec3SPeter Holm int maxfiles, oldmaxfiles, current; 139*a31faec3SPeter Holm char buf[80]; 140*a31faec3SPeter Holm 141*a31faec3SPeter Holm oldlen = sizeof(maxfiles); 142*a31faec3SPeter Holm if (sysctlbyname("kern.maxfiles", &maxfiles, &oldlen, NULL, 0) == -1) 143*a31faec3SPeter Holm atf_tc_fail("getsysctlbyname(%s): %s", "kern.maxfiles", 144*a31faec3SPeter Holm strerror(errno)); 145*a31faec3SPeter Holm if (sysctlbyname("kern.openfiles", ¤t, &oldlen, NULL, 0) == -1) 146*a31faec3SPeter Holm atf_tc_fail("getsysctlbyname(%s): %s", "kern.openfiles", 147*a31faec3SPeter Holm strerror(errno)); 148*a31faec3SPeter Holm 149*a31faec3SPeter Holm oldmaxfiles = maxfiles; 150*a31faec3SPeter Holm 151*a31faec3SPeter Holm /* Store old kern.maxfiles in a symlink for cleanup */ 152*a31faec3SPeter Holm snprintf(buf, sizeof(buf), "%d", oldmaxfiles); 153*a31faec3SPeter Holm if (symlink(buf, VALUE) == 1) 154*a31faec3SPeter Holm atf_tc_fail("symlink(%s, %s): %s", buf, VALUE, 155*a31faec3SPeter Holm strerror(errno)); 156*a31faec3SPeter Holm 157*a31faec3SPeter Holm maxfiles += EXPANDBY; 158*a31faec3SPeter Holm if (sysctlbyname("kern.maxfiles", NULL, 0, &maxfiles, oldlen) == -1) 159*a31faec3SPeter Holm atf_tc_fail("getsysctlbyname(%s): %s", "kern.maxfiles", 160*a31faec3SPeter Holm strerror(errno)); 161*a31faec3SPeter Holm 162*a31faec3SPeter Holm openfiles(oldmaxfiles - current + 1); 163*a31faec3SPeter Holm (void)unlink(VALUE); 164*a31faec3SPeter Holm } 165*a31faec3SPeter Holm 166*a31faec3SPeter Holm ATF_TC_CLEANUP(kern_maxfiles__increase, tc) 167*a31faec3SPeter Holm { 168*a31faec3SPeter Holm size_t oldlen; 169*a31faec3SPeter Holm int n, oldmaxfiles; 170*a31faec3SPeter Holm char buf[80]; 171*a31faec3SPeter Holm 172*a31faec3SPeter Holm if ((n = readlink(VALUE, buf, sizeof(buf))) > 0) { 173*a31faec3SPeter Holm buf[n] = '\0'; 174*a31faec3SPeter Holm if (sscanf(buf, "%d", &oldmaxfiles) == 1) { 175*a31faec3SPeter Holm oldlen = sizeof(oldmaxfiles); 176*a31faec3SPeter Holm (void) sysctlbyname("kern.maxfiles", NULL, 0, 177*a31faec3SPeter Holm &oldmaxfiles, oldlen); 178*a31faec3SPeter Holm } 179*a31faec3SPeter Holm } 180*a31faec3SPeter Holm } 181*a31faec3SPeter Holm 182276ffe2dSPeter Holm ATF_TP_ADD_TCS(tp) 183276ffe2dSPeter Holm { 184276ffe2dSPeter Holm 185f8eccd0aSPeter Holm ATF_TP_ADD_TC(tp, dup2__simple); 186af7b51e6SPeter Holm ATF_TP_ADD_TC(tp, dup2__ebadf_when_2nd_arg_out_of_range); 187*a31faec3SPeter Holm ATF_TP_ADD_TC(tp, kern_maxfiles__increase); 188276ffe2dSPeter Holm 189*a31faec3SPeter Holm return (atf_no_error()); 190276ffe2dSPeter Holm } 191