1 /* $NetBSD: t_setrlimit.c,v 1.6 2017/01/13 21:16:38 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.6 2017/01/13 21:16:38 christos Exp $");
34 #include <sys/resource.h>
54 void set_vm_max_wired(int);
55 void restore_vm_max_wired(void);
58 static void sighandler(int);
59 static const char path[] = "setrlimit";
61 static const int rlimit[] = {
75 ATF_TC(setrlimit_basic);
76 ATF_TC_HEAD(setrlimit_basic, tc)
78 atf_tc_set_md_var(tc, "descr", "A basic soft limit test");
81 ATF_TC_BODY(setrlimit_basic, tc)
87 buf = calloc(__arraycount(rlimit), sizeof(int));
90 atf_tc_fail("initialization failed");
92 for (i = lim = 0; i < __arraycount(rlimit); i++) {
94 (void)memset(&res, 0, sizeof(struct rlimit));
96 if (getrlimit(rlimit[i], &res) != 0)
99 if (res.rlim_cur == RLIM_INFINITY || res.rlim_cur == 0)
102 if (res.rlim_cur == res.rlim_max) /* An unprivileged run. */
105 buf[i] = res.rlim_cur;
106 res.rlim_cur = res.rlim_cur - 1;
108 if (setrlimit(rlimit[i], &res) != 0) {
115 for (i = 0; i < __arraycount(rlimit); i++) {
117 (void)memset(&res, 0, sizeof(struct rlimit));
122 if (getrlimit(rlimit[i], &res) != 0)
125 res.rlim_cur = buf[i];
127 (void)setrlimit(rlimit[i], &res);
131 atf_tc_fail("failed to set limit (%d)", lim);
135 ATF_TC(setrlimit_current);
136 ATF_TC_HEAD(setrlimit_current, tc)
138 atf_tc_set_md_var(tc, "descr", "setrlimit(3) with current limits");
141 ATF_TC_BODY(setrlimit_current, tc)
146 for (i = 0; i < __arraycount(rlimit); i++) {
148 (void)memset(&res, 0, sizeof(struct rlimit));
150 ATF_REQUIRE(getrlimit(rlimit[i], &res) == 0);
151 ATF_REQUIRE(setrlimit(rlimit[i], &res) == 0);
155 ATF_TC(setrlimit_err);
156 ATF_TC_HEAD(setrlimit_err, tc)
158 atf_tc_set_md_var(tc, "descr", "Test error conditions");
161 ATF_TC_BODY(setrlimit_err, tc)
166 for (i = 0; i < __arraycount(rlimit); i++) {
170 ATF_REQUIRE(getrlimit(rlimit[i], (void *)0) != 0);
171 ATF_REQUIRE(errno == EFAULT);
176 ATF_REQUIRE(getrlimit(INT_MAX, &res) != 0);
177 ATF_REQUIRE(errno == EINVAL);
180 ATF_TC_WITH_CLEANUP(setrlimit_fsize);
181 ATF_TC_HEAD(setrlimit_fsize, tc)
183 atf_tc_set_md_var(tc, "descr", "Test setrlimit(2), RLIMIT_FSIZE");
186 ATF_TC_BODY(setrlimit_fsize, tc)
192 fd = open(path, O_RDWR | O_CREAT, 0700);
195 atf_tc_fail("initialization failed");
198 ATF_REQUIRE(pid >= 0);
205 if (setrlimit(RLIMIT_FSIZE, &res) != 0)
208 if (signal(SIGXFSZ, sighandler) == SIG_ERR)
212 * The third call should generate a SIGXFSZ.
214 (void)write(fd, "X", 1);
215 (void)write(fd, "X", 1);
216 (void)write(fd, "X", 1);
225 if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
226 atf_tc_fail("RLIMIT_FSIZE not enforced");
229 ATF_TC_CLEANUP(setrlimit_fsize, tc)
235 sighandler(int signo)
238 if (signo != SIGXFSZ)
245 ATF_TC_WITH_CLEANUP(setrlimit_memlock);
247 ATF_TC(setrlimit_memlock);
249 ATF_TC_HEAD(setrlimit_memlock, tc)
251 atf_tc_set_md_var(tc, "descr", "Test setrlimit(2), RLIMIT_MEMLOCK");
253 atf_tc_set_md_var(tc, "require.config", "allow_sysctl_side_effects");
254 atf_tc_set_md_var(tc, "require.user", "root");
258 ATF_TC_BODY(setrlimit_memlock, tc)
267 /* Set max_wired really really high to avoid EAGAIN */
268 set_vm_max_wired(INT_MAX);
271 page = sysconf(_SC_PAGESIZE);
272 ATF_REQUIRE(page >= 0);
277 if (buf == NULL || pid < 0)
278 atf_tc_fail("initialization failed");
283 * Try to lock a page while
284 * RLIMIT_MEMLOCK is zero.
286 if (mlock(buf, page) != 0)
289 if (munlock(buf, page) != 0)
295 if (setrlimit(RLIMIT_MEMLOCK, &res) != 0)
298 if (mlock(buf, page) != 0)
301 (void)munlock(buf, page);
310 if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
311 atf_tc_fail("RLIMIT_MEMLOCK not enforced");
315 ATF_TC_CLEANUP(setrlimit_memlock, tc)
318 restore_vm_max_wired();
322 ATF_TC(setrlimit_nofile_1);
323 ATF_TC_HEAD(setrlimit_nofile_1, tc)
325 atf_tc_set_md_var(tc, "descr", "Test setrlimit(2), RLIMIT_NOFILE, #1");
328 ATF_TC_BODY(setrlimit_nofile_1, tc)
338 ATF_REQUIRE(pid >= 0);
343 * Close all descriptors, set RLIMIT_NOFILE
344 * to zero, and try to open a random file.
345 * This should fail with EMFILE.
347 for (i = 0; i < 1024; i++)
350 rv = setrlimit(RLIMIT_NOFILE, &res);
356 fd = open("/etc/passwd", O_RDONLY);
358 if (fd >= 0 || errno != EMFILE)
366 if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
367 atf_tc_fail("RLIMIT_NOFILE not enforced");
370 ATF_TC(setrlimit_nofile_2);
371 ATF_TC_HEAD(setrlimit_nofile_2, tc)
373 atf_tc_set_md_var(tc, "descr", "Test setrlimit(2), RLIMIT_NOFILE, #2");
376 ATF_TC_BODY(setrlimit_nofile_2, tc)
378 static const rlim_t lim = 12;
384 * See that an arbitrary limit on
385 * open files is being enforced.
391 ATF_REQUIRE(pid >= 0);
395 for (i = 0; i < 1024; i++)
398 rv = setrlimit(RLIMIT_NOFILE, &res);
403 for (i = 0; i < (int)lim; i++) {
405 fd = open("/etc/passwd", O_RDONLY);
412 * After the limit has been reached,
413 * EMFILE should again follow.
415 fd = open("/etc/passwd", O_RDONLY);
417 if (fd >= 0 || errno != EMFILE)
425 if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
426 atf_tc_fail("RLIMIT_NOFILE not enforced");
429 ATF_TC(setrlimit_nproc);
430 ATF_TC_HEAD(setrlimit_nproc, tc)
432 atf_tc_set_md_var(tc, "descr", "Test setrlimit(2), RLIMIT_NPROC");
433 atf_tc_set_md_var(tc, "require.user", "unprivileged");
436 ATF_TC_BODY(setrlimit_nproc, tc)
443 ATF_REQUIRE(pid >= 0);
448 * Set RLIMIT_NPROC to zero and try to fork.
453 if (setrlimit(RLIMIT_NPROC, &res) != 0)
464 (void)waitpid(pid, &sta, 0);
466 if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
467 atf_tc_fail("RLIMIT_NPROC not enforced");
471 ATF_TC(setrlimit_nthr);
472 ATF_TC_HEAD(setrlimit_nthr, tc)
474 atf_tc_set_md_var(tc, "descr", "Test setrlimit(2), RLIMIT_NTHR");
475 atf_tc_set_md_var(tc, "require.user", "unprivileged");
481 printf("thread %d\n", *id);
486 ATF_TC_BODY(setrlimit_nthr, tc)
493 * Set RLIMIT_NTHR to zero and try to create a thread.
497 ATF_REQUIRE(setrlimit(RLIMIT_NTHR, &res) == 0);
498 ATF_REQUIRE(getcontext(&c) == 0);
500 sigemptyset(&c.uc_sigmask);
501 c.uc_stack.ss_flags = 0;
502 c.uc_stack.ss_size = 4096;
503 ATF_REQUIRE((c.uc_stack.ss_sp = malloc(c.uc_stack.ss_size)) != NULL);
504 makecontext(&c, func, 1, &lwpid);
505 ATF_CHECK_ERRNO(EAGAIN, _lwp_create(&c, 0, &lwpid) == -1);
509 ATF_TC(setrlimit_perm);
510 ATF_TC_HEAD(setrlimit_perm, tc)
512 atf_tc_set_md_var(tc, "descr", "Test setrlimit(2) for EPERM");
513 atf_tc_set_md_var(tc, "require.user", "unprivileged");
516 ATF_TC_BODY(setrlimit_perm, tc)
522 * Try to raise the maximum limits as an user.
524 for (i = 0; i < __arraycount(rlimit); i++) {
526 ATF_REQUIRE(getrlimit(rlimit[i], &res) == 0);
529 if (res.rlim_max == INT64_MAX) /* Overflow. */
531 if (res.rlim_max == UINT64_MAX) /* Overflow. */
536 res.rlim_max = res.rlim_max + 1;
538 ATF_CHECK_ERRNO(EPERM, setrlimit(rlimit[i], &res) != 0);
542 ATF_TC(setrlimit_stack);
543 ATF_TC_HEAD(setrlimit_stack, tc)
545 atf_tc_set_md_var(tc, "descr", "Test setrlimit(2), RLIMIT_STACK");
546 atf_tc_set_md_var(tc, "require.user", "unprivileged");
549 ATF_TC_BODY(setrlimit_stack, tc)
553 /* Ensure soft limit is not bigger than hard limit */
554 res.rlim_cur = res.rlim_max = 4192256;
555 ATF_REQUIRE(setrlimit(RLIMIT_STACK, &res) == 0);
556 ATF_REQUIRE(getrlimit(RLIMIT_STACK, &res) == 0);
557 ATF_CHECK(res.rlim_cur <= res.rlim_max);
564 ATF_TP_ADD_TC(tp, setrlimit_basic);
565 ATF_TP_ADD_TC(tp, setrlimit_current);
566 ATF_TP_ADD_TC(tp, setrlimit_err);
567 ATF_TP_ADD_TC(tp, setrlimit_fsize);
568 ATF_TP_ADD_TC(tp, setrlimit_memlock);
569 ATF_TP_ADD_TC(tp, setrlimit_nofile_1);
570 ATF_TP_ADD_TC(tp, setrlimit_nofile_2);
571 ATF_TP_ADD_TC(tp, setrlimit_nproc);
572 ATF_TP_ADD_TC(tp, setrlimit_perm);
574 ATF_TP_ADD_TC(tp, setrlimit_nthr);
576 ATF_TP_ADD_TC(tp, setrlimit_stack);
578 return atf_no_error();