1139743Simp/* $NetBSD: t_setrlimit.c,v 1.6 2017/01/13 21:16:38 christos Exp $ */ 2123474Swpaul 3123474Swpaul/*- 4123474Swpaul * Copyright (c) 2011 The NetBSD Foundation, Inc. 5123474Swpaul * All rights reserved. 6123474Swpaul * 7123474Swpaul * This code is derived from software contributed to The NetBSD Foundation 8123474Swpaul * by Jukka Ruohonen. 9123474Swpaul * 10123474Swpaul * Redistribution and use in source and binary forms, with or without 11123474Swpaul * modification, are permitted provided that the following conditions 12123474Swpaul * are met: 13123474Swpaul * 1. Redistributions of source code must retain the above copyright 14123474Swpaul * notice, this list of conditions and the following disclaimer. 15123474Swpaul * 2. Redistributions in binary form must reproduce the above copyright 16123474Swpaul * notice, this list of conditions and the following disclaimer in the 17123474Swpaul * documentation and/or other materials provided with the distribution. 18123474Swpaul * 19123474Swpaul * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20123474Swpaul * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21123474Swpaul * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22123474Swpaul * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23123474Swpaul * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24123474Swpaul * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25123474Swpaul * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26123474Swpaul * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27123474Swpaul * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28123474Swpaul * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29123474Swpaul * POSSIBILITY OF SUCH DAMAGE. 30123474Swpaul */ 31123474Swpaul#include <sys/cdefs.h> 32123474Swpaul__RCSID("$NetBSD: t_setrlimit.c,v 1.6 2017/01/13 21:16:38 christos Exp $"); 33123474Swpaul 34123474Swpaul#include <sys/resource.h> 35123474Swpaul#include <sys/mman.h> 36123474Swpaul#include <sys/wait.h> 37123474Swpaul 38123474Swpaul#include <atf-c.h> 39123474Swpaul#include <errno.h> 40123474Swpaul#include <fcntl.h> 41123474Swpaul#include <limits.h> 42123474Swpaul#ifdef __NetBSD__ 43123474Swpaul#include <lwp.h> 44123474Swpaul#endif 45123474Swpaul#include <signal.h> 46123474Swpaul#include <stdint.h> 47123474Swpaul#include <stdio.h> 48123474Swpaul#include <stdlib.h> 49123474Swpaul#include <string.h> 50123474Swpaul#include <ucontext.h> 51123474Swpaul#include <unistd.h> 52129834Swpaul 53123474Swpaul#ifdef __FreeBSD__ 54123474Swpaulvoid set_vm_max_wired(int); 55123474Swpaulvoid restore_vm_max_wired(void); 56123474Swpaul#endif 57123474Swpaul 58123474Swpaulstatic void sighandler(int); 59123474Swpaulstatic const char path[] = "setrlimit"; 60123474Swpaul 61123474Swpaulstatic const int rlimit[] = { 62123474Swpaul RLIMIT_AS, 63123474Swpaul RLIMIT_CORE, 64123474Swpaul RLIMIT_CPU, 65123504Swpaul RLIMIT_DATA, 66123848Swpaul RLIMIT_FSIZE, 67124122Swpaul RLIMIT_MEMLOCK, 68124272Swpaul RLIMIT_NOFILE, 69125377Swpaul RLIMIT_NPROC, 70124272Swpaul RLIMIT_RSS, 71124272Swpaul RLIMIT_SBSIZE, 72124272Swpaul RLIMIT_STACK 73125551Swpaul}; 74132973Swpaul 75132973SwpaulATF_TC(setrlimit_basic); 76132973SwpaulATF_TC_HEAD(setrlimit_basic, tc) 77123474Swpaul{ 78123474Swpaul atf_tc_set_md_var(tc, "descr", "A basic soft limit test"); 79123474Swpaul} 80123474Swpaul 81123474SwpaulATF_TC_BODY(setrlimit_basic, tc) 82123474Swpaul{ 83123474Swpaul struct rlimit res; 84124203Swpaul int *buf, lim; 85123474Swpaul size_t i; 86123474Swpaul 87123474Swpaul buf = calloc(__arraycount(rlimit), sizeof(int)); 88123474Swpaul 89123474Swpaul if (buf == NULL) 90123474Swpaul atf_tc_fail("initialization failed"); 91123474Swpaul 92123474Swpaul for (i = lim = 0; i < __arraycount(rlimit); i++) { 93123474Swpaul 94123474Swpaul (void)memset(&res, 0, sizeof(struct rlimit)); 95123695Swpaul 96123695Swpaul if (getrlimit(rlimit[i], &res) != 0) 97123695Swpaul continue; 98123474Swpaul 99123474Swpaul if (res.rlim_cur == RLIM_INFINITY || res.rlim_cur == 0) 100123474Swpaul continue; 101123474Swpaul 102145485Swpaul if (res.rlim_cur == res.rlim_max) /* An unprivileged run. */ 103123474Swpaul continue; 104123512Swpaul 105128229Swpaul buf[i] = res.rlim_cur; 106123474Swpaul res.rlim_cur = res.rlim_cur - 1; 107123474Swpaul 108123474Swpaul if (setrlimit(rlimit[i], &res) != 0) { 109124272Swpaul lim = rlimit[i]; 110125057Swpaul goto out; 111123474Swpaul } 112124272Swpaul } 113124272Swpaul 114124272Swpaulout: 115144888Swpaul for (i = 0; i < __arraycount(rlimit); i++) { 116141524Swpaul 117144888Swpaul (void)memset(&res, 0, sizeof(struct rlimit)); 118123474Swpaul 119144888Swpaul if (buf[i] == 0) 120140751Swpaul continue; 121144888Swpaul 122123474Swpaul if (getrlimit(rlimit[i], &res) != 0) 123144888Swpaul continue; 124144888Swpaul 125123474Swpaul res.rlim_cur = buf[i]; 126144888Swpaul 127140751Swpaul (void)setrlimit(rlimit[i], &res); 128144888Swpaul } 129140751Swpaul 130144888Swpaul if (lim != 0) 131140751Swpaul atf_tc_fail("failed to set limit (%d)", lim); 132123474Swpaul free(buf); 133123474Swpaul} 134123526Swpaul 135123526SwpaulATF_TC(setrlimit_current); 136144888SwpaulATF_TC_HEAD(setrlimit_current, tc) 137123474Swpaul{ 138144888Swpaul atf_tc_set_md_var(tc, "descr", "setrlimit(3) with current limits"); 139123526Swpaul} 140144888Swpaul 141144888SwpaulATF_TC_BODY(setrlimit_current, tc) 142144888Swpaul{ 143144888Swpaul struct rlimit res; 144144888Swpaul size_t i; 145144888Swpaul 146144888Swpaul for (i = 0; i < __arraycount(rlimit); i++) { 147145895Swpaul 148145895Swpaul (void)memset(&res, 0, sizeof(struct rlimit)); 149145895Swpaul 150145895Swpaul ATF_REQUIRE(getrlimit(rlimit[i], &res) == 0); 151144888Swpaul ATF_REQUIRE(setrlimit(rlimit[i], &res) == 0); 152123474Swpaul } 153144888Swpaul} 154123474Swpaul 155140751SwpaulATF_TC(setrlimit_err); 156123474SwpaulATF_TC_HEAD(setrlimit_err, tc) 157144888Swpaul{ 158140751Swpaul atf_tc_set_md_var(tc, "descr", "Test error conditions"); 159144888Swpaul} 160140751Swpaul 161144888SwpaulATF_TC_BODY(setrlimit_err, tc) 162123474Swpaul{ 163144888Swpaul struct rlimit res; 164125057Swpaul size_t i; 165144888Swpaul 166144888Swpaul for (i = 0; i < __arraycount(rlimit); i++) { 167144888Swpaul 168144888Swpaul errno = 0; 169144174Swpaul 170144888Swpaul ATF_REQUIRE(getrlimit(rlimit[i], (void *)0) != 0); 171123474Swpaul ATF_REQUIRE(errno == EFAULT); 172144888Swpaul } 173123474Swpaul 174144888Swpaul errno = 0; 175123474Swpaul 176144888Swpaul ATF_REQUIRE(getrlimit(INT_MAX, &res) != 0); 177123474Swpaul ATF_REQUIRE(errno == EINVAL); 178144888Swpaul} 179144888Swpaul 180123474SwpaulATF_TC_WITH_CLEANUP(setrlimit_fsize); 181144888SwpaulATF_TC_HEAD(setrlimit_fsize, tc) 182123474Swpaul{ 183144888Swpaul atf_tc_set_md_var(tc, "descr", "Test setrlimit(2), RLIMIT_FSIZE"); 184123474Swpaul} 185145895Swpaul 186144888SwpaulATF_TC_BODY(setrlimit_fsize, tc) 187123474Swpaul{ 188144888Swpaul struct rlimit res; 189123474Swpaul int fd, sta; 190144888Swpaul pid_t pid; 191123474Swpaul 192144888Swpaul fd = open(path, O_RDWR | O_CREAT, 0700); 193144888Swpaul 194144888Swpaul if (fd < 0) 195144888Swpaul atf_tc_fail("initialization failed"); 196123474Swpaul 197144888Swpaul pid = fork(); 198144888Swpaul ATF_REQUIRE(pid >= 0); 199144888Swpaul 200123474Swpaul if (pid == 0) { 201144888Swpaul 202144888Swpaul res.rlim_cur = 2; 203123474Swpaul res.rlim_max = 2; 204144888Swpaul 205144888Swpaul if (setrlimit(RLIMIT_FSIZE, &res) != 0) 206144888Swpaul _exit(EXIT_FAILURE); 207144888Swpaul 208123474Swpaul if (signal(SIGXFSZ, sighandler) == SIG_ERR) 209144888Swpaul _exit(EXIT_FAILURE); 210144888Swpaul 211144888Swpaul /* 212144888Swpaul * The third call should generate a SIGXFSZ. 213144888Swpaul */ 214144888Swpaul (void)write(fd, "X", 1); 215144888Swpaul (void)write(fd, "X", 1); 216144888Swpaul (void)write(fd, "X", 1); 217144888Swpaul 218144888Swpaul _exit(EXIT_FAILURE); 219123474Swpaul } 220144888Swpaul 221140751Swpaul (void)close(fd); 222123526Swpaul (void)wait(&sta); 223144888Swpaul (void)unlink(path); 224123474Swpaul 225144888Swpaul if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS) 226123474Swpaul atf_tc_fail("RLIMIT_FSIZE not enforced"); 227123474Swpaul} 228144888Swpaul 229144888SwpaulATF_TC_CLEANUP(setrlimit_fsize, tc) 230123474Swpaul{ 231144888Swpaul (void)unlink(path); 232144888Swpaul} 233144888Swpaul 234140751Swpaulstatic void 235144888Swpaulsighandler(int signo) 236123474Swpaul{ 237144888Swpaul 238144888Swpaul if (signo != SIGXFSZ) 239123474Swpaul _exit(EXIT_FAILURE); 240144888Swpaul 241123474Swpaul _exit(EXIT_SUCCESS); 242144888Swpaul} 243125551Swpaul 244144888Swpaul#ifdef __FreeBSD__ 245123474SwpaulATF_TC_WITH_CLEANUP(setrlimit_memlock); 246144888Swpaul#else 247125551SwpaulATF_TC(setrlimit_memlock); 248144888Swpaul#endif 249140751SwpaulATF_TC_HEAD(setrlimit_memlock, tc) 250123474Swpaul{ 251144888Swpaul atf_tc_set_md_var(tc, "descr", "Test setrlimit(2), RLIMIT_MEMLOCK"); 252144888Swpaul#ifdef __FreeBSD__ 253144888Swpaul atf_tc_set_md_var(tc, "require.config", "allow_sysctl_side_effects"); 254144888Swpaul atf_tc_set_md_var(tc, "require.user", "root"); 255144888Swpaul#endif 256123941Swpaul} 257144888Swpaul 258144888SwpaulATF_TC_BODY(setrlimit_memlock, tc) 259144888Swpaul{ 260144888Swpaul struct rlimit res; 261125551Swpaul void *buf; 262125551Swpaul long page; 263144888Swpaul pid_t pid; 264140751Swpaul int sta; 265144888Swpaul 266140751Swpaul#ifdef __FreeBSD__ 267132973Swpaul /* Set max_wired really really high to avoid EAGAIN */ 268144888Swpaul set_vm_max_wired(INT_MAX); 269123822Swpaul#endif 270144888Swpaul 271144888Swpaul page = sysconf(_SC_PAGESIZE); 272144888Swpaul ATF_REQUIRE(page >= 0); 273144888Swpaul 274144888Swpaul buf = malloc(page); 275144888Swpaul pid = fork(); 276124116Swpaul 277144402Swpaul if (buf == NULL || pid < 0) 278144888Swpaul atf_tc_fail("initialization failed"); 279140751Swpaul 280144888Swpaul if (pid == 0) { 281140751Swpaul 282144888Swpaul /* 283125551Swpaul * Try to lock a page while 284125551Swpaul * RLIMIT_MEMLOCK is zero. 285144888Swpaul */ 286144888Swpaul if (mlock(buf, page) != 0) 287140751Swpaul _exit(EXIT_FAILURE); 288125551Swpaul 289144888Swpaul if (munlock(buf, page) != 0) 290144888Swpaul _exit(EXIT_FAILURE); 291123474Swpaul 292124116Swpaul res.rlim_cur = 0; 293124116Swpaul res.rlim_max = 0; 294124116Swpaul 295124116Swpaul if (setrlimit(RLIMIT_MEMLOCK, &res) != 0) 296124116Swpaul _exit(EXIT_FAILURE); 297124116Swpaul 298124116Swpaul if (mlock(buf, page) != 0) 299124116Swpaul _exit(EXIT_SUCCESS); 300124116Swpaul 301123474Swpaul (void)munlock(buf, page); 302123474Swpaul 303123474Swpaul _exit(EXIT_FAILURE); 304123474Swpaul } 305141963Swpaul 306141963Swpaul free(buf); 307124272Swpaul 308141963Swpaul (void)wait(&sta); 309141963Swpaul 310141963Swpaul if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS) 311141963Swpaul atf_tc_fail("RLIMIT_MEMLOCK not enforced"); 312144888Swpaul} 313144888Swpaul 314141963Swpaul#ifdef __FreeBSD__ 315141963SwpaulATF_TC_CLEANUP(setrlimit_memlock, tc) 316141963Swpaul{ 317123474Swpaul 318123474Swpaul restore_vm_max_wired(); 319123474Swpaul} 320123474Swpaul#endif 321123474Swpaul 322123474SwpaulATF_TC(setrlimit_nofile_1); 323141963SwpaulATF_TC_HEAD(setrlimit_nofile_1, tc) 324141963Swpaul{ 325141963Swpaul atf_tc_set_md_var(tc, "descr", "Test setrlimit(2), RLIMIT_NOFILE, #1"); 326141963Swpaul} 327141963Swpaul 328141963SwpaulATF_TC_BODY(setrlimit_nofile_1, tc) 329141963Swpaul{ 330141963Swpaul struct rlimit res; 331123474Swpaul int fd, i, rv, sta; 332123474Swpaul pid_t pid; 333123474Swpaul 334144402Swpaul res.rlim_cur = 0; 335144402Swpaul res.rlim_max = 0; 336144402Swpaul 337144402Swpaul pid = fork(); 338144402Swpaul ATF_REQUIRE(pid >= 0); 339144402Swpaul 340144428Swpaul if (pid == 0) { 341144402Swpaul 342144402Swpaul /* 343144402Swpaul * Close all descriptors, set RLIMIT_NOFILE 344144402Swpaul * to zero, and try to open a random file. 345144402Swpaul * This should fail with EMFILE. 346144402Swpaul */ 347144402Swpaul for (i = 0; i < 1024; i++) 348144402Swpaul (void)close(i); 349144402Swpaul 350123474Swpaul rv = setrlimit(RLIMIT_NOFILE, &res); 351123474Swpaul 352123474Swpaul if (rv != 0) 353123474Swpaul _exit(EXIT_FAILURE); 354123474Swpaul 355123474Swpaul errno = 0; 356123474Swpaul fd = open("/etc/passwd", O_RDONLY); 357123474Swpaul 358123474Swpaul if (fd >= 0 || errno != EMFILE) 359123474Swpaul _exit(EXIT_FAILURE); 360123474Swpaul 361123474Swpaul _exit(EXIT_SUCCESS); 362123474Swpaul } 363123474Swpaul 364123474Swpaul (void)wait(&sta); 365123474Swpaul 366144174Swpaul if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS) 367123474Swpaul atf_tc_fail("RLIMIT_NOFILE not enforced"); 368123474Swpaul} 369123474Swpaul 370123474SwpaulATF_TC(setrlimit_nofile_2); 371123474SwpaulATF_TC_HEAD(setrlimit_nofile_2, tc) 372123474Swpaul{ 373123474Swpaul atf_tc_set_md_var(tc, "descr", "Test setrlimit(2), RLIMIT_NOFILE, #2"); 374123474Swpaul} 375123474Swpaul 376123474SwpaulATF_TC_BODY(setrlimit_nofile_2, tc) 377123474Swpaul{ 378123474Swpaul static const rlim_t lim = 12; 379123474Swpaul struct rlimit res; 380123474Swpaul int fd, i, rv, sta; 381123474Swpaul pid_t pid; 382123474Swpaul 383123474Swpaul /* 384123474Swpaul * See that an arbitrary limit on 385123474Swpaul * open files is being enforced. 386123474Swpaul */ 387123474Swpaul res.rlim_cur = lim; 388123474Swpaul res.rlim_max = lim; 389144174Swpaul 390123474Swpaul pid = fork(); 391123474Swpaul ATF_REQUIRE(pid >= 0); 392123474Swpaul 393124100Swpaul if (pid == 0) { 394123474Swpaul 395123474Swpaul for (i = 0; i < 1024; i++) 396123474Swpaul (void)close(i); 397123474Swpaul 398123474Swpaul rv = setrlimit(RLIMIT_NOFILE, &res); 399123474Swpaul 400123474Swpaul if (rv != 0) 401141524Swpaul _exit(EXIT_FAILURE); 402141524Swpaul 403141524Swpaul for (i = 0; i < (int)lim; i++) { 404141524Swpaul 405141524Swpaul fd = open("/etc/passwd", O_RDONLY); 406144888Swpaul 407141524Swpaul if (fd < 0) 408125551Swpaul _exit(EXIT_FAILURE); 409141524Swpaul } 410123474Swpaul 411123474Swpaul /* 412123474Swpaul * After the limit has been reached, 413141524Swpaul * EMFILE should again follow. 414141524Swpaul */ 415141524Swpaul fd = open("/etc/passwd", O_RDONLY); 416141524Swpaul 417141524Swpaul if (fd >= 0 || errno != EMFILE) 418141524Swpaul _exit(EXIT_FAILURE); 419141524Swpaul 420141524Swpaul _exit(EXIT_SUCCESS); 421141524Swpaul } 422123474Swpaul 423141524Swpaul (void)wait(&sta); 424123474Swpaul 425141524Swpaul if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS) 426141524Swpaul atf_tc_fail("RLIMIT_NOFILE not enforced"); 427141524Swpaul} 428141524Swpaul 429141524SwpaulATF_TC(setrlimit_nproc); 430141524SwpaulATF_TC_HEAD(setrlimit_nproc, tc) 431141524Swpaul{ 432141524Swpaul atf_tc_set_md_var(tc, "descr", "Test setrlimit(2), RLIMIT_NPROC"); 433141524Swpaul atf_tc_set_md_var(tc, "require.user", "unprivileged"); 434141524Swpaul} 435123474Swpaul 436123474SwpaulATF_TC_BODY(setrlimit_nproc, tc) 437123474Swpaul{ 438144888Swpaul struct rlimit res; 439140751Swpaul pid_t pid, cpid; 440123526Swpaul int sta; 441123526Swpaul 442123526Swpaul pid = fork(); 443141524Swpaul ATF_REQUIRE(pid >= 0); 444123526Swpaul 445123526Swpaul if (pid == 0) { 446123526Swpaul 447144888Swpaul /* 448140751Swpaul * Set RLIMIT_NPROC to zero and try to fork. 449123474Swpaul */ 450123474Swpaul res.rlim_cur = 0; 451123474Swpaul res.rlim_max = 0; 452123474Swpaul 453141524Swpaul if (setrlimit(RLIMIT_NPROC, &res) != 0) 454141524Swpaul _exit(EXIT_FAILURE); 455123474Swpaul 456141524Swpaul cpid = fork(); 457141524Swpaul 458141524Swpaul if (cpid < 0) 459141524Swpaul _exit(EXIT_SUCCESS); 460141524Swpaul 461141524Swpaul _exit(EXIT_FAILURE); 462141524Swpaul } 463141524Swpaul 464141524Swpaul (void)waitpid(pid, &sta, 0); 465141524Swpaul 466141524Swpaul if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS) 467141524Swpaul atf_tc_fail("RLIMIT_NPROC not enforced"); 468141524Swpaul} 469141524Swpaul 470141524Swpaul#ifdef __NetBSD__ 471141524SwpaulATF_TC(setrlimit_nthr); 472141524SwpaulATF_TC_HEAD(setrlimit_nthr, tc) 473141524Swpaul{ 474141524Swpaul atf_tc_set_md_var(tc, "descr", "Test setrlimit(2), RLIMIT_NTHR"); 475141524Swpaul atf_tc_set_md_var(tc, "require.user", "unprivileged"); 476141524Swpaul} 477141524Swpaul 478141524Swpaulstatic void 479141524Swpaulfunc(lwpid_t *id) 480141524Swpaul{ 481125551Swpaul printf("thread %d\n", *id); 482125551Swpaul fflush(stdout); 483123474Swpaul _lwp_exit(); 484123474Swpaul} 485123474Swpaul 486144888SwpaulATF_TC_BODY(setrlimit_nthr, tc) 487140751Swpaul{ 488123474Swpaul struct rlimit res; 489123474Swpaul lwpid_t lwpid; 490123474Swpaul ucontext_t c; 491123474Swpaul 492123474Swpaul /* 493123474Swpaul * Set RLIMIT_NTHR to zero and try to create a thread. 494141963Swpaul */ 495141524Swpaul res.rlim_cur = 0; 496123474Swpaul res.rlim_max = 0; 497123474Swpaul ATF_REQUIRE(setrlimit(RLIMIT_NTHR, &res) == 0); 498123474Swpaul ATF_REQUIRE(getcontext(&c) == 0); 499123474Swpaul c.uc_link = NULL; 500123474Swpaul sigemptyset(&c.uc_sigmask); 501123474Swpaul c.uc_stack.ss_flags = 0; 502123474Swpaul c.uc_stack.ss_size = 4096; 503144888Swpaul ATF_REQUIRE((c.uc_stack.ss_sp = malloc(c.uc_stack.ss_size)) != NULL); 504140751Swpaul makecontext(&c, func, 1, &lwpid); 505123474Swpaul ATF_CHECK_ERRNO(EAGAIN, _lwp_create(&c, 0, &lwpid) == -1); 506123474Swpaul} 507123474Swpaul#endif 508123474Swpaul 509123474SwpaulATF_TC(setrlimit_perm); 510123474SwpaulATF_TC_HEAD(setrlimit_perm, tc) 511123474Swpaul{ 512141524Swpaul atf_tc_set_md_var(tc, "descr", "Test setrlimit(2) for EPERM"); 513123474Swpaul atf_tc_set_md_var(tc, "require.user", "unprivileged"); 514123474Swpaul} 515123474Swpaul 516123474SwpaulATF_TC_BODY(setrlimit_perm, tc) 517123474Swpaul{ 518123474Swpaul struct rlimit res; 519123474Swpaul size_t i; 520144888Swpaul 521140751Swpaul /* 522123474Swpaul * Try to raise the maximum limits as an user. 523123474Swpaul */ 524123474Swpaul for (i = 0; i < __arraycount(rlimit); i++) { 525123474Swpaul 526123474Swpaul ATF_REQUIRE(getrlimit(rlimit[i], &res) == 0); 527123474Swpaul 528125551Swpaul#ifdef __FreeBSD__ 529141524Swpaul if (res.rlim_max == INT64_MAX) /* Overflow. */ 530141524Swpaul#else 531123474Swpaul if (res.rlim_max == UINT64_MAX) /* Overflow. */ 532123474Swpaul#endif 533123474Swpaul continue; 534144888Swpaul 535140751Swpaul errno = 0; 536123474Swpaul res.rlim_max = res.rlim_max + 1; 537123474Swpaul 538123474Swpaul ATF_CHECK_ERRNO(EPERM, setrlimit(rlimit[i], &res) != 0); 539123474Swpaul } 540123474Swpaul} 541123474Swpaul 542123474SwpaulATF_TC(setrlimit_stack); 543123474SwpaulATF_TC_HEAD(setrlimit_stack, tc) 544123474Swpaul{ 545123474Swpaul atf_tc_set_md_var(tc, "descr", "Test setrlimit(2), RLIMIT_STACK"); 546123474Swpaul atf_tc_set_md_var(tc, "require.user", "unprivileged"); 547123474Swpaul} 548123474Swpaul 549123474SwpaulATF_TC_BODY(setrlimit_stack, tc) 550123474Swpaul{ 551123474Swpaul struct rlimit res; 552126833Swpaul 553123474Swpaul /* Ensure soft limit is not bigger than hard limit */ 554123474Swpaul res.rlim_cur = res.rlim_max = 4192256; 555123474Swpaul ATF_REQUIRE(setrlimit(RLIMIT_STACK, &res) == 0); 556123474Swpaul ATF_REQUIRE(getrlimit(RLIMIT_STACK, &res) == 0); 557144888Swpaul ATF_CHECK(res.rlim_cur <= res.rlim_max); 558140751Swpaul 559123474Swpaul} 560123474Swpaul 561123474SwpaulATF_TP_ADD_TCS(tp) 562123474Swpaul{ 563123474Swpaul 564123474Swpaul ATF_TP_ADD_TC(tp, setrlimit_basic); 565141524Swpaul ATF_TP_ADD_TC(tp, setrlimit_current); 566123474Swpaul ATF_TP_ADD_TC(tp, setrlimit_err); 567123474Swpaul ATF_TP_ADD_TC(tp, setrlimit_fsize); 568123474Swpaul ATF_TP_ADD_TC(tp, setrlimit_memlock); 569144888Swpaul ATF_TP_ADD_TC(tp, setrlimit_nofile_1); 570140751Swpaul ATF_TP_ADD_TC(tp, setrlimit_nofile_2); 571123526Swpaul ATF_TP_ADD_TC(tp, setrlimit_nproc); 572123526Swpaul ATF_TP_ADD_TC(tp, setrlimit_perm); 573123526Swpaul#ifdef __NetBSD__ 574123526Swpaul ATF_TP_ADD_TC(tp, setrlimit_nthr); 575123526Swpaul#endif 576123526Swpaul ATF_TP_ADD_TC(tp, setrlimit_stack); 577123526Swpaul 578145895Swpaul return atf_no_error(); 579123526Swpaul} 580123526Swpaul