1*69c811abSRobert Mustacchi /* 2*69c811abSRobert Mustacchi * This file and its contents are supplied under the terms of the 3*69c811abSRobert Mustacchi * Common Development and Distribution License ("CDDL"), version 1.0. 4*69c811abSRobert Mustacchi * You may only use this file in accordance with the terms of version 5*69c811abSRobert Mustacchi * 1.0 of the CDDL. 6*69c811abSRobert Mustacchi * 7*69c811abSRobert Mustacchi * A full copy of the text of the CDDL should have accompanied this 8*69c811abSRobert Mustacchi * source. A copy of the CDDL is also available via the Internet at 9*69c811abSRobert Mustacchi * http://www.illumos.org/license/CDDL. 10*69c811abSRobert Mustacchi */ 11*69c811abSRobert Mustacchi 12*69c811abSRobert Mustacchi /* 13*69c811abSRobert Mustacchi * Copyright 2020 Robert Mustacchi 14*69c811abSRobert Mustacchi */ 15*69c811abSRobert Mustacchi 16*69c811abSRobert Mustacchi /* 17*69c811abSRobert Mustacchi * Test different O_DIRECTORY open cases. 18*69c811abSRobert Mustacchi */ 19*69c811abSRobert Mustacchi 20*69c811abSRobert Mustacchi #include <sys/types.h> 21*69c811abSRobert Mustacchi #include <sys/stat.h> 22*69c811abSRobert Mustacchi #include <fcntl.h> 23*69c811abSRobert Mustacchi #include <stdio.h> 24*69c811abSRobert Mustacchi #include <errno.h> 25*69c811abSRobert Mustacchi #include <unistd.h> 26*69c811abSRobert Mustacchi #include <err.h> 27*69c811abSRobert Mustacchi #include <string.h> 28*69c811abSRobert Mustacchi #include <stdlib.h> 29*69c811abSRobert Mustacchi #include <limits.h> 30*69c811abSRobert Mustacchi #include <door.h> 31*69c811abSRobert Mustacchi #include <stropts.h> 32*69c811abSRobert Mustacchi #include <sys/socket.h> 33*69c811abSRobert Mustacchi 34*69c811abSRobert Mustacchi static uint_t odir_failures; 35*69c811abSRobert Mustacchi static char odir_fpath[PATH_MAX]; 36*69c811abSRobert Mustacchi static char odir_dpath[PATH_MAX]; 37*69c811abSRobert Mustacchi static char odir_doorpath[PATH_MAX]; 38*69c811abSRobert Mustacchi static char odir_enoent[PATH_MAX]; 39*69c811abSRobert Mustacchi static char odir_udspath[PATH_MAX]; 40*69c811abSRobert Mustacchi static int odir_did = -1; 41*69c811abSRobert Mustacchi static int odir_uds = -1; 42*69c811abSRobert Mustacchi 43*69c811abSRobert Mustacchi static void 44*69c811abSRobert Mustacchi odir_test_one(const char *test, const char *path, int flags, int err) 45*69c811abSRobert Mustacchi { 46*69c811abSRobert Mustacchi int fd = open(path, flags | O_DIRECTORY | O_RDONLY, 0644); 47*69c811abSRobert Mustacchi if (fd >= 0) { 48*69c811abSRobert Mustacchi (void) close(fd); 49*69c811abSRobert Mustacchi if (err != 0) { 50*69c811abSRobert Mustacchi odir_failures++; 51*69c811abSRobert Mustacchi warnx("TEST FAILED: %s: opened %s, but expected error: " 52*69c811abSRobert Mustacchi "%d", test, path, err); 53*69c811abSRobert Mustacchi } 54*69c811abSRobert Mustacchi } else { 55*69c811abSRobert Mustacchi if (err == 0) { 56*69c811abSRobert Mustacchi odir_failures++; 57*69c811abSRobert Mustacchi warnx("TEST FAILED: %s: failed to open %s, error: %d", 58*69c811abSRobert Mustacchi test, path, err); 59*69c811abSRobert Mustacchi } else if (err != errno) { 60*69c811abSRobert Mustacchi odir_failures++; 61*69c811abSRobert Mustacchi warnx("TEST FAILED: %s: wrong error for path %s, " 62*69c811abSRobert Mustacchi "found %d, expected %d", test, path, errno, err); 63*69c811abSRobert Mustacchi } 64*69c811abSRobert Mustacchi } 65*69c811abSRobert Mustacchi } 66*69c811abSRobert Mustacchi 67*69c811abSRobert Mustacchi static void 68*69c811abSRobert Mustacchi odir_door_server(void *cookie, char *argp, size_t arg_size, door_desc_t *dp, 69*69c811abSRobert Mustacchi uint_t ndesc) 70*69c811abSRobert Mustacchi { 71*69c811abSRobert Mustacchi (void) door_return(NULL, 0, NULL, 0); 72*69c811abSRobert Mustacchi } 73*69c811abSRobert Mustacchi 74*69c811abSRobert Mustacchi static boolean_t 75*69c811abSRobert Mustacchi odir_setup(void) 76*69c811abSRobert Mustacchi { 77*69c811abSRobert Mustacchi int fd; 78*69c811abSRobert Mustacchi struct stat st; 79*69c811abSRobert Mustacchi struct sockaddr_un un; 80*69c811abSRobert Mustacchi pid_t pid = getpid(); 81*69c811abSRobert Mustacchi 82*69c811abSRobert Mustacchi (void) snprintf(odir_fpath, sizeof (odir_fpath), 83*69c811abSRobert Mustacchi "/tmp/odir.%d.file", pid); 84*69c811abSRobert Mustacchi if ((fd = creat(odir_fpath, 0644)) < 0) { 85*69c811abSRobert Mustacchi warn("failed to create temp file %s", odir_fpath); 86*69c811abSRobert Mustacchi odir_fpath[0] = '\0'; 87*69c811abSRobert Mustacchi return (B_FALSE); 88*69c811abSRobert Mustacchi } 89*69c811abSRobert Mustacchi (void) close(fd); 90*69c811abSRobert Mustacchi 91*69c811abSRobert Mustacchi (void) snprintf(odir_dpath, sizeof (odir_dpath), 92*69c811abSRobert Mustacchi "/tmp/odir.%d.dir", pid); 93*69c811abSRobert Mustacchi if (mkdir(odir_dpath, 0755) != 0) { 94*69c811abSRobert Mustacchi warn("failed to create temp directory %s", odir_dpath); 95*69c811abSRobert Mustacchi odir_dpath[0] = '\0'; 96*69c811abSRobert Mustacchi return (B_FALSE); 97*69c811abSRobert Mustacchi } 98*69c811abSRobert Mustacchi 99*69c811abSRobert Mustacchi odir_did = door_create(odir_door_server, NULL, 0); 100*69c811abSRobert Mustacchi if (odir_did == -1) { 101*69c811abSRobert Mustacchi warnx("failed to create door"); 102*69c811abSRobert Mustacchi return (B_FALSE); 103*69c811abSRobert Mustacchi } 104*69c811abSRobert Mustacchi (void) snprintf(odir_doorpath, sizeof (odir_doorpath), 105*69c811abSRobert Mustacchi "/tmp/odir.%d.door", pid); 106*69c811abSRobert Mustacchi if ((fd = creat(odir_doorpath, 0644)) < 0) { 107*69c811abSRobert Mustacchi warn("failed to create %s", odir_doorpath); 108*69c811abSRobert Mustacchi odir_doorpath[0] = '\0'; 109*69c811abSRobert Mustacchi return (B_FALSE); 110*69c811abSRobert Mustacchi } 111*69c811abSRobert Mustacchi (void) close(fd); 112*69c811abSRobert Mustacchi if (fattach(odir_did, odir_doorpath) != 0) { 113*69c811abSRobert Mustacchi warn("failed to attach door to %s", odir_doorpath); 114*69c811abSRobert Mustacchi (void) unlink(odir_doorpath); 115*69c811abSRobert Mustacchi odir_doorpath[0] = '\0'; 116*69c811abSRobert Mustacchi return (B_FALSE); 117*69c811abSRobert Mustacchi } 118*69c811abSRobert Mustacchi 119*69c811abSRobert Mustacchi (void) snprintf(odir_enoent, sizeof (odir_enoent), 120*69c811abSRobert Mustacchi "/tmp/odir.%d.enoent", pid); 121*69c811abSRobert Mustacchi if (stat(odir_enoent, &st) == 0) { 122*69c811abSRobert Mustacchi warnx("somehow random file %s exists!", odir_enoent); 123*69c811abSRobert Mustacchi } 124*69c811abSRobert Mustacchi 125*69c811abSRobert Mustacchi odir_uds = socket(PF_UNIX, SOCK_STREAM, 0); 126*69c811abSRobert Mustacchi if (odir_uds == -1) { 127*69c811abSRobert Mustacchi warn("failed to create UDS"); 128*69c811abSRobert Mustacchi return (B_FALSE); 129*69c811abSRobert Mustacchi } 130*69c811abSRobert Mustacchi (void) snprintf(odir_udspath, sizeof (odir_udspath), 131*69c811abSRobert Mustacchi "/tmp/odir.%d.uds", pid); 132*69c811abSRobert Mustacchi (void) memset(&un, '\0', sizeof (un)); 133*69c811abSRobert Mustacchi un.sun_family = AF_UNIX; 134*69c811abSRobert Mustacchi if (strlcpy(un.sun_path, odir_udspath, sizeof (un.sun_path)) >= 135*69c811abSRobert Mustacchi sizeof (un.sun_path)) { 136*69c811abSRobert Mustacchi warnx("%s overflows AF_UNIX path", odir_udspath); 137*69c811abSRobert Mustacchi odir_udspath[0] = '\0'; 138*69c811abSRobert Mustacchi return (B_FALSE); 139*69c811abSRobert Mustacchi } 140*69c811abSRobert Mustacchi 141*69c811abSRobert Mustacchi if (bind(odir_uds, (struct sockaddr *)&un, SUN_LEN(&un)) != 0) { 142*69c811abSRobert Mustacchi warn("failed to bind %s", odir_udspath); 143*69c811abSRobert Mustacchi odir_udspath[0] = '\0'; 144*69c811abSRobert Mustacchi return (B_FALSE); 145*69c811abSRobert Mustacchi } 146*69c811abSRobert Mustacchi 147*69c811abSRobert Mustacchi if (listen(odir_uds, 1) != 0) { 148*69c811abSRobert Mustacchi warn("failed to listen on %s", odir_udspath); 149*69c811abSRobert Mustacchi return (B_FALSE); 150*69c811abSRobert Mustacchi } 151*69c811abSRobert Mustacchi 152*69c811abSRobert Mustacchi return (B_TRUE); 153*69c811abSRobert Mustacchi } 154*69c811abSRobert Mustacchi 155*69c811abSRobert Mustacchi static void 156*69c811abSRobert Mustacchi odir_verify_enoent(void) 157*69c811abSRobert Mustacchi { 158*69c811abSRobert Mustacchi struct stat st; 159*69c811abSRobert Mustacchi 160*69c811abSRobert Mustacchi if (stat(odir_enoent, &st) == 0) { 161*69c811abSRobert Mustacchi warnx("TEST FAILED: %s was created", odir_enoent); 162*69c811abSRobert Mustacchi odir_failures++; 163*69c811abSRobert Mustacchi } else if (errno != ENOENT) { 164*69c811abSRobert Mustacchi warn("TEST FAILED: stat on %s failed", odir_enoent); 165*69c811abSRobert Mustacchi odir_failures++; 166*69c811abSRobert Mustacchi } 167*69c811abSRobert Mustacchi } 168*69c811abSRobert Mustacchi 169*69c811abSRobert Mustacchi static void 170*69c811abSRobert Mustacchi odir_cleanup(void) 171*69c811abSRobert Mustacchi { 172*69c811abSRobert Mustacchi if (odir_udspath[0] != '\0') { 173*69c811abSRobert Mustacchi if (unlink(odir_udspath) != 0) { 174*69c811abSRobert Mustacchi warn("failed to unlink %s", odir_udspath); 175*69c811abSRobert Mustacchi } 176*69c811abSRobert Mustacchi } 177*69c811abSRobert Mustacchi 178*69c811abSRobert Mustacchi if (odir_uds != -1) { 179*69c811abSRobert Mustacchi if (close(odir_uds) != 0) { 180*69c811abSRobert Mustacchi warn("failed to close UDS"); 181*69c811abSRobert Mustacchi } 182*69c811abSRobert Mustacchi } 183*69c811abSRobert Mustacchi 184*69c811abSRobert Mustacchi if (odir_doorpath[0] != '\0') { 185*69c811abSRobert Mustacchi if (fdetach(odir_doorpath) != 0) { 186*69c811abSRobert Mustacchi warn("failed to detach door %s", odir_doorpath); 187*69c811abSRobert Mustacchi } 188*69c811abSRobert Mustacchi } 189*69c811abSRobert Mustacchi 190*69c811abSRobert Mustacchi if (odir_did != -1) { 191*69c811abSRobert Mustacchi if (door_revoke(odir_did) != 0) { 192*69c811abSRobert Mustacchi warn("failed to revoke door"); 193*69c811abSRobert Mustacchi } 194*69c811abSRobert Mustacchi } 195*69c811abSRobert Mustacchi 196*69c811abSRobert Mustacchi if (odir_dpath[0] != '\0') { 197*69c811abSRobert Mustacchi if (rmdir(odir_dpath) != 0) { 198*69c811abSRobert Mustacchi warn("failed to clean up %s", odir_dpath); 199*69c811abSRobert Mustacchi } 200*69c811abSRobert Mustacchi } 201*69c811abSRobert Mustacchi 202*69c811abSRobert Mustacchi if (odir_fpath[0] != '\0') { 203*69c811abSRobert Mustacchi if (unlink(odir_fpath) != 0) { 204*69c811abSRobert Mustacchi warn("failed to clean up %s", odir_fpath); 205*69c811abSRobert Mustacchi } 206*69c811abSRobert Mustacchi } 207*69c811abSRobert Mustacchi } 208*69c811abSRobert Mustacchi 209*69c811abSRobert Mustacchi int 210*69c811abSRobert Mustacchi main(void) 211*69c811abSRobert Mustacchi { 212*69c811abSRobert Mustacchi if (!odir_setup()) { 213*69c811abSRobert Mustacchi odir_cleanup(); 214*69c811abSRobert Mustacchi return (EXIT_FAILURE); 215*69c811abSRobert Mustacchi } 216*69c811abSRobert Mustacchi 217*69c811abSRobert Mustacchi odir_test_one("regular file", odir_fpath, 0, ENOTDIR); 218*69c811abSRobert Mustacchi odir_test_one("directory", odir_dpath, 0, 0); 219*69c811abSRobert Mustacchi odir_test_one("character device", "/dev/null", 0, ENOTDIR); 220*69c811abSRobert Mustacchi odir_test_one("door server", odir_doorpath, 0, ENOTDIR); 221*69c811abSRobert Mustacchi odir_test_one("missing file", odir_enoent, 0, ENOENT); 222*69c811abSRobert Mustacchi odir_test_one("UDS", odir_udspath, 0, ENOTDIR); 223*69c811abSRobert Mustacchi 224*69c811abSRobert Mustacchi odir_test_one("O_CREAT | O_DIRECTORY on a regular file", odir_fpath, 225*69c811abSRobert Mustacchi O_CREAT, ENOTDIR); 226*69c811abSRobert Mustacchi odir_test_one("O_CREAT | O_DIRECTORY | O_EXCL on a regular file", 227*69c811abSRobert Mustacchi odir_fpath, O_CREAT | O_EXCL, EINVAL); 228*69c811abSRobert Mustacchi 229*69c811abSRobert Mustacchi odir_test_one("O_CREAT | O_DIRECTORY on a directory", odir_dpath, 230*69c811abSRobert Mustacchi O_CREAT, 0); 231*69c811abSRobert Mustacchi odir_test_one("O_CREAT | O_DIRECTORY | O_EXCL on a directory", 232*69c811abSRobert Mustacchi odir_dpath, O_CREAT | O_EXCL, EINVAL); 233*69c811abSRobert Mustacchi 234*69c811abSRobert Mustacchi odir_test_one("O_CREAT | O_DIRECTORY on a missing file", odir_enoent, 235*69c811abSRobert Mustacchi O_CREAT, ENOENT); 236*69c811abSRobert Mustacchi odir_verify_enoent(); 237*69c811abSRobert Mustacchi odir_test_one("O_CREAT | O_DIRECTORY | O_EXCL on a missing file", 238*69c811abSRobert Mustacchi odir_enoent, O_CREAT | O_EXCL, EINVAL); 239*69c811abSRobert Mustacchi odir_verify_enoent(); 240*69c811abSRobert Mustacchi 241*69c811abSRobert Mustacchi odir_cleanup(); 242*69c811abSRobert Mustacchi if (odir_failures > 0) { 243*69c811abSRobert Mustacchi warnx("%u tests failed", odir_failures); 244*69c811abSRobert Mustacchi } 245*69c811abSRobert Mustacchi 246*69c811abSRobert Mustacchi return (odir_failures > 0 ? EXIT_FAILURE : EXIT_SUCCESS); 247*69c811abSRobert Mustacchi } 248