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