1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 1999-2003 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate #include <auth_attr.h> 30*7c478bd9Sstevel@tonic-gate #include <auth_list.h> 31*7c478bd9Sstevel@tonic-gate #include <dirent.h> 32*7c478bd9Sstevel@tonic-gate #include <errno.h> 33*7c478bd9Sstevel@tonic-gate #include <fcntl.h> 34*7c478bd9Sstevel@tonic-gate #include <libintl.h> 35*7c478bd9Sstevel@tonic-gate #include <locale.h> 36*7c478bd9Sstevel@tonic-gate #include <pwd.h> 37*7c478bd9Sstevel@tonic-gate #include <signal.h> 38*7c478bd9Sstevel@tonic-gate #include <stdio.h> 39*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 40*7c478bd9Sstevel@tonic-gate #include <string.h> 41*7c478bd9Sstevel@tonic-gate #include <unistd.h> 42*7c478bd9Sstevel@tonic-gate 43*7c478bd9Sstevel@tonic-gate #include <bsm/devices.h> 44*7c478bd9Sstevel@tonic-gate #include <bsm/audit_uevents.h> 45*7c478bd9Sstevel@tonic-gate 46*7c478bd9Sstevel@tonic-gate #include <sys/acl.h> 47*7c478bd9Sstevel@tonic-gate #include <sys/file.h> 48*7c478bd9Sstevel@tonic-gate #include <sys/procfs.h> 49*7c478bd9Sstevel@tonic-gate #include <sys/param.h> 50*7c478bd9Sstevel@tonic-gate #include <sys/resource.h> 51*7c478bd9Sstevel@tonic-gate #include <sys/stat.h> 52*7c478bd9Sstevel@tonic-gate #include <sys/time.h> 53*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 54*7c478bd9Sstevel@tonic-gate #include <sys/wait.h> 55*7c478bd9Sstevel@tonic-gate 56*7c478bd9Sstevel@tonic-gate #include "allocate.h" 57*7c478bd9Sstevel@tonic-gate 58*7c478bd9Sstevel@tonic-gate #ifdef DEBUG 59*7c478bd9Sstevel@tonic-gate #define dprintf(s, a) (void) fprintf(stderr, s, a) 60*7c478bd9Sstevel@tonic-gate #define dperror(s) perror(s) 61*7c478bd9Sstevel@tonic-gate #else /* !DEBUG */ 62*7c478bd9Sstevel@tonic-gate #define dprintf(s, a) 63*7c478bd9Sstevel@tonic-gate #define dperror(s) 64*7c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 65*7c478bd9Sstevel@tonic-gate 66*7c478bd9Sstevel@tonic-gate #define EXIT(number) { \ 67*7c478bd9Sstevel@tonic-gate if (optflg & FORCE) \ 68*7c478bd9Sstevel@tonic-gate error = number; \ 69*7c478bd9Sstevel@tonic-gate else \ 70*7c478bd9Sstevel@tonic-gate return (number); \ 71*7c478bd9Sstevel@tonic-gate } 72*7c478bd9Sstevel@tonic-gate 73*7c478bd9Sstevel@tonic-gate #define DEV_ALLOCATED(sbuf) ((sbuf).st_uid != ALLOC_UID || \ 74*7c478bd9Sstevel@tonic-gate ((sbuf).st_mode & ~S_IFMT) == ALLOC_MODE) 75*7c478bd9Sstevel@tonic-gate 76*7c478bd9Sstevel@tonic-gate #define DEVICE_AUTH_SEPARATOR "," 77*7c478bd9Sstevel@tonic-gate #define PROCFS "/proc/" 78*7c478bd9Sstevel@tonic-gate 79*7c478bd9Sstevel@tonic-gate extern void audit_allocate_list(char *); 80*7c478bd9Sstevel@tonic-gate extern void audit_allocate_device(char *); 81*7c478bd9Sstevel@tonic-gate 82*7c478bd9Sstevel@tonic-gate extern char *newenv[]; 83*7c478bd9Sstevel@tonic-gate 84*7c478bd9Sstevel@tonic-gate /* 85*7c478bd9Sstevel@tonic-gate * Checks if the specified user has any of the authorizations in the 86*7c478bd9Sstevel@tonic-gate * list of authorizations 87*7c478bd9Sstevel@tonic-gate */ 88*7c478bd9Sstevel@tonic-gate 89*7c478bd9Sstevel@tonic-gate static int 90*7c478bd9Sstevel@tonic-gate is_authorized(char *auth_list, uid_t uid) 91*7c478bd9Sstevel@tonic-gate { 92*7c478bd9Sstevel@tonic-gate char *auth; 93*7c478bd9Sstevel@tonic-gate struct passwd *pw; 94*7c478bd9Sstevel@tonic-gate 95*7c478bd9Sstevel@tonic-gate pw = getpwuid(uid); 96*7c478bd9Sstevel@tonic-gate if (pw == NULL) { 97*7c478bd9Sstevel@tonic-gate dprintf("Can't get user info for uid=%d\n", (int)uid); 98*7c478bd9Sstevel@tonic-gate return (0); 99*7c478bd9Sstevel@tonic-gate } 100*7c478bd9Sstevel@tonic-gate 101*7c478bd9Sstevel@tonic-gate auth = strtok(auth_list, DEVICE_AUTH_SEPARATOR); 102*7c478bd9Sstevel@tonic-gate while (auth != NULL) { 103*7c478bd9Sstevel@tonic-gate if (chkauthattr(auth, pw->pw_name)) 104*7c478bd9Sstevel@tonic-gate return (1); 105*7c478bd9Sstevel@tonic-gate auth = strtok(NULL, DEVICE_AUTH_SEPARATOR); 106*7c478bd9Sstevel@tonic-gate } 107*7c478bd9Sstevel@tonic-gate return (0); 108*7c478bd9Sstevel@tonic-gate } 109*7c478bd9Sstevel@tonic-gate 110*7c478bd9Sstevel@tonic-gate static int 111*7c478bd9Sstevel@tonic-gate check_devs(char *list) 112*7c478bd9Sstevel@tonic-gate { 113*7c478bd9Sstevel@tonic-gate char *file; 114*7c478bd9Sstevel@tonic-gate 115*7c478bd9Sstevel@tonic-gate file = strtok(list, " "); 116*7c478bd9Sstevel@tonic-gate while (file != NULL) { 117*7c478bd9Sstevel@tonic-gate 118*7c478bd9Sstevel@tonic-gate if (access(file, F_OK) == -1) { 119*7c478bd9Sstevel@tonic-gate dprintf("Unable to access file %s\n", file); 120*7c478bd9Sstevel@tonic-gate return (-1); 121*7c478bd9Sstevel@tonic-gate } 122*7c478bd9Sstevel@tonic-gate file = strtok(NULL, " "); 123*7c478bd9Sstevel@tonic-gate } 124*7c478bd9Sstevel@tonic-gate return (0); 125*7c478bd9Sstevel@tonic-gate } 126*7c478bd9Sstevel@tonic-gate 127*7c478bd9Sstevel@tonic-gate static void 128*7c478bd9Sstevel@tonic-gate print_dev(devmap_t *dev_list) 129*7c478bd9Sstevel@tonic-gate { 130*7c478bd9Sstevel@tonic-gate char *file; 131*7c478bd9Sstevel@tonic-gate 132*7c478bd9Sstevel@tonic-gate (void) printf(gettext("device: %s "), dev_list->dmap_devname); 133*7c478bd9Sstevel@tonic-gate (void) printf(gettext("type: %s "), dev_list->dmap_devtype); 134*7c478bd9Sstevel@tonic-gate (void) printf(gettext("files: ")); 135*7c478bd9Sstevel@tonic-gate 136*7c478bd9Sstevel@tonic-gate file = strtok(dev_list->dmap_devlist, " "); 137*7c478bd9Sstevel@tonic-gate while (file != NULL) { 138*7c478bd9Sstevel@tonic-gate (void) printf("%s ", file); 139*7c478bd9Sstevel@tonic-gate file = strtok(NULL, " "); 140*7c478bd9Sstevel@tonic-gate } 141*7c478bd9Sstevel@tonic-gate (void) printf("\n"); 142*7c478bd9Sstevel@tonic-gate } 143*7c478bd9Sstevel@tonic-gate 144*7c478bd9Sstevel@tonic-gate static int 145*7c478bd9Sstevel@tonic-gate list_device(int optflg, uid_t uid, char *device) 146*7c478bd9Sstevel@tonic-gate { 147*7c478bd9Sstevel@tonic-gate devalloc_t *dev_ent; 148*7c478bd9Sstevel@tonic-gate devmap_t *dev_list; 149*7c478bd9Sstevel@tonic-gate char file_name[MAXPATHLEN]; 150*7c478bd9Sstevel@tonic-gate struct stat stat_buf; 151*7c478bd9Sstevel@tonic-gate char *list; 152*7c478bd9Sstevel@tonic-gate int bytes_formated; 153*7c478bd9Sstevel@tonic-gate 154*7c478bd9Sstevel@tonic-gate if ((dev_ent = getdanam(device)) == NULL) { 155*7c478bd9Sstevel@tonic-gate if ((dev_list = getdmapdev(device)) == NULL) { 156*7c478bd9Sstevel@tonic-gate dprintf("Unable to find %s in the allocate database\n", 157*7c478bd9Sstevel@tonic-gate device); 158*7c478bd9Sstevel@tonic-gate return (NODMAPENT); 159*7c478bd9Sstevel@tonic-gate } else if ((dev_ent = getdanam(dev_list->dmap_devname)) == 160*7c478bd9Sstevel@tonic-gate NULL) { 161*7c478bd9Sstevel@tonic-gate dprintf("Unable to find %s in the allocate database\n", 162*7c478bd9Sstevel@tonic-gate device); 163*7c478bd9Sstevel@tonic-gate return (NODAENT); 164*7c478bd9Sstevel@tonic-gate } 165*7c478bd9Sstevel@tonic-gate } else if ((dev_list = getdmapnam(device)) == NULL) { 166*7c478bd9Sstevel@tonic-gate dprintf("Unable to find %s in the allocate database\n", device); 167*7c478bd9Sstevel@tonic-gate return (NODMAPENT); 168*7c478bd9Sstevel@tonic-gate } 169*7c478bd9Sstevel@tonic-gate 170*7c478bd9Sstevel@tonic-gate bytes_formated = snprintf(file_name, MAXPATHLEN, "%s/%s", DAC_DIR, 171*7c478bd9Sstevel@tonic-gate dev_ent->da_devname); 172*7c478bd9Sstevel@tonic-gate if (bytes_formated <= 0) { 173*7c478bd9Sstevel@tonic-gate return (DEVNAME_ERR); 174*7c478bd9Sstevel@tonic-gate } else if (bytes_formated >= MAXPATHLEN) { 175*7c478bd9Sstevel@tonic-gate dprintf("device name %s is too long.\n", dev_ent->da_devname); 176*7c478bd9Sstevel@tonic-gate return (DEVNAME_TOOLONG); 177*7c478bd9Sstevel@tonic-gate } 178*7c478bd9Sstevel@tonic-gate 179*7c478bd9Sstevel@tonic-gate if (stat(file_name, &stat_buf)) { 180*7c478bd9Sstevel@tonic-gate dprintf("Unable to stat %s\n", file_name); 181*7c478bd9Sstevel@tonic-gate dperror("Error:"); 182*7c478bd9Sstevel@tonic-gate return (DACACC); 183*7c478bd9Sstevel@tonic-gate } 184*7c478bd9Sstevel@tonic-gate 185*7c478bd9Sstevel@tonic-gate if ((optflg & FREE) && DEV_ALLOCATED(stat_buf)) 186*7c478bd9Sstevel@tonic-gate return (ALLOC); 187*7c478bd9Sstevel@tonic-gate 188*7c478bd9Sstevel@tonic-gate if ((optflg & LIST) && DEV_ALLOCATED(stat_buf) && 189*7c478bd9Sstevel@tonic-gate (stat_buf.st_uid != uid)) 190*7c478bd9Sstevel@tonic-gate return (ALLOC_OTHER); 191*7c478bd9Sstevel@tonic-gate 192*7c478bd9Sstevel@tonic-gate if ((optflg & CURRENT) && (stat_buf.st_uid != uid)) 193*7c478bd9Sstevel@tonic-gate return (NALLOC); 194*7c478bd9Sstevel@tonic-gate 195*7c478bd9Sstevel@tonic-gate if ((stat_buf.st_mode & ~S_IFMT) == ALLOC_ERR_MODE) 196*7c478bd9Sstevel@tonic-gate return (ALLOCERR); 197*7c478bd9Sstevel@tonic-gate 198*7c478bd9Sstevel@tonic-gate if ((list = strdup(dev_list->dmap_devlist)) == NULL) 199*7c478bd9Sstevel@tonic-gate return (SYSERROR); 200*7c478bd9Sstevel@tonic-gate 201*7c478bd9Sstevel@tonic-gate if (check_devs(list) == -1) { 202*7c478bd9Sstevel@tonic-gate free(list); 203*7c478bd9Sstevel@tonic-gate return (DSPMISS); 204*7c478bd9Sstevel@tonic-gate } 205*7c478bd9Sstevel@tonic-gate 206*7c478bd9Sstevel@tonic-gate print_dev(dev_list); 207*7c478bd9Sstevel@tonic-gate 208*7c478bd9Sstevel@tonic-gate free(list); 209*7c478bd9Sstevel@tonic-gate return (0); 210*7c478bd9Sstevel@tonic-gate } 211*7c478bd9Sstevel@tonic-gate 212*7c478bd9Sstevel@tonic-gate int 213*7c478bd9Sstevel@tonic-gate list_devices(int optflg, uid_t uid, char *device) 214*7c478bd9Sstevel@tonic-gate { 215*7c478bd9Sstevel@tonic-gate DIR * dev_dir; 216*7c478bd9Sstevel@tonic-gate struct dirent *dac_file; 217*7c478bd9Sstevel@tonic-gate int error = 0, ret_code = 1; 218*7c478bd9Sstevel@tonic-gate 219*7c478bd9Sstevel@tonic-gate if (optflg & USERID) { 220*7c478bd9Sstevel@tonic-gate if (!is_authorized(DEVICE_REVOKE_AUTH, getuid())) 221*7c478bd9Sstevel@tonic-gate return (NOTAUTH); 222*7c478bd9Sstevel@tonic-gate } 223*7c478bd9Sstevel@tonic-gate setdaent(); 224*7c478bd9Sstevel@tonic-gate 225*7c478bd9Sstevel@tonic-gate if (device) { 226*7c478bd9Sstevel@tonic-gate return (list_device(optflg, uid, device)); 227*7c478bd9Sstevel@tonic-gate } 228*7c478bd9Sstevel@tonic-gate 229*7c478bd9Sstevel@tonic-gate if ((dev_dir = opendir(DAC_DIR)) == NULL) { 230*7c478bd9Sstevel@tonic-gate 231*7c478bd9Sstevel@tonic-gate dperror("Can't open DAC_DIR"); 232*7c478bd9Sstevel@tonic-gate return (DACACC); 233*7c478bd9Sstevel@tonic-gate } 234*7c478bd9Sstevel@tonic-gate 235*7c478bd9Sstevel@tonic-gate while ((dac_file = readdir(dev_dir)) != NULL) { 236*7c478bd9Sstevel@tonic-gate if ((strcmp(dac_file->d_name, ".") == 0) || 237*7c478bd9Sstevel@tonic-gate (strcmp(dac_file->d_name, "..") == 0)) { 238*7c478bd9Sstevel@tonic-gate continue; 239*7c478bd9Sstevel@tonic-gate } else { 240*7c478bd9Sstevel@tonic-gate error = list_device(optflg, uid, dac_file->d_name); 241*7c478bd9Sstevel@tonic-gate ret_code = ret_code ? error : ret_code; 242*7c478bd9Sstevel@tonic-gate } 243*7c478bd9Sstevel@tonic-gate } 244*7c478bd9Sstevel@tonic-gate (void) closedir(dev_dir); 245*7c478bd9Sstevel@tonic-gate enddaent(); 246*7c478bd9Sstevel@tonic-gate return (ret_code); 247*7c478bd9Sstevel@tonic-gate } 248*7c478bd9Sstevel@tonic-gate 249*7c478bd9Sstevel@tonic-gate /* 250*7c478bd9Sstevel@tonic-gate * Set the DAC characteristics of the file. 251*7c478bd9Sstevel@tonic-gate * This uses a fancy chmod() by setting a minimal ACL which sets the mode 252*7c478bd9Sstevel@tonic-gate * and discards any existing ACL. 253*7c478bd9Sstevel@tonic-gate */ 254*7c478bd9Sstevel@tonic-gate 255*7c478bd9Sstevel@tonic-gate static int 256*7c478bd9Sstevel@tonic-gate newdac(char *file, uid_t owner, gid_t group, o_mode_t mode) 257*7c478bd9Sstevel@tonic-gate { 258*7c478bd9Sstevel@tonic-gate int err = 0; 259*7c478bd9Sstevel@tonic-gate aclent_t min_acl[MIN_ACL_ENTRIES]; 260*7c478bd9Sstevel@tonic-gate 261*7c478bd9Sstevel@tonic-gate min_acl[0].a_type = USER_OBJ; 262*7c478bd9Sstevel@tonic-gate min_acl[0].a_id = owner; 263*7c478bd9Sstevel@tonic-gate min_acl[0].a_perm = ((mode & 0700) >> 6); 264*7c478bd9Sstevel@tonic-gate 265*7c478bd9Sstevel@tonic-gate min_acl[1].a_type = GROUP_OBJ; 266*7c478bd9Sstevel@tonic-gate min_acl[1].a_id = group; 267*7c478bd9Sstevel@tonic-gate min_acl[1].a_perm = ((mode & 0070) >> 3); 268*7c478bd9Sstevel@tonic-gate 269*7c478bd9Sstevel@tonic-gate min_acl[2].a_type = CLASS_OBJ; 270*7c478bd9Sstevel@tonic-gate min_acl[2].a_id = (uid_t)-1; 271*7c478bd9Sstevel@tonic-gate min_acl[2].a_perm = ((mode & 0070) >> 3); 272*7c478bd9Sstevel@tonic-gate 273*7c478bd9Sstevel@tonic-gate min_acl[3].a_type = OTHER_OBJ; 274*7c478bd9Sstevel@tonic-gate min_acl[3].a_id = (uid_t)-1; 275*7c478bd9Sstevel@tonic-gate min_acl[3].a_perm = (mode & 0007); 276*7c478bd9Sstevel@tonic-gate 277*7c478bd9Sstevel@tonic-gate do { 278*7c478bd9Sstevel@tonic-gate if (chown(file, owner, group) == -1) { 279*7c478bd9Sstevel@tonic-gate dperror("newdac, unable to chown"); 280*7c478bd9Sstevel@tonic-gate err = CHOWN_PERR; 281*7c478bd9Sstevel@tonic-gate } 282*7c478bd9Sstevel@tonic-gate } while (fdetach(file) == 0); 283*7c478bd9Sstevel@tonic-gate 284*7c478bd9Sstevel@tonic-gate if (acl(file, SETACL, MIN_ACL_ENTRIES, min_acl) < 0) { 285*7c478bd9Sstevel@tonic-gate dperror("newdac, unable to setacl"); 286*7c478bd9Sstevel@tonic-gate err = SETACL_PERR; 287*7c478bd9Sstevel@tonic-gate } 288*7c478bd9Sstevel@tonic-gate 289*7c478bd9Sstevel@tonic-gate return (err); 290*7c478bd9Sstevel@tonic-gate } 291*7c478bd9Sstevel@tonic-gate 292*7c478bd9Sstevel@tonic-gate static int 293*7c478bd9Sstevel@tonic-gate lock_dev(char *file) 294*7c478bd9Sstevel@tonic-gate { 295*7c478bd9Sstevel@tonic-gate int fd; 296*7c478bd9Sstevel@tonic-gate 297*7c478bd9Sstevel@tonic-gate dprintf("locking %s\n", file); 298*7c478bd9Sstevel@tonic-gate if ((fd = open(file, O_RDWR)) == -1) { 299*7c478bd9Sstevel@tonic-gate dperror("lock_dev, cannot open DAC file"); 300*7c478bd9Sstevel@tonic-gate return (DACACC); 301*7c478bd9Sstevel@tonic-gate } 302*7c478bd9Sstevel@tonic-gate 303*7c478bd9Sstevel@tonic-gate if (lockf(fd, F_TLOCK, 0) == -1) { 304*7c478bd9Sstevel@tonic-gate dperror("lock_dev, cannot set lock"); 305*7c478bd9Sstevel@tonic-gate return (DACLCK); 306*7c478bd9Sstevel@tonic-gate } 307*7c478bd9Sstevel@tonic-gate 308*7c478bd9Sstevel@tonic-gate return (0); 309*7c478bd9Sstevel@tonic-gate } 310*7c478bd9Sstevel@tonic-gate 311*7c478bd9Sstevel@tonic-gate static int 312*7c478bd9Sstevel@tonic-gate mk_alloc(char *list, uid_t uid) 313*7c478bd9Sstevel@tonic-gate { 314*7c478bd9Sstevel@tonic-gate char *file; 315*7c478bd9Sstevel@tonic-gate int err; 316*7c478bd9Sstevel@tonic-gate 317*7c478bd9Sstevel@tonic-gate file = strtok(list, " "); 318*7c478bd9Sstevel@tonic-gate while (file != NULL) { 319*7c478bd9Sstevel@tonic-gate 320*7c478bd9Sstevel@tonic-gate dprintf("Allocating %s\n", file); 321*7c478bd9Sstevel@tonic-gate if ((err = newdac(file, uid, getgid(), ALLOC_MODE)) != 0) { 322*7c478bd9Sstevel@tonic-gate (void) newdac(file, ALLOC_UID, ALLOC_GID, 323*7c478bd9Sstevel@tonic-gate ALLOC_ERR_MODE); 324*7c478bd9Sstevel@tonic-gate return (err); 325*7c478bd9Sstevel@tonic-gate } 326*7c478bd9Sstevel@tonic-gate 327*7c478bd9Sstevel@tonic-gate file = strtok(NULL, " "); 328*7c478bd9Sstevel@tonic-gate } 329*7c478bd9Sstevel@tonic-gate return (0); 330*7c478bd9Sstevel@tonic-gate } 331*7c478bd9Sstevel@tonic-gate 332*7c478bd9Sstevel@tonic-gate /* 333*7c478bd9Sstevel@tonic-gate * mk_revoke() is used instead of system("/usr/sbin/fuser -k file") 334*7c478bd9Sstevel@tonic-gate * because "/usr/sbin/fuser -k file" kills all processes 335*7c478bd9Sstevel@tonic-gate * working with the file, even "vold" (bug #4095152). 336*7c478bd9Sstevel@tonic-gate */ 337*7c478bd9Sstevel@tonic-gate static int 338*7c478bd9Sstevel@tonic-gate mk_revoke(int optflg, char *file) 339*7c478bd9Sstevel@tonic-gate { 340*7c478bd9Sstevel@tonic-gate char buf[MAXPATHLEN]; 341*7c478bd9Sstevel@tonic-gate int r = 0, p[2], fp, lock; 342*7c478bd9Sstevel@tonic-gate FILE *ptr; 343*7c478bd9Sstevel@tonic-gate prpsinfo_t info; 344*7c478bd9Sstevel@tonic-gate pid_t pid, c_pid; 345*7c478bd9Sstevel@tonic-gate 346*7c478bd9Sstevel@tonic-gate (void) strcpy(buf, PROCFS); 347*7c478bd9Sstevel@tonic-gate 348*7c478bd9Sstevel@tonic-gate /* 349*7c478bd9Sstevel@tonic-gate * vfork() and execle() just to make the same output 350*7c478bd9Sstevel@tonic-gate * as before fixing of bug #4095152. 351*7c478bd9Sstevel@tonic-gate * The problem is that the "fuser" command prints 352*7c478bd9Sstevel@tonic-gate * one part of output into stderr and another into stdout, 353*7c478bd9Sstevel@tonic-gate * but user sees them mixed. Of course, better to change "fuser" 354*7c478bd9Sstevel@tonic-gate * or to intercept and not to print its output. 355*7c478bd9Sstevel@tonic-gate */ 356*7c478bd9Sstevel@tonic-gate if (!(optflg & SILENT)) { 357*7c478bd9Sstevel@tonic-gate c_pid = vfork(); 358*7c478bd9Sstevel@tonic-gate if (c_pid == -1) 359*7c478bd9Sstevel@tonic-gate return (-1); 360*7c478bd9Sstevel@tonic-gate if (c_pid == 0) { 361*7c478bd9Sstevel@tonic-gate dprintf("first exec fuser %s\n", file); 362*7c478bd9Sstevel@tonic-gate (void) execle("/usr/sbin/fuser", "fuser", file, NULL, 363*7c478bd9Sstevel@tonic-gate newenv); 364*7c478bd9Sstevel@tonic-gate dperror("first exec fuser"); 365*7c478bd9Sstevel@tonic-gate _exit(1); 366*7c478bd9Sstevel@tonic-gate } 367*7c478bd9Sstevel@tonic-gate 368*7c478bd9Sstevel@tonic-gate (void) waitpid(c_pid, &lock, 0); 369*7c478bd9Sstevel@tonic-gate dprintf("exit status %x\n", lock); 370*7c478bd9Sstevel@tonic-gate if (WEXITSTATUS(lock) != 0) 371*7c478bd9Sstevel@tonic-gate return (-1); 372*7c478bd9Sstevel@tonic-gate } 373*7c478bd9Sstevel@tonic-gate dprintf("first continuing c_pid=%d\n", c_pid); 374*7c478bd9Sstevel@tonic-gate 375*7c478bd9Sstevel@tonic-gate if (pipe(p)) { 376*7c478bd9Sstevel@tonic-gate dperror("pipe"); 377*7c478bd9Sstevel@tonic-gate return (-1); 378*7c478bd9Sstevel@tonic-gate } 379*7c478bd9Sstevel@tonic-gate 380*7c478bd9Sstevel@tonic-gate /* vfork() and execle() to catch output and to process it */ 381*7c478bd9Sstevel@tonic-gate c_pid = vfork(); 382*7c478bd9Sstevel@tonic-gate if (c_pid == -1) { 383*7c478bd9Sstevel@tonic-gate dperror("second vfork"); 384*7c478bd9Sstevel@tonic-gate return (-1); 385*7c478bd9Sstevel@tonic-gate } 386*7c478bd9Sstevel@tonic-gate dprintf("second continuing c_pid=%d\n", c_pid); 387*7c478bd9Sstevel@tonic-gate 388*7c478bd9Sstevel@tonic-gate if (c_pid == 0) { 389*7c478bd9Sstevel@tonic-gate (void) close(p[0]); 390*7c478bd9Sstevel@tonic-gate (void) close(1); 391*7c478bd9Sstevel@tonic-gate (void) fcntl(p[1], F_DUPFD, 1); 392*7c478bd9Sstevel@tonic-gate (void) close(p[1]); 393*7c478bd9Sstevel@tonic-gate (void) close(2); 394*7c478bd9Sstevel@tonic-gate dprintf("second exec fuser %s\n", file); 395*7c478bd9Sstevel@tonic-gate (void) execle("/usr/sbin/fuser", "fuser", file, NULL, newenv); 396*7c478bd9Sstevel@tonic-gate dperror("second exec fuser"); 397*7c478bd9Sstevel@tonic-gate _exit(1); 398*7c478bd9Sstevel@tonic-gate } 399*7c478bd9Sstevel@tonic-gate 400*7c478bd9Sstevel@tonic-gate (void) close(p[1]); 401*7c478bd9Sstevel@tonic-gate if ((ptr = fdopen(p[0], "r")) != NULL) { 402*7c478bd9Sstevel@tonic-gate while (!feof(ptr)) { 403*7c478bd9Sstevel@tonic-gate if (fscanf(ptr, "%d", &pid) > 0) { 404*7c478bd9Sstevel@tonic-gate (void) sprintf(buf + strlen(PROCFS), "%d", pid); 405*7c478bd9Sstevel@tonic-gate if ((fp = open(buf, O_RDONLY)) == -1) { 406*7c478bd9Sstevel@tonic-gate dperror(buf); 407*7c478bd9Sstevel@tonic-gate continue; 408*7c478bd9Sstevel@tonic-gate } 409*7c478bd9Sstevel@tonic-gate if (ioctl(fp, PIOCPSINFO, (char *)&info) 410*7c478bd9Sstevel@tonic-gate == -1) { 411*7c478bd9Sstevel@tonic-gate dprintf("%d psinfo failed", pid); 412*7c478bd9Sstevel@tonic-gate dperror(""); 413*7c478bd9Sstevel@tonic-gate (void) close(fp); 414*7c478bd9Sstevel@tonic-gate continue; 415*7c478bd9Sstevel@tonic-gate } 416*7c478bd9Sstevel@tonic-gate (void) close(fp); 417*7c478bd9Sstevel@tonic-gate if (strcmp(info.pr_fname, "vold") == NULL) { 418*7c478bd9Sstevel@tonic-gate dprintf("%d matched vold name\n", pid); 419*7c478bd9Sstevel@tonic-gate continue; 420*7c478bd9Sstevel@tonic-gate } 421*7c478bd9Sstevel@tonic-gate dprintf("killing %s", info.pr_fname); 422*7c478bd9Sstevel@tonic-gate dprintf("(%d)\n", pid); 423*7c478bd9Sstevel@tonic-gate if ((r = kill(pid, SIGKILL)) == -1) { 424*7c478bd9Sstevel@tonic-gate dprintf("kill %d", pid); 425*7c478bd9Sstevel@tonic-gate dperror(""); 426*7c478bd9Sstevel@tonic-gate break; 427*7c478bd9Sstevel@tonic-gate } 428*7c478bd9Sstevel@tonic-gate } 429*7c478bd9Sstevel@tonic-gate } 430*7c478bd9Sstevel@tonic-gate dprintf("eof reached %x\n", ptr); 431*7c478bd9Sstevel@tonic-gate } else { 432*7c478bd9Sstevel@tonic-gate dperror("fdopen(p[0])"); 433*7c478bd9Sstevel@tonic-gate r = -1; 434*7c478bd9Sstevel@tonic-gate } 435*7c478bd9Sstevel@tonic-gate 436*7c478bd9Sstevel@tonic-gate (void) fclose(ptr); 437*7c478bd9Sstevel@tonic-gate return (r); 438*7c478bd9Sstevel@tonic-gate } 439*7c478bd9Sstevel@tonic-gate 440*7c478bd9Sstevel@tonic-gate static int 441*7c478bd9Sstevel@tonic-gate mk_unalloc(int optflg, char *list) 442*7c478bd9Sstevel@tonic-gate { 443*7c478bd9Sstevel@tonic-gate char *file; 444*7c478bd9Sstevel@tonic-gate int error = 0; 445*7c478bd9Sstevel@tonic-gate int child, status; 446*7c478bd9Sstevel@tonic-gate 447*7c478bd9Sstevel@tonic-gate audit_allocate_list(list); 448*7c478bd9Sstevel@tonic-gate 449*7c478bd9Sstevel@tonic-gate child = vfork(); 450*7c478bd9Sstevel@tonic-gate switch (child) { 451*7c478bd9Sstevel@tonic-gate case -1: 452*7c478bd9Sstevel@tonic-gate return (-1); 453*7c478bd9Sstevel@tonic-gate case 0: 454*7c478bd9Sstevel@tonic-gate (void) setuid(0); 455*7c478bd9Sstevel@tonic-gate file = strtok(list, " "); 456*7c478bd9Sstevel@tonic-gate while (file != NULL) { 457*7c478bd9Sstevel@tonic-gate dprintf("Deallocating %s\n", file); 458*7c478bd9Sstevel@tonic-gate if (mk_revoke(optflg, file) < 0) { 459*7c478bd9Sstevel@tonic-gate dprintf("mk_unalloc: unable to revoke %s\n", 460*7c478bd9Sstevel@tonic-gate file); 461*7c478bd9Sstevel@tonic-gate dperror(""); 462*7c478bd9Sstevel@tonic-gate error = CNTFRC; 463*7c478bd9Sstevel@tonic-gate break; 464*7c478bd9Sstevel@tonic-gate } 465*7c478bd9Sstevel@tonic-gate error = newdac(file, ALLOC_UID, ALLOC_GID, 466*7c478bd9Sstevel@tonic-gate DEALLOC_MODE); 467*7c478bd9Sstevel@tonic-gate file = strtok(NULL, " "); 468*7c478bd9Sstevel@tonic-gate } 469*7c478bd9Sstevel@tonic-gate exit(error); 470*7c478bd9Sstevel@tonic-gate default: 471*7c478bd9Sstevel@tonic-gate while (wait(&status) != child); 472*7c478bd9Sstevel@tonic-gate if (WIFEXITED(status)) { 473*7c478bd9Sstevel@tonic-gate return (WEXITSTATUS(status)); 474*7c478bd9Sstevel@tonic-gate } 475*7c478bd9Sstevel@tonic-gate return (-1); 476*7c478bd9Sstevel@tonic-gate } 477*7c478bd9Sstevel@tonic-gate } 478*7c478bd9Sstevel@tonic-gate 479*7c478bd9Sstevel@tonic-gate static int 480*7c478bd9Sstevel@tonic-gate exec_clean(int optflg, char *name, char *path) 481*7c478bd9Sstevel@tonic-gate { 482*7c478bd9Sstevel@tonic-gate char *mode, *cmd; 483*7c478bd9Sstevel@tonic-gate int status; 484*7c478bd9Sstevel@tonic-gate int c; 485*7c478bd9Sstevel@tonic-gate 486*7c478bd9Sstevel@tonic-gate if ((optflg & (FORCE_ALL | SILENT)) == (FORCE_ALL | SILENT)) 487*7c478bd9Sstevel@tonic-gate mode = "-I"; 488*7c478bd9Sstevel@tonic-gate else if (optflg & FORCE_ALL) 489*7c478bd9Sstevel@tonic-gate mode = "-i"; 490*7c478bd9Sstevel@tonic-gate else if (optflg & FORCE) 491*7c478bd9Sstevel@tonic-gate mode = "-f"; 492*7c478bd9Sstevel@tonic-gate else 493*7c478bd9Sstevel@tonic-gate mode = "-s"; 494*7c478bd9Sstevel@tonic-gate if ((cmd = strrchr(path, '/')) == NULL) 495*7c478bd9Sstevel@tonic-gate cmd = path; 496*7c478bd9Sstevel@tonic-gate else 497*7c478bd9Sstevel@tonic-gate cmd++; /* skip leading '/' */ 498*7c478bd9Sstevel@tonic-gate 499*7c478bd9Sstevel@tonic-gate c = vfork(); 500*7c478bd9Sstevel@tonic-gate switch (c) { 501*7c478bd9Sstevel@tonic-gate case -1: 502*7c478bd9Sstevel@tonic-gate return (-1); 503*7c478bd9Sstevel@tonic-gate case 0: 504*7c478bd9Sstevel@tonic-gate (void) setuid(0); 505*7c478bd9Sstevel@tonic-gate dprintf("clean script: %s, ", path); 506*7c478bd9Sstevel@tonic-gate dprintf("cmd=%s, ", cmd); 507*7c478bd9Sstevel@tonic-gate dprintf("mode=%s, ", mode); 508*7c478bd9Sstevel@tonic-gate dprintf("name=%s\n", name); 509*7c478bd9Sstevel@tonic-gate (void) execle(path, cmd, mode, name, NULL, newenv); 510*7c478bd9Sstevel@tonic-gate dprintf("Unable to execute clean up script %s\n", path); 511*7c478bd9Sstevel@tonic-gate dperror(""); 512*7c478bd9Sstevel@tonic-gate exit(CNTDEXEC); 513*7c478bd9Sstevel@tonic-gate default: 514*7c478bd9Sstevel@tonic-gate while (wait(&status) != c); 515*7c478bd9Sstevel@tonic-gate if (WIFEXITED(status)) 516*7c478bd9Sstevel@tonic-gate return (WEXITSTATUS(status)); 517*7c478bd9Sstevel@tonic-gate dprintf("exit status %d\n", status); 518*7c478bd9Sstevel@tonic-gate return (-1); 519*7c478bd9Sstevel@tonic-gate } 520*7c478bd9Sstevel@tonic-gate } 521*7c478bd9Sstevel@tonic-gate 522*7c478bd9Sstevel@tonic-gate static int 523*7c478bd9Sstevel@tonic-gate deallocate_dev(int optflg, devalloc_t *dev_ent, uid_t uid) 524*7c478bd9Sstevel@tonic-gate { 525*7c478bd9Sstevel@tonic-gate devmap_t *dev_list; 526*7c478bd9Sstevel@tonic-gate char file_name[MAXPATHLEN]; 527*7c478bd9Sstevel@tonic-gate struct stat stat_buf; 528*7c478bd9Sstevel@tonic-gate char *list; 529*7c478bd9Sstevel@tonic-gate int error = 0, err; 530*7c478bd9Sstevel@tonic-gate int bytes_formated; 531*7c478bd9Sstevel@tonic-gate 532*7c478bd9Sstevel@tonic-gate bytes_formated = snprintf(file_name, MAXPATHLEN, "%s/%s", DAC_DIR, 533*7c478bd9Sstevel@tonic-gate dev_ent->da_devname); 534*7c478bd9Sstevel@tonic-gate if (bytes_formated <= 0) { 535*7c478bd9Sstevel@tonic-gate return (DEVNAME_ERR); 536*7c478bd9Sstevel@tonic-gate } else if (bytes_formated >= MAXPATHLEN) { 537*7c478bd9Sstevel@tonic-gate dprintf("device name %s is too long.\n", dev_ent->da_devname); 538*7c478bd9Sstevel@tonic-gate return (DEVNAME_TOOLONG); 539*7c478bd9Sstevel@tonic-gate } 540*7c478bd9Sstevel@tonic-gate 541*7c478bd9Sstevel@tonic-gate audit_allocate_device(file_name); 542*7c478bd9Sstevel@tonic-gate 543*7c478bd9Sstevel@tonic-gate if (stat(file_name, &stat_buf)) { 544*7c478bd9Sstevel@tonic-gate dprintf("Unable to stat %s\n", file_name); 545*7c478bd9Sstevel@tonic-gate dperror("Error:"); 546*7c478bd9Sstevel@tonic-gate return (DACACC); 547*7c478bd9Sstevel@tonic-gate } 548*7c478bd9Sstevel@tonic-gate 549*7c478bd9Sstevel@tonic-gate if (!(optflg & FORCE) && stat_buf.st_uid != uid && 550*7c478bd9Sstevel@tonic-gate DEV_ALLOCATED(stat_buf)) { 551*7c478bd9Sstevel@tonic-gate return (NALLOCU); 552*7c478bd9Sstevel@tonic-gate } 553*7c478bd9Sstevel@tonic-gate 554*7c478bd9Sstevel@tonic-gate if (!(optflg & FORCE_ALL) && !DEV_ALLOCATED(stat_buf)) { 555*7c478bd9Sstevel@tonic-gate if ((stat_buf.st_mode & ~S_IFMT) == ALLOC_ERR_MODE) { 556*7c478bd9Sstevel@tonic-gate if (!(optflg & FORCE)) 557*7c478bd9Sstevel@tonic-gate return (ALLOCERR); 558*7c478bd9Sstevel@tonic-gate } else 559*7c478bd9Sstevel@tonic-gate return (NALLOC); 560*7c478bd9Sstevel@tonic-gate } 561*7c478bd9Sstevel@tonic-gate 562*7c478bd9Sstevel@tonic-gate /* All checks passed, time to lock and deallocate */ 563*7c478bd9Sstevel@tonic-gate if ((error = lock_dev(file_name)) != 0) 564*7c478bd9Sstevel@tonic-gate return (error); 565*7c478bd9Sstevel@tonic-gate 566*7c478bd9Sstevel@tonic-gate if ((err = newdac(file_name, ALLOC_UID, ALLOC_GID, DEALLOC_MODE)) 567*7c478bd9Sstevel@tonic-gate != 0) { 568*7c478bd9Sstevel@tonic-gate (void) newdac(file_name, ALLOC_UID, ALLOC_GID, ALLOC_ERR_MODE); 569*7c478bd9Sstevel@tonic-gate EXIT(err); 570*7c478bd9Sstevel@tonic-gate } 571*7c478bd9Sstevel@tonic-gate 572*7c478bd9Sstevel@tonic-gate if ((dev_list = getdmapnam(dev_ent->da_devname)) == NULL) { 573*7c478bd9Sstevel@tonic-gate dprintf("Unable to find %s in the device map database\n", 574*7c478bd9Sstevel@tonic-gate dev_ent->da_devname); 575*7c478bd9Sstevel@tonic-gate EXIT(NODMAPENT); 576*7c478bd9Sstevel@tonic-gate } else { 577*7c478bd9Sstevel@tonic-gate if ((list = strdup(dev_list->dmap_devlist)) == NULL) { 578*7c478bd9Sstevel@tonic-gate EXIT(SYSERROR) 579*7c478bd9Sstevel@tonic-gate } else { 580*7c478bd9Sstevel@tonic-gate if (mk_unalloc(optflg, list) != 0) { 581*7c478bd9Sstevel@tonic-gate (void) newdac(file_name, ALLOC_UID, ALLOC_GID, 582*7c478bd9Sstevel@tonic-gate ALLOC_ERR_MODE); 583*7c478bd9Sstevel@tonic-gate free(list); 584*7c478bd9Sstevel@tonic-gate list = NULL; 585*7c478bd9Sstevel@tonic-gate EXIT(DEVLST); 586*7c478bd9Sstevel@tonic-gate } 587*7c478bd9Sstevel@tonic-gate } 588*7c478bd9Sstevel@tonic-gate } 589*7c478bd9Sstevel@tonic-gate 590*7c478bd9Sstevel@tonic-gate if (list != NULL) 591*7c478bd9Sstevel@tonic-gate free(list); 592*7c478bd9Sstevel@tonic-gate if (exec_clean(optflg, dev_ent->da_devname, dev_ent->da_devexec)) 593*7c478bd9Sstevel@tonic-gate EXIT(CLEAN_ERR); 594*7c478bd9Sstevel@tonic-gate return (error); 595*7c478bd9Sstevel@tonic-gate } 596*7c478bd9Sstevel@tonic-gate 597*7c478bd9Sstevel@tonic-gate static int 598*7c478bd9Sstevel@tonic-gate allocate_dev(int optflg, uid_t uid, devalloc_t *dev_ent) 599*7c478bd9Sstevel@tonic-gate { 600*7c478bd9Sstevel@tonic-gate devmap_t *dev_list; 601*7c478bd9Sstevel@tonic-gate char file_name[MAXPATHLEN]; 602*7c478bd9Sstevel@tonic-gate struct stat stat_buf; 603*7c478bd9Sstevel@tonic-gate char *list; 604*7c478bd9Sstevel@tonic-gate int error = 0; 605*7c478bd9Sstevel@tonic-gate int bytes_formated; 606*7c478bd9Sstevel@tonic-gate 607*7c478bd9Sstevel@tonic-gate bytes_formated = snprintf(file_name, MAXPATHLEN, "%s/%s", DAC_DIR, 608*7c478bd9Sstevel@tonic-gate dev_ent->da_devname); 609*7c478bd9Sstevel@tonic-gate if (bytes_formated <= 0) { 610*7c478bd9Sstevel@tonic-gate return (DEVNAME_ERR); 611*7c478bd9Sstevel@tonic-gate } else if (bytes_formated >= MAXPATHLEN) { 612*7c478bd9Sstevel@tonic-gate dprintf("device name %s is too long.\n", dev_ent->da_devname); 613*7c478bd9Sstevel@tonic-gate return (DEVNAME_TOOLONG); 614*7c478bd9Sstevel@tonic-gate } 615*7c478bd9Sstevel@tonic-gate 616*7c478bd9Sstevel@tonic-gate audit_allocate_device(file_name); 617*7c478bd9Sstevel@tonic-gate 618*7c478bd9Sstevel@tonic-gate if (stat(file_name, &stat_buf)) { 619*7c478bd9Sstevel@tonic-gate dprintf("Unable to stat %s\n", file_name); 620*7c478bd9Sstevel@tonic-gate dperror("Error:"); 621*7c478bd9Sstevel@tonic-gate return (DACACC); 622*7c478bd9Sstevel@tonic-gate } 623*7c478bd9Sstevel@tonic-gate 624*7c478bd9Sstevel@tonic-gate if (DEV_ALLOCATED(stat_buf)) { 625*7c478bd9Sstevel@tonic-gate if (optflg & FORCE) { 626*7c478bd9Sstevel@tonic-gate if (deallocate_dev(FORCE, dev_ent, uid)) { 627*7c478bd9Sstevel@tonic-gate dprintf("Couldn't force deallocate device %s\n", 628*7c478bd9Sstevel@tonic-gate dev_ent->da_devname); 629*7c478bd9Sstevel@tonic-gate return (CNTFRC); 630*7c478bd9Sstevel@tonic-gate } 631*7c478bd9Sstevel@tonic-gate } else if (stat_buf.st_uid == uid) { 632*7c478bd9Sstevel@tonic-gate return (ALLOC); 633*7c478bd9Sstevel@tonic-gate } else 634*7c478bd9Sstevel@tonic-gate return (ALLOC_OTHER); 635*7c478bd9Sstevel@tonic-gate } 636*7c478bd9Sstevel@tonic-gate if ((stat_buf.st_mode & ~S_IFMT) == ALLOC_ERR_MODE) 637*7c478bd9Sstevel@tonic-gate return (ALLOCERR); 638*7c478bd9Sstevel@tonic-gate 639*7c478bd9Sstevel@tonic-gate if (strcmp(dev_ent->da_devauth, "*") == 0) { 640*7c478bd9Sstevel@tonic-gate dprintf("Device %s is not allocatable\n", dev_ent->da_devname); 641*7c478bd9Sstevel@tonic-gate return (AUTHERR); 642*7c478bd9Sstevel@tonic-gate } 643*7c478bd9Sstevel@tonic-gate 644*7c478bd9Sstevel@tonic-gate if (strcmp(dev_ent->da_devauth, "@")) { 645*7c478bd9Sstevel@tonic-gate if (!is_authorized(dev_ent->da_devauth, uid)) { 646*7c478bd9Sstevel@tonic-gate dprintf("User %d is unauthorized to allocate\n", 647*7c478bd9Sstevel@tonic-gate (int)uid); 648*7c478bd9Sstevel@tonic-gate return (IMPORT_ERR); 649*7c478bd9Sstevel@tonic-gate } 650*7c478bd9Sstevel@tonic-gate } 651*7c478bd9Sstevel@tonic-gate 652*7c478bd9Sstevel@tonic-gate if ((dev_list = getdmapnam(dev_ent->da_devname)) == NULL) { 653*7c478bd9Sstevel@tonic-gate dprintf("Unable to find %s in device map database\n", 654*7c478bd9Sstevel@tonic-gate dev_ent->da_devname); 655*7c478bd9Sstevel@tonic-gate return (NODMAPENT); 656*7c478bd9Sstevel@tonic-gate } 657*7c478bd9Sstevel@tonic-gate 658*7c478bd9Sstevel@tonic-gate if ((list = strdup(dev_list->dmap_devlist)) == NULL) 659*7c478bd9Sstevel@tonic-gate return (SYSERROR); 660*7c478bd9Sstevel@tonic-gate 661*7c478bd9Sstevel@tonic-gate if (check_devs(list) == -1) { 662*7c478bd9Sstevel@tonic-gate free(list); 663*7c478bd9Sstevel@tonic-gate return (DSPMISS); 664*7c478bd9Sstevel@tonic-gate } 665*7c478bd9Sstevel@tonic-gate 666*7c478bd9Sstevel@tonic-gate /* All checks passed, time to lock and allocate */ 667*7c478bd9Sstevel@tonic-gate if ((error = lock_dev(file_name)) != 0) { 668*7c478bd9Sstevel@tonic-gate free(list); 669*7c478bd9Sstevel@tonic-gate return (error); 670*7c478bd9Sstevel@tonic-gate } 671*7c478bd9Sstevel@tonic-gate 672*7c478bd9Sstevel@tonic-gate if ((error = newdac(file_name, uid, getgid(), ALLOC_MODE)) != 0) { 673*7c478bd9Sstevel@tonic-gate (void) newdac(file_name, ALLOC_UID, ALLOC_GID, ALLOC_ERR_MODE); 674*7c478bd9Sstevel@tonic-gate free(list); 675*7c478bd9Sstevel@tonic-gate return (error); 676*7c478bd9Sstevel@tonic-gate } 677*7c478bd9Sstevel@tonic-gate 678*7c478bd9Sstevel@tonic-gate /* refresh list from check_devs overwritting it */ 679*7c478bd9Sstevel@tonic-gate (void) strcpy(list, dev_list->dmap_devlist); 680*7c478bd9Sstevel@tonic-gate audit_allocate_list(list); 681*7c478bd9Sstevel@tonic-gate 682*7c478bd9Sstevel@tonic-gate if (mk_alloc(list, uid) != 0) { 683*7c478bd9Sstevel@tonic-gate /* refresh list from mk_alloc overwritting it */ 684*7c478bd9Sstevel@tonic-gate (void) strcpy(list, dev_list->dmap_devlist); 685*7c478bd9Sstevel@tonic-gate (void) mk_unalloc(optflg, list); 686*7c478bd9Sstevel@tonic-gate free(list); 687*7c478bd9Sstevel@tonic-gate return (DEVLST); 688*7c478bd9Sstevel@tonic-gate } 689*7c478bd9Sstevel@tonic-gate 690*7c478bd9Sstevel@tonic-gate free(list); 691*7c478bd9Sstevel@tonic-gate return (0); 692*7c478bd9Sstevel@tonic-gate } 693*7c478bd9Sstevel@tonic-gate 694*7c478bd9Sstevel@tonic-gate int 695*7c478bd9Sstevel@tonic-gate allocate(int optflg, uid_t uid, char *device) 696*7c478bd9Sstevel@tonic-gate { 697*7c478bd9Sstevel@tonic-gate devalloc_t *dev_ent; 698*7c478bd9Sstevel@tonic-gate devmap_t *dev_list; 699*7c478bd9Sstevel@tonic-gate 700*7c478bd9Sstevel@tonic-gate if (((optflg & FORCE) || uid != getuid()) && 701*7c478bd9Sstevel@tonic-gate !is_authorized(DEVICE_REVOKE_AUTH, getuid())) 702*7c478bd9Sstevel@tonic-gate return (NOTAUTH); 703*7c478bd9Sstevel@tonic-gate 704*7c478bd9Sstevel@tonic-gate setdaent(); 705*7c478bd9Sstevel@tonic-gate setdmapent(); 706*7c478bd9Sstevel@tonic-gate 707*7c478bd9Sstevel@tonic-gate if (!(optflg & TYPE)) { 708*7c478bd9Sstevel@tonic-gate if ((dev_ent = getdanam(device)) == NULL) { 709*7c478bd9Sstevel@tonic-gate if ((dev_list = getdmapdev(device)) == NULL) 710*7c478bd9Sstevel@tonic-gate return (NODMAPENT); 711*7c478bd9Sstevel@tonic-gate else if ((dev_ent = getdanam(dev_list->dmap_devname)) 712*7c478bd9Sstevel@tonic-gate == NULL) 713*7c478bd9Sstevel@tonic-gate return (NODAENT); 714*7c478bd9Sstevel@tonic-gate } 715*7c478bd9Sstevel@tonic-gate return (allocate_dev(optflg, uid, dev_ent)); 716*7c478bd9Sstevel@tonic-gate } 717*7c478bd9Sstevel@tonic-gate 718*7c478bd9Sstevel@tonic-gate while ((dev_ent = getdatype(device)) != NULL) { 719*7c478bd9Sstevel@tonic-gate dprintf("trying to allocate %s\n", dev_ent->da_devname); 720*7c478bd9Sstevel@tonic-gate if (!allocate_dev(optflg, uid, dev_ent)) { 721*7c478bd9Sstevel@tonic-gate return (0); 722*7c478bd9Sstevel@tonic-gate } 723*7c478bd9Sstevel@tonic-gate } 724*7c478bd9Sstevel@tonic-gate enddaent(); 725*7c478bd9Sstevel@tonic-gate return (NO_DEVICE); 726*7c478bd9Sstevel@tonic-gate } 727*7c478bd9Sstevel@tonic-gate 728*7c478bd9Sstevel@tonic-gate int 729*7c478bd9Sstevel@tonic-gate deallocate(int optflg, uid_t uid, char *device) 730*7c478bd9Sstevel@tonic-gate { 731*7c478bd9Sstevel@tonic-gate DIR *dev_dir; 732*7c478bd9Sstevel@tonic-gate struct dirent *dac_file; 733*7c478bd9Sstevel@tonic-gate devalloc_t *dev_ent; 734*7c478bd9Sstevel@tonic-gate devmap_t *dev_list; 735*7c478bd9Sstevel@tonic-gate int error = NODAENT; 736*7c478bd9Sstevel@tonic-gate 737*7c478bd9Sstevel@tonic-gate if (optflg & (FORCE | FORCE_ALL) && 738*7c478bd9Sstevel@tonic-gate !is_authorized(DEVICE_REVOKE_AUTH, getuid())) 739*7c478bd9Sstevel@tonic-gate return (NOTAUTH); 740*7c478bd9Sstevel@tonic-gate if (optflg & FORCE_ALL) 741*7c478bd9Sstevel@tonic-gate optflg |= FORCE; 742*7c478bd9Sstevel@tonic-gate 743*7c478bd9Sstevel@tonic-gate setdaent(); 744*7c478bd9Sstevel@tonic-gate setdmapent(); 745*7c478bd9Sstevel@tonic-gate 746*7c478bd9Sstevel@tonic-gate if (!(optflg & FORCE_ALL)) { 747*7c478bd9Sstevel@tonic-gate if ((dev_ent = getdanam(device)) == NULL) { 748*7c478bd9Sstevel@tonic-gate if ((dev_list = getdmapdev(device)) == NULL) 749*7c478bd9Sstevel@tonic-gate return (NODMAPENT); 750*7c478bd9Sstevel@tonic-gate else if ((dev_ent = getdanam(dev_list->dmap_devname)) 751*7c478bd9Sstevel@tonic-gate == NULL) 752*7c478bd9Sstevel@tonic-gate return (NODAENT); 753*7c478bd9Sstevel@tonic-gate } 754*7c478bd9Sstevel@tonic-gate 755*7c478bd9Sstevel@tonic-gate return (deallocate_dev(optflg, dev_ent, uid)); 756*7c478bd9Sstevel@tonic-gate } 757*7c478bd9Sstevel@tonic-gate 758*7c478bd9Sstevel@tonic-gate if ((dev_dir = opendir(DAC_DIR)) == NULL) { 759*7c478bd9Sstevel@tonic-gate dperror("Can't open DAC_DIR"); 760*7c478bd9Sstevel@tonic-gate return (DACACC); 761*7c478bd9Sstevel@tonic-gate } 762*7c478bd9Sstevel@tonic-gate 763*7c478bd9Sstevel@tonic-gate while ((dac_file = readdir(dev_dir)) != NULL) { 764*7c478bd9Sstevel@tonic-gate if ((strcmp(dac_file->d_name, ".") == 0) || 765*7c478bd9Sstevel@tonic-gate (strcmp(dac_file->d_name, "..") == 0)) { 766*7c478bd9Sstevel@tonic-gate continue; 767*7c478bd9Sstevel@tonic-gate } else { 768*7c478bd9Sstevel@tonic-gate if ((dev_ent = getdanam(dac_file->d_name)) == NULL) { 769*7c478bd9Sstevel@tonic-gate continue; 770*7c478bd9Sstevel@tonic-gate } 771*7c478bd9Sstevel@tonic-gate error = deallocate_dev(optflg, dev_ent, uid); 772*7c478bd9Sstevel@tonic-gate } 773*7c478bd9Sstevel@tonic-gate } 774*7c478bd9Sstevel@tonic-gate (void) closedir(dev_dir); 775*7c478bd9Sstevel@tonic-gate enddaent(); 776*7c478bd9Sstevel@tonic-gate return (error); 777*7c478bd9Sstevel@tonic-gate } 778