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 30079375d1SConrad Meyer #include <sys/param.h> 31*4661f8afSEric van Gyzen #include <sys/limits.h> 32*4661f8afSEric van Gyzen #include <sys/resource.h> 33*4661f8afSEric van Gyzen #include <sys/stat.h> 34*4661f8afSEric van Gyzen #include <sys/sysctl.h> 35*4661f8afSEric van Gyzen #include <sys/time.h> 36*4661f8afSEric van Gyzen #include <sys/wait.h> 37*4661f8afSEric van Gyzen 38276ffe2dSPeter Holm #include <errno.h> 39276ffe2dSPeter Holm #include <fcntl.h> 40a31faec3SPeter Holm #include <signal.h> 41276ffe2dSPeter Holm #include <stdio.h> 42276ffe2dSPeter Holm #include <stdlib.h> 43*4661f8afSEric van Gyzen #include <string.h> 44276ffe2dSPeter Holm #include <strings.h> 45276ffe2dSPeter Holm #include <unistd.h> 46*4661f8afSEric van Gyzen 47276ffe2dSPeter Holm #include <atf-c.h> 48276ffe2dSPeter Holm 49a31faec3SPeter Holm static volatile sig_atomic_t done; 50a31faec3SPeter Holm 51a31faec3SPeter Holm #define AFILE "afile" 52a31faec3SPeter Holm #define EXPANDBY 1000 53a31faec3SPeter Holm #define PARALLEL 4 54a31faec3SPeter Holm #define RENDEZVOUS "rendezvous" 55a31faec3SPeter Holm #define VALUE "value" 56a31faec3SPeter Holm 57f8eccd0aSPeter Holm ATF_TC_WITHOUT_HEAD(dup2__simple); 58f8eccd0aSPeter Holm ATF_TC_BODY(dup2__simple, tc) 59276ffe2dSPeter Holm { 60276ffe2dSPeter Holm int fd1, fd2; 61276ffe2dSPeter Holm struct stat sb1, sb2; 62276ffe2dSPeter Holm 63a31faec3SPeter Holm ATF_REQUIRE((fd1 = open(AFILE, O_CREAT, 0644)) != -1); 64276ffe2dSPeter Holm fd2 = 27; 65276ffe2dSPeter Holm ATF_REQUIRE(dup2(fd1, fd2) != -1); 66276ffe2dSPeter Holm ATF_REQUIRE(fstat(fd1, &sb1) != -1); 67276ffe2dSPeter Holm ATF_REQUIRE(fstat(fd2, &sb2) != -1); 68276ffe2dSPeter Holm ATF_REQUIRE(bcmp(&sb1, &sb2, sizeof(sb1)) == 0); 69276ffe2dSPeter Holm } 70276ffe2dSPeter Holm 71af7b51e6SPeter Holm ATF_TC(dup2__ebadf_when_2nd_arg_out_of_range); 72af7b51e6SPeter Holm ATF_TC_HEAD(dup2__ebadf_when_2nd_arg_out_of_range, tc) 73af7b51e6SPeter Holm { 74af7b51e6SPeter Holm atf_tc_set_md_var(tc, "descr", "Regression test for r234131"); 75af7b51e6SPeter Holm } 76a31faec3SPeter Holm 77af7b51e6SPeter Holm ATF_TC_BODY(dup2__ebadf_when_2nd_arg_out_of_range, tc) 78276ffe2dSPeter Holm { 79276ffe2dSPeter Holm int fd1, fd2, ret; 80276ffe2dSPeter Holm 81a31faec3SPeter Holm ATF_REQUIRE((fd1 = open(AFILE, O_CREAT, 0644)) != -1); 82276ffe2dSPeter Holm fd2 = INT_MAX; 83276ffe2dSPeter Holm ret = dup2(fd1, fd2); 84276ffe2dSPeter Holm ATF_CHECK_EQ(-1, ret); 85276ffe2dSPeter Holm ATF_CHECK_EQ(EBADF, errno); 86276ffe2dSPeter Holm } 87276ffe2dSPeter Holm 88a31faec3SPeter Holm static void 89a31faec3SPeter Holm handler(int s __unused) 90a31faec3SPeter Holm { 91a31faec3SPeter Holm done++; 92a31faec3SPeter Holm } 93a31faec3SPeter Holm 94a31faec3SPeter Holm static void 95a31faec3SPeter Holm openfiles2(size_t n) 96a31faec3SPeter Holm { 97a31faec3SPeter Holm size_t i; 98a31faec3SPeter Holm int r; 99a31faec3SPeter Holm 100a31faec3SPeter Holm errno = 0; 101*4661f8afSEric van Gyzen for (i = 0; i < n; i++) { 102*4661f8afSEric van Gyzen r = open(AFILE, O_RDONLY); 103*4661f8afSEric van Gyzen if (r < 0) { 104*4661f8afSEric van Gyzen fprintf(stderr, "open: %s\n", strerror(errno)); 105*4661f8afSEric van Gyzen _exit(1); 106*4661f8afSEric van Gyzen } 107*4661f8afSEric van Gyzen } 108a31faec3SPeter Holm kill(getppid(), SIGUSR1); 109a31faec3SPeter Holm 110a31faec3SPeter Holm for (;;) { 111a31faec3SPeter Holm if (access(RENDEZVOUS, R_OK) != 0) 112a31faec3SPeter Holm break; 113a31faec3SPeter Holm usleep(1000); 114a31faec3SPeter Holm } 115a31faec3SPeter Holm _exit(0); 116a31faec3SPeter Holm } 117a31faec3SPeter Holm 118a31faec3SPeter Holm static void 119a31faec3SPeter Holm openfiles(size_t n) 120a31faec3SPeter Holm { 121a31faec3SPeter Holm int i, fd; 122a31faec3SPeter Holm 123a31faec3SPeter Holm signal(SIGUSR1, handler); 124a31faec3SPeter Holm ATF_REQUIRE((fd = open(AFILE, O_CREAT, 0644)) != -1); 125a31faec3SPeter Holm close(fd); 126a31faec3SPeter Holm ATF_REQUIRE((fd = open(RENDEZVOUS, O_CREAT, 0644)) != -1); 127a31faec3SPeter Holm close(fd); 128a31faec3SPeter Holm done = 0; 129a31faec3SPeter Holm for (i = 0; i < PARALLEL; i++) 130a31faec3SPeter Holm if (fork() == 0) 131a31faec3SPeter Holm openfiles2(n / PARALLEL); 132*4661f8afSEric van Gyzen while (done != PARALLEL) { 133a31faec3SPeter Holm usleep(1000); 134*4661f8afSEric van Gyzen ATF_REQUIRE_EQ_MSG(0, waitpid(-1, NULL, WNOHANG), 135*4661f8afSEric van Gyzen "a child exited unexpectedly"); 136*4661f8afSEric van Gyzen } 137a31faec3SPeter Holm unlink(RENDEZVOUS); 138*4661f8afSEric van Gyzen for (i = 0; i < PARALLEL; i++) 139*4661f8afSEric van Gyzen ATF_CHECK_MSG(wait(NULL) > 0, "wait: %s", strerror(errno)); 140a31faec3SPeter Holm } 141a31faec3SPeter Holm 142a31faec3SPeter Holm ATF_TC_WITH_CLEANUP(kern_maxfiles__increase); 143a31faec3SPeter Holm ATF_TC_HEAD(kern_maxfiles__increase, tc) 144a31faec3SPeter Holm { 145a31faec3SPeter Holm atf_tc_set_md_var(tc, "require.user", "root"); 146a31faec3SPeter Holm atf_tc_set_md_var(tc, "require.config", "allow_sysctl_side_effects"); 147a31faec3SPeter Holm atf_tc_set_md_var(tc, "descr", 148a31faec3SPeter Holm "Check kern.maxfiles expansion"); 149a31faec3SPeter Holm } 150a31faec3SPeter Holm 151a31faec3SPeter Holm ATF_TC_BODY(kern_maxfiles__increase, tc) 152a31faec3SPeter Holm { 153a31faec3SPeter Holm size_t oldlen; 154a31faec3SPeter Holm int maxfiles, oldmaxfiles, current; 155a31faec3SPeter Holm char buf[80]; 156*4661f8afSEric van Gyzen struct rlimit rl; 157a31faec3SPeter Holm 158a31faec3SPeter Holm oldlen = sizeof(maxfiles); 159a31faec3SPeter Holm if (sysctlbyname("kern.maxfiles", &maxfiles, &oldlen, NULL, 0) == -1) 160a31faec3SPeter Holm atf_tc_fail("getsysctlbyname(%s): %s", "kern.maxfiles", 161a31faec3SPeter Holm strerror(errno)); 162a31faec3SPeter Holm if (sysctlbyname("kern.openfiles", ¤t, &oldlen, NULL, 0) == -1) 163a31faec3SPeter Holm atf_tc_fail("getsysctlbyname(%s): %s", "kern.openfiles", 164a31faec3SPeter Holm strerror(errno)); 165a31faec3SPeter Holm 166a31faec3SPeter Holm oldmaxfiles = maxfiles; 167a31faec3SPeter Holm 168a31faec3SPeter Holm /* Store old kern.maxfiles in a symlink for cleanup */ 169a31faec3SPeter Holm snprintf(buf, sizeof(buf), "%d", oldmaxfiles); 170a31faec3SPeter Holm if (symlink(buf, VALUE) == 1) 171a31faec3SPeter Holm atf_tc_fail("symlink(%s, %s): %s", buf, VALUE, 172a31faec3SPeter Holm strerror(errno)); 173a31faec3SPeter Holm 174a31faec3SPeter Holm maxfiles += EXPANDBY; 175a31faec3SPeter Holm if (sysctlbyname("kern.maxfiles", NULL, 0, &maxfiles, oldlen) == -1) 176a31faec3SPeter Holm atf_tc_fail("getsysctlbyname(%s): %s", "kern.maxfiles", 177a31faec3SPeter Holm strerror(errno)); 178a31faec3SPeter Holm 179*4661f8afSEric van Gyzen rl.rlim_cur = rl.rlim_max = maxfiles; 180*4661f8afSEric van Gyzen ATF_REQUIRE_EQ_MSG(0, setrlimit(RLIMIT_NOFILE, &rl), 181*4661f8afSEric van Gyzen "setrlimit(RLIMIT_NOFILE, %d): %s", maxfiles, strerror(errno)); 182*4661f8afSEric van Gyzen 183*4661f8afSEric van Gyzen openfiles(oldmaxfiles - current + EXPANDBY / 2); 184a31faec3SPeter Holm } 185a31faec3SPeter Holm 186a31faec3SPeter Holm ATF_TC_CLEANUP(kern_maxfiles__increase, tc) 187a31faec3SPeter Holm { 188a31faec3SPeter Holm size_t oldlen; 189a31faec3SPeter Holm int n, oldmaxfiles; 190a31faec3SPeter Holm char buf[80]; 191a31faec3SPeter Holm 192a31faec3SPeter Holm if ((n = readlink(VALUE, buf, sizeof(buf))) > 0) { 193079375d1SConrad Meyer buf[MIN((size_t)n, sizeof(buf) - 1)] = '\0'; 194a31faec3SPeter Holm if (sscanf(buf, "%d", &oldmaxfiles) == 1) { 195a31faec3SPeter Holm oldlen = sizeof(oldmaxfiles); 196a31faec3SPeter Holm (void) sysctlbyname("kern.maxfiles", NULL, 0, 197a31faec3SPeter Holm &oldmaxfiles, oldlen); 198a31faec3SPeter Holm } 199a31faec3SPeter Holm } 200*4661f8afSEric van Gyzen (void)unlink(VALUE); 201*4661f8afSEric van Gyzen (void)unlink(AFILE); 202a31faec3SPeter Holm } 203a31faec3SPeter Holm 204276ffe2dSPeter Holm ATF_TP_ADD_TCS(tp) 205276ffe2dSPeter Holm { 206276ffe2dSPeter Holm 207f8eccd0aSPeter Holm ATF_TP_ADD_TC(tp, dup2__simple); 208af7b51e6SPeter Holm ATF_TP_ADD_TC(tp, dup2__ebadf_when_2nd_arg_out_of_range); 209a31faec3SPeter Holm ATF_TP_ADD_TC(tp, kern_maxfiles__increase); 210276ffe2dSPeter Holm 211a31faec3SPeter Holm return (atf_no_error()); 212276ffe2dSPeter Holm } 213