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