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>
51 static void sighandler(int);
52 static const char path
[] = "setrlimit";
54 static const int rlimit
[] = {
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
)
80 buf
= calloc(__arraycount(rlimit
), sizeof(int));
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)
92 if (res
.rlim_cur
== RLIM_INFINITY
|| res
.rlim_cur
== 0)
95 if (res
.rlim_cur
== res
.rlim_max
) /* An unprivileged run. */
98 buf
[i
] = res
.rlim_cur
;
99 res
.rlim_cur
= res
.rlim_cur
- 1;
101 if (setrlimit(rlimit
[i
], &res
) != 0) {
108 for (i
= 0; i
< __arraycount(rlimit
); i
++) {
110 (void)memset(&res
, 0, sizeof(struct rlimit
));
115 if (getrlimit(rlimit
[i
], &res
) != 0)
118 res
.rlim_cur
= buf
[i
];
120 (void)setrlimit(rlimit
[i
], &res
);
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
)
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
)
158 for (i
= 0; i
< __arraycount(rlimit
); i
++) {
162 ATF_REQUIRE(getrlimit(rlimit
[i
], (void *)0) != 0);
163 ATF_REQUIRE(errno
== EFAULT
);
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
)
184 fd
= open(path
, O_RDWR
| O_CREAT
, 0700);
187 atf_tc_fail("initialization failed");
190 ATF_REQUIRE(pid
>= 0);
197 if (setrlimit(RLIMIT_FSIZE
, &res
) != 0)
200 if (signal(SIGXFSZ
, sighandler
) == SIG_ERR
)
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);
217 if (WIFEXITED(sta
) == 0 || WEXITSTATUS(sta
) != EXIT_SUCCESS
)
218 atf_tc_fail("RLIMIT_FSIZE not enforced");
221 ATF_TC_CLEANUP(setrlimit_fsize
, tc
)
227 sighandler(int signo
)
230 if (signo
!= SIGXFSZ
)
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
)
250 page
= sysconf(_SC_PAGESIZE
);
251 ATF_REQUIRE(page
>= 0);
256 if (buf
== NULL
|| pid
< 0)
257 atf_tc_fail("initialization failed");
262 * Try to lock a page while
263 * RLIMIT_MEMLOCK is zero.
265 if (mlock(buf
, page
) != 0)
268 if (munlock(buf
, page
) != 0)
274 if (setrlimit(RLIMIT_MEMLOCK
, &res
) != 0)
277 if (mlock(buf
, page
) != 0)
280 (void)munlock(buf
, page
);
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
)
309 ATF_REQUIRE(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
++)
321 rv
= setrlimit(RLIMIT_NOFILE
, &res
);
327 fd
= open("/etc/passwd", O_RDONLY
);
329 if (fd
>= 0 || errno
!= EMFILE
)
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;
355 * See that an arbitrary limit on
356 * open files is being enforced.
362 ATF_REQUIRE(pid
>= 0);
366 for (i
= 0; i
< 1024; i
++)
369 rv
= setrlimit(RLIMIT_NOFILE
, &res
);
374 for (i
= 0; i
< (int)lim
; i
++) {
376 fd
= open("/etc/passwd", O_RDONLY
);
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
)
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
)
414 ATF_REQUIRE(pid
>= 0);
419 * Set RLIMIT_NPROC to zero and try to fork.
424 if (setrlimit(RLIMIT_NPROC
, &res
) != 0)
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");
451 printf("thread %d\n", *id
);
456 ATF_TC_BODY(setrlimit_nthr
, tc
)
463 * Set RLIMIT_NTHR to zero and try to create a thread.
467 ATF_REQUIRE(setrlimit(RLIMIT_NTHR
, &res
) == 0);
468 ATF_REQUIRE(getcontext(&c
) == 0);
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
)
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. */
501 res
.rlim_max
= res
.rlim_max
+ 1;
503 ATF_CHECK_ERRNO(EPERM
, setrlimit(rlimit
[i
], &res
) != 0);
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();