1 /* $NetBSD: t_setrlimit.c,v 1.4 2012/06/12 23:56:19 christos Exp $ */
4 * Copyright (c) 2011 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
31 #include <sys/cdefs.h>
32 __RCSID("$NetBSD: t_setrlimit.c,v 1.4 2012/06/12 23:56:19 christos Exp $");
34 #include <sys/resource.h>
53 static void sighandler(int);
54 static const char path[] = "setrlimit";
56 static const int rlimit[] = {
70 ATF_TC(setrlimit_basic);
71 ATF_TC_HEAD(setrlimit_basic, tc)
73 atf_tc_set_md_var(tc, "descr", "A basic soft limit test");
76 ATF_TC_BODY(setrlimit_basic, tc)
82 buf = calloc(__arraycount(rlimit), sizeof(int));
85 atf_tc_fail("initialization failed");
87 for (i = lim = 0; i < __arraycount(rlimit); i++) {
89 (void)memset(&res, 0, sizeof(struct rlimit));
91 if (getrlimit(rlimit[i], &res) != 0)
94 if (res.rlim_cur == RLIM_INFINITY || res.rlim_cur == 0)
97 if (res.rlim_cur == res.rlim_max) /* An unprivileged run. */
100 buf[i] = res.rlim_cur;
101 res.rlim_cur = res.rlim_cur - 1;
103 if (setrlimit(rlimit[i], &res) != 0) {
110 for (i = 0; i < __arraycount(rlimit); i++) {
112 (void)memset(&res, 0, sizeof(struct rlimit));
117 if (getrlimit(rlimit[i], &res) != 0)
120 res.rlim_cur = buf[i];
122 (void)setrlimit(rlimit[i], &res);
126 atf_tc_fail("failed to set limit (%d)", lim);
129 ATF_TC(setrlimit_current);
130 ATF_TC_HEAD(setrlimit_current, tc)
132 atf_tc_set_md_var(tc, "descr", "setrlimit(3) with current limits");
135 ATF_TC_BODY(setrlimit_current, tc)
140 for (i = 0; i < __arraycount(rlimit); i++) {
142 (void)memset(&res, 0, sizeof(struct rlimit));
144 ATF_REQUIRE(getrlimit(rlimit[i], &res) == 0);
145 ATF_REQUIRE(setrlimit(rlimit[i], &res) == 0);
149 ATF_TC(setrlimit_err);
150 ATF_TC_HEAD(setrlimit_err, tc)
152 atf_tc_set_md_var(tc, "descr", "Test error conditions");
155 ATF_TC_BODY(setrlimit_err, tc)
160 for (i = 0; i < __arraycount(rlimit); i++) {
164 ATF_REQUIRE(getrlimit(rlimit[i], (void *)0) != 0);
165 ATF_REQUIRE(errno == EFAULT);
170 ATF_REQUIRE(getrlimit(INT_MAX, &res) != 0);
171 ATF_REQUIRE(errno == EINVAL);
174 ATF_TC_WITH_CLEANUP(setrlimit_fsize);
175 ATF_TC_HEAD(setrlimit_fsize, tc)
177 atf_tc_set_md_var(tc, "descr", "Test setrlimit(2), RLIMIT_FSIZE");
180 ATF_TC_BODY(setrlimit_fsize, tc)
186 fd = open(path, O_RDWR | O_CREAT, 0700);
189 atf_tc_fail("initialization failed");
192 ATF_REQUIRE(pid >= 0);
199 if (setrlimit(RLIMIT_FSIZE, &res) != 0)
202 if (signal(SIGXFSZ, sighandler) == SIG_ERR)
206 * The third call should generate a SIGXFSZ.
208 (void)write(fd, "X", 1);
209 (void)write(fd, "X", 1);
210 (void)write(fd, "X", 1);
219 if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
220 atf_tc_fail("RLIMIT_FSIZE not enforced");
223 ATF_TC_CLEANUP(setrlimit_fsize, tc)
229 sighandler(int signo)
232 if (signo != SIGXFSZ)
238 ATF_TC(setrlimit_memlock);
239 ATF_TC_HEAD(setrlimit_memlock, tc)
241 atf_tc_set_md_var(tc, "descr", "Test setrlimit(2), RLIMIT_MEMLOCK");
244 ATF_TC_BODY(setrlimit_memlock, tc)
252 page = sysconf(_SC_PAGESIZE);
253 ATF_REQUIRE(page >= 0);
258 if (buf == NULL || pid < 0)
259 atf_tc_fail("initialization failed");
264 * Try to lock a page while
265 * RLIMIT_MEMLOCK is zero.
267 if (mlock(buf, page) != 0)
270 if (munlock(buf, page) != 0)
276 if (setrlimit(RLIMIT_MEMLOCK, &res) != 0)
279 if (mlock(buf, page) != 0)
282 (void)munlock(buf, page);
291 if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
292 atf_tc_fail("RLIMIT_MEMLOCK not enforced");
295 ATF_TC(setrlimit_nofile_1);
296 ATF_TC_HEAD(setrlimit_nofile_1, tc)
298 atf_tc_set_md_var(tc, "descr", "Test setrlimit(2), RLIMIT_NOFILE, #1");
301 ATF_TC_BODY(setrlimit_nofile_1, tc)
311 ATF_REQUIRE(pid >= 0);
316 * Close all descriptors, set RLIMIT_NOFILE
317 * to zero, and try to open a random file.
318 * This should fail with EMFILE.
320 for (i = 0; i < 1024; i++)
323 rv = setrlimit(RLIMIT_NOFILE, &res);
329 fd = open("/etc/passwd", O_RDONLY);
331 if (fd >= 0 || errno != EMFILE)
339 if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
340 atf_tc_fail("RLIMIT_NOFILE not enforced");
343 ATF_TC(setrlimit_nofile_2);
344 ATF_TC_HEAD(setrlimit_nofile_2, tc)
346 atf_tc_set_md_var(tc, "descr", "Test setrlimit(2), RLIMIT_NOFILE, #2");
349 ATF_TC_BODY(setrlimit_nofile_2, tc)
351 static const rlim_t lim = 12;
357 * See that an arbitrary limit on
358 * open files is being enforced.
364 ATF_REQUIRE(pid >= 0);
368 for (i = 0; i < 1024; i++)
371 rv = setrlimit(RLIMIT_NOFILE, &res);
376 for (i = 0; i < (int)lim; i++) {
378 fd = open("/etc/passwd", O_RDONLY);
385 * After the limit has been reached,
386 * EMFILE should again follow.
388 fd = open("/etc/passwd", O_RDONLY);
390 if (fd >= 0 || errno != EMFILE)
398 if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
399 atf_tc_fail("RLIMIT_NOFILE not enforced");
402 ATF_TC(setrlimit_nproc);
403 ATF_TC_HEAD(setrlimit_nproc, tc)
405 atf_tc_set_md_var(tc, "descr", "Test setrlimit(2), RLIMIT_NPROC");
406 atf_tc_set_md_var(tc, "require.user", "unprivileged");
409 ATF_TC_BODY(setrlimit_nproc, tc)
416 ATF_REQUIRE(pid >= 0);
421 * Set RLIMIT_NPROC to zero and try to fork.
426 if (setrlimit(RLIMIT_NPROC, &res) != 0)
437 (void)waitpid(pid, &sta, 0);
439 if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
440 atf_tc_fail("RLIMIT_NPROC not enforced");
444 ATF_TC(setrlimit_nthr);
445 ATF_TC_HEAD(setrlimit_nthr, tc)
447 atf_tc_set_md_var(tc, "descr", "Test setrlimit(2), RLIMIT_NTHR");
448 atf_tc_set_md_var(tc, "require.user", "unprivileged");
454 printf("thread %d\n", *id);
459 ATF_TC_BODY(setrlimit_nthr, tc)
466 * Set RLIMIT_NTHR to zero and try to create a thread.
470 ATF_REQUIRE(setrlimit(RLIMIT_NTHR, &res) == 0);
471 ATF_REQUIRE(getcontext(&c) == 0);
473 sigemptyset(&c.uc_sigmask);
474 c.uc_stack.ss_flags = 0;
475 c.uc_stack.ss_size = 4096;
476 ATF_REQUIRE((c.uc_stack.ss_sp = malloc(c.uc_stack.ss_size)) != NULL);
477 makecontext(&c, func, 1, &lwpid);
478 ATF_CHECK_ERRNO(EAGAIN, _lwp_create(&c, 0, &lwpid) == -1);
482 ATF_TC(setrlimit_perm);
483 ATF_TC_HEAD(setrlimit_perm, tc)
485 atf_tc_set_md_var(tc, "descr", "Test setrlimit(2) for EPERM");
486 atf_tc_set_md_var(tc, "require.user", "unprivileged");
489 ATF_TC_BODY(setrlimit_perm, tc)
495 * Try to raise the maximum limits as an user.
497 for (i = 0; i < __arraycount(rlimit); i++) {
499 ATF_REQUIRE(getrlimit(rlimit[i], &res) == 0);
502 if (res.rlim_max == INT64_MAX) /* Overflow. */
504 if (res.rlim_max == UINT64_MAX) /* Overflow. */
509 res.rlim_max = res.rlim_max + 1;
511 ATF_CHECK_ERRNO(EPERM, setrlimit(rlimit[i], &res) != 0);
518 ATF_TP_ADD_TC(tp, setrlimit_basic);
519 ATF_TP_ADD_TC(tp, setrlimit_current);
520 ATF_TP_ADD_TC(tp, setrlimit_err);
521 ATF_TP_ADD_TC(tp, setrlimit_fsize);
522 ATF_TP_ADD_TC(tp, setrlimit_memlock);
523 ATF_TP_ADD_TC(tp, setrlimit_nofile_1);
524 ATF_TP_ADD_TC(tp, setrlimit_nofile_2);
525 ATF_TP_ADD_TC(tp, setrlimit_nproc);
526 ATF_TP_ADD_TC(tp, setrlimit_perm);
528 ATF_TP_ADD_TC(tp, setrlimit_nthr);
531 return atf_no_error();