1 /* $OpenBSD: t_pipe2.c,v 1.4 2023/10/31 07:56:44 claudio Exp $ */ 2 /* $NetBSD: t_pipe2.c,v 1.9 2017/01/13 21:19:45 christos 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 Christos Zoulas. 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 * 3. All advertising materials mentioning features or use of this software 20 * must display the following acknowledgement: 21 * This product includes software developed by the NetBSD 22 * Foundation, Inc. and its contributors. 23 * 4. Neither the name of The NetBSD Foundation nor the names of its 24 * contributors may be used to endorse or promote products derived 25 * from this software without specific prior written permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 29 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 30 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 31 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 37 * POSSIBILITY OF SUCH DAMAGE. 38 */ 39 40 #include "macros.h" 41 42 #include "atf-c.h" 43 #include <fcntl.h> 44 #include <unistd.h> 45 #include <stdlib.h> 46 #include <errno.h> 47 #include <sys/resource.h> 48 49 static void 50 run(int flags) 51 { 52 int fd[2], i; 53 54 while ((i = open("/", O_RDONLY)) < 3) 55 ATF_REQUIRE(i != -1); 56 57 ATF_REQUIRE_MSG(closefrom(3) != -1, "closefrom failed: %s", 58 strerror(errno)); 59 60 ATF_REQUIRE(pipe2(fd, flags) == 0); 61 62 ATF_REQUIRE(fd[0] == 3); 63 ATF_REQUIRE(fd[1] == 4); 64 65 if (flags & O_CLOEXEC) { 66 ATF_REQUIRE((fcntl(fd[0], F_GETFD) & FD_CLOEXEC) != 0); 67 ATF_REQUIRE((fcntl(fd[1], F_GETFD) & FD_CLOEXEC) != 0); 68 } else { 69 ATF_REQUIRE((fcntl(fd[0], F_GETFD) & FD_CLOEXEC) == 0); 70 ATF_REQUIRE((fcntl(fd[1], F_GETFD) & FD_CLOEXEC) == 0); 71 } 72 73 if (flags & O_NONBLOCK) { 74 ATF_REQUIRE((fcntl(fd[0], F_GETFL) & O_NONBLOCK) != 0); 75 ATF_REQUIRE((fcntl(fd[1], F_GETFL) & O_NONBLOCK) != 0); 76 } else { 77 ATF_REQUIRE((fcntl(fd[0], F_GETFL) & O_NONBLOCK) == 0); 78 ATF_REQUIRE((fcntl(fd[1], F_GETFL) & O_NONBLOCK) == 0); 79 } 80 81 #ifndef __OpenBSD__ 82 /* F_GETNOSIGPIPE not available */ 83 if (flags & O_NOSIGPIPE) { 84 ATF_REQUIRE(fcntl(fd[0], F_GETNOSIGPIPE) != 0); 85 ATF_REQUIRE(fcntl(fd[1], F_GETNOSIGPIPE) != 0); 86 } else { 87 ATF_REQUIRE(fcntl(fd[0], F_GETNOSIGPIPE) == 0); 88 ATF_REQUIRE(fcntl(fd[1], F_GETNOSIGPIPE) == 0); 89 } 90 #endif 91 92 ATF_REQUIRE(close(fd[0]) != -1); 93 ATF_REQUIRE(close(fd[1]) != -1); 94 } 95 96 ATF_TC(pipe2_basic); 97 ATF_TC_HEAD(pipe2_basic, tc) 98 { 99 atf_tc_set_md_var(tc, "descr", "A basic test of pipe2(2)"); 100 } 101 102 ATF_TC_BODY(pipe2_basic, tc) 103 { 104 run(0); 105 } 106 107 ATF_TC(pipe2_consume); 108 ATF_TC_HEAD(pipe2_consume, tc) 109 { 110 atf_tc_set_md_var(tc, "descr", "Test that consuming file descriptors " 111 "with pipe2(2) does not crash the system (PR kern/46457)"); 112 } 113 114 ATF_TC_BODY(pipe2_consume, tc) 115 { 116 struct rlimit rl; 117 int err, filedes[2]; 118 int old; 119 120 (void)closefrom(4); 121 122 err = getrlimit(RLIMIT_NOFILE, &rl); 123 ATF_REQUIRE(err == 0); 124 /* 125 * The heart of this test is to run against the number of open 126 * file descriptor limit in the middle of a pipe2() call - i.e. 127 * before the call only a single descriptor may be openend. 128 */ 129 old = rl.rlim_cur; 130 rl.rlim_cur = 4; 131 err = setrlimit(RLIMIT_NOFILE, &rl); 132 ATF_REQUIRE(err == 0); 133 134 err = pipe2(filedes, O_CLOEXEC); 135 ATF_REQUIRE(err == -1); 136 rl.rlim_cur = old; 137 err = setrlimit(RLIMIT_NOFILE, &rl); 138 } 139 140 ATF_TC(pipe2_nonblock); 141 ATF_TC_HEAD(pipe2_nonblock, tc) 142 { 143 atf_tc_set_md_var(tc, "descr", "A non-blocking test of pipe2(2)"); 144 } 145 146 ATF_TC_BODY(pipe2_nonblock, tc) 147 { 148 run(O_NONBLOCK); 149 } 150 151 ATF_TC(pipe2_cloexec); 152 ATF_TC_HEAD(pipe2_cloexec, tc) 153 { 154 atf_tc_set_md_var(tc, "descr", "A close-on-exec test of pipe2(2)"); 155 } 156 157 ATF_TC_BODY(pipe2_cloexec, tc) 158 { 159 run(O_CLOEXEC); 160 } 161 162 ATF_TC(pipe2_nosigpipe); 163 ATF_TC_HEAD(pipe2_nosigpipe, tc) 164 { 165 atf_tc_set_md_var(tc, "descr", "A no sigpipe test of pipe2(2)"); 166 } 167 168 ATF_TC_BODY(pipe2_nosigpipe, tc) 169 { 170 run(O_NOSIGPIPE); 171 } 172 173 ATF_TC(pipe2_einval); 174 ATF_TC_HEAD(pipe2_einval, tc) 175 { 176 atf_tc_set_md_var(tc, "descr", "A error check of pipe2(2)"); 177 } 178 179 ATF_TC_BODY(pipe2_einval, tc) 180 { 181 int fd[2]; 182 ATF_REQUIRE_ERRNO(EINVAL, pipe2(fd, O_ASYNC) == -1); 183 } 184 185 ATF_TP_ADD_TCS(tp) 186 { 187 188 ATF_TP_ADD_TC(tp, pipe2_basic); 189 ATF_TP_ADD_TC(tp, pipe2_consume); 190 ATF_TP_ADD_TC(tp, pipe2_nonblock); 191 ATF_TP_ADD_TC(tp, pipe2_cloexec); 192 #ifndef __OpenBSD__ 193 /* O_NOSIGPIPE not available */ 194 ATF_TP_ADD_TC(tp, pipe2_nosigpipe); 195 #endif 196 ATF_TP_ADD_TC(tp, pipe2_einval); 197 198 return atf_no_error(); 199 } 200