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