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 30*079375d1SConrad Meyer #include <sys/param.h> 31276ffe2dSPeter Holm #include <errno.h> 32276ffe2dSPeter Holm #include <fcntl.h> 33a31faec3SPeter Holm #include <signal.h> 34276ffe2dSPeter Holm #include <stdio.h> 35276ffe2dSPeter Holm #include <stdlib.h> 36276ffe2dSPeter Holm #include <strings.h> 37276ffe2dSPeter Holm #include <sys/limits.h> 38276ffe2dSPeter Holm #include <sys/stat.h> 39a31faec3SPeter Holm #include <sys/sysctl.h> 40276ffe2dSPeter Holm #include <unistd.h> 41276ffe2dSPeter Holm #include <atf-c.h> 42276ffe2dSPeter Holm 43a31faec3SPeter Holm static volatile sig_atomic_t done; 44a31faec3SPeter Holm 45a31faec3SPeter Holm #define AFILE "afile" 46a31faec3SPeter Holm #define EXPANDBY 1000 47a31faec3SPeter Holm #define PARALLEL 4 48a31faec3SPeter Holm #define RENDEZVOUS "rendezvous" 49a31faec3SPeter Holm #define VALUE "value" 50a31faec3SPeter Holm 51f8eccd0aSPeter Holm ATF_TC_WITHOUT_HEAD(dup2__simple); 52f8eccd0aSPeter Holm ATF_TC_BODY(dup2__simple, tc) 53276ffe2dSPeter Holm { 54276ffe2dSPeter Holm int fd1, fd2; 55276ffe2dSPeter Holm struct stat sb1, sb2; 56276ffe2dSPeter Holm 57a31faec3SPeter Holm ATF_REQUIRE((fd1 = open(AFILE, O_CREAT, 0644)) != -1); 58276ffe2dSPeter Holm fd2 = 27; 59276ffe2dSPeter Holm ATF_REQUIRE(dup2(fd1, fd2) != -1); 60276ffe2dSPeter Holm ATF_REQUIRE(fstat(fd1, &sb1) != -1); 61276ffe2dSPeter Holm ATF_REQUIRE(fstat(fd2, &sb2) != -1); 62276ffe2dSPeter Holm ATF_REQUIRE(bcmp(&sb1, &sb2, sizeof(sb1)) == 0); 63276ffe2dSPeter Holm } 64276ffe2dSPeter Holm 65af7b51e6SPeter Holm ATF_TC(dup2__ebadf_when_2nd_arg_out_of_range); 66af7b51e6SPeter Holm ATF_TC_HEAD(dup2__ebadf_when_2nd_arg_out_of_range, tc) 67af7b51e6SPeter Holm { 68af7b51e6SPeter Holm atf_tc_set_md_var(tc, "descr", "Regression test for r234131"); 69af7b51e6SPeter Holm } 70a31faec3SPeter Holm 71af7b51e6SPeter Holm ATF_TC_BODY(dup2__ebadf_when_2nd_arg_out_of_range, tc) 72276ffe2dSPeter Holm { 73276ffe2dSPeter Holm int fd1, fd2, ret; 74276ffe2dSPeter Holm 75a31faec3SPeter Holm ATF_REQUIRE((fd1 = open(AFILE, O_CREAT, 0644)) != -1); 76276ffe2dSPeter Holm fd2 = INT_MAX; 77276ffe2dSPeter Holm ret = dup2(fd1, fd2); 78276ffe2dSPeter Holm ATF_CHECK_EQ(-1, ret); 79276ffe2dSPeter Holm ATF_CHECK_EQ(EBADF, errno); 80276ffe2dSPeter Holm } 81276ffe2dSPeter Holm 82a31faec3SPeter Holm static void 83a31faec3SPeter Holm handler(int s __unused) 84a31faec3SPeter Holm { 85a31faec3SPeter Holm done++; 86a31faec3SPeter Holm } 87a31faec3SPeter Holm 88a31faec3SPeter Holm static void 89a31faec3SPeter Holm openfiles2(size_t n) 90a31faec3SPeter Holm { 91a31faec3SPeter Holm size_t i; 92a31faec3SPeter Holm int r; 93a31faec3SPeter Holm 94a31faec3SPeter Holm errno = 0; 95a31faec3SPeter Holm for (i = 0; i < n; i++) 96a31faec3SPeter Holm ATF_REQUIRE((r = open(AFILE, O_RDONLY)) != -1); 97a31faec3SPeter Holm kill(getppid(), SIGUSR1); 98a31faec3SPeter Holm 99a31faec3SPeter Holm for (;;) { 100a31faec3SPeter Holm if (access(RENDEZVOUS, R_OK) != 0) 101a31faec3SPeter Holm break; 102a31faec3SPeter Holm usleep(1000); 103a31faec3SPeter Holm } 104a31faec3SPeter Holm _exit(0); 105a31faec3SPeter Holm } 106a31faec3SPeter Holm 107a31faec3SPeter Holm static void 108a31faec3SPeter Holm openfiles(size_t n) 109a31faec3SPeter Holm { 110a31faec3SPeter Holm int i, fd; 111a31faec3SPeter Holm 112a31faec3SPeter Holm signal(SIGUSR1, handler); 113a31faec3SPeter Holm ATF_REQUIRE((fd = open(AFILE, O_CREAT, 0644)) != -1); 114a31faec3SPeter Holm close(fd); 115a31faec3SPeter Holm ATF_REQUIRE((fd = open(RENDEZVOUS, O_CREAT, 0644)) != -1); 116a31faec3SPeter Holm close(fd); 117a31faec3SPeter Holm done = 0; 118a31faec3SPeter Holm for (i = 0; i < PARALLEL; i++) 119a31faec3SPeter Holm if (fork() == 0) 120a31faec3SPeter Holm openfiles2(n / PARALLEL); 121a31faec3SPeter Holm while (done != PARALLEL) 122a31faec3SPeter Holm usleep(1000); 123a31faec3SPeter Holm unlink(RENDEZVOUS); 124a31faec3SPeter Holm usleep(40000); 125a31faec3SPeter Holm } 126a31faec3SPeter Holm 127a31faec3SPeter Holm ATF_TC_WITH_CLEANUP(kern_maxfiles__increase); 128a31faec3SPeter Holm ATF_TC_HEAD(kern_maxfiles__increase, tc) 129a31faec3SPeter Holm { 130a31faec3SPeter Holm atf_tc_set_md_var(tc, "require.user", "root"); 131a31faec3SPeter Holm atf_tc_set_md_var(tc, "require.config", "allow_sysctl_side_effects"); 132a31faec3SPeter Holm atf_tc_set_md_var(tc, "descr", 133a31faec3SPeter Holm "Check kern.maxfiles expansion"); 134a31faec3SPeter Holm } 135a31faec3SPeter Holm 136a31faec3SPeter Holm ATF_TC_BODY(kern_maxfiles__increase, tc) 137a31faec3SPeter Holm { 138a31faec3SPeter Holm size_t oldlen; 139a31faec3SPeter Holm int maxfiles, oldmaxfiles, current; 140a31faec3SPeter Holm char buf[80]; 141a31faec3SPeter Holm 142a31faec3SPeter Holm oldlen = sizeof(maxfiles); 143a31faec3SPeter Holm if (sysctlbyname("kern.maxfiles", &maxfiles, &oldlen, NULL, 0) == -1) 144a31faec3SPeter Holm atf_tc_fail("getsysctlbyname(%s): %s", "kern.maxfiles", 145a31faec3SPeter Holm strerror(errno)); 146a31faec3SPeter Holm if (sysctlbyname("kern.openfiles", ¤t, &oldlen, NULL, 0) == -1) 147a31faec3SPeter Holm atf_tc_fail("getsysctlbyname(%s): %s", "kern.openfiles", 148a31faec3SPeter Holm strerror(errno)); 149a31faec3SPeter Holm 150a31faec3SPeter Holm oldmaxfiles = maxfiles; 151a31faec3SPeter Holm 152a31faec3SPeter Holm /* Store old kern.maxfiles in a symlink for cleanup */ 153a31faec3SPeter Holm snprintf(buf, sizeof(buf), "%d", oldmaxfiles); 154a31faec3SPeter Holm if (symlink(buf, VALUE) == 1) 155a31faec3SPeter Holm atf_tc_fail("symlink(%s, %s): %s", buf, VALUE, 156a31faec3SPeter Holm strerror(errno)); 157a31faec3SPeter Holm 158a31faec3SPeter Holm maxfiles += EXPANDBY; 159a31faec3SPeter Holm if (sysctlbyname("kern.maxfiles", NULL, 0, &maxfiles, oldlen) == -1) 160a31faec3SPeter Holm atf_tc_fail("getsysctlbyname(%s): %s", "kern.maxfiles", 161a31faec3SPeter Holm strerror(errno)); 162a31faec3SPeter Holm 163a31faec3SPeter Holm openfiles(oldmaxfiles - current + 1); 164a31faec3SPeter Holm (void)unlink(VALUE); 165a31faec3SPeter Holm } 166a31faec3SPeter Holm 167a31faec3SPeter Holm ATF_TC_CLEANUP(kern_maxfiles__increase, tc) 168a31faec3SPeter Holm { 169a31faec3SPeter Holm size_t oldlen; 170a31faec3SPeter Holm int n, oldmaxfiles; 171a31faec3SPeter Holm char buf[80]; 172a31faec3SPeter Holm 173a31faec3SPeter Holm if ((n = readlink(VALUE, buf, sizeof(buf))) > 0) { 174*079375d1SConrad Meyer buf[MIN((size_t)n, sizeof(buf) - 1)] = '\0'; 175a31faec3SPeter Holm if (sscanf(buf, "%d", &oldmaxfiles) == 1) { 176a31faec3SPeter Holm oldlen = sizeof(oldmaxfiles); 177a31faec3SPeter Holm (void) sysctlbyname("kern.maxfiles", NULL, 0, 178a31faec3SPeter Holm &oldmaxfiles, oldlen); 179a31faec3SPeter Holm } 180a31faec3SPeter Holm } 181a31faec3SPeter Holm } 182a31faec3SPeter Holm 183276ffe2dSPeter Holm ATF_TP_ADD_TCS(tp) 184276ffe2dSPeter Holm { 185276ffe2dSPeter Holm 186f8eccd0aSPeter Holm ATF_TP_ADD_TC(tp, dup2__simple); 187af7b51e6SPeter Holm ATF_TP_ADD_TC(tp, dup2__ebadf_when_2nd_arg_out_of_range); 188a31faec3SPeter Holm ATF_TP_ADD_TC(tp, kern_maxfiles__increase); 189276ffe2dSPeter Holm 190a31faec3SPeter Holm return (atf_no_error()); 191276ffe2dSPeter Holm } 192