xref: /freebsd/tests/sys/kern/kern_descrip_test.c (revision a31faec3d18cfbf3f96c7f0d99f255cb3f7da005)
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", &current, &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