1de503941SPawel Jakub Dawidek /*- 2de503941SPawel Jakub Dawidek * Copyright (c) 2012 The FreeBSD Foundation 3de503941SPawel Jakub Dawidek * All rights reserved. 4de503941SPawel Jakub Dawidek * 5de503941SPawel Jakub Dawidek * This software was developed by Pawel Jakub Dawidek under sponsorship from 6de503941SPawel Jakub Dawidek * the FreeBSD Foundation. 7de503941SPawel Jakub Dawidek * 8de503941SPawel Jakub Dawidek * Redistribution and use in source and binary forms, with or without 9de503941SPawel Jakub Dawidek * modification, are permitted provided that the following conditions 10de503941SPawel Jakub Dawidek * are met: 11de503941SPawel Jakub Dawidek * 1. Redistributions of source code must retain the above copyright 12de503941SPawel Jakub Dawidek * notice, this list of conditions and the following disclaimer. 13de503941SPawel Jakub Dawidek * 2. Redistributions in binary form must reproduce the above copyright 14de503941SPawel Jakub Dawidek * notice, this list of conditions and the following disclaimer in the 15de503941SPawel Jakub Dawidek * documentation and/or other materials provided with the distribution. 16de503941SPawel Jakub Dawidek * 17de503941SPawel Jakub Dawidek * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 18de503941SPawel Jakub Dawidek * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19de503941SPawel Jakub Dawidek * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20de503941SPawel Jakub Dawidek * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 21de503941SPawel Jakub Dawidek * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22de503941SPawel Jakub Dawidek * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23de503941SPawel Jakub Dawidek * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24de503941SPawel Jakub Dawidek * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25de503941SPawel Jakub Dawidek * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26de503941SPawel Jakub Dawidek * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27de503941SPawel Jakub Dawidek * SUCH DAMAGE. 28de503941SPawel Jakub Dawidek */ 29de503941SPawel Jakub Dawidek 30de503941SPawel Jakub Dawidek #include <sys/cdefs.h> 31de503941SPawel Jakub Dawidek __FBSDID("$FreeBSD$"); 32de503941SPawel Jakub Dawidek 33de503941SPawel Jakub Dawidek #include <sys/param.h> 34*b881b8beSRobert Watson #include <sys/capsicum.h> 35de503941SPawel Jakub Dawidek #include <sys/ioctl.h> 36de503941SPawel Jakub Dawidek #include <sys/procdesc.h> 37de503941SPawel Jakub Dawidek #include <sys/socket.h> 38de503941SPawel Jakub Dawidek #include <sys/wait.h> 39de503941SPawel Jakub Dawidek 40de503941SPawel Jakub Dawidek #include <err.h> 41de503941SPawel Jakub Dawidek #include <errno.h> 42de503941SPawel Jakub Dawidek #include <limits.h> 43de503941SPawel Jakub Dawidek #include <stdio.h> 44de503941SPawel Jakub Dawidek #include <stdlib.h> 45de503941SPawel Jakub Dawidek #include <unistd.h> 46de503941SPawel Jakub Dawidek 47de503941SPawel Jakub Dawidek #include "misc.h" 48de503941SPawel Jakub Dawidek 49de503941SPawel Jakub Dawidek static void 50de503941SPawel Jakub Dawidek ioctl_tests_0(int fd) 51de503941SPawel Jakub Dawidek { 52de503941SPawel Jakub Dawidek unsigned long cmds[2]; 53de503941SPawel Jakub Dawidek 542328a74aSPawel Jakub Dawidek CHECK(cap_ioctls_get(fd, NULL, 0) == CAP_IOCTLS_ALL); 55de503941SPawel Jakub Dawidek 56de503941SPawel Jakub Dawidek CHECK(fcntl(fd, F_GETFD) == 0); 57de503941SPawel Jakub Dawidek CHECK(ioctl(fd, FIOCLEX) == 0); 58de503941SPawel Jakub Dawidek CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC); 59de503941SPawel Jakub Dawidek CHECK(ioctl(fd, FIONCLEX) == 0); 60de503941SPawel Jakub Dawidek CHECK(fcntl(fd, F_GETFD) == 0); 61de503941SPawel Jakub Dawidek 62de503941SPawel Jakub Dawidek cmds[0] = FIOCLEX; 63de503941SPawel Jakub Dawidek cmds[1] = FIONCLEX; 64de503941SPawel Jakub Dawidek CHECK(cap_ioctls_limit(fd, cmds, nitems(cmds)) == 0); 65de503941SPawel Jakub Dawidek cmds[0] = cmds[1] = 0; 66de503941SPawel Jakub Dawidek CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == nitems(cmds)); 67de503941SPawel Jakub Dawidek CHECK((cmds[0] == FIOCLEX && cmds[1] == FIONCLEX) || 68de503941SPawel Jakub Dawidek (cmds[0] == FIONCLEX && cmds[1] == FIOCLEX)); 69de503941SPawel Jakub Dawidek cmds[0] = FIOCLEX; 70de503941SPawel Jakub Dawidek cmds[1] = FIONCLEX; 71de503941SPawel Jakub Dawidek CHECK(cap_ioctls_limit(fd, cmds, nitems(cmds)) == 0); 72de503941SPawel Jakub Dawidek cmds[0] = cmds[1] = 0; 73de503941SPawel Jakub Dawidek CHECK(cap_ioctls_get(fd, cmds, 1) == nitems(cmds)); 74de503941SPawel Jakub Dawidek CHECK(cmds[0] == FIOCLEX || cmds[0] == FIONCLEX); 75de503941SPawel Jakub Dawidek CHECK(cmds[1] == 0); 76de503941SPawel Jakub Dawidek 77de503941SPawel Jakub Dawidek CHECK(fcntl(fd, F_GETFD) == 0); 78de503941SPawel Jakub Dawidek CHECK(ioctl(fd, FIOCLEX) == 0); 79de503941SPawel Jakub Dawidek CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC); 80de503941SPawel Jakub Dawidek CHECK(ioctl(fd, FIONCLEX) == 0); 81de503941SPawel Jakub Dawidek CHECK(fcntl(fd, F_GETFD) == 0); 82de503941SPawel Jakub Dawidek 83de503941SPawel Jakub Dawidek cmds[0] = FIOCLEX; 84de503941SPawel Jakub Dawidek CHECK(cap_ioctls_limit(fd, cmds, 1) == 0); 85de503941SPawel Jakub Dawidek cmds[0] = cmds[1] = 0; 86de503941SPawel Jakub Dawidek CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == 1); 87de503941SPawel Jakub Dawidek CHECK(cmds[0] == FIOCLEX); 88de503941SPawel Jakub Dawidek cmds[0] = FIOCLEX; 89de503941SPawel Jakub Dawidek cmds[1] = FIONCLEX; 90de503941SPawel Jakub Dawidek errno = 0; 91de503941SPawel Jakub Dawidek CHECK(cap_ioctls_limit(fd, cmds, nitems(cmds)) == -1); 92de503941SPawel Jakub Dawidek CHECK(errno == ENOTCAPABLE); 93de503941SPawel Jakub Dawidek cmds[0] = cmds[1] = 0; 94de503941SPawel Jakub Dawidek CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == 1); 95de503941SPawel Jakub Dawidek CHECK(cmds[0] == FIOCLEX); 96de503941SPawel Jakub Dawidek 97de503941SPawel Jakub Dawidek CHECK(fcntl(fd, F_GETFD) == 0); 98de503941SPawel Jakub Dawidek CHECK(ioctl(fd, FIOCLEX) == 0); 99de503941SPawel Jakub Dawidek CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC); 100de503941SPawel Jakub Dawidek errno = 0; 101de503941SPawel Jakub Dawidek CHECK(ioctl(fd, FIONCLEX) == -1); 102de503941SPawel Jakub Dawidek CHECK(errno == ENOTCAPABLE); 103de503941SPawel Jakub Dawidek CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC); 104de503941SPawel Jakub Dawidek CHECK(fcntl(fd, F_SETFD, 0) == 0); 105de503941SPawel Jakub Dawidek CHECK(fcntl(fd, F_GETFD) == 0); 106de503941SPawel Jakub Dawidek 107de503941SPawel Jakub Dawidek CHECK(cap_ioctls_limit(fd, NULL, 0) == 0); 108de503941SPawel Jakub Dawidek CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == 0); 109de503941SPawel Jakub Dawidek cmds[0] = FIOCLEX; 110de503941SPawel Jakub Dawidek errno = 0; 111de503941SPawel Jakub Dawidek CHECK(cap_ioctls_limit(fd, cmds, 1) == -1); 112de503941SPawel Jakub Dawidek CHECK(errno == ENOTCAPABLE); 113de503941SPawel Jakub Dawidek CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == 0); 114de503941SPawel Jakub Dawidek 115de503941SPawel Jakub Dawidek CHECK(fcntl(fd, F_GETFD) == 0); 116de503941SPawel Jakub Dawidek errno = 0; 117de503941SPawel Jakub Dawidek CHECK(ioctl(fd, FIOCLEX) == -1); 118de503941SPawel Jakub Dawidek CHECK(errno == ENOTCAPABLE); 119de503941SPawel Jakub Dawidek CHECK(fcntl(fd, F_GETFD) == 0); 120de503941SPawel Jakub Dawidek CHECK(fcntl(fd, F_SETFD, FD_CLOEXEC) == 0); 121de503941SPawel Jakub Dawidek CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC); 122de503941SPawel Jakub Dawidek errno = 0; 123de503941SPawel Jakub Dawidek CHECK(ioctl(fd, FIONCLEX) == -1); 124de503941SPawel Jakub Dawidek CHECK(errno == ENOTCAPABLE); 125de503941SPawel Jakub Dawidek CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC); 126de503941SPawel Jakub Dawidek CHECK(fcntl(fd, F_SETFD, 0) == 0); 127de503941SPawel Jakub Dawidek CHECK(fcntl(fd, F_GETFD) == 0); 128de503941SPawel Jakub Dawidek } 129de503941SPawel Jakub Dawidek 130de503941SPawel Jakub Dawidek static void 131de503941SPawel Jakub Dawidek ioctl_tests_1(int fd) 132de503941SPawel Jakub Dawidek { 133de503941SPawel Jakub Dawidek unsigned long cmds[2]; 134de503941SPawel Jakub Dawidek 135de503941SPawel Jakub Dawidek cmds[0] = FIOCLEX; 136de503941SPawel Jakub Dawidek CHECK(cap_ioctls_limit(fd, cmds, 1) == 0); 137de503941SPawel Jakub Dawidek cmds[0] = cmds[1] = 0; 138de503941SPawel Jakub Dawidek CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == 1); 139de503941SPawel Jakub Dawidek CHECK(cmds[0] == FIOCLEX); 140de503941SPawel Jakub Dawidek CHECK(cmds[1] == 0); 141de503941SPawel Jakub Dawidek 142de503941SPawel Jakub Dawidek CHECK(cap_rights_limit(fd, CAP_ALL & ~CAP_IOCTL) == 0); 143de503941SPawel Jakub Dawidek CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == 0); 144de503941SPawel Jakub Dawidek 145de503941SPawel Jakub Dawidek cmds[0] = FIOCLEX; 146de503941SPawel Jakub Dawidek cmds[1] = FIONCLEX; 147de503941SPawel Jakub Dawidek errno = 0; 148de503941SPawel Jakub Dawidek CHECK(cap_ioctls_limit(fd, cmds, nitems(cmds)) == -1); 149de503941SPawel Jakub Dawidek CHECK(errno == ENOTCAPABLE); 150de503941SPawel Jakub Dawidek CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == 0); 151de503941SPawel Jakub Dawidek cmds[0] = FIOCLEX; 152de503941SPawel Jakub Dawidek errno = 0; 153de503941SPawel Jakub Dawidek CHECK(cap_ioctls_limit(fd, cmds, 1) == -1); 154de503941SPawel Jakub Dawidek CHECK(errno == ENOTCAPABLE); 155de503941SPawel Jakub Dawidek CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == 0); 156de503941SPawel Jakub Dawidek 157de503941SPawel Jakub Dawidek CHECK(fcntl(fd, F_GETFD) == 0); 158de503941SPawel Jakub Dawidek errno = 0; 159de503941SPawel Jakub Dawidek CHECK(ioctl(fd, FIOCLEX) == -1); 160de503941SPawel Jakub Dawidek CHECK(errno == ENOTCAPABLE); 161de503941SPawel Jakub Dawidek CHECK(fcntl(fd, F_GETFD) == 0); 162de503941SPawel Jakub Dawidek CHECK(fcntl(fd, F_SETFD, FD_CLOEXEC) == 0); 163de503941SPawel Jakub Dawidek CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC); 164de503941SPawel Jakub Dawidek errno = 0; 165de503941SPawel Jakub Dawidek CHECK(ioctl(fd, FIONCLEX) == -1); 166de503941SPawel Jakub Dawidek CHECK(errno == ENOTCAPABLE); 167de503941SPawel Jakub Dawidek CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC); 168de503941SPawel Jakub Dawidek CHECK(fcntl(fd, F_SETFD, 0) == 0); 169de503941SPawel Jakub Dawidek CHECK(fcntl(fd, F_GETFD) == 0); 170de503941SPawel Jakub Dawidek } 171de503941SPawel Jakub Dawidek 172de503941SPawel Jakub Dawidek static void 173de503941SPawel Jakub Dawidek ioctl_tests_2(int fd) 174de503941SPawel Jakub Dawidek { 175de503941SPawel Jakub Dawidek unsigned long cmds[2]; 176de503941SPawel Jakub Dawidek 177de503941SPawel Jakub Dawidek CHECK(cap_rights_limit(fd, CAP_ALL & ~CAP_IOCTL) == 0); 178de503941SPawel Jakub Dawidek CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == 0); 179de503941SPawel Jakub Dawidek 180de503941SPawel Jakub Dawidek cmds[0] = FIOCLEX; 181de503941SPawel Jakub Dawidek cmds[1] = FIONCLEX; 182de503941SPawel Jakub Dawidek errno = 0; 183de503941SPawel Jakub Dawidek CHECK(cap_ioctls_limit(fd, cmds, nitems(cmds)) == -1); 184de503941SPawel Jakub Dawidek CHECK(errno == ENOTCAPABLE); 185de503941SPawel Jakub Dawidek CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == 0); 186de503941SPawel Jakub Dawidek cmds[0] = FIOCLEX; 187de503941SPawel Jakub Dawidek errno = 0; 188de503941SPawel Jakub Dawidek CHECK(cap_ioctls_limit(fd, cmds, 1) == -1); 189de503941SPawel Jakub Dawidek CHECK(errno == ENOTCAPABLE); 190de503941SPawel Jakub Dawidek CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == 0); 191de503941SPawel Jakub Dawidek 192de503941SPawel Jakub Dawidek CHECK(fcntl(fd, F_GETFD) == 0); 193de503941SPawel Jakub Dawidek errno = 0; 194de503941SPawel Jakub Dawidek CHECK(ioctl(fd, FIOCLEX) == -1); 195de503941SPawel Jakub Dawidek CHECK(errno == ENOTCAPABLE); 196de503941SPawel Jakub Dawidek CHECK(fcntl(fd, F_GETFD) == 0); 197de503941SPawel Jakub Dawidek CHECK(fcntl(fd, F_SETFD, FD_CLOEXEC) == 0); 198de503941SPawel Jakub Dawidek CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC); 199de503941SPawel Jakub Dawidek errno = 0; 200de503941SPawel Jakub Dawidek CHECK(ioctl(fd, FIONCLEX) == -1); 201de503941SPawel Jakub Dawidek CHECK(errno == ENOTCAPABLE); 202de503941SPawel Jakub Dawidek CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC); 203de503941SPawel Jakub Dawidek CHECK(fcntl(fd, F_SETFD, 0) == 0); 204de503941SPawel Jakub Dawidek CHECK(fcntl(fd, F_GETFD) == 0); 205de503941SPawel Jakub Dawidek } 206de503941SPawel Jakub Dawidek 207de503941SPawel Jakub Dawidek static void 208de503941SPawel Jakub Dawidek ioctl_tests_send_0(int sock) 209de503941SPawel Jakub Dawidek { 210de503941SPawel Jakub Dawidek unsigned long cmds[2]; 211de503941SPawel Jakub Dawidek int fd; 212de503941SPawel Jakub Dawidek 213de503941SPawel Jakub Dawidek CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0); 214de503941SPawel Jakub Dawidek CHECK(descriptor_send(sock, fd) == 0); 215de503941SPawel Jakub Dawidek CHECK(close(fd) == 0); 216de503941SPawel Jakub Dawidek 217de503941SPawel Jakub Dawidek CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0); 218de503941SPawel Jakub Dawidek cmds[0] = FIOCLEX; 219de503941SPawel Jakub Dawidek cmds[1] = FIONCLEX; 220de503941SPawel Jakub Dawidek CHECK(cap_ioctls_limit(fd, cmds, nitems(cmds)) == 0); 221de503941SPawel Jakub Dawidek CHECK(descriptor_send(sock, fd) == 0); 222de503941SPawel Jakub Dawidek CHECK(close(fd) == 0); 223de503941SPawel Jakub Dawidek 224de503941SPawel Jakub Dawidek CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0); 225de503941SPawel Jakub Dawidek cmds[0] = FIOCLEX; 226de503941SPawel Jakub Dawidek CHECK(cap_ioctls_limit(fd, cmds, 1) == 0); 227de503941SPawel Jakub Dawidek CHECK(descriptor_send(sock, fd) == 0); 228de503941SPawel Jakub Dawidek CHECK(close(fd) == 0); 229de503941SPawel Jakub Dawidek 230de503941SPawel Jakub Dawidek CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0); 231de503941SPawel Jakub Dawidek CHECK(cap_ioctls_limit(fd, NULL, 0) == 0); 232de503941SPawel Jakub Dawidek CHECK(descriptor_send(sock, fd) == 0); 233de503941SPawel Jakub Dawidek CHECK(close(fd) == 0); 234de503941SPawel Jakub Dawidek } 235de503941SPawel Jakub Dawidek 236de503941SPawel Jakub Dawidek static void 237de503941SPawel Jakub Dawidek ioctl_tests_recv_0(int sock) 238de503941SPawel Jakub Dawidek { 239de503941SPawel Jakub Dawidek unsigned long cmds[2]; 240de503941SPawel Jakub Dawidek int fd; 241de503941SPawel Jakub Dawidek 242de503941SPawel Jakub Dawidek CHECK(descriptor_recv(sock, &fd) == 0); 243de503941SPawel Jakub Dawidek 2442328a74aSPawel Jakub Dawidek CHECK(cap_ioctls_get(fd, NULL, 0) == CAP_IOCTLS_ALL); 245de503941SPawel Jakub Dawidek 246de503941SPawel Jakub Dawidek CHECK(fcntl(fd, F_GETFD) == 0); 247de503941SPawel Jakub Dawidek CHECK(ioctl(fd, FIOCLEX) == 0); 248de503941SPawel Jakub Dawidek CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC); 249de503941SPawel Jakub Dawidek CHECK(ioctl(fd, FIONCLEX) == 0); 250de503941SPawel Jakub Dawidek CHECK(fcntl(fd, F_GETFD) == 0); 251de503941SPawel Jakub Dawidek 252de503941SPawel Jakub Dawidek CHECK(close(fd) == 0); 253de503941SPawel Jakub Dawidek 254de503941SPawel Jakub Dawidek CHECK(descriptor_recv(sock, &fd) == 0); 255de503941SPawel Jakub Dawidek 256de503941SPawel Jakub Dawidek cmds[0] = cmds[1] = 0; 257de503941SPawel Jakub Dawidek CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == nitems(cmds)); 258de503941SPawel Jakub Dawidek CHECK((cmds[0] == FIOCLEX && cmds[1] == FIONCLEX) || 259de503941SPawel Jakub Dawidek (cmds[0] == FIONCLEX && cmds[1] == FIOCLEX)); 260de503941SPawel Jakub Dawidek 261de503941SPawel Jakub Dawidek CHECK(fcntl(fd, F_GETFD) == 0); 262de503941SPawel Jakub Dawidek CHECK(ioctl(fd, FIOCLEX) == 0); 263de503941SPawel Jakub Dawidek CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC); 264de503941SPawel Jakub Dawidek CHECK(ioctl(fd, FIONCLEX) == 0); 265de503941SPawel Jakub Dawidek CHECK(fcntl(fd, F_GETFD) == 0); 266de503941SPawel Jakub Dawidek 267de503941SPawel Jakub Dawidek CHECK(close(fd) == 0); 268de503941SPawel Jakub Dawidek 269de503941SPawel Jakub Dawidek CHECK(descriptor_recv(sock, &fd) == 0); 270de503941SPawel Jakub Dawidek 271de503941SPawel Jakub Dawidek cmds[0] = cmds[1] = 0; 272de503941SPawel Jakub Dawidek CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == 1); 273de503941SPawel Jakub Dawidek CHECK(cmds[0] == FIOCLEX); 274de503941SPawel Jakub Dawidek 275de503941SPawel Jakub Dawidek CHECK(fcntl(fd, F_GETFD) == 0); 276de503941SPawel Jakub Dawidek CHECK(ioctl(fd, FIOCLEX) == 0); 277de503941SPawel Jakub Dawidek CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC); 278de503941SPawel Jakub Dawidek errno = 0; 279de503941SPawel Jakub Dawidek CHECK(ioctl(fd, FIONCLEX) == -1); 280de503941SPawel Jakub Dawidek CHECK(errno == ENOTCAPABLE); 281de503941SPawel Jakub Dawidek CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC); 282de503941SPawel Jakub Dawidek CHECK(fcntl(fd, F_SETFD, 0) == 0); 283de503941SPawel Jakub Dawidek CHECK(fcntl(fd, F_GETFD) == 0); 284de503941SPawel Jakub Dawidek 285de503941SPawel Jakub Dawidek CHECK(close(fd) == 0); 286de503941SPawel Jakub Dawidek 287de503941SPawel Jakub Dawidek CHECK(descriptor_recv(sock, &fd) == 0); 288de503941SPawel Jakub Dawidek 289de503941SPawel Jakub Dawidek CHECK(cap_ioctls_get(fd, cmds, nitems(cmds)) == 0); 290de503941SPawel Jakub Dawidek 291de503941SPawel Jakub Dawidek CHECK(fcntl(fd, F_GETFD) == 0); 292de503941SPawel Jakub Dawidek errno = 0; 293de503941SPawel Jakub Dawidek CHECK(ioctl(fd, FIOCLEX) == -1); 294de503941SPawel Jakub Dawidek CHECK(errno == ENOTCAPABLE); 295de503941SPawel Jakub Dawidek CHECK(fcntl(fd, F_GETFD) == 0); 296de503941SPawel Jakub Dawidek CHECK(fcntl(fd, F_SETFD, FD_CLOEXEC) == 0); 297de503941SPawel Jakub Dawidek CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC); 298de503941SPawel Jakub Dawidek errno = 0; 299de503941SPawel Jakub Dawidek CHECK(ioctl(fd, FIONCLEX) == -1); 300de503941SPawel Jakub Dawidek CHECK(errno == ENOTCAPABLE); 301de503941SPawel Jakub Dawidek CHECK(fcntl(fd, F_GETFD) == FD_CLOEXEC); 302de503941SPawel Jakub Dawidek CHECK(fcntl(fd, F_SETFD, 0) == 0); 303de503941SPawel Jakub Dawidek CHECK(fcntl(fd, F_GETFD) == 0); 304de503941SPawel Jakub Dawidek 305de503941SPawel Jakub Dawidek CHECK(close(fd) == 0); 306de503941SPawel Jakub Dawidek } 307de503941SPawel Jakub Dawidek 308de503941SPawel Jakub Dawidek int 309de503941SPawel Jakub Dawidek main(void) 310de503941SPawel Jakub Dawidek { 311de503941SPawel Jakub Dawidek int fd, pfd, sp[2]; 312de503941SPawel Jakub Dawidek pid_t pid; 313de503941SPawel Jakub Dawidek 314de503941SPawel Jakub Dawidek printf("1..607\n"); 315de503941SPawel Jakub Dawidek 316de503941SPawel Jakub Dawidek CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0); 317de503941SPawel Jakub Dawidek ioctl_tests_0(fd); 318de503941SPawel Jakub Dawidek CHECK(close(fd) == 0); 319de503941SPawel Jakub Dawidek 320de503941SPawel Jakub Dawidek CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0); 321de503941SPawel Jakub Dawidek ioctl_tests_1(fd); 322de503941SPawel Jakub Dawidek CHECK(close(fd) == 0); 323de503941SPawel Jakub Dawidek 324de503941SPawel Jakub Dawidek CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0); 325de503941SPawel Jakub Dawidek ioctl_tests_2(fd); 326de503941SPawel Jakub Dawidek CHECK(close(fd) == 0); 327de503941SPawel Jakub Dawidek 328de503941SPawel Jakub Dawidek /* Child inherits descriptor and operates on it first. */ 329de503941SPawel Jakub Dawidek CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0); 330de503941SPawel Jakub Dawidek pid = fork(); 331de503941SPawel Jakub Dawidek switch (pid) { 332de503941SPawel Jakub Dawidek case -1: 333de503941SPawel Jakub Dawidek err(1, "fork() failed"); 334de503941SPawel Jakub Dawidek case 0: 335de503941SPawel Jakub Dawidek ioctl_tests_0(fd); 336de503941SPawel Jakub Dawidek CHECK(close(fd) == 0); 337de503941SPawel Jakub Dawidek exit(0); 338de503941SPawel Jakub Dawidek default: 339de503941SPawel Jakub Dawidek if (waitpid(pid, NULL, 0) == -1) 340de503941SPawel Jakub Dawidek err(1, "waitpid() failed"); 341de503941SPawel Jakub Dawidek ioctl_tests_0(fd); 342de503941SPawel Jakub Dawidek } 343de503941SPawel Jakub Dawidek CHECK(close(fd) == 0); 344de503941SPawel Jakub Dawidek 345de503941SPawel Jakub Dawidek /* Child inherits descriptor, but operates on it after parent. */ 346de503941SPawel Jakub Dawidek CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0); 347de503941SPawel Jakub Dawidek pid = fork(); 348de503941SPawel Jakub Dawidek switch (pid) { 349de503941SPawel Jakub Dawidek case -1: 350de503941SPawel Jakub Dawidek err(1, "fork() failed"); 351de503941SPawel Jakub Dawidek case 0: 352de503941SPawel Jakub Dawidek sleep(1); 353de503941SPawel Jakub Dawidek ioctl_tests_0(fd); 354de503941SPawel Jakub Dawidek CHECK(close(fd) == 0); 355de503941SPawel Jakub Dawidek exit(0); 356de503941SPawel Jakub Dawidek default: 357de503941SPawel Jakub Dawidek ioctl_tests_0(fd); 358de503941SPawel Jakub Dawidek if (waitpid(pid, NULL, 0) == -1) 359de503941SPawel Jakub Dawidek err(1, "waitpid() failed"); 360de503941SPawel Jakub Dawidek } 361de503941SPawel Jakub Dawidek CHECK(close(fd) == 0); 362de503941SPawel Jakub Dawidek 363de503941SPawel Jakub Dawidek /* Child inherits descriptor and operates on it first. */ 364de503941SPawel Jakub Dawidek CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0); 365de503941SPawel Jakub Dawidek pid = pdfork(&pfd, 0); 366de503941SPawel Jakub Dawidek switch (pid) { 367de503941SPawel Jakub Dawidek case -1: 368de503941SPawel Jakub Dawidek err(1, "pdfork() failed"); 369de503941SPawel Jakub Dawidek case 0: 370de503941SPawel Jakub Dawidek ioctl_tests_1(fd); 371de503941SPawel Jakub Dawidek exit(0); 372de503941SPawel Jakub Dawidek default: 373de503941SPawel Jakub Dawidek if (pdwait(pfd) == -1) 374de503941SPawel Jakub Dawidek err(1, "pdwait() failed"); 375de503941SPawel Jakub Dawidek close(pfd); 376de503941SPawel Jakub Dawidek ioctl_tests_1(fd); 377de503941SPawel Jakub Dawidek } 378de503941SPawel Jakub Dawidek CHECK(close(fd) == 0); 379de503941SPawel Jakub Dawidek 380de503941SPawel Jakub Dawidek /* Child inherits descriptor, but operates on it after parent. */ 381de503941SPawel Jakub Dawidek CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0); 382de503941SPawel Jakub Dawidek pid = pdfork(&pfd, 0); 383de503941SPawel Jakub Dawidek switch (pid) { 384de503941SPawel Jakub Dawidek case -1: 385de503941SPawel Jakub Dawidek err(1, "pdfork() failed"); 386de503941SPawel Jakub Dawidek case 0: 387de503941SPawel Jakub Dawidek sleep(1); 388de503941SPawel Jakub Dawidek ioctl_tests_1(fd); 389de503941SPawel Jakub Dawidek exit(0); 390de503941SPawel Jakub Dawidek default: 391de503941SPawel Jakub Dawidek ioctl_tests_1(fd); 392de503941SPawel Jakub Dawidek if (pdwait(pfd) == -1) 393de503941SPawel Jakub Dawidek err(1, "pdwait() failed"); 394de503941SPawel Jakub Dawidek close(pfd); 395de503941SPawel Jakub Dawidek } 396de503941SPawel Jakub Dawidek CHECK(close(fd) == 0); 397de503941SPawel Jakub Dawidek 398de503941SPawel Jakub Dawidek /* Child inherits descriptor and operates on it first. */ 399de503941SPawel Jakub Dawidek CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0); 400de503941SPawel Jakub Dawidek pid = fork(); 401de503941SPawel Jakub Dawidek switch (pid) { 402de503941SPawel Jakub Dawidek case -1: 403de503941SPawel Jakub Dawidek err(1, "fork() failed"); 404de503941SPawel Jakub Dawidek case 0: 405de503941SPawel Jakub Dawidek ioctl_tests_2(fd); 406de503941SPawel Jakub Dawidek exit(0); 407de503941SPawel Jakub Dawidek default: 408de503941SPawel Jakub Dawidek if (waitpid(pid, NULL, 0) == -1) 409de503941SPawel Jakub Dawidek err(1, "waitpid() failed"); 410de503941SPawel Jakub Dawidek ioctl_tests_2(fd); 411de503941SPawel Jakub Dawidek } 412de503941SPawel Jakub Dawidek CHECK(close(fd) == 0); 413de503941SPawel Jakub Dawidek 414de503941SPawel Jakub Dawidek /* Child inherits descriptor, but operates on it after parent. */ 415de503941SPawel Jakub Dawidek CHECK((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0); 416de503941SPawel Jakub Dawidek pid = fork(); 417de503941SPawel Jakub Dawidek switch (pid) { 418de503941SPawel Jakub Dawidek case -1: 419de503941SPawel Jakub Dawidek err(1, "fork() failed"); 420de503941SPawel Jakub Dawidek case 0: 421de503941SPawel Jakub Dawidek sleep(1); 422de503941SPawel Jakub Dawidek ioctl_tests_2(fd); 423de503941SPawel Jakub Dawidek exit(0); 424de503941SPawel Jakub Dawidek default: 425de503941SPawel Jakub Dawidek ioctl_tests_2(fd); 426de503941SPawel Jakub Dawidek if (waitpid(pid, NULL, 0) == -1) 427de503941SPawel Jakub Dawidek err(1, "waitpid() failed"); 428de503941SPawel Jakub Dawidek } 429de503941SPawel Jakub Dawidek CHECK(close(fd) == 0); 430de503941SPawel Jakub Dawidek 431de503941SPawel Jakub Dawidek /* Send descriptors from parent to child. */ 432de503941SPawel Jakub Dawidek CHECK(socketpair(AF_UNIX, SOCK_STREAM, 0, sp) == 0); 433de503941SPawel Jakub Dawidek CHECK((pid = fork()) >= 0); 434de503941SPawel Jakub Dawidek if (pid == 0) { 435de503941SPawel Jakub Dawidek CHECK(close(sp[0]) == 0); 436de503941SPawel Jakub Dawidek ioctl_tests_recv_0(sp[1]); 437de503941SPawel Jakub Dawidek CHECK(close(sp[1]) == 0); 438de503941SPawel Jakub Dawidek exit(0); 439de503941SPawel Jakub Dawidek } else { 440de503941SPawel Jakub Dawidek CHECK(close(sp[1]) == 0); 441de503941SPawel Jakub Dawidek ioctl_tests_send_0(sp[0]); 442de503941SPawel Jakub Dawidek CHECK(waitpid(pid, NULL, 0) == pid); 443de503941SPawel Jakub Dawidek CHECK(close(sp[0]) == 0); 444de503941SPawel Jakub Dawidek } 445de503941SPawel Jakub Dawidek 446de503941SPawel Jakub Dawidek /* Send descriptors from child to parent. */ 447de503941SPawel Jakub Dawidek CHECK(socketpair(AF_UNIX, SOCK_STREAM, 0, sp) == 0); 448de503941SPawel Jakub Dawidek CHECK((pid = fork()) >= 0); 449de503941SPawel Jakub Dawidek if (pid == 0) { 450de503941SPawel Jakub Dawidek CHECK(close(sp[0]) == 0); 451de503941SPawel Jakub Dawidek ioctl_tests_send_0(sp[1]); 452de503941SPawel Jakub Dawidek CHECK(close(sp[1]) == 0); 453de503941SPawel Jakub Dawidek exit(0); 454de503941SPawel Jakub Dawidek } else { 455de503941SPawel Jakub Dawidek CHECK(close(sp[1]) == 0); 456de503941SPawel Jakub Dawidek ioctl_tests_recv_0(sp[0]); 457de503941SPawel Jakub Dawidek CHECK(waitpid(pid, NULL, 0) == pid); 458de503941SPawel Jakub Dawidek CHECK(close(sp[0]) == 0); 459de503941SPawel Jakub Dawidek } 460de503941SPawel Jakub Dawidek 461de503941SPawel Jakub Dawidek exit(0); 462de503941SPawel Jakub Dawidek } 463