1 /* $NetBSD: t_setrlimit.c,v 1.5 2016/07/13 09:53:16 njoly 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.5 2016/07/13 09:53:16 njoly 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);
132 ATF_TC(setrlimit_current);
133 ATF_TC_HEAD(setrlimit_current, tc)
135 atf_tc_set_md_var(tc, "descr", "setrlimit(3) with current limits");
138 ATF_TC_BODY(setrlimit_current, tc)
143 for (i = 0; i < __arraycount(rlimit); i++) {
145 (void)memset(&res, 0, sizeof(struct rlimit));
147 ATF_REQUIRE(getrlimit(rlimit[i], &res) == 0);
148 ATF_REQUIRE(setrlimit(rlimit[i], &res) == 0);
152 ATF_TC(setrlimit_err);
153 ATF_TC_HEAD(setrlimit_err, tc)
155 atf_tc_set_md_var(tc, "descr", "Test error conditions");
158 ATF_TC_BODY(setrlimit_err, tc)
163 for (i = 0; i < __arraycount(rlimit); i++) {
167 ATF_REQUIRE(getrlimit(rlimit[i], (void *)0) != 0);
168 ATF_REQUIRE(errno == EFAULT);
173 ATF_REQUIRE(getrlimit(INT_MAX, &res) != 0);
174 ATF_REQUIRE(errno == EINVAL);
177 ATF_TC_WITH_CLEANUP(setrlimit_fsize);
178 ATF_TC_HEAD(setrlimit_fsize, tc)
180 atf_tc_set_md_var(tc, "descr", "Test setrlimit(2), RLIMIT_FSIZE");
183 ATF_TC_BODY(setrlimit_fsize, tc)
189 fd = open(path, O_RDWR | O_CREAT, 0700);
192 atf_tc_fail("initialization failed");
195 ATF_REQUIRE(pid >= 0);
202 if (setrlimit(RLIMIT_FSIZE, &res) != 0)
205 if (signal(SIGXFSZ, sighandler) == SIG_ERR)
209 * The third call should generate a SIGXFSZ.
211 (void)write(fd, "X", 1);
212 (void)write(fd, "X", 1);
213 (void)write(fd, "X", 1);
222 if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
223 atf_tc_fail("RLIMIT_FSIZE not enforced");
226 ATF_TC_CLEANUP(setrlimit_fsize, tc)
232 sighandler(int signo)
235 if (signo != SIGXFSZ)
241 ATF_TC(setrlimit_memlock);
242 ATF_TC_HEAD(setrlimit_memlock, tc)
244 atf_tc_set_md_var(tc, "descr", "Test setrlimit(2), RLIMIT_MEMLOCK");
247 ATF_TC_BODY(setrlimit_memlock, tc)
255 page = sysconf(_SC_PAGESIZE);
256 ATF_REQUIRE(page >= 0);
261 if (buf == NULL || pid < 0)
262 atf_tc_fail("initialization failed");
267 * Try to lock a page while
268 * RLIMIT_MEMLOCK is zero.
270 if (mlock(buf, page) != 0)
273 if (munlock(buf, page) != 0)
279 if (setrlimit(RLIMIT_MEMLOCK, &res) != 0)
282 if (mlock(buf, page) != 0)
285 (void)munlock(buf, page);
294 if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
295 atf_tc_fail("RLIMIT_MEMLOCK not enforced");
298 ATF_TC(setrlimit_nofile_1);
299 ATF_TC_HEAD(setrlimit_nofile_1, tc)
301 atf_tc_set_md_var(tc, "descr", "Test setrlimit(2), RLIMIT_NOFILE, #1");
304 ATF_TC_BODY(setrlimit_nofile_1, tc)
314 ATF_REQUIRE(pid >= 0);
319 * Close all descriptors, set RLIMIT_NOFILE
320 * to zero, and try to open a random file.
321 * This should fail with EMFILE.
323 for (i = 0; i < 1024; i++)
326 rv = setrlimit(RLIMIT_NOFILE, &res);
332 fd = open("/etc/passwd", O_RDONLY);
334 if (fd >= 0 || errno != EMFILE)
342 if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
343 atf_tc_fail("RLIMIT_NOFILE not enforced");
346 ATF_TC(setrlimit_nofile_2);
347 ATF_TC_HEAD(setrlimit_nofile_2, tc)
349 atf_tc_set_md_var(tc, "descr", "Test setrlimit(2), RLIMIT_NOFILE, #2");
352 ATF_TC_BODY(setrlimit_nofile_2, tc)
354 static const rlim_t lim = 12;
360 * See that an arbitrary limit on
361 * open files is being enforced.
367 ATF_REQUIRE(pid >= 0);
371 for (i = 0; i < 1024; i++)
374 rv = setrlimit(RLIMIT_NOFILE, &res);
379 for (i = 0; i < (int)lim; i++) {
381 fd = open("/etc/passwd", O_RDONLY);
388 * After the limit has been reached,
389 * EMFILE should again follow.
391 fd = open("/etc/passwd", O_RDONLY);
393 if (fd >= 0 || errno != EMFILE)
401 if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
402 atf_tc_fail("RLIMIT_NOFILE not enforced");
405 ATF_TC(setrlimit_nproc);
406 ATF_TC_HEAD(setrlimit_nproc, tc)
408 atf_tc_set_md_var(tc, "descr", "Test setrlimit(2), RLIMIT_NPROC");
409 atf_tc_set_md_var(tc, "require.user", "unprivileged");
412 ATF_TC_BODY(setrlimit_nproc, tc)
419 ATF_REQUIRE(pid >= 0);
424 * Set RLIMIT_NPROC to zero and try to fork.
429 if (setrlimit(RLIMIT_NPROC, &res) != 0)
440 (void)waitpid(pid, &sta, 0);
442 if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
443 atf_tc_fail("RLIMIT_NPROC not enforced");
447 ATF_TC(setrlimit_nthr);
448 ATF_TC_HEAD(setrlimit_nthr, tc)
450 atf_tc_set_md_var(tc, "descr", "Test setrlimit(2), RLIMIT_NTHR");
451 atf_tc_set_md_var(tc, "require.user", "unprivileged");
457 printf("thread %d\n", *id);
462 ATF_TC_BODY(setrlimit_nthr, tc)
469 * Set RLIMIT_NTHR to zero and try to create a thread.
473 ATF_REQUIRE(setrlimit(RLIMIT_NTHR, &res) == 0);
474 ATF_REQUIRE(getcontext(&c) == 0);
476 sigemptyset(&c.uc_sigmask);
477 c.uc_stack.ss_flags = 0;
478 c.uc_stack.ss_size = 4096;
479 ATF_REQUIRE((c.uc_stack.ss_sp = malloc(c.uc_stack.ss_size)) != NULL);
480 makecontext(&c, func, 1, &lwpid);
481 ATF_CHECK_ERRNO(EAGAIN, _lwp_create(&c, 0, &lwpid) == -1);
485 ATF_TC(setrlimit_perm);
486 ATF_TC_HEAD(setrlimit_perm, tc)
488 atf_tc_set_md_var(tc, "descr", "Test setrlimit(2) for EPERM");
489 atf_tc_set_md_var(tc, "require.user", "unprivileged");
492 ATF_TC_BODY(setrlimit_perm, tc)
498 * Try to raise the maximum limits as an user.
500 for (i = 0; i < __arraycount(rlimit); i++) {
502 ATF_REQUIRE(getrlimit(rlimit[i], &res) == 0);
505 if (res.rlim_max == INT64_MAX) /* Overflow. */
507 if (res.rlim_max == UINT64_MAX) /* Overflow. */
512 res.rlim_max = res.rlim_max + 1;
514 ATF_CHECK_ERRNO(EPERM, setrlimit(rlimit[i], &res) != 0);
518 ATF_TC(setrlimit_stack);
519 ATF_TC_HEAD(setrlimit_stack, tc)
521 atf_tc_set_md_var(tc, "descr", "Test setrlimit(2), RLIMIT_STACK");
522 atf_tc_set_md_var(tc, "require.user", "unprivileged");
525 ATF_TC_BODY(setrlimit_stack, tc)
529 /* Ensure soft limit is not bigger than hard limit */
530 res.rlim_cur = res.rlim_max = 4192256;
531 ATF_REQUIRE(setrlimit(RLIMIT_STACK, &res) == 0);
532 ATF_REQUIRE(getrlimit(RLIMIT_STACK, &res) == 0);
533 ATF_CHECK(res.rlim_cur <= res.rlim_max);
540 ATF_TP_ADD_TC(tp, setrlimit_basic);
541 ATF_TP_ADD_TC(tp, setrlimit_current);
542 ATF_TP_ADD_TC(tp, setrlimit_err);
543 ATF_TP_ADD_TC(tp, setrlimit_fsize);
544 ATF_TP_ADD_TC(tp, setrlimit_memlock);
545 ATF_TP_ADD_TC(tp, setrlimit_nofile_1);
546 ATF_TP_ADD_TC(tp, setrlimit_nofile_2);
547 ATF_TP_ADD_TC(tp, setrlimit_nproc);
548 ATF_TP_ADD_TC(tp, setrlimit_perm);
550 ATF_TP_ADD_TC(tp, setrlimit_nthr);
552 ATF_TP_ADD_TC(tp, setrlimit_stack);
554 return atf_no_error();