1*63d1fd59SEnji Cooper /* $NetBSD: t_setrlimit.c,v 1.6 2017/01/13 21:16:38 christos Exp $ */
257718be8SEnji Cooper
357718be8SEnji Cooper /*-
457718be8SEnji Cooper * Copyright (c) 2011 The NetBSD Foundation, Inc.
557718be8SEnji Cooper * All rights reserved.
657718be8SEnji Cooper *
757718be8SEnji Cooper * This code is derived from software contributed to The NetBSD Foundation
857718be8SEnji Cooper * by Jukka Ruohonen.
957718be8SEnji Cooper *
1057718be8SEnji Cooper * Redistribution and use in source and binary forms, with or without
1157718be8SEnji Cooper * modification, are permitted provided that the following conditions
1257718be8SEnji Cooper * are met:
1357718be8SEnji Cooper * 1. Redistributions of source code must retain the above copyright
1457718be8SEnji Cooper * notice, this list of conditions and the following disclaimer.
1557718be8SEnji Cooper * 2. Redistributions in binary form must reproduce the above copyright
1657718be8SEnji Cooper * notice, this list of conditions and the following disclaimer in the
1757718be8SEnji Cooper * documentation and/or other materials provided with the distribution.
1857718be8SEnji Cooper *
1957718be8SEnji Cooper * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
2057718be8SEnji Cooper * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
2157718be8SEnji Cooper * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2257718be8SEnji Cooper * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
2357718be8SEnji Cooper * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2457718be8SEnji Cooper * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2557718be8SEnji Cooper * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2657718be8SEnji Cooper * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2757718be8SEnji Cooper * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2857718be8SEnji Cooper * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2957718be8SEnji Cooper * POSSIBILITY OF SUCH DAMAGE.
3057718be8SEnji Cooper */
3157718be8SEnji Cooper #include <sys/cdefs.h>
32*63d1fd59SEnji Cooper __RCSID("$NetBSD: t_setrlimit.c,v 1.6 2017/01/13 21:16:38 christos Exp $");
3357718be8SEnji Cooper
3457718be8SEnji Cooper #include <sys/resource.h>
3557718be8SEnji Cooper #include <sys/mman.h>
3657718be8SEnji Cooper #include <sys/wait.h>
3757718be8SEnji Cooper
3857718be8SEnji Cooper #include <atf-c.h>
3957718be8SEnji Cooper #include <errno.h>
4057718be8SEnji Cooper #include <fcntl.h>
4157718be8SEnji Cooper #include <limits.h>
42928eb3afSEnji Cooper #ifdef __NetBSD__
4357718be8SEnji Cooper #include <lwp.h>
44928eb3afSEnji Cooper #endif
4557718be8SEnji Cooper #include <signal.h>
4657718be8SEnji Cooper #include <stdint.h>
4757718be8SEnji Cooper #include <stdio.h>
4857718be8SEnji Cooper #include <stdlib.h>
4957718be8SEnji Cooper #include <string.h>
5057718be8SEnji Cooper #include <ucontext.h>
5157718be8SEnji Cooper #include <unistd.h>
5257718be8SEnji Cooper
53710542dfSBryan Drewery #ifdef __FreeBSD__
54710542dfSBryan Drewery void set_vm_max_wired(int);
55710542dfSBryan Drewery void restore_vm_max_wired(void);
56710542dfSBryan Drewery #endif
57710542dfSBryan Drewery
5857718be8SEnji Cooper static void sighandler(int);
5957718be8SEnji Cooper static const char path[] = "setrlimit";
6057718be8SEnji Cooper
6157718be8SEnji Cooper static const int rlimit[] = {
6257718be8SEnji Cooper RLIMIT_AS,
6357718be8SEnji Cooper RLIMIT_CORE,
6457718be8SEnji Cooper RLIMIT_CPU,
6557718be8SEnji Cooper RLIMIT_DATA,
6657718be8SEnji Cooper RLIMIT_FSIZE,
6757718be8SEnji Cooper RLIMIT_MEMLOCK,
6857718be8SEnji Cooper RLIMIT_NOFILE,
6957718be8SEnji Cooper RLIMIT_NPROC,
7057718be8SEnji Cooper RLIMIT_RSS,
7157718be8SEnji Cooper RLIMIT_SBSIZE,
7257718be8SEnji Cooper RLIMIT_STACK
7357718be8SEnji Cooper };
7457718be8SEnji Cooper
7557718be8SEnji Cooper ATF_TC(setrlimit_basic);
ATF_TC_HEAD(setrlimit_basic,tc)7657718be8SEnji Cooper ATF_TC_HEAD(setrlimit_basic, tc)
7757718be8SEnji Cooper {
7857718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "A basic soft limit test");
7957718be8SEnji Cooper }
8057718be8SEnji Cooper
ATF_TC_BODY(setrlimit_basic,tc)8157718be8SEnji Cooper ATF_TC_BODY(setrlimit_basic, tc)
8257718be8SEnji Cooper {
8357718be8SEnji Cooper struct rlimit res;
8457718be8SEnji Cooper int *buf, lim;
8557718be8SEnji Cooper size_t i;
8657718be8SEnji Cooper
8757718be8SEnji Cooper buf = calloc(__arraycount(rlimit), sizeof(int));
8857718be8SEnji Cooper
8957718be8SEnji Cooper if (buf == NULL)
9057718be8SEnji Cooper atf_tc_fail("initialization failed");
9157718be8SEnji Cooper
9257718be8SEnji Cooper for (i = lim = 0; i < __arraycount(rlimit); i++) {
9357718be8SEnji Cooper
9457718be8SEnji Cooper (void)memset(&res, 0, sizeof(struct rlimit));
9557718be8SEnji Cooper
9657718be8SEnji Cooper if (getrlimit(rlimit[i], &res) != 0)
9757718be8SEnji Cooper continue;
9857718be8SEnji Cooper
9957718be8SEnji Cooper if (res.rlim_cur == RLIM_INFINITY || res.rlim_cur == 0)
10057718be8SEnji Cooper continue;
10157718be8SEnji Cooper
10257718be8SEnji Cooper if (res.rlim_cur == res.rlim_max) /* An unprivileged run. */
10357718be8SEnji Cooper continue;
10457718be8SEnji Cooper
10557718be8SEnji Cooper buf[i] = res.rlim_cur;
10657718be8SEnji Cooper res.rlim_cur = res.rlim_cur - 1;
10757718be8SEnji Cooper
10857718be8SEnji Cooper if (setrlimit(rlimit[i], &res) != 0) {
10957718be8SEnji Cooper lim = rlimit[i];
11057718be8SEnji Cooper goto out;
11157718be8SEnji Cooper }
11257718be8SEnji Cooper }
11357718be8SEnji Cooper
11457718be8SEnji Cooper out:
11557718be8SEnji Cooper for (i = 0; i < __arraycount(rlimit); i++) {
11657718be8SEnji Cooper
11757718be8SEnji Cooper (void)memset(&res, 0, sizeof(struct rlimit));
11857718be8SEnji Cooper
11957718be8SEnji Cooper if (buf[i] == 0)
12057718be8SEnji Cooper continue;
12157718be8SEnji Cooper
12257718be8SEnji Cooper if (getrlimit(rlimit[i], &res) != 0)
12357718be8SEnji Cooper continue;
12457718be8SEnji Cooper
12557718be8SEnji Cooper res.rlim_cur = buf[i];
12657718be8SEnji Cooper
12757718be8SEnji Cooper (void)setrlimit(rlimit[i], &res);
12857718be8SEnji Cooper }
12957718be8SEnji Cooper
13057718be8SEnji Cooper if (lim != 0)
13157718be8SEnji Cooper atf_tc_fail("failed to set limit (%d)", lim);
132dca7cc98SEnji Cooper free(buf);
13357718be8SEnji Cooper }
13457718be8SEnji Cooper
13557718be8SEnji Cooper ATF_TC(setrlimit_current);
ATF_TC_HEAD(setrlimit_current,tc)13657718be8SEnji Cooper ATF_TC_HEAD(setrlimit_current, tc)
13757718be8SEnji Cooper {
13857718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "setrlimit(3) with current limits");
13957718be8SEnji Cooper }
14057718be8SEnji Cooper
ATF_TC_BODY(setrlimit_current,tc)14157718be8SEnji Cooper ATF_TC_BODY(setrlimit_current, tc)
14257718be8SEnji Cooper {
14357718be8SEnji Cooper struct rlimit res;
14457718be8SEnji Cooper size_t i;
14557718be8SEnji Cooper
14657718be8SEnji Cooper for (i = 0; i < __arraycount(rlimit); i++) {
14757718be8SEnji Cooper
14857718be8SEnji Cooper (void)memset(&res, 0, sizeof(struct rlimit));
14957718be8SEnji Cooper
15057718be8SEnji Cooper ATF_REQUIRE(getrlimit(rlimit[i], &res) == 0);
15157718be8SEnji Cooper ATF_REQUIRE(setrlimit(rlimit[i], &res) == 0);
15257718be8SEnji Cooper }
15357718be8SEnji Cooper }
15457718be8SEnji Cooper
15557718be8SEnji Cooper ATF_TC(setrlimit_err);
ATF_TC_HEAD(setrlimit_err,tc)15657718be8SEnji Cooper ATF_TC_HEAD(setrlimit_err, tc)
15757718be8SEnji Cooper {
15857718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Test error conditions");
15957718be8SEnji Cooper }
16057718be8SEnji Cooper
ATF_TC_BODY(setrlimit_err,tc)16157718be8SEnji Cooper ATF_TC_BODY(setrlimit_err, tc)
16257718be8SEnji Cooper {
16357718be8SEnji Cooper struct rlimit res;
16457718be8SEnji Cooper size_t i;
16557718be8SEnji Cooper
16657718be8SEnji Cooper for (i = 0; i < __arraycount(rlimit); i++) {
16757718be8SEnji Cooper
16857718be8SEnji Cooper errno = 0;
16957718be8SEnji Cooper
17057718be8SEnji Cooper ATF_REQUIRE(getrlimit(rlimit[i], (void *)0) != 0);
17157718be8SEnji Cooper ATF_REQUIRE(errno == EFAULT);
17257718be8SEnji Cooper }
17357718be8SEnji Cooper
17457718be8SEnji Cooper errno = 0;
17557718be8SEnji Cooper
17657718be8SEnji Cooper ATF_REQUIRE(getrlimit(INT_MAX, &res) != 0);
17757718be8SEnji Cooper ATF_REQUIRE(errno == EINVAL);
17857718be8SEnji Cooper }
17957718be8SEnji Cooper
18057718be8SEnji Cooper ATF_TC_WITH_CLEANUP(setrlimit_fsize);
ATF_TC_HEAD(setrlimit_fsize,tc)18157718be8SEnji Cooper ATF_TC_HEAD(setrlimit_fsize, tc)
18257718be8SEnji Cooper {
18357718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Test setrlimit(2), RLIMIT_FSIZE");
18457718be8SEnji Cooper }
18557718be8SEnji Cooper
ATF_TC_BODY(setrlimit_fsize,tc)18657718be8SEnji Cooper ATF_TC_BODY(setrlimit_fsize, tc)
18757718be8SEnji Cooper {
18857718be8SEnji Cooper struct rlimit res;
18957718be8SEnji Cooper int fd, sta;
19057718be8SEnji Cooper pid_t pid;
19157718be8SEnji Cooper
19257718be8SEnji Cooper fd = open(path, O_RDWR | O_CREAT, 0700);
19357718be8SEnji Cooper
19457718be8SEnji Cooper if (fd < 0)
19557718be8SEnji Cooper atf_tc_fail("initialization failed");
19657718be8SEnji Cooper
19757718be8SEnji Cooper pid = fork();
19857718be8SEnji Cooper ATF_REQUIRE(pid >= 0);
19957718be8SEnji Cooper
20057718be8SEnji Cooper if (pid == 0) {
20157718be8SEnji Cooper
20257718be8SEnji Cooper res.rlim_cur = 2;
20357718be8SEnji Cooper res.rlim_max = 2;
20457718be8SEnji Cooper
20557718be8SEnji Cooper if (setrlimit(RLIMIT_FSIZE, &res) != 0)
20657718be8SEnji Cooper _exit(EXIT_FAILURE);
20757718be8SEnji Cooper
20857718be8SEnji Cooper if (signal(SIGXFSZ, sighandler) == SIG_ERR)
20957718be8SEnji Cooper _exit(EXIT_FAILURE);
21057718be8SEnji Cooper
21157718be8SEnji Cooper /*
21257718be8SEnji Cooper * The third call should generate a SIGXFSZ.
21357718be8SEnji Cooper */
21457718be8SEnji Cooper (void)write(fd, "X", 1);
21557718be8SEnji Cooper (void)write(fd, "X", 1);
21657718be8SEnji Cooper (void)write(fd, "X", 1);
21757718be8SEnji Cooper
21857718be8SEnji Cooper _exit(EXIT_FAILURE);
21957718be8SEnji Cooper }
22057718be8SEnji Cooper
22157718be8SEnji Cooper (void)close(fd);
22257718be8SEnji Cooper (void)wait(&sta);
22357718be8SEnji Cooper (void)unlink(path);
22457718be8SEnji Cooper
22557718be8SEnji Cooper if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
22657718be8SEnji Cooper atf_tc_fail("RLIMIT_FSIZE not enforced");
22757718be8SEnji Cooper }
22857718be8SEnji Cooper
ATF_TC_CLEANUP(setrlimit_fsize,tc)22957718be8SEnji Cooper ATF_TC_CLEANUP(setrlimit_fsize, tc)
23057718be8SEnji Cooper {
23157718be8SEnji Cooper (void)unlink(path);
23257718be8SEnji Cooper }
23357718be8SEnji Cooper
23457718be8SEnji Cooper static void
sighandler(int signo)23557718be8SEnji Cooper sighandler(int signo)
23657718be8SEnji Cooper {
23757718be8SEnji Cooper
23857718be8SEnji Cooper if (signo != SIGXFSZ)
23957718be8SEnji Cooper _exit(EXIT_FAILURE);
24057718be8SEnji Cooper
24157718be8SEnji Cooper _exit(EXIT_SUCCESS);
24257718be8SEnji Cooper }
24357718be8SEnji Cooper
244710542dfSBryan Drewery #ifdef __FreeBSD__
245710542dfSBryan Drewery ATF_TC_WITH_CLEANUP(setrlimit_memlock);
246710542dfSBryan Drewery #else
24757718be8SEnji Cooper ATF_TC(setrlimit_memlock);
248710542dfSBryan Drewery #endif
ATF_TC_HEAD(setrlimit_memlock,tc)24957718be8SEnji Cooper ATF_TC_HEAD(setrlimit_memlock, tc)
25057718be8SEnji Cooper {
25157718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Test setrlimit(2), RLIMIT_MEMLOCK");
252710542dfSBryan Drewery #ifdef __FreeBSD__
253710542dfSBryan Drewery atf_tc_set_md_var(tc, "require.config", "allow_sysctl_side_effects");
254710542dfSBryan Drewery atf_tc_set_md_var(tc, "require.user", "root");
255710542dfSBryan Drewery #endif
25657718be8SEnji Cooper }
25757718be8SEnji Cooper
ATF_TC_BODY(setrlimit_memlock,tc)25857718be8SEnji Cooper ATF_TC_BODY(setrlimit_memlock, tc)
25957718be8SEnji Cooper {
26057718be8SEnji Cooper struct rlimit res;
26157718be8SEnji Cooper void *buf;
26257718be8SEnji Cooper long page;
26357718be8SEnji Cooper pid_t pid;
26457718be8SEnji Cooper int sta;
26557718be8SEnji Cooper
266710542dfSBryan Drewery #ifdef __FreeBSD__
267710542dfSBryan Drewery /* Set max_wired really really high to avoid EAGAIN */
268710542dfSBryan Drewery set_vm_max_wired(INT_MAX);
269710542dfSBryan Drewery #endif
270710542dfSBryan Drewery
27157718be8SEnji Cooper page = sysconf(_SC_PAGESIZE);
27257718be8SEnji Cooper ATF_REQUIRE(page >= 0);
27357718be8SEnji Cooper
27457718be8SEnji Cooper buf = malloc(page);
27557718be8SEnji Cooper pid = fork();
27657718be8SEnji Cooper
27757718be8SEnji Cooper if (buf == NULL || pid < 0)
27857718be8SEnji Cooper atf_tc_fail("initialization failed");
27957718be8SEnji Cooper
28057718be8SEnji Cooper if (pid == 0) {
28157718be8SEnji Cooper
28257718be8SEnji Cooper /*
28357718be8SEnji Cooper * Try to lock a page while
28457718be8SEnji Cooper * RLIMIT_MEMLOCK is zero.
28557718be8SEnji Cooper */
28657718be8SEnji Cooper if (mlock(buf, page) != 0)
28757718be8SEnji Cooper _exit(EXIT_FAILURE);
28857718be8SEnji Cooper
28957718be8SEnji Cooper if (munlock(buf, page) != 0)
29057718be8SEnji Cooper _exit(EXIT_FAILURE);
29157718be8SEnji Cooper
29257718be8SEnji Cooper res.rlim_cur = 0;
29357718be8SEnji Cooper res.rlim_max = 0;
29457718be8SEnji Cooper
29557718be8SEnji Cooper if (setrlimit(RLIMIT_MEMLOCK, &res) != 0)
29657718be8SEnji Cooper _exit(EXIT_FAILURE);
29757718be8SEnji Cooper
29857718be8SEnji Cooper if (mlock(buf, page) != 0)
29957718be8SEnji Cooper _exit(EXIT_SUCCESS);
30057718be8SEnji Cooper
30157718be8SEnji Cooper (void)munlock(buf, page);
30257718be8SEnji Cooper
30357718be8SEnji Cooper _exit(EXIT_FAILURE);
30457718be8SEnji Cooper }
30557718be8SEnji Cooper
30657718be8SEnji Cooper free(buf);
30757718be8SEnji Cooper
30857718be8SEnji Cooper (void)wait(&sta);
30957718be8SEnji Cooper
31057718be8SEnji Cooper if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
31157718be8SEnji Cooper atf_tc_fail("RLIMIT_MEMLOCK not enforced");
31257718be8SEnji Cooper }
31357718be8SEnji Cooper
314710542dfSBryan Drewery #ifdef __FreeBSD__
ATF_TC_CLEANUP(setrlimit_memlock,tc)315710542dfSBryan Drewery ATF_TC_CLEANUP(setrlimit_memlock, tc)
316710542dfSBryan Drewery {
317710542dfSBryan Drewery
318710542dfSBryan Drewery restore_vm_max_wired();
319710542dfSBryan Drewery }
320710542dfSBryan Drewery #endif
321710542dfSBryan Drewery
32257718be8SEnji Cooper ATF_TC(setrlimit_nofile_1);
ATF_TC_HEAD(setrlimit_nofile_1,tc)32357718be8SEnji Cooper ATF_TC_HEAD(setrlimit_nofile_1, tc)
32457718be8SEnji Cooper {
32557718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Test setrlimit(2), RLIMIT_NOFILE, #1");
32657718be8SEnji Cooper }
32757718be8SEnji Cooper
ATF_TC_BODY(setrlimit_nofile_1,tc)32857718be8SEnji Cooper ATF_TC_BODY(setrlimit_nofile_1, tc)
32957718be8SEnji Cooper {
33057718be8SEnji Cooper struct rlimit res;
33157718be8SEnji Cooper int fd, i, rv, sta;
33257718be8SEnji Cooper pid_t pid;
33357718be8SEnji Cooper
33457718be8SEnji Cooper res.rlim_cur = 0;
33557718be8SEnji Cooper res.rlim_max = 0;
33657718be8SEnji Cooper
33757718be8SEnji Cooper pid = fork();
33857718be8SEnji Cooper ATF_REQUIRE(pid >= 0);
33957718be8SEnji Cooper
34057718be8SEnji Cooper if (pid == 0) {
34157718be8SEnji Cooper
34257718be8SEnji Cooper /*
34357718be8SEnji Cooper * Close all descriptors, set RLIMIT_NOFILE
34457718be8SEnji Cooper * to zero, and try to open a random file.
34557718be8SEnji Cooper * This should fail with EMFILE.
34657718be8SEnji Cooper */
34757718be8SEnji Cooper for (i = 0; i < 1024; i++)
34857718be8SEnji Cooper (void)close(i);
34957718be8SEnji Cooper
35057718be8SEnji Cooper rv = setrlimit(RLIMIT_NOFILE, &res);
35157718be8SEnji Cooper
35257718be8SEnji Cooper if (rv != 0)
35357718be8SEnji Cooper _exit(EXIT_FAILURE);
35457718be8SEnji Cooper
35557718be8SEnji Cooper errno = 0;
35657718be8SEnji Cooper fd = open("/etc/passwd", O_RDONLY);
35757718be8SEnji Cooper
35857718be8SEnji Cooper if (fd >= 0 || errno != EMFILE)
35957718be8SEnji Cooper _exit(EXIT_FAILURE);
36057718be8SEnji Cooper
36157718be8SEnji Cooper _exit(EXIT_SUCCESS);
36257718be8SEnji Cooper }
36357718be8SEnji Cooper
36457718be8SEnji Cooper (void)wait(&sta);
36557718be8SEnji Cooper
36657718be8SEnji Cooper if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
36757718be8SEnji Cooper atf_tc_fail("RLIMIT_NOFILE not enforced");
36857718be8SEnji Cooper }
36957718be8SEnji Cooper
37057718be8SEnji Cooper ATF_TC(setrlimit_nofile_2);
ATF_TC_HEAD(setrlimit_nofile_2,tc)37157718be8SEnji Cooper ATF_TC_HEAD(setrlimit_nofile_2, tc)
37257718be8SEnji Cooper {
37357718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Test setrlimit(2), RLIMIT_NOFILE, #2");
37457718be8SEnji Cooper }
37557718be8SEnji Cooper
ATF_TC_BODY(setrlimit_nofile_2,tc)37657718be8SEnji Cooper ATF_TC_BODY(setrlimit_nofile_2, tc)
37757718be8SEnji Cooper {
37857718be8SEnji Cooper static const rlim_t lim = 12;
37957718be8SEnji Cooper struct rlimit res;
38057718be8SEnji Cooper int fd, i, rv, sta;
38157718be8SEnji Cooper pid_t pid;
38257718be8SEnji Cooper
38357718be8SEnji Cooper /*
38457718be8SEnji Cooper * See that an arbitrary limit on
38557718be8SEnji Cooper * open files is being enforced.
38657718be8SEnji Cooper */
38757718be8SEnji Cooper res.rlim_cur = lim;
38857718be8SEnji Cooper res.rlim_max = lim;
38957718be8SEnji Cooper
39057718be8SEnji Cooper pid = fork();
39157718be8SEnji Cooper ATF_REQUIRE(pid >= 0);
39257718be8SEnji Cooper
39357718be8SEnji Cooper if (pid == 0) {
39457718be8SEnji Cooper
39557718be8SEnji Cooper for (i = 0; i < 1024; i++)
39657718be8SEnji Cooper (void)close(i);
39757718be8SEnji Cooper
39857718be8SEnji Cooper rv = setrlimit(RLIMIT_NOFILE, &res);
39957718be8SEnji Cooper
40057718be8SEnji Cooper if (rv != 0)
40157718be8SEnji Cooper _exit(EXIT_FAILURE);
40257718be8SEnji Cooper
40357718be8SEnji Cooper for (i = 0; i < (int)lim; i++) {
40457718be8SEnji Cooper
40557718be8SEnji Cooper fd = open("/etc/passwd", O_RDONLY);
40657718be8SEnji Cooper
40757718be8SEnji Cooper if (fd < 0)
40857718be8SEnji Cooper _exit(EXIT_FAILURE);
40957718be8SEnji Cooper }
41057718be8SEnji Cooper
41157718be8SEnji Cooper /*
41257718be8SEnji Cooper * After the limit has been reached,
41357718be8SEnji Cooper * EMFILE should again follow.
41457718be8SEnji Cooper */
41557718be8SEnji Cooper fd = open("/etc/passwd", O_RDONLY);
41657718be8SEnji Cooper
41757718be8SEnji Cooper if (fd >= 0 || errno != EMFILE)
41857718be8SEnji Cooper _exit(EXIT_FAILURE);
41957718be8SEnji Cooper
42057718be8SEnji Cooper _exit(EXIT_SUCCESS);
42157718be8SEnji Cooper }
42257718be8SEnji Cooper
42357718be8SEnji Cooper (void)wait(&sta);
42457718be8SEnji Cooper
42557718be8SEnji Cooper if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
42657718be8SEnji Cooper atf_tc_fail("RLIMIT_NOFILE not enforced");
42757718be8SEnji Cooper }
42857718be8SEnji Cooper
42957718be8SEnji Cooper ATF_TC(setrlimit_nproc);
ATF_TC_HEAD(setrlimit_nproc,tc)43057718be8SEnji Cooper ATF_TC_HEAD(setrlimit_nproc, tc)
43157718be8SEnji Cooper {
43257718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Test setrlimit(2), RLIMIT_NPROC");
43357718be8SEnji Cooper atf_tc_set_md_var(tc, "require.user", "unprivileged");
43457718be8SEnji Cooper }
43557718be8SEnji Cooper
ATF_TC_BODY(setrlimit_nproc,tc)43657718be8SEnji Cooper ATF_TC_BODY(setrlimit_nproc, tc)
43757718be8SEnji Cooper {
43857718be8SEnji Cooper struct rlimit res;
43957718be8SEnji Cooper pid_t pid, cpid;
44057718be8SEnji Cooper int sta;
44157718be8SEnji Cooper
44257718be8SEnji Cooper pid = fork();
44357718be8SEnji Cooper ATF_REQUIRE(pid >= 0);
44457718be8SEnji Cooper
44557718be8SEnji Cooper if (pid == 0) {
44657718be8SEnji Cooper
44757718be8SEnji Cooper /*
44857718be8SEnji Cooper * Set RLIMIT_NPROC to zero and try to fork.
44957718be8SEnji Cooper */
45057718be8SEnji Cooper res.rlim_cur = 0;
45157718be8SEnji Cooper res.rlim_max = 0;
45257718be8SEnji Cooper
45357718be8SEnji Cooper if (setrlimit(RLIMIT_NPROC, &res) != 0)
45457718be8SEnji Cooper _exit(EXIT_FAILURE);
45557718be8SEnji Cooper
45657718be8SEnji Cooper cpid = fork();
45757718be8SEnji Cooper
45857718be8SEnji Cooper if (cpid < 0)
45957718be8SEnji Cooper _exit(EXIT_SUCCESS);
46057718be8SEnji Cooper
46157718be8SEnji Cooper _exit(EXIT_FAILURE);
46257718be8SEnji Cooper }
46357718be8SEnji Cooper
46457718be8SEnji Cooper (void)waitpid(pid, &sta, 0);
46557718be8SEnji Cooper
46657718be8SEnji Cooper if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
46757718be8SEnji Cooper atf_tc_fail("RLIMIT_NPROC not enforced");
46857718be8SEnji Cooper }
46957718be8SEnji Cooper
470928eb3afSEnji Cooper #ifdef __NetBSD__
47157718be8SEnji Cooper ATF_TC(setrlimit_nthr);
ATF_TC_HEAD(setrlimit_nthr,tc)47257718be8SEnji Cooper ATF_TC_HEAD(setrlimit_nthr, tc)
47357718be8SEnji Cooper {
47457718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Test setrlimit(2), RLIMIT_NTHR");
47557718be8SEnji Cooper atf_tc_set_md_var(tc, "require.user", "unprivileged");
47657718be8SEnji Cooper }
47757718be8SEnji Cooper
47857718be8SEnji Cooper static void
func(lwpid_t * id)47957718be8SEnji Cooper func(lwpid_t *id)
48057718be8SEnji Cooper {
48157718be8SEnji Cooper printf("thread %d\n", *id);
48257718be8SEnji Cooper fflush(stdout);
48357718be8SEnji Cooper _lwp_exit();
48457718be8SEnji Cooper }
48557718be8SEnji Cooper
ATF_TC_BODY(setrlimit_nthr,tc)48657718be8SEnji Cooper ATF_TC_BODY(setrlimit_nthr, tc)
48757718be8SEnji Cooper {
48857718be8SEnji Cooper struct rlimit res;
48957718be8SEnji Cooper lwpid_t lwpid;
49057718be8SEnji Cooper ucontext_t c;
49157718be8SEnji Cooper
49257718be8SEnji Cooper /*
49357718be8SEnji Cooper * Set RLIMIT_NTHR to zero and try to create a thread.
49457718be8SEnji Cooper */
49557718be8SEnji Cooper res.rlim_cur = 0;
49657718be8SEnji Cooper res.rlim_max = 0;
49757718be8SEnji Cooper ATF_REQUIRE(setrlimit(RLIMIT_NTHR, &res) == 0);
49857718be8SEnji Cooper ATF_REQUIRE(getcontext(&c) == 0);
49957718be8SEnji Cooper c.uc_link = NULL;
50057718be8SEnji Cooper sigemptyset(&c.uc_sigmask);
50157718be8SEnji Cooper c.uc_stack.ss_flags = 0;
50257718be8SEnji Cooper c.uc_stack.ss_size = 4096;
50357718be8SEnji Cooper ATF_REQUIRE((c.uc_stack.ss_sp = malloc(c.uc_stack.ss_size)) != NULL);
50457718be8SEnji Cooper makecontext(&c, func, 1, &lwpid);
50557718be8SEnji Cooper ATF_CHECK_ERRNO(EAGAIN, _lwp_create(&c, 0, &lwpid) == -1);
50657718be8SEnji Cooper }
507928eb3afSEnji Cooper #endif
50857718be8SEnji Cooper
50957718be8SEnji Cooper ATF_TC(setrlimit_perm);
ATF_TC_HEAD(setrlimit_perm,tc)51057718be8SEnji Cooper ATF_TC_HEAD(setrlimit_perm, tc)
51157718be8SEnji Cooper {
51257718be8SEnji Cooper atf_tc_set_md_var(tc, "descr", "Test setrlimit(2) for EPERM");
51357718be8SEnji Cooper atf_tc_set_md_var(tc, "require.user", "unprivileged");
51457718be8SEnji Cooper }
51557718be8SEnji Cooper
ATF_TC_BODY(setrlimit_perm,tc)51657718be8SEnji Cooper ATF_TC_BODY(setrlimit_perm, tc)
51757718be8SEnji Cooper {
51857718be8SEnji Cooper struct rlimit res;
51957718be8SEnji Cooper size_t i;
52057718be8SEnji Cooper
52157718be8SEnji Cooper /*
52257718be8SEnji Cooper * Try to raise the maximum limits as an user.
52357718be8SEnji Cooper */
52457718be8SEnji Cooper for (i = 0; i < __arraycount(rlimit); i++) {
52557718be8SEnji Cooper
52657718be8SEnji Cooper ATF_REQUIRE(getrlimit(rlimit[i], &res) == 0);
52757718be8SEnji Cooper
528928eb3afSEnji Cooper #ifdef __FreeBSD__
529928eb3afSEnji Cooper if (res.rlim_max == INT64_MAX) /* Overflow. */
530928eb3afSEnji Cooper #else
53157718be8SEnji Cooper if (res.rlim_max == UINT64_MAX) /* Overflow. */
532928eb3afSEnji Cooper #endif
53357718be8SEnji Cooper continue;
53457718be8SEnji Cooper
53557718be8SEnji Cooper errno = 0;
53657718be8SEnji Cooper res.rlim_max = res.rlim_max + 1;
53757718be8SEnji Cooper
53857718be8SEnji Cooper ATF_CHECK_ERRNO(EPERM, setrlimit(rlimit[i], &res) != 0);
53957718be8SEnji Cooper }
54057718be8SEnji Cooper }
54157718be8SEnji Cooper
542640235e2SEnji Cooper ATF_TC(setrlimit_stack);
ATF_TC_HEAD(setrlimit_stack,tc)543640235e2SEnji Cooper ATF_TC_HEAD(setrlimit_stack, tc)
544640235e2SEnji Cooper {
545640235e2SEnji Cooper atf_tc_set_md_var(tc, "descr", "Test setrlimit(2), RLIMIT_STACK");
546640235e2SEnji Cooper atf_tc_set_md_var(tc, "require.user", "unprivileged");
547640235e2SEnji Cooper }
548640235e2SEnji Cooper
ATF_TC_BODY(setrlimit_stack,tc)549640235e2SEnji Cooper ATF_TC_BODY(setrlimit_stack, tc)
550640235e2SEnji Cooper {
551640235e2SEnji Cooper struct rlimit res;
552640235e2SEnji Cooper
553640235e2SEnji Cooper /* Ensure soft limit is not bigger than hard limit */
554640235e2SEnji Cooper res.rlim_cur = res.rlim_max = 4192256;
555640235e2SEnji Cooper ATF_REQUIRE(setrlimit(RLIMIT_STACK, &res) == 0);
556640235e2SEnji Cooper ATF_REQUIRE(getrlimit(RLIMIT_STACK, &res) == 0);
557640235e2SEnji Cooper ATF_CHECK(res.rlim_cur <= res.rlim_max);
558640235e2SEnji Cooper
559640235e2SEnji Cooper }
560640235e2SEnji Cooper
ATF_TP_ADD_TCS(tp)56157718be8SEnji Cooper ATF_TP_ADD_TCS(tp)
56257718be8SEnji Cooper {
56357718be8SEnji Cooper
56457718be8SEnji Cooper ATF_TP_ADD_TC(tp, setrlimit_basic);
56557718be8SEnji Cooper ATF_TP_ADD_TC(tp, setrlimit_current);
56657718be8SEnji Cooper ATF_TP_ADD_TC(tp, setrlimit_err);
56757718be8SEnji Cooper ATF_TP_ADD_TC(tp, setrlimit_fsize);
56857718be8SEnji Cooper ATF_TP_ADD_TC(tp, setrlimit_memlock);
56957718be8SEnji Cooper ATF_TP_ADD_TC(tp, setrlimit_nofile_1);
57057718be8SEnji Cooper ATF_TP_ADD_TC(tp, setrlimit_nofile_2);
57157718be8SEnji Cooper ATF_TP_ADD_TC(tp, setrlimit_nproc);
57257718be8SEnji Cooper ATF_TP_ADD_TC(tp, setrlimit_perm);
57370d69ef1SEnji Cooper #ifdef __NetBSD__
57457718be8SEnji Cooper ATF_TP_ADD_TC(tp, setrlimit_nthr);
575928eb3afSEnji Cooper #endif
576640235e2SEnji Cooper ATF_TP_ADD_TC(tp, setrlimit_stack);
57757718be8SEnji Cooper
57857718be8SEnji Cooper return atf_no_error();
57957718be8SEnji Cooper }
580