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