Remove building with NOCRYPTO option
[minix.git] / tests / lib / libc / sys / t_setrlimit.c
blobc760cfbf59eaa408ce7ae59be557b3956fb2d983
1 /* $NetBSD: t_setrlimit.c,v 1.4 2012/06/12 23:56:19 christos Exp $ */
3 /*-
4 * Copyright (c) 2011 The NetBSD Foundation, Inc.
5 * All rights reserved.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Jukka Ruohonen.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
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>
35 #include <sys/mman.h>
36 #include <sys/wait.h>
38 #include <atf-c.h>
39 #include <errno.h>
40 #include <fcntl.h>
41 #include <limits.h>
42 #include <lwp.h>
43 #include <signal.h>
44 #include <stdint.h>
45 #include <stdio.h>
46 #include <stdlib.h>
47 #include <string.h>
48 #include <ucontext.h>
49 #include <unistd.h>
51 static void sighandler(int);
52 static const char path[] = "setrlimit";
54 static const int rlimit[] = {
55 RLIMIT_AS,
56 RLIMIT_CORE,
57 RLIMIT_CPU,
58 RLIMIT_DATA,
59 RLIMIT_FSIZE,
60 RLIMIT_MEMLOCK,
61 RLIMIT_NOFILE,
62 RLIMIT_NPROC,
63 RLIMIT_RSS,
64 RLIMIT_SBSIZE,
65 RLIMIT_STACK
68 ATF_TC(setrlimit_basic);
69 ATF_TC_HEAD(setrlimit_basic, tc)
71 atf_tc_set_md_var(tc, "descr", "A basic soft limit test");
74 ATF_TC_BODY(setrlimit_basic, tc)
76 struct rlimit res;
77 int *buf, lim;
78 size_t i;
80 buf = calloc(__arraycount(rlimit), sizeof(int));
82 if (buf == NULL)
83 atf_tc_fail("initialization failed");
85 for (i = lim = 0; i < __arraycount(rlimit); i++) {
87 (void)memset(&res, 0, sizeof(struct rlimit));
89 if (getrlimit(rlimit[i], &res) != 0)
90 continue;
92 if (res.rlim_cur == RLIM_INFINITY || res.rlim_cur == 0)
93 continue;
95 if (res.rlim_cur == res.rlim_max) /* An unprivileged run. */
96 continue;
98 buf[i] = res.rlim_cur;
99 res.rlim_cur = res.rlim_cur - 1;
101 if (setrlimit(rlimit[i], &res) != 0) {
102 lim = rlimit[i];
103 goto out;
107 out:
108 for (i = 0; i < __arraycount(rlimit); i++) {
110 (void)memset(&res, 0, sizeof(struct rlimit));
112 if (buf[i] == 0)
113 continue;
115 if (getrlimit(rlimit[i], &res) != 0)
116 continue;
118 res.rlim_cur = buf[i];
120 (void)setrlimit(rlimit[i], &res);
123 if (lim != 0)
124 atf_tc_fail("failed to set limit (%d)", lim);
127 ATF_TC(setrlimit_current);
128 ATF_TC_HEAD(setrlimit_current, tc)
130 atf_tc_set_md_var(tc, "descr", "setrlimit(3) with current limits");
133 ATF_TC_BODY(setrlimit_current, tc)
135 struct rlimit res;
136 size_t i;
138 for (i = 0; i < __arraycount(rlimit); i++) {
140 (void)memset(&res, 0, sizeof(struct rlimit));
142 ATF_REQUIRE(getrlimit(rlimit[i], &res) == 0);
143 ATF_REQUIRE(setrlimit(rlimit[i], &res) == 0);
147 ATF_TC(setrlimit_err);
148 ATF_TC_HEAD(setrlimit_err, tc)
150 atf_tc_set_md_var(tc, "descr", "Test error conditions");
153 ATF_TC_BODY(setrlimit_err, tc)
155 struct rlimit res;
156 size_t i;
158 for (i = 0; i < __arraycount(rlimit); i++) {
160 errno = 0;
162 ATF_REQUIRE(getrlimit(rlimit[i], (void *)0) != 0);
163 ATF_REQUIRE(errno == EFAULT);
166 errno = 0;
168 ATF_REQUIRE(getrlimit(INT_MAX, &res) != 0);
169 ATF_REQUIRE(errno == EINVAL);
172 ATF_TC_WITH_CLEANUP(setrlimit_fsize);
173 ATF_TC_HEAD(setrlimit_fsize, tc)
175 atf_tc_set_md_var(tc, "descr", "Test setrlimit(2), RLIMIT_FSIZE");
178 ATF_TC_BODY(setrlimit_fsize, tc)
180 struct rlimit res;
181 int fd, sta;
182 pid_t pid;
184 fd = open(path, O_RDWR | O_CREAT, 0700);
186 if (fd < 0)
187 atf_tc_fail("initialization failed");
189 pid = fork();
190 ATF_REQUIRE(pid >= 0);
192 if (pid == 0) {
194 res.rlim_cur = 2;
195 res.rlim_max = 2;
197 if (setrlimit(RLIMIT_FSIZE, &res) != 0)
198 _exit(EXIT_FAILURE);
200 if (signal(SIGXFSZ, sighandler) == SIG_ERR)
201 _exit(EXIT_FAILURE);
204 * The third call should generate a SIGXFSZ.
206 (void)write(fd, "X", 1);
207 (void)write(fd, "X", 1);
208 (void)write(fd, "X", 1);
210 _exit(EXIT_FAILURE);
213 (void)close(fd);
214 (void)wait(&sta);
215 (void)unlink(path);
217 if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
218 atf_tc_fail("RLIMIT_FSIZE not enforced");
221 ATF_TC_CLEANUP(setrlimit_fsize, tc)
223 (void)unlink(path);
226 static void
227 sighandler(int signo)
230 if (signo != SIGXFSZ)
231 _exit(EXIT_FAILURE);
233 _exit(EXIT_SUCCESS);
236 ATF_TC(setrlimit_memlock);
237 ATF_TC_HEAD(setrlimit_memlock, tc)
239 atf_tc_set_md_var(tc, "descr", "Test setrlimit(2), RLIMIT_MEMLOCK");
242 ATF_TC_BODY(setrlimit_memlock, tc)
244 struct rlimit res;
245 void *buf;
246 long page;
247 pid_t pid;
248 int sta;
250 page = sysconf(_SC_PAGESIZE);
251 ATF_REQUIRE(page >= 0);
253 buf = malloc(page);
254 pid = fork();
256 if (buf == NULL || pid < 0)
257 atf_tc_fail("initialization failed");
259 if (pid == 0) {
262 * Try to lock a page while
263 * RLIMIT_MEMLOCK is zero.
265 if (mlock(buf, page) != 0)
266 _exit(EXIT_FAILURE);
268 if (munlock(buf, page) != 0)
269 _exit(EXIT_FAILURE);
271 res.rlim_cur = 0;
272 res.rlim_max = 0;
274 if (setrlimit(RLIMIT_MEMLOCK, &res) != 0)
275 _exit(EXIT_FAILURE);
277 if (mlock(buf, page) != 0)
278 _exit(EXIT_SUCCESS);
280 (void)munlock(buf, page);
282 _exit(EXIT_FAILURE);
285 free(buf);
287 (void)wait(&sta);
289 if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
290 atf_tc_fail("RLIMIT_MEMLOCK not enforced");
293 ATF_TC(setrlimit_nofile_1);
294 ATF_TC_HEAD(setrlimit_nofile_1, tc)
296 atf_tc_set_md_var(tc, "descr", "Test setrlimit(2), RLIMIT_NOFILE, #1");
299 ATF_TC_BODY(setrlimit_nofile_1, tc)
301 struct rlimit res;
302 int fd, i, rv, sta;
303 pid_t pid;
305 res.rlim_cur = 0;
306 res.rlim_max = 0;
308 pid = fork();
309 ATF_REQUIRE(pid >= 0);
311 if (pid == 0) {
314 * Close all descriptors, set RLIMIT_NOFILE
315 * to zero, and try to open a random file.
316 * This should fail with EMFILE.
318 for (i = 0; i < 1024; i++)
319 (void)close(i);
321 rv = setrlimit(RLIMIT_NOFILE, &res);
323 if (rv != 0)
324 _exit(EXIT_FAILURE);
326 errno = 0;
327 fd = open("/etc/passwd", O_RDONLY);
329 if (fd >= 0 || errno != EMFILE)
330 _exit(EXIT_FAILURE);
332 _exit(EXIT_SUCCESS);
335 (void)wait(&sta);
337 if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
338 atf_tc_fail("RLIMIT_NOFILE not enforced");
341 ATF_TC(setrlimit_nofile_2);
342 ATF_TC_HEAD(setrlimit_nofile_2, tc)
344 atf_tc_set_md_var(tc, "descr", "Test setrlimit(2), RLIMIT_NOFILE, #2");
347 ATF_TC_BODY(setrlimit_nofile_2, tc)
349 static const rlim_t lim = 12;
350 struct rlimit res;
351 int fd, i, rv, sta;
352 pid_t pid;
355 * See that an arbitrary limit on
356 * open files is being enforced.
358 res.rlim_cur = lim;
359 res.rlim_max = lim;
361 pid = fork();
362 ATF_REQUIRE(pid >= 0);
364 if (pid == 0) {
366 for (i = 0; i < 1024; i++)
367 (void)close(i);
369 rv = setrlimit(RLIMIT_NOFILE, &res);
371 if (rv != 0)
372 _exit(EXIT_FAILURE);
374 for (i = 0; i < (int)lim; i++) {
376 fd = open("/etc/passwd", O_RDONLY);
378 if (fd < 0)
379 _exit(EXIT_FAILURE);
383 * After the limit has been reached,
384 * EMFILE should again follow.
386 fd = open("/etc/passwd", O_RDONLY);
388 if (fd >= 0 || errno != EMFILE)
389 _exit(EXIT_FAILURE);
391 _exit(EXIT_SUCCESS);
394 (void)wait(&sta);
396 if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
397 atf_tc_fail("RLIMIT_NOFILE not enforced");
400 ATF_TC(setrlimit_nproc);
401 ATF_TC_HEAD(setrlimit_nproc, tc)
403 atf_tc_set_md_var(tc, "descr", "Test setrlimit(2), RLIMIT_NPROC");
404 atf_tc_set_md_var(tc, "require.user", "unprivileged");
407 ATF_TC_BODY(setrlimit_nproc, tc)
409 struct rlimit res;
410 pid_t pid, cpid;
411 int sta;
413 pid = fork();
414 ATF_REQUIRE(pid >= 0);
416 if (pid == 0) {
419 * Set RLIMIT_NPROC to zero and try to fork.
421 res.rlim_cur = 0;
422 res.rlim_max = 0;
424 if (setrlimit(RLIMIT_NPROC, &res) != 0)
425 _exit(EXIT_FAILURE);
427 cpid = fork();
429 if (cpid < 0)
430 _exit(EXIT_SUCCESS);
432 _exit(EXIT_FAILURE);
435 (void)waitpid(pid, &sta, 0);
437 if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
438 atf_tc_fail("RLIMIT_NPROC not enforced");
441 ATF_TC(setrlimit_nthr);
442 ATF_TC_HEAD(setrlimit_nthr, tc)
444 atf_tc_set_md_var(tc, "descr", "Test setrlimit(2), RLIMIT_NTHR");
445 atf_tc_set_md_var(tc, "require.user", "unprivileged");
448 static void
449 func(lwpid_t *id)
451 printf("thread %d\n", *id);
452 fflush(stdout);
453 _lwp_exit();
456 ATF_TC_BODY(setrlimit_nthr, tc)
458 struct rlimit res;
459 lwpid_t lwpid;
460 ucontext_t c;
463 * Set RLIMIT_NTHR to zero and try to create a thread.
465 res.rlim_cur = 0;
466 res.rlim_max = 0;
467 ATF_REQUIRE(setrlimit(RLIMIT_NTHR, &res) == 0);
468 ATF_REQUIRE(getcontext(&c) == 0);
469 c.uc_link = NULL;
470 sigemptyset(&c.uc_sigmask);
471 c.uc_stack.ss_flags = 0;
472 c.uc_stack.ss_size = 4096;
473 ATF_REQUIRE((c.uc_stack.ss_sp = malloc(c.uc_stack.ss_size)) != NULL);
474 makecontext(&c, func, 1, &lwpid);
475 ATF_CHECK_ERRNO(EAGAIN, _lwp_create(&c, 0, &lwpid) == -1);
478 ATF_TC(setrlimit_perm);
479 ATF_TC_HEAD(setrlimit_perm, tc)
481 atf_tc_set_md_var(tc, "descr", "Test setrlimit(2) for EPERM");
482 atf_tc_set_md_var(tc, "require.user", "unprivileged");
485 ATF_TC_BODY(setrlimit_perm, tc)
487 struct rlimit res;
488 size_t i;
491 * Try to raise the maximum limits as an user.
493 for (i = 0; i < __arraycount(rlimit); i++) {
495 ATF_REQUIRE(getrlimit(rlimit[i], &res) == 0);
497 if (res.rlim_max == UINT64_MAX) /* Overflow. */
498 continue;
500 errno = 0;
501 res.rlim_max = res.rlim_max + 1;
503 ATF_CHECK_ERRNO(EPERM, setrlimit(rlimit[i], &res) != 0);
507 ATF_TP_ADD_TCS(tp)
510 ATF_TP_ADD_TC(tp, setrlimit_basic);
511 ATF_TP_ADD_TC(tp, setrlimit_current);
512 ATF_TP_ADD_TC(tp, setrlimit_err);
513 ATF_TP_ADD_TC(tp, setrlimit_fsize);
514 ATF_TP_ADD_TC(tp, setrlimit_memlock);
515 ATF_TP_ADD_TC(tp, setrlimit_nofile_1);
516 ATF_TP_ADD_TC(tp, setrlimit_nofile_2);
517 ATF_TP_ADD_TC(tp, setrlimit_nproc);
518 ATF_TP_ADD_TC(tp, setrlimit_perm);
519 ATF_TP_ADD_TC(tp, setrlimit_nthr);
521 return atf_no_error();