1*11be35a1SLionel Sambuc /* $NetBSD: t_setrlimit.c,v 1.4 2012/06/12 23:56:19 christos Exp $ */
2*11be35a1SLionel Sambuc
3*11be35a1SLionel Sambuc /*-
4*11be35a1SLionel Sambuc * Copyright (c) 2011 The NetBSD Foundation, Inc.
5*11be35a1SLionel Sambuc * All rights reserved.
6*11be35a1SLionel Sambuc *
7*11be35a1SLionel Sambuc * This code is derived from software contributed to The NetBSD Foundation
8*11be35a1SLionel Sambuc * by Jukka Ruohonen.
9*11be35a1SLionel Sambuc *
10*11be35a1SLionel Sambuc * Redistribution and use in source and binary forms, with or without
11*11be35a1SLionel Sambuc * modification, are permitted provided that the following conditions
12*11be35a1SLionel Sambuc * are met:
13*11be35a1SLionel Sambuc * 1. Redistributions of source code must retain the above copyright
14*11be35a1SLionel Sambuc * notice, this list of conditions and the following disclaimer.
15*11be35a1SLionel Sambuc * 2. Redistributions in binary form must reproduce the above copyright
16*11be35a1SLionel Sambuc * notice, this list of conditions and the following disclaimer in the
17*11be35a1SLionel Sambuc * documentation and/or other materials provided with the distribution.
18*11be35a1SLionel Sambuc *
19*11be35a1SLionel Sambuc * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20*11be35a1SLionel Sambuc * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21*11be35a1SLionel Sambuc * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22*11be35a1SLionel Sambuc * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23*11be35a1SLionel Sambuc * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24*11be35a1SLionel Sambuc * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25*11be35a1SLionel Sambuc * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26*11be35a1SLionel Sambuc * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27*11be35a1SLionel Sambuc * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28*11be35a1SLionel Sambuc * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29*11be35a1SLionel Sambuc * POSSIBILITY OF SUCH DAMAGE.
30*11be35a1SLionel Sambuc */
31*11be35a1SLionel Sambuc #include <sys/cdefs.h>
32*11be35a1SLionel Sambuc __RCSID("$NetBSD: t_setrlimit.c,v 1.4 2012/06/12 23:56:19 christos Exp $");
33*11be35a1SLionel Sambuc
34*11be35a1SLionel Sambuc #include <sys/resource.h>
35*11be35a1SLionel Sambuc #include <sys/mman.h>
36*11be35a1SLionel Sambuc #include <sys/wait.h>
37*11be35a1SLionel Sambuc
38*11be35a1SLionel Sambuc #include <atf-c.h>
39*11be35a1SLionel Sambuc #include <errno.h>
40*11be35a1SLionel Sambuc #include <fcntl.h>
41*11be35a1SLionel Sambuc #include <limits.h>
42*11be35a1SLionel Sambuc #include <lwp.h>
43*11be35a1SLionel Sambuc #include <signal.h>
44*11be35a1SLionel Sambuc #include <stdint.h>
45*11be35a1SLionel Sambuc #include <stdio.h>
46*11be35a1SLionel Sambuc #include <stdlib.h>
47*11be35a1SLionel Sambuc #include <string.h>
48*11be35a1SLionel Sambuc #include <ucontext.h>
49*11be35a1SLionel Sambuc #include <unistd.h>
50*11be35a1SLionel Sambuc
51*11be35a1SLionel Sambuc static void sighandler(int);
52*11be35a1SLionel Sambuc static const char path[] = "setrlimit";
53*11be35a1SLionel Sambuc
54*11be35a1SLionel Sambuc static const int rlimit[] = {
55*11be35a1SLionel Sambuc RLIMIT_AS,
56*11be35a1SLionel Sambuc RLIMIT_CORE,
57*11be35a1SLionel Sambuc RLIMIT_CPU,
58*11be35a1SLionel Sambuc RLIMIT_DATA,
59*11be35a1SLionel Sambuc RLIMIT_FSIZE,
60*11be35a1SLionel Sambuc RLIMIT_MEMLOCK,
61*11be35a1SLionel Sambuc RLIMIT_NOFILE,
62*11be35a1SLionel Sambuc RLIMIT_NPROC,
63*11be35a1SLionel Sambuc RLIMIT_RSS,
64*11be35a1SLionel Sambuc RLIMIT_SBSIZE,
65*11be35a1SLionel Sambuc RLIMIT_STACK
66*11be35a1SLionel Sambuc };
67*11be35a1SLionel Sambuc
68*11be35a1SLionel Sambuc ATF_TC(setrlimit_basic);
ATF_TC_HEAD(setrlimit_basic,tc)69*11be35a1SLionel Sambuc ATF_TC_HEAD(setrlimit_basic, tc)
70*11be35a1SLionel Sambuc {
71*11be35a1SLionel Sambuc atf_tc_set_md_var(tc, "descr", "A basic soft limit test");
72*11be35a1SLionel Sambuc }
73*11be35a1SLionel Sambuc
ATF_TC_BODY(setrlimit_basic,tc)74*11be35a1SLionel Sambuc ATF_TC_BODY(setrlimit_basic, tc)
75*11be35a1SLionel Sambuc {
76*11be35a1SLionel Sambuc struct rlimit res;
77*11be35a1SLionel Sambuc int *buf, lim;
78*11be35a1SLionel Sambuc size_t i;
79*11be35a1SLionel Sambuc
80*11be35a1SLionel Sambuc buf = calloc(__arraycount(rlimit), sizeof(int));
81*11be35a1SLionel Sambuc
82*11be35a1SLionel Sambuc if (buf == NULL)
83*11be35a1SLionel Sambuc atf_tc_fail("initialization failed");
84*11be35a1SLionel Sambuc
85*11be35a1SLionel Sambuc for (i = lim = 0; i < __arraycount(rlimit); i++) {
86*11be35a1SLionel Sambuc
87*11be35a1SLionel Sambuc (void)memset(&res, 0, sizeof(struct rlimit));
88*11be35a1SLionel Sambuc
89*11be35a1SLionel Sambuc if (getrlimit(rlimit[i], &res) != 0)
90*11be35a1SLionel Sambuc continue;
91*11be35a1SLionel Sambuc
92*11be35a1SLionel Sambuc if (res.rlim_cur == RLIM_INFINITY || res.rlim_cur == 0)
93*11be35a1SLionel Sambuc continue;
94*11be35a1SLionel Sambuc
95*11be35a1SLionel Sambuc if (res.rlim_cur == res.rlim_max) /* An unprivileged run. */
96*11be35a1SLionel Sambuc continue;
97*11be35a1SLionel Sambuc
98*11be35a1SLionel Sambuc buf[i] = res.rlim_cur;
99*11be35a1SLionel Sambuc res.rlim_cur = res.rlim_cur - 1;
100*11be35a1SLionel Sambuc
101*11be35a1SLionel Sambuc if (setrlimit(rlimit[i], &res) != 0) {
102*11be35a1SLionel Sambuc lim = rlimit[i];
103*11be35a1SLionel Sambuc goto out;
104*11be35a1SLionel Sambuc }
105*11be35a1SLionel Sambuc }
106*11be35a1SLionel Sambuc
107*11be35a1SLionel Sambuc out:
108*11be35a1SLionel Sambuc for (i = 0; i < __arraycount(rlimit); i++) {
109*11be35a1SLionel Sambuc
110*11be35a1SLionel Sambuc (void)memset(&res, 0, sizeof(struct rlimit));
111*11be35a1SLionel Sambuc
112*11be35a1SLionel Sambuc if (buf[i] == 0)
113*11be35a1SLionel Sambuc continue;
114*11be35a1SLionel Sambuc
115*11be35a1SLionel Sambuc if (getrlimit(rlimit[i], &res) != 0)
116*11be35a1SLionel Sambuc continue;
117*11be35a1SLionel Sambuc
118*11be35a1SLionel Sambuc res.rlim_cur = buf[i];
119*11be35a1SLionel Sambuc
120*11be35a1SLionel Sambuc (void)setrlimit(rlimit[i], &res);
121*11be35a1SLionel Sambuc }
122*11be35a1SLionel Sambuc
123*11be35a1SLionel Sambuc if (lim != 0)
124*11be35a1SLionel Sambuc atf_tc_fail("failed to set limit (%d)", lim);
125*11be35a1SLionel Sambuc }
126*11be35a1SLionel Sambuc
127*11be35a1SLionel Sambuc ATF_TC(setrlimit_current);
ATF_TC_HEAD(setrlimit_current,tc)128*11be35a1SLionel Sambuc ATF_TC_HEAD(setrlimit_current, tc)
129*11be35a1SLionel Sambuc {
130*11be35a1SLionel Sambuc atf_tc_set_md_var(tc, "descr", "setrlimit(3) with current limits");
131*11be35a1SLionel Sambuc }
132*11be35a1SLionel Sambuc
ATF_TC_BODY(setrlimit_current,tc)133*11be35a1SLionel Sambuc ATF_TC_BODY(setrlimit_current, tc)
134*11be35a1SLionel Sambuc {
135*11be35a1SLionel Sambuc struct rlimit res;
136*11be35a1SLionel Sambuc size_t i;
137*11be35a1SLionel Sambuc
138*11be35a1SLionel Sambuc for (i = 0; i < __arraycount(rlimit); i++) {
139*11be35a1SLionel Sambuc
140*11be35a1SLionel Sambuc (void)memset(&res, 0, sizeof(struct rlimit));
141*11be35a1SLionel Sambuc
142*11be35a1SLionel Sambuc ATF_REQUIRE(getrlimit(rlimit[i], &res) == 0);
143*11be35a1SLionel Sambuc ATF_REQUIRE(setrlimit(rlimit[i], &res) == 0);
144*11be35a1SLionel Sambuc }
145*11be35a1SLionel Sambuc }
146*11be35a1SLionel Sambuc
147*11be35a1SLionel Sambuc ATF_TC(setrlimit_err);
ATF_TC_HEAD(setrlimit_err,tc)148*11be35a1SLionel Sambuc ATF_TC_HEAD(setrlimit_err, tc)
149*11be35a1SLionel Sambuc {
150*11be35a1SLionel Sambuc atf_tc_set_md_var(tc, "descr", "Test error conditions");
151*11be35a1SLionel Sambuc }
152*11be35a1SLionel Sambuc
ATF_TC_BODY(setrlimit_err,tc)153*11be35a1SLionel Sambuc ATF_TC_BODY(setrlimit_err, tc)
154*11be35a1SLionel Sambuc {
155*11be35a1SLionel Sambuc struct rlimit res;
156*11be35a1SLionel Sambuc size_t i;
157*11be35a1SLionel Sambuc
158*11be35a1SLionel Sambuc for (i = 0; i < __arraycount(rlimit); i++) {
159*11be35a1SLionel Sambuc
160*11be35a1SLionel Sambuc errno = 0;
161*11be35a1SLionel Sambuc
162*11be35a1SLionel Sambuc ATF_REQUIRE(getrlimit(rlimit[i], (void *)0) != 0);
163*11be35a1SLionel Sambuc ATF_REQUIRE(errno == EFAULT);
164*11be35a1SLionel Sambuc }
165*11be35a1SLionel Sambuc
166*11be35a1SLionel Sambuc errno = 0;
167*11be35a1SLionel Sambuc
168*11be35a1SLionel Sambuc ATF_REQUIRE(getrlimit(INT_MAX, &res) != 0);
169*11be35a1SLionel Sambuc ATF_REQUIRE(errno == EINVAL);
170*11be35a1SLionel Sambuc }
171*11be35a1SLionel Sambuc
172*11be35a1SLionel Sambuc ATF_TC_WITH_CLEANUP(setrlimit_fsize);
ATF_TC_HEAD(setrlimit_fsize,tc)173*11be35a1SLionel Sambuc ATF_TC_HEAD(setrlimit_fsize, tc)
174*11be35a1SLionel Sambuc {
175*11be35a1SLionel Sambuc atf_tc_set_md_var(tc, "descr", "Test setrlimit(2), RLIMIT_FSIZE");
176*11be35a1SLionel Sambuc }
177*11be35a1SLionel Sambuc
ATF_TC_BODY(setrlimit_fsize,tc)178*11be35a1SLionel Sambuc ATF_TC_BODY(setrlimit_fsize, tc)
179*11be35a1SLionel Sambuc {
180*11be35a1SLionel Sambuc struct rlimit res;
181*11be35a1SLionel Sambuc int fd, sta;
182*11be35a1SLionel Sambuc pid_t pid;
183*11be35a1SLionel Sambuc
184*11be35a1SLionel Sambuc fd = open(path, O_RDWR | O_CREAT, 0700);
185*11be35a1SLionel Sambuc
186*11be35a1SLionel Sambuc if (fd < 0)
187*11be35a1SLionel Sambuc atf_tc_fail("initialization failed");
188*11be35a1SLionel Sambuc
189*11be35a1SLionel Sambuc pid = fork();
190*11be35a1SLionel Sambuc ATF_REQUIRE(pid >= 0);
191*11be35a1SLionel Sambuc
192*11be35a1SLionel Sambuc if (pid == 0) {
193*11be35a1SLionel Sambuc
194*11be35a1SLionel Sambuc res.rlim_cur = 2;
195*11be35a1SLionel Sambuc res.rlim_max = 2;
196*11be35a1SLionel Sambuc
197*11be35a1SLionel Sambuc if (setrlimit(RLIMIT_FSIZE, &res) != 0)
198*11be35a1SLionel Sambuc _exit(EXIT_FAILURE);
199*11be35a1SLionel Sambuc
200*11be35a1SLionel Sambuc if (signal(SIGXFSZ, sighandler) == SIG_ERR)
201*11be35a1SLionel Sambuc _exit(EXIT_FAILURE);
202*11be35a1SLionel Sambuc
203*11be35a1SLionel Sambuc /*
204*11be35a1SLionel Sambuc * The third call should generate a SIGXFSZ.
205*11be35a1SLionel Sambuc */
206*11be35a1SLionel Sambuc (void)write(fd, "X", 1);
207*11be35a1SLionel Sambuc (void)write(fd, "X", 1);
208*11be35a1SLionel Sambuc (void)write(fd, "X", 1);
209*11be35a1SLionel Sambuc
210*11be35a1SLionel Sambuc _exit(EXIT_FAILURE);
211*11be35a1SLionel Sambuc }
212*11be35a1SLionel Sambuc
213*11be35a1SLionel Sambuc (void)close(fd);
214*11be35a1SLionel Sambuc (void)wait(&sta);
215*11be35a1SLionel Sambuc (void)unlink(path);
216*11be35a1SLionel Sambuc
217*11be35a1SLionel Sambuc if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
218*11be35a1SLionel Sambuc atf_tc_fail("RLIMIT_FSIZE not enforced");
219*11be35a1SLionel Sambuc }
220*11be35a1SLionel Sambuc
ATF_TC_CLEANUP(setrlimit_fsize,tc)221*11be35a1SLionel Sambuc ATF_TC_CLEANUP(setrlimit_fsize, tc)
222*11be35a1SLionel Sambuc {
223*11be35a1SLionel Sambuc (void)unlink(path);
224*11be35a1SLionel Sambuc }
225*11be35a1SLionel Sambuc
226*11be35a1SLionel Sambuc static void
sighandler(int signo)227*11be35a1SLionel Sambuc sighandler(int signo)
228*11be35a1SLionel Sambuc {
229*11be35a1SLionel Sambuc
230*11be35a1SLionel Sambuc if (signo != SIGXFSZ)
231*11be35a1SLionel Sambuc _exit(EXIT_FAILURE);
232*11be35a1SLionel Sambuc
233*11be35a1SLionel Sambuc _exit(EXIT_SUCCESS);
234*11be35a1SLionel Sambuc }
235*11be35a1SLionel Sambuc
236*11be35a1SLionel Sambuc ATF_TC(setrlimit_memlock);
ATF_TC_HEAD(setrlimit_memlock,tc)237*11be35a1SLionel Sambuc ATF_TC_HEAD(setrlimit_memlock, tc)
238*11be35a1SLionel Sambuc {
239*11be35a1SLionel Sambuc atf_tc_set_md_var(tc, "descr", "Test setrlimit(2), RLIMIT_MEMLOCK");
240*11be35a1SLionel Sambuc }
241*11be35a1SLionel Sambuc
ATF_TC_BODY(setrlimit_memlock,tc)242*11be35a1SLionel Sambuc ATF_TC_BODY(setrlimit_memlock, tc)
243*11be35a1SLionel Sambuc {
244*11be35a1SLionel Sambuc struct rlimit res;
245*11be35a1SLionel Sambuc void *buf;
246*11be35a1SLionel Sambuc long page;
247*11be35a1SLionel Sambuc pid_t pid;
248*11be35a1SLionel Sambuc int sta;
249*11be35a1SLionel Sambuc
250*11be35a1SLionel Sambuc page = sysconf(_SC_PAGESIZE);
251*11be35a1SLionel Sambuc ATF_REQUIRE(page >= 0);
252*11be35a1SLionel Sambuc
253*11be35a1SLionel Sambuc buf = malloc(page);
254*11be35a1SLionel Sambuc pid = fork();
255*11be35a1SLionel Sambuc
256*11be35a1SLionel Sambuc if (buf == NULL || pid < 0)
257*11be35a1SLionel Sambuc atf_tc_fail("initialization failed");
258*11be35a1SLionel Sambuc
259*11be35a1SLionel Sambuc if (pid == 0) {
260*11be35a1SLionel Sambuc
261*11be35a1SLionel Sambuc /*
262*11be35a1SLionel Sambuc * Try to lock a page while
263*11be35a1SLionel Sambuc * RLIMIT_MEMLOCK is zero.
264*11be35a1SLionel Sambuc */
265*11be35a1SLionel Sambuc if (mlock(buf, page) != 0)
266*11be35a1SLionel Sambuc _exit(EXIT_FAILURE);
267*11be35a1SLionel Sambuc
268*11be35a1SLionel Sambuc if (munlock(buf, page) != 0)
269*11be35a1SLionel Sambuc _exit(EXIT_FAILURE);
270*11be35a1SLionel Sambuc
271*11be35a1SLionel Sambuc res.rlim_cur = 0;
272*11be35a1SLionel Sambuc res.rlim_max = 0;
273*11be35a1SLionel Sambuc
274*11be35a1SLionel Sambuc if (setrlimit(RLIMIT_MEMLOCK, &res) != 0)
275*11be35a1SLionel Sambuc _exit(EXIT_FAILURE);
276*11be35a1SLionel Sambuc
277*11be35a1SLionel Sambuc if (mlock(buf, page) != 0)
278*11be35a1SLionel Sambuc _exit(EXIT_SUCCESS);
279*11be35a1SLionel Sambuc
280*11be35a1SLionel Sambuc (void)munlock(buf, page);
281*11be35a1SLionel Sambuc
282*11be35a1SLionel Sambuc _exit(EXIT_FAILURE);
283*11be35a1SLionel Sambuc }
284*11be35a1SLionel Sambuc
285*11be35a1SLionel Sambuc free(buf);
286*11be35a1SLionel Sambuc
287*11be35a1SLionel Sambuc (void)wait(&sta);
288*11be35a1SLionel Sambuc
289*11be35a1SLionel Sambuc if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
290*11be35a1SLionel Sambuc atf_tc_fail("RLIMIT_MEMLOCK not enforced");
291*11be35a1SLionel Sambuc }
292*11be35a1SLionel Sambuc
293*11be35a1SLionel Sambuc ATF_TC(setrlimit_nofile_1);
ATF_TC_HEAD(setrlimit_nofile_1,tc)294*11be35a1SLionel Sambuc ATF_TC_HEAD(setrlimit_nofile_1, tc)
295*11be35a1SLionel Sambuc {
296*11be35a1SLionel Sambuc atf_tc_set_md_var(tc, "descr", "Test setrlimit(2), RLIMIT_NOFILE, #1");
297*11be35a1SLionel Sambuc }
298*11be35a1SLionel Sambuc
ATF_TC_BODY(setrlimit_nofile_1,tc)299*11be35a1SLionel Sambuc ATF_TC_BODY(setrlimit_nofile_1, tc)
300*11be35a1SLionel Sambuc {
301*11be35a1SLionel Sambuc struct rlimit res;
302*11be35a1SLionel Sambuc int fd, i, rv, sta;
303*11be35a1SLionel Sambuc pid_t pid;
304*11be35a1SLionel Sambuc
305*11be35a1SLionel Sambuc res.rlim_cur = 0;
306*11be35a1SLionel Sambuc res.rlim_max = 0;
307*11be35a1SLionel Sambuc
308*11be35a1SLionel Sambuc pid = fork();
309*11be35a1SLionel Sambuc ATF_REQUIRE(pid >= 0);
310*11be35a1SLionel Sambuc
311*11be35a1SLionel Sambuc if (pid == 0) {
312*11be35a1SLionel Sambuc
313*11be35a1SLionel Sambuc /*
314*11be35a1SLionel Sambuc * Close all descriptors, set RLIMIT_NOFILE
315*11be35a1SLionel Sambuc * to zero, and try to open a random file.
316*11be35a1SLionel Sambuc * This should fail with EMFILE.
317*11be35a1SLionel Sambuc */
318*11be35a1SLionel Sambuc for (i = 0; i < 1024; i++)
319*11be35a1SLionel Sambuc (void)close(i);
320*11be35a1SLionel Sambuc
321*11be35a1SLionel Sambuc rv = setrlimit(RLIMIT_NOFILE, &res);
322*11be35a1SLionel Sambuc
323*11be35a1SLionel Sambuc if (rv != 0)
324*11be35a1SLionel Sambuc _exit(EXIT_FAILURE);
325*11be35a1SLionel Sambuc
326*11be35a1SLionel Sambuc errno = 0;
327*11be35a1SLionel Sambuc fd = open("/etc/passwd", O_RDONLY);
328*11be35a1SLionel Sambuc
329*11be35a1SLionel Sambuc if (fd >= 0 || errno != EMFILE)
330*11be35a1SLionel Sambuc _exit(EXIT_FAILURE);
331*11be35a1SLionel Sambuc
332*11be35a1SLionel Sambuc _exit(EXIT_SUCCESS);
333*11be35a1SLionel Sambuc }
334*11be35a1SLionel Sambuc
335*11be35a1SLionel Sambuc (void)wait(&sta);
336*11be35a1SLionel Sambuc
337*11be35a1SLionel Sambuc if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
338*11be35a1SLionel Sambuc atf_tc_fail("RLIMIT_NOFILE not enforced");
339*11be35a1SLionel Sambuc }
340*11be35a1SLionel Sambuc
341*11be35a1SLionel Sambuc ATF_TC(setrlimit_nofile_2);
ATF_TC_HEAD(setrlimit_nofile_2,tc)342*11be35a1SLionel Sambuc ATF_TC_HEAD(setrlimit_nofile_2, tc)
343*11be35a1SLionel Sambuc {
344*11be35a1SLionel Sambuc atf_tc_set_md_var(tc, "descr", "Test setrlimit(2), RLIMIT_NOFILE, #2");
345*11be35a1SLionel Sambuc }
346*11be35a1SLionel Sambuc
ATF_TC_BODY(setrlimit_nofile_2,tc)347*11be35a1SLionel Sambuc ATF_TC_BODY(setrlimit_nofile_2, tc)
348*11be35a1SLionel Sambuc {
349*11be35a1SLionel Sambuc static const rlim_t lim = 12;
350*11be35a1SLionel Sambuc struct rlimit res;
351*11be35a1SLionel Sambuc int fd, i, rv, sta;
352*11be35a1SLionel Sambuc pid_t pid;
353*11be35a1SLionel Sambuc
354*11be35a1SLionel Sambuc /*
355*11be35a1SLionel Sambuc * See that an arbitrary limit on
356*11be35a1SLionel Sambuc * open files is being enforced.
357*11be35a1SLionel Sambuc */
358*11be35a1SLionel Sambuc res.rlim_cur = lim;
359*11be35a1SLionel Sambuc res.rlim_max = lim;
360*11be35a1SLionel Sambuc
361*11be35a1SLionel Sambuc pid = fork();
362*11be35a1SLionel Sambuc ATF_REQUIRE(pid >= 0);
363*11be35a1SLionel Sambuc
364*11be35a1SLionel Sambuc if (pid == 0) {
365*11be35a1SLionel Sambuc
366*11be35a1SLionel Sambuc for (i = 0; i < 1024; i++)
367*11be35a1SLionel Sambuc (void)close(i);
368*11be35a1SLionel Sambuc
369*11be35a1SLionel Sambuc rv = setrlimit(RLIMIT_NOFILE, &res);
370*11be35a1SLionel Sambuc
371*11be35a1SLionel Sambuc if (rv != 0)
372*11be35a1SLionel Sambuc _exit(EXIT_FAILURE);
373*11be35a1SLionel Sambuc
374*11be35a1SLionel Sambuc for (i = 0; i < (int)lim; i++) {
375*11be35a1SLionel Sambuc
376*11be35a1SLionel Sambuc fd = open("/etc/passwd", O_RDONLY);
377*11be35a1SLionel Sambuc
378*11be35a1SLionel Sambuc if (fd < 0)
379*11be35a1SLionel Sambuc _exit(EXIT_FAILURE);
380*11be35a1SLionel Sambuc }
381*11be35a1SLionel Sambuc
382*11be35a1SLionel Sambuc /*
383*11be35a1SLionel Sambuc * After the limit has been reached,
384*11be35a1SLionel Sambuc * EMFILE should again follow.
385*11be35a1SLionel Sambuc */
386*11be35a1SLionel Sambuc fd = open("/etc/passwd", O_RDONLY);
387*11be35a1SLionel Sambuc
388*11be35a1SLionel Sambuc if (fd >= 0 || errno != EMFILE)
389*11be35a1SLionel Sambuc _exit(EXIT_FAILURE);
390*11be35a1SLionel Sambuc
391*11be35a1SLionel Sambuc _exit(EXIT_SUCCESS);
392*11be35a1SLionel Sambuc }
393*11be35a1SLionel Sambuc
394*11be35a1SLionel Sambuc (void)wait(&sta);
395*11be35a1SLionel Sambuc
396*11be35a1SLionel Sambuc if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
397*11be35a1SLionel Sambuc atf_tc_fail("RLIMIT_NOFILE not enforced");
398*11be35a1SLionel Sambuc }
399*11be35a1SLionel Sambuc
400*11be35a1SLionel Sambuc ATF_TC(setrlimit_nproc);
ATF_TC_HEAD(setrlimit_nproc,tc)401*11be35a1SLionel Sambuc ATF_TC_HEAD(setrlimit_nproc, tc)
402*11be35a1SLionel Sambuc {
403*11be35a1SLionel Sambuc atf_tc_set_md_var(tc, "descr", "Test setrlimit(2), RLIMIT_NPROC");
404*11be35a1SLionel Sambuc atf_tc_set_md_var(tc, "require.user", "unprivileged");
405*11be35a1SLionel Sambuc }
406*11be35a1SLionel Sambuc
ATF_TC_BODY(setrlimit_nproc,tc)407*11be35a1SLionel Sambuc ATF_TC_BODY(setrlimit_nproc, tc)
408*11be35a1SLionel Sambuc {
409*11be35a1SLionel Sambuc struct rlimit res;
410*11be35a1SLionel Sambuc pid_t pid, cpid;
411*11be35a1SLionel Sambuc int sta;
412*11be35a1SLionel Sambuc
413*11be35a1SLionel Sambuc pid = fork();
414*11be35a1SLionel Sambuc ATF_REQUIRE(pid >= 0);
415*11be35a1SLionel Sambuc
416*11be35a1SLionel Sambuc if (pid == 0) {
417*11be35a1SLionel Sambuc
418*11be35a1SLionel Sambuc /*
419*11be35a1SLionel Sambuc * Set RLIMIT_NPROC to zero and try to fork.
420*11be35a1SLionel Sambuc */
421*11be35a1SLionel Sambuc res.rlim_cur = 0;
422*11be35a1SLionel Sambuc res.rlim_max = 0;
423*11be35a1SLionel Sambuc
424*11be35a1SLionel Sambuc if (setrlimit(RLIMIT_NPROC, &res) != 0)
425*11be35a1SLionel Sambuc _exit(EXIT_FAILURE);
426*11be35a1SLionel Sambuc
427*11be35a1SLionel Sambuc cpid = fork();
428*11be35a1SLionel Sambuc
429*11be35a1SLionel Sambuc if (cpid < 0)
430*11be35a1SLionel Sambuc _exit(EXIT_SUCCESS);
431*11be35a1SLionel Sambuc
432*11be35a1SLionel Sambuc _exit(EXIT_FAILURE);
433*11be35a1SLionel Sambuc }
434*11be35a1SLionel Sambuc
435*11be35a1SLionel Sambuc (void)waitpid(pid, &sta, 0);
436*11be35a1SLionel Sambuc
437*11be35a1SLionel Sambuc if (WIFEXITED(sta) == 0 || WEXITSTATUS(sta) != EXIT_SUCCESS)
438*11be35a1SLionel Sambuc atf_tc_fail("RLIMIT_NPROC not enforced");
439*11be35a1SLionel Sambuc }
440*11be35a1SLionel Sambuc
441*11be35a1SLionel Sambuc ATF_TC(setrlimit_nthr);
ATF_TC_HEAD(setrlimit_nthr,tc)442*11be35a1SLionel Sambuc ATF_TC_HEAD(setrlimit_nthr, tc)
443*11be35a1SLionel Sambuc {
444*11be35a1SLionel Sambuc atf_tc_set_md_var(tc, "descr", "Test setrlimit(2), RLIMIT_NTHR");
445*11be35a1SLionel Sambuc atf_tc_set_md_var(tc, "require.user", "unprivileged");
446*11be35a1SLionel Sambuc }
447*11be35a1SLionel Sambuc
448*11be35a1SLionel Sambuc static void
func(lwpid_t * id)449*11be35a1SLionel Sambuc func(lwpid_t *id)
450*11be35a1SLionel Sambuc {
451*11be35a1SLionel Sambuc printf("thread %d\n", *id);
452*11be35a1SLionel Sambuc fflush(stdout);
453*11be35a1SLionel Sambuc _lwp_exit();
454*11be35a1SLionel Sambuc }
455*11be35a1SLionel Sambuc
ATF_TC_BODY(setrlimit_nthr,tc)456*11be35a1SLionel Sambuc ATF_TC_BODY(setrlimit_nthr, tc)
457*11be35a1SLionel Sambuc {
458*11be35a1SLionel Sambuc struct rlimit res;
459*11be35a1SLionel Sambuc lwpid_t lwpid;
460*11be35a1SLionel Sambuc ucontext_t c;
461*11be35a1SLionel Sambuc
462*11be35a1SLionel Sambuc /*
463*11be35a1SLionel Sambuc * Set RLIMIT_NTHR to zero and try to create a thread.
464*11be35a1SLionel Sambuc */
465*11be35a1SLionel Sambuc res.rlim_cur = 0;
466*11be35a1SLionel Sambuc res.rlim_max = 0;
467*11be35a1SLionel Sambuc ATF_REQUIRE(setrlimit(RLIMIT_NTHR, &res) == 0);
468*11be35a1SLionel Sambuc ATF_REQUIRE(getcontext(&c) == 0);
469*11be35a1SLionel Sambuc c.uc_link = NULL;
470*11be35a1SLionel Sambuc sigemptyset(&c.uc_sigmask);
471*11be35a1SLionel Sambuc c.uc_stack.ss_flags = 0;
472*11be35a1SLionel Sambuc c.uc_stack.ss_size = 4096;
473*11be35a1SLionel Sambuc ATF_REQUIRE((c.uc_stack.ss_sp = malloc(c.uc_stack.ss_size)) != NULL);
474*11be35a1SLionel Sambuc makecontext(&c, func, 1, &lwpid);
475*11be35a1SLionel Sambuc ATF_CHECK_ERRNO(EAGAIN, _lwp_create(&c, 0, &lwpid) == -1);
476*11be35a1SLionel Sambuc }
477*11be35a1SLionel Sambuc
478*11be35a1SLionel Sambuc ATF_TC(setrlimit_perm);
ATF_TC_HEAD(setrlimit_perm,tc)479*11be35a1SLionel Sambuc ATF_TC_HEAD(setrlimit_perm, tc)
480*11be35a1SLionel Sambuc {
481*11be35a1SLionel Sambuc atf_tc_set_md_var(tc, "descr", "Test setrlimit(2) for EPERM");
482*11be35a1SLionel Sambuc atf_tc_set_md_var(tc, "require.user", "unprivileged");
483*11be35a1SLionel Sambuc }
484*11be35a1SLionel Sambuc
ATF_TC_BODY(setrlimit_perm,tc)485*11be35a1SLionel Sambuc ATF_TC_BODY(setrlimit_perm, tc)
486*11be35a1SLionel Sambuc {
487*11be35a1SLionel Sambuc struct rlimit res;
488*11be35a1SLionel Sambuc size_t i;
489*11be35a1SLionel Sambuc
490*11be35a1SLionel Sambuc /*
491*11be35a1SLionel Sambuc * Try to raise the maximum limits as an user.
492*11be35a1SLionel Sambuc */
493*11be35a1SLionel Sambuc for (i = 0; i < __arraycount(rlimit); i++) {
494*11be35a1SLionel Sambuc
495*11be35a1SLionel Sambuc ATF_REQUIRE(getrlimit(rlimit[i], &res) == 0);
496*11be35a1SLionel Sambuc
497*11be35a1SLionel Sambuc if (res.rlim_max == UINT64_MAX) /* Overflow. */
498*11be35a1SLionel Sambuc continue;
499*11be35a1SLionel Sambuc
500*11be35a1SLionel Sambuc errno = 0;
501*11be35a1SLionel Sambuc res.rlim_max = res.rlim_max + 1;
502*11be35a1SLionel Sambuc
503*11be35a1SLionel Sambuc ATF_CHECK_ERRNO(EPERM, setrlimit(rlimit[i], &res) != 0);
504*11be35a1SLionel Sambuc }
505*11be35a1SLionel Sambuc }
506*11be35a1SLionel Sambuc
ATF_TP_ADD_TCS(tp)507*11be35a1SLionel Sambuc ATF_TP_ADD_TCS(tp)
508*11be35a1SLionel Sambuc {
509*11be35a1SLionel Sambuc
510*11be35a1SLionel Sambuc ATF_TP_ADD_TC(tp, setrlimit_basic);
511*11be35a1SLionel Sambuc ATF_TP_ADD_TC(tp, setrlimit_current);
512*11be35a1SLionel Sambuc ATF_TP_ADD_TC(tp, setrlimit_err);
513*11be35a1SLionel Sambuc ATF_TP_ADD_TC(tp, setrlimit_fsize);
514*11be35a1SLionel Sambuc ATF_TP_ADD_TC(tp, setrlimit_memlock);
515*11be35a1SLionel Sambuc ATF_TP_ADD_TC(tp, setrlimit_nofile_1);
516*11be35a1SLionel Sambuc ATF_TP_ADD_TC(tp, setrlimit_nofile_2);
517*11be35a1SLionel Sambuc ATF_TP_ADD_TC(tp, setrlimit_nproc);
518*11be35a1SLionel Sambuc ATF_TP_ADD_TC(tp, setrlimit_perm);
519*11be35a1SLionel Sambuc ATF_TP_ADD_TC(tp, setrlimit_nthr);
520*11be35a1SLionel Sambuc
521*11be35a1SLionel Sambuc return atf_no_error();
522*11be35a1SLionel Sambuc }
523