1 /*- 2 * Copyright (c) 2023 Klara, Inc. 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7 #include <sys/resource.h> 8 #include <sys/wait.h> 9 10 #include <errno.h> 11 #include <libutil.h> 12 #include <unistd.h> 13 14 #include <atf-c.h> 15 16 ATF_TC(forkfail); 17 ATF_TC_HEAD(forkfail, tc) 18 { 19 atf_tc_set_md_var(tc, "descr", "Check for fd leak when fork() fails"); 20 atf_tc_set_md_var(tc, "require.user", "unprivileged"); 21 } 22 23 ATF_TC_BODY(forkfail, tc) 24 { 25 struct rlimit orl, nrl; 26 pid_t pid; 27 int prevfd, fd, pty; 28 29 /* set process limit to 1 so fork() will fail */ 30 ATF_REQUIRE_EQ(0, getrlimit(RLIMIT_NPROC, &orl)); 31 nrl = orl; 32 nrl.rlim_cur = 1; 33 ATF_REQUIRE_EQ(0, setrlimit(RLIMIT_NPROC, &nrl)); 34 /* check first free fd */ 35 ATF_REQUIRE((fd = dup(0)) > 0); 36 ATF_REQUIRE_EQ(0, close(fd)); 37 /* attempt forkpty() */ 38 pid = forkpty(&pty, NULL, NULL, NULL); 39 if (pid == 0) { 40 /* child - fork() unexpectedly succeeded */ 41 _exit(0); 42 } 43 ATF_CHECK_ERRNO(EAGAIN, pid < 0); 44 if (pid > 0) { 45 /* parent - fork() unexpectedly succeeded */ 46 (void)waitpid(pid, NULL, 0); 47 } 48 /* check that first free fd hasn't changed */ 49 prevfd = fd; 50 ATF_REQUIRE((fd = dup(0)) > 0); 51 ATF_CHECK_EQ(prevfd, fd); 52 } 53 54 ATF_TP_ADD_TCS(tp) 55 { 56 ATF_TP_ADD_TC(tp, forkfail); 57 return (atf_no_error()); 58 } 59