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); 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 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); 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 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); 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 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); 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 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 22957718be8SEnji Cooper ATF_TC_CLEANUP(setrlimit_fsize, tc) 23057718be8SEnji Cooper { 23157718be8SEnji Cooper (void)unlink(path); 23257718be8SEnji Cooper } 23357718be8SEnji Cooper 23457718be8SEnji Cooper static void 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 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 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__ 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); 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 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); 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 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); 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 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); 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 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 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); 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 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); 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 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 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