17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*45916cd2Sjpk * Common Development and Distribution License (the "License"). 6*45916cd2Sjpk * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 21*45916cd2Sjpk 227c478bd9Sstevel@tonic-gate /* 2340e2b7c9Spaulson * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 287c478bd9Sstevel@tonic-gate 297c478bd9Sstevel@tonic-gate #include <auth_attr.h> 307c478bd9Sstevel@tonic-gate #include <auth_list.h> 317c478bd9Sstevel@tonic-gate #include <dirent.h> 327c478bd9Sstevel@tonic-gate #include <errno.h> 337c478bd9Sstevel@tonic-gate #include <fcntl.h> 347c478bd9Sstevel@tonic-gate #include <libintl.h> 357c478bd9Sstevel@tonic-gate #include <locale.h> 367c478bd9Sstevel@tonic-gate #include <pwd.h> 377c478bd9Sstevel@tonic-gate #include <signal.h> 387c478bd9Sstevel@tonic-gate #include <stdio.h> 397c478bd9Sstevel@tonic-gate #include <stdlib.h> 407c478bd9Sstevel@tonic-gate #include <string.h> 41*45916cd2Sjpk #include <strings.h> 427c478bd9Sstevel@tonic-gate #include <unistd.h> 437c478bd9Sstevel@tonic-gate #include <bsm/devices.h> 44*45916cd2Sjpk #include <sys/acl.h> 45*45916cd2Sjpk #include <tsol/label.h> 46*45916cd2Sjpk #include <syslog.h> 47*45916cd2Sjpk #include <limits.h> 48*45916cd2Sjpk #include <user_attr.h> 49*45916cd2Sjpk #include <secdb.h> 50*45916cd2Sjpk #include <sys/mkdev.h> 517c478bd9Sstevel@tonic-gate #include <sys/acl.h> 527c478bd9Sstevel@tonic-gate #include <sys/file.h> 537c478bd9Sstevel@tonic-gate #include <sys/procfs.h> 547c478bd9Sstevel@tonic-gate #include <sys/param.h> 557c478bd9Sstevel@tonic-gate #include <sys/resource.h> 567c478bd9Sstevel@tonic-gate #include <sys/stat.h> 577c478bd9Sstevel@tonic-gate #include <sys/time.h> 587c478bd9Sstevel@tonic-gate #include <sys/types.h> 597c478bd9Sstevel@tonic-gate #include <sys/wait.h> 60*45916cd2Sjpk #include <utime.h> 61*45916cd2Sjpk #include <libgen.h> 62*45916cd2Sjpk #include <zone.h> 63*45916cd2Sjpk #include <nss_dbdefs.h> 64*45916cd2Sjpk #include <bsm/devalloc.h> 657c478bd9Sstevel@tonic-gate #include "allocate.h" 667c478bd9Sstevel@tonic-gate 67*45916cd2Sjpk extern void print_error(int, char *); 68*45916cd2Sjpk 69*45916cd2Sjpk #if defined(DEBUG) || defined(lint) 707c478bd9Sstevel@tonic-gate #define dprintf(s, a) (void) fprintf(stderr, s, a) 717c478bd9Sstevel@tonic-gate #define dperror(s) perror(s) 727c478bd9Sstevel@tonic-gate #else /* !DEBUG */ 73*45916cd2Sjpk #define dprintf(s, a) 0 74*45916cd2Sjpk #define dperror(s) 0 757c478bd9Sstevel@tonic-gate #endif /* DEBUG */ 767c478bd9Sstevel@tonic-gate 77*45916cd2Sjpk #define DEV_ERRORED(sbuf) (((sbuf).st_mode & ~S_IFMT) == ALLOC_ERR_MODE) 78*45916cd2Sjpk #define DEV_INVALID(sbuf) (((sbuf).st_mode & ~S_IFMT) == ALLOC_INVALID) 797c478bd9Sstevel@tonic-gate #define DEV_ALLOCATED(sbuf) ((sbuf).st_uid != ALLOC_UID || \ 80*45916cd2Sjpk !(((sbuf).st_mode & ~S_IFMT) == DEALLOC_MODE || \ 81*45916cd2Sjpk DEV_ERRORED(sbuf) || DEV_INVALID(sbuf))) 827c478bd9Sstevel@tonic-gate 83*45916cd2Sjpk #define ALLOC_CLEAN "-A" 84*45916cd2Sjpk #define DEALLOC_CLEAN "-D" 85*45916cd2Sjpk #define DAC_DIR "/etc/security/dev" 867c478bd9Sstevel@tonic-gate #define DEVICE_AUTH_SEPARATOR "," 87*45916cd2Sjpk #define LOCALDEVICE "/dev/console" 887c478bd9Sstevel@tonic-gate #define PROCFS "/proc/" 89*45916cd2Sjpk #define SFF_NO_ERROR 0x1 90*45916cd2Sjpk 91*45916cd2Sjpk #define ALLOC_BY_NONE -1 92*45916cd2Sjpk #define CHECK_DRANGE 1 93*45916cd2Sjpk #define CHECK_URANGE 2 94*45916cd2Sjpk #define CHECK_ZLABEL 3 957c478bd9Sstevel@tonic-gate 967c478bd9Sstevel@tonic-gate extern void audit_allocate_list(char *); 977c478bd9Sstevel@tonic-gate extern void audit_allocate_device(char *); 987c478bd9Sstevel@tonic-gate 99*45916cd2Sjpk extern int system_labeled; 1007c478bd9Sstevel@tonic-gate extern char *newenv[]; 1017c478bd9Sstevel@tonic-gate 102*45916cd2Sjpk struct state_file { 103*45916cd2Sjpk int sf_flags; 104*45916cd2Sjpk char sf_path[MAXPATHLEN]; 105*45916cd2Sjpk }; 106*45916cd2Sjpk 107*45916cd2Sjpk struct file_info { 108*45916cd2Sjpk struct stat fi_stat; 109*45916cd2Sjpk char *fi_message; 110*45916cd2Sjpk }; 111*45916cd2Sjpk 112*45916cd2Sjpk struct zone_path { 113*45916cd2Sjpk int count; 114*45916cd2Sjpk char **path; 115*45916cd2Sjpk }; 116*45916cd2Sjpk 117*45916cd2Sjpk struct devnames { 118*45916cd2Sjpk char **dnames; 119*45916cd2Sjpk }; 120*45916cd2Sjpk 121*45916cd2Sjpk static int _dev_file_name(struct state_file *, devmap_t *); 122*45916cd2Sjpk static int lock_dev(char *); 123*45916cd2Sjpk static int _check_label(devalloc_t *, char *, uid_t, int); 124*45916cd2Sjpk static int create_znode(char *, struct zone_path *, devmap_t *); 125*45916cd2Sjpk static int remove_znode(char *, devmap_t *); 126*45916cd2Sjpk static int update_device(char **, char *, int); 127*45916cd2Sjpk 1287c478bd9Sstevel@tonic-gate /* 129*45916cd2Sjpk * checks if the invoking user is local to the device 1307c478bd9Sstevel@tonic-gate */ 131*45916cd2Sjpk /*ARGSUSED*/ 132*45916cd2Sjpk int 133*45916cd2Sjpk _is_local(uid_t uid) 1347c478bd9Sstevel@tonic-gate { 135*45916cd2Sjpk struct stat statbuf; 1367c478bd9Sstevel@tonic-gate 137*45916cd2Sjpk if (stat(LOCALDEVICE, &statbuf) == 0 && 138*45916cd2Sjpk statbuf.st_uid == uid) 1397c478bd9Sstevel@tonic-gate return (1); 140*45916cd2Sjpk 1417c478bd9Sstevel@tonic-gate return (0); 1427c478bd9Sstevel@tonic-gate } 1437c478bd9Sstevel@tonic-gate 144*45916cd2Sjpk /* 145*45916cd2Sjpk * Checks if the user with the specified uid has the specified authorization 146*45916cd2Sjpk */ 147*45916cd2Sjpk int 148*45916cd2Sjpk _is_authorized(char *auths, uid_t uid) 1497c478bd9Sstevel@tonic-gate { 150*45916cd2Sjpk char *dcp, *authlist, *lasts; 151*45916cd2Sjpk char pw_buf[NSS_BUFLEN_PASSWD]; 152*45916cd2Sjpk struct passwd pw_ent; 1537c478bd9Sstevel@tonic-gate 154*45916cd2Sjpk /* 155*45916cd2Sjpk * first, the easy cases 156*45916cd2Sjpk */ 157*45916cd2Sjpk if (strcmp(auths, "@") == 0) 158*45916cd2Sjpk return (1); 159*45916cd2Sjpk if (strcmp(auths, "*") == 0) 160*45916cd2Sjpk return (ALLOC_BY_NONE); 161*45916cd2Sjpk if (getpwuid_r(uid, &pw_ent, pw_buf, sizeof (pw_buf)) == NULL) 162*45916cd2Sjpk return (0); 163*45916cd2Sjpk if (strpbrk(auths, DEVICE_AUTH_SEPARATOR) == NULL) 164*45916cd2Sjpk return (chkauthattr(auths, pw_ent.pw_name)); 165*45916cd2Sjpk authlist = strdup(auths); 166*45916cd2Sjpk if (authlist == NULL) 167*45916cd2Sjpk return (0); 168*45916cd2Sjpk for (dcp = authlist; 169*45916cd2Sjpk (dcp = strtok_r(dcp, DEVICE_AUTH_SEPARATOR, &lasts)) != NULL; 170*45916cd2Sjpk dcp = NULL) { 171*45916cd2Sjpk if (chkauthattr(dcp, pw_ent.pw_name)) 172*45916cd2Sjpk break; 173*45916cd2Sjpk } 174*45916cd2Sjpk free(authlist); 1757c478bd9Sstevel@tonic-gate 176*45916cd2Sjpk return (dcp != NULL); 1777c478bd9Sstevel@tonic-gate } 178*45916cd2Sjpk 179*45916cd2Sjpk /* 180*45916cd2Sjpk * Checks if the specified user has authorization for the device 181*45916cd2Sjpk */ 182*45916cd2Sjpk int 183*45916cd2Sjpk _is_dev_authorized(devalloc_t *da, uid_t uid) 184*45916cd2Sjpk { 185*45916cd2Sjpk int ares; 186*45916cd2Sjpk char *auth_list, *dcp, *subauth = NULL; 187*45916cd2Sjpk 188*45916cd2Sjpk auth_list = da->da_devauth; 189*45916cd2Sjpk if (auth_list == NULL) 190*45916cd2Sjpk return (0); 191*45916cd2Sjpk dcp = strpbrk(auth_list, KV_TOKEN_DELIMIT); 192*45916cd2Sjpk if (dcp == NULL) 193*45916cd2Sjpk return (_is_authorized(auth_list, uid)); 194*45916cd2Sjpk if (_is_local(uid)) { 195*45916cd2Sjpk /* the local authorization is before the separator */ 196*45916cd2Sjpk ares = dcp - auth_list; 197*45916cd2Sjpk subauth = malloc(ares + 1); 198*45916cd2Sjpk if (subauth == NULL) 199*45916cd2Sjpk return (0); 200*45916cd2Sjpk (void) strlcpy(subauth, auth_list, (ares + 1)); 201*45916cd2Sjpk auth_list = subauth; 202*45916cd2Sjpk } else 203*45916cd2Sjpk auth_list = dcp + 1; 204*45916cd2Sjpk ares = _is_authorized(auth_list, uid); 205*45916cd2Sjpk if (subauth != NULL) 206*45916cd2Sjpk free(subauth); 207*45916cd2Sjpk 208*45916cd2Sjpk return (ares); 2097c478bd9Sstevel@tonic-gate } 210*45916cd2Sjpk 211*45916cd2Sjpk int 212*45916cd2Sjpk check_devs(devmap_t *dm) 213*45916cd2Sjpk { 214*45916cd2Sjpk int status = 0; 215*45916cd2Sjpk char **file; 216*45916cd2Sjpk 217*45916cd2Sjpk if (dm->dmap_devarray == NULL) 218*45916cd2Sjpk return (NODMAPERR); 219*45916cd2Sjpk for (file = dm->dmap_devarray; *file != NULL; file++) { 220*45916cd2Sjpk if ((status = access(*file, F_OK)) == -1) { 221*45916cd2Sjpk dprintf("Unable to access file %s\n", *file); 222*45916cd2Sjpk break; 223*45916cd2Sjpk } 224*45916cd2Sjpk } 225*45916cd2Sjpk 226*45916cd2Sjpk return (status); 227*45916cd2Sjpk } 228*45916cd2Sjpk 229*45916cd2Sjpk int 230*45916cd2Sjpk print_da_defs(da_defs_t *da_defs) 231*45916cd2Sjpk { 232*45916cd2Sjpk char optbuf[BUFSIZ]; 233*45916cd2Sjpk char *p = NULL; 234*45916cd2Sjpk 235*45916cd2Sjpk if (da_defs->devopts == NULL) { 236*45916cd2Sjpk dprintf("No default attributes for %s\n", da_defs->devtype); 237*45916cd2Sjpk return (DEFATTRSERR); 238*45916cd2Sjpk } 239*45916cd2Sjpk (void) printf("dev_type=%s\n", da_defs->devtype); 240*45916cd2Sjpk if (_kva2str(da_defs->devopts, optbuf, sizeof (optbuf), KV_ASSIGN, 241*45916cd2Sjpk KV_TOKEN_DELIMIT) == 0) { 242*45916cd2Sjpk if (p = rindex(optbuf, ':')) 243*45916cd2Sjpk *p = '\0'; 244*45916cd2Sjpk (void) printf("\t%s\n", optbuf); 245*45916cd2Sjpk } 246*45916cd2Sjpk 2477c478bd9Sstevel@tonic-gate return (0); 2487c478bd9Sstevel@tonic-gate } 2497c478bd9Sstevel@tonic-gate 250*45916cd2Sjpk void 251*45916cd2Sjpk print_dev_attrs(int optflag, devalloc_t *da, devmap_t *dm, 252*45916cd2Sjpk struct file_info *fip) 2537c478bd9Sstevel@tonic-gate { 254*45916cd2Sjpk char *p = NULL; 255*45916cd2Sjpk char optbuf[BUFSIZ]; 2567c478bd9Sstevel@tonic-gate 257*45916cd2Sjpk (void) printf("device=%s%s", dm->dmap_devname, KV_DELIMITER); 258*45916cd2Sjpk (void) printf("type=%s%s", dm->dmap_devtype, KV_DELIMITER); 259*45916cd2Sjpk (void) printf("auths=%s%s", 260*45916cd2Sjpk (da->da_devauth ? da->da_devauth : ""), KV_DELIMITER); 261*45916cd2Sjpk (void) printf("clean=%s%s", 262*45916cd2Sjpk (da->da_devexec ? da->da_devexec : ""), KV_DELIMITER); 263*45916cd2Sjpk if (da->da_devopts != NULL) { 264*45916cd2Sjpk if (_kva2str(da->da_devopts, optbuf, sizeof (optbuf), 265*45916cd2Sjpk KV_ASSIGN, KV_TOKEN_DELIMIT) == 0) { 266*45916cd2Sjpk if (p = rindex(optbuf, ':')) 267*45916cd2Sjpk *p = '\0'; 268*45916cd2Sjpk (void) printf("%s", optbuf); 269*45916cd2Sjpk } 270*45916cd2Sjpk } 271*45916cd2Sjpk (void) printf("%s", KV_DELIMITER); 272*45916cd2Sjpk if (optflag & WINDOWING) { 273*45916cd2Sjpk if (DEV_INVALID(fip->fi_stat)) 274*45916cd2Sjpk (void) printf("owner=/INVALID:%s%s", fip->fi_message, 275*45916cd2Sjpk KV_DELIMITER); 276*45916cd2Sjpk else if (DEV_ERRORED(fip->fi_stat)) 277*45916cd2Sjpk (void) printf("owner=/ERROR%s", KV_DELIMITER); 278*45916cd2Sjpk else if (!DEV_ALLOCATED(fip->fi_stat)) 279*45916cd2Sjpk (void) printf("owner=/FREE%s", KV_DELIMITER); 280*45916cd2Sjpk else 281*45916cd2Sjpk (void) printf("owner=%ld%s", fip->fi_stat.st_uid, 282*45916cd2Sjpk KV_DELIMITER); 283*45916cd2Sjpk } 284*45916cd2Sjpk (void) printf("files=%s", dm->dmap_devlist); 285*45916cd2Sjpk (void) printf("\n"); 286*45916cd2Sjpk } 287*45916cd2Sjpk 288*45916cd2Sjpk void 289*45916cd2Sjpk print_dev(devmap_t *dm) 290*45916cd2Sjpk { 291*45916cd2Sjpk char **file; 292*45916cd2Sjpk 293*45916cd2Sjpk (void) printf(gettext("device: %s "), dm->dmap_devname); 294*45916cd2Sjpk (void) printf(gettext("type: %s "), dm->dmap_devtype); 2957c478bd9Sstevel@tonic-gate (void) printf(gettext("files:")); 296*45916cd2Sjpk file = dm->dmap_devarray; 297*45916cd2Sjpk if (file != NULL) { 298*45916cd2Sjpk for (; *file != NULL; file++) 299*45916cd2Sjpk (void) printf(" %s", *file); 3007c478bd9Sstevel@tonic-gate } 3017c478bd9Sstevel@tonic-gate (void) printf("\n"); 3027c478bd9Sstevel@tonic-gate } 3037c478bd9Sstevel@tonic-gate 304*45916cd2Sjpk /* ARGSUSED */ 305*45916cd2Sjpk int 306*45916cd2Sjpk _list_device(int optflag, uid_t uid, devalloc_t *da, char *zonename) 3077c478bd9Sstevel@tonic-gate { 308*45916cd2Sjpk int bytes = 0; 309*45916cd2Sjpk int error = 0; 310*45916cd2Sjpk int is_authorized = 0; 311*45916cd2Sjpk char *fname = NULL; 3127c478bd9Sstevel@tonic-gate char file_name[MAXPATHLEN]; 313*45916cd2Sjpk devmap_t *dm; 314*45916cd2Sjpk struct file_info fi; 315*45916cd2Sjpk struct state_file sf; 3167c478bd9Sstevel@tonic-gate 317*45916cd2Sjpk setdmapent(); 318*45916cd2Sjpk if ((dm = getdmapnam(da->da_devname)) == NULL) { 319*45916cd2Sjpk enddmapent(); 320*45916cd2Sjpk dprintf("Unable to find %s in the maps database\n", 321*45916cd2Sjpk da->da_devname); 322*45916cd2Sjpk return (NODMAPERR); 3237c478bd9Sstevel@tonic-gate } 324*45916cd2Sjpk enddmapent(); 325*45916cd2Sjpk if (system_labeled) { 326*45916cd2Sjpk if ((error = _dev_file_name(&sf, dm)) != 0) { 327*45916cd2Sjpk freedmapent(dm); 328*45916cd2Sjpk dprintf("Unable to find %s device files\n", 329*45916cd2Sjpk da->da_devname); 330*45916cd2Sjpk error = NODMAPERR; 331*45916cd2Sjpk goto out; 3327c478bd9Sstevel@tonic-gate } 333*45916cd2Sjpk fname = sf.sf_path; 334*45916cd2Sjpk } else { 335*45916cd2Sjpk bytes = snprintf(file_name, MAXPATHLEN, "%s/%s", DAC_DIR, 336*45916cd2Sjpk da->da_devname); 337*45916cd2Sjpk if (bytes <= 0) { 338*45916cd2Sjpk error = DEVNAMEERR; 339*45916cd2Sjpk goto out; 340*45916cd2Sjpk } else if (bytes >= MAXPATHLEN) { 341*45916cd2Sjpk dprintf("device name %s is too long.\n", 342*45916cd2Sjpk da->da_devname); 343*45916cd2Sjpk error = DEVLONGERR; 344*45916cd2Sjpk goto out; 3457c478bd9Sstevel@tonic-gate } 346*45916cd2Sjpk fname = file_name; 347*45916cd2Sjpk } 348*45916cd2Sjpk if (stat(fname, &fi.fi_stat) != 0) { 349*45916cd2Sjpk dprintf("Unable to stat %s\n", fname); 3507c478bd9Sstevel@tonic-gate dperror("Error:"); 351*45916cd2Sjpk error = DACACCERR; 352*45916cd2Sjpk goto out; 353*45916cd2Sjpk } 354*45916cd2Sjpk if (optflag & USERID) 355*45916cd2Sjpk is_authorized = 1; 356*45916cd2Sjpk else 357*45916cd2Sjpk is_authorized = _is_dev_authorized(da, uid); 358*45916cd2Sjpk if (optflag & LISTFREE) { /* list_devices -n */ 359*45916cd2Sjpk /* 360*45916cd2Sjpk * list all free devices 361*45916cd2Sjpk */ 362*45916cd2Sjpk if (DEV_ALLOCATED(fi.fi_stat)) { 363*45916cd2Sjpk error = PREALLOCERR; 364*45916cd2Sjpk goto out; 365*45916cd2Sjpk } 366*45916cd2Sjpk if (system_labeled) { 367*45916cd2Sjpk /* 368*45916cd2Sjpk * for this free device, check if - 369*45916cd2Sjpk * 1. user has authorization to allocate 370*45916cd2Sjpk * 2. the zone label is within the label range of the 371*45916cd2Sjpk * device 372*45916cd2Sjpk */ 373*45916cd2Sjpk if (is_authorized == ALLOC_BY_NONE) { 374*45916cd2Sjpk error = DAUTHERR; 375*45916cd2Sjpk goto out; 376*45916cd2Sjpk } else if (is_authorized == 0) { 377*45916cd2Sjpk error = UAUTHERR; 378*45916cd2Sjpk goto out; 379*45916cd2Sjpk } 380*45916cd2Sjpk if (_check_label(da, zonename, uid, 381*45916cd2Sjpk CHECK_DRANGE) != 0) { 382*45916cd2Sjpk error = LABELRNGERR; 383*45916cd2Sjpk goto out; 384*45916cd2Sjpk } 385*45916cd2Sjpk } 386*45916cd2Sjpk } else if (optflag & LISTALLOC) { /* list_devices -u */ 387*45916cd2Sjpk /* 388*45916cd2Sjpk * list all allocated devices 389*45916cd2Sjpk */ 390*45916cd2Sjpk if (!DEV_ALLOCATED(fi.fi_stat)) { 391*45916cd2Sjpk error = DEVNALLOCERR; 392*45916cd2Sjpk goto out; 393*45916cd2Sjpk } 394*45916cd2Sjpk if (fi.fi_stat.st_uid != uid) { 395*45916cd2Sjpk error = DEVSTATEERR; 396*45916cd2Sjpk goto out; 397*45916cd2Sjpk } 398*45916cd2Sjpk if (system_labeled) { 399*45916cd2Sjpk /* 400*45916cd2Sjpk * check if the zone label equals the label at which 401*45916cd2Sjpk * the device is allocated. 402*45916cd2Sjpk */ 403*45916cd2Sjpk if (_check_label(da, zonename, uid, 404*45916cd2Sjpk CHECK_ZLABEL) != 0) { 405*45916cd2Sjpk error = LABELRNGERR; 406*45916cd2Sjpk goto out; 407*45916cd2Sjpk } 408*45916cd2Sjpk } 409*45916cd2Sjpk } else if (optflag & LISTALL) { /* list_devices -l */ 410*45916cd2Sjpk /* 411*45916cd2Sjpk * list all devices - free and allocated - available 412*45916cd2Sjpk */ 413*45916cd2Sjpk if (DEV_ALLOCATED(fi.fi_stat)) { 414*45916cd2Sjpk if (optflag & WINDOWING && 415*45916cd2Sjpk (is_authorized == ALLOC_BY_NONE)) { 416*45916cd2Sjpk /* 417*45916cd2Sjpk * don't complain if we're here for the GUI. 418*45916cd2Sjpk */ 419*45916cd2Sjpk error = 0; 420*45916cd2Sjpk } else if (fi.fi_stat.st_uid != uid) { 421*45916cd2Sjpk if (!(optflag & WINDOWING)) { 422*45916cd2Sjpk error = ALLOCUERR; 423*45916cd2Sjpk goto out; 424*45916cd2Sjpk } 425*45916cd2Sjpk } 426*45916cd2Sjpk if (system_labeled && !(optflag & WINDOWING)) { 427*45916cd2Sjpk /* 428*45916cd2Sjpk * if we're not displaying in the GUI, 429*45916cd2Sjpk * check if the zone label equals the label 430*45916cd2Sjpk * at which the device is allocated. 431*45916cd2Sjpk */ 432*45916cd2Sjpk if (_check_label(da, zonename, uid, 433*45916cd2Sjpk CHECK_ZLABEL) != 0) { 434*45916cd2Sjpk error = LABELRNGERR; 435*45916cd2Sjpk goto out; 436*45916cd2Sjpk } 437*45916cd2Sjpk } 438*45916cd2Sjpk } else if (system_labeled && !(optflag & WINDOWING)) { 439*45916cd2Sjpk /* 440*45916cd2Sjpk * if we're not displaying in the GUI, 441*45916cd2Sjpk * for this free device, check if - 442*45916cd2Sjpk * 1. user has authorization to allocate 443*45916cd2Sjpk * 2. the zone label is within the label range of the 444*45916cd2Sjpk * device 445*45916cd2Sjpk */ 446*45916cd2Sjpk if (is_authorized == ALLOC_BY_NONE) { 447*45916cd2Sjpk error = DAUTHERR; 448*45916cd2Sjpk goto out; 449*45916cd2Sjpk } else if (is_authorized == 0) { 450*45916cd2Sjpk error = UAUTHERR; 451*45916cd2Sjpk goto out; 452*45916cd2Sjpk } 453*45916cd2Sjpk if (_check_label(da, zonename, uid, 454*45916cd2Sjpk CHECK_DRANGE) != 0) { 455*45916cd2Sjpk error = LABELRNGERR; 456*45916cd2Sjpk goto out; 457*45916cd2Sjpk } 458*45916cd2Sjpk } 459*45916cd2Sjpk } 460*45916cd2Sjpk if (system_labeled && DEV_ERRORED(fi.fi_stat) && !(optflag & LISTALL)) { 461*45916cd2Sjpk error = DEVSTATEERR; 462*45916cd2Sjpk goto out; 463*45916cd2Sjpk } 464*45916cd2Sjpk if (check_devs(dm) == -1) { 465*45916cd2Sjpk error = DSPMISSERR; 466*45916cd2Sjpk goto out; 467*45916cd2Sjpk } 468*45916cd2Sjpk if (optflag & LISTATTRS) 469*45916cd2Sjpk print_dev_attrs(optflag, da, dm, &fi); 470*45916cd2Sjpk else 471*45916cd2Sjpk print_dev(dm); 472*45916cd2Sjpk 473*45916cd2Sjpk error = 0; 474*45916cd2Sjpk 475*45916cd2Sjpk out: 476*45916cd2Sjpk freedmapent(dm); 477*45916cd2Sjpk return (error); 4787c478bd9Sstevel@tonic-gate } 4797c478bd9Sstevel@tonic-gate 480*45916cd2Sjpk /* ARGSUSED */ 481*45916cd2Sjpk int 482*45916cd2Sjpk list_devices(int optflag, uid_t uid, char *device, char *zonename) 483*45916cd2Sjpk { 484*45916cd2Sjpk int error = 0; 485*45916cd2Sjpk da_defs_t *da_defs; 486*45916cd2Sjpk devalloc_t *da; 4877c478bd9Sstevel@tonic-gate 488*45916cd2Sjpk if (system_labeled && optflag & WINDOWING && !(optflag & LISTATTRS)) { 489*45916cd2Sjpk /* 490*45916cd2Sjpk * Private interface for GUI. 491*45916cd2Sjpk */ 492*45916cd2Sjpk (void) lock_dev(NULL); 493*45916cd2Sjpk (void) puts(DA_DB_LOCK); 4947c478bd9Sstevel@tonic-gate return (0); 4957c478bd9Sstevel@tonic-gate } 496*45916cd2Sjpk if (optflag & USERID) { 497*45916cd2Sjpk /* 498*45916cd2Sjpk * we need device.revoke to list someone else's devices 499*45916cd2Sjpk */ 500*45916cd2Sjpk if (!_is_authorized(DEVICE_REVOKE_AUTH, getuid())) 501*45916cd2Sjpk return (UAUTHERR); 502*45916cd2Sjpk } 503*45916cd2Sjpk if (system_labeled) { 504*45916cd2Sjpk if (!(optflag & USERID) && 505*45916cd2Sjpk !_is_authorized(DEFAULT_DEV_ALLOC_AUTH, uid)) 506*45916cd2Sjpk /* 507*45916cd2Sjpk * we need device.allocate to list our devices 508*45916cd2Sjpk */ 509*45916cd2Sjpk return (UAUTHERR); 510*45916cd2Sjpk if (optflag & LISTDEFS) { 511*45916cd2Sjpk /* 512*45916cd2Sjpk * list default attrs from devalloc_defaults 513*45916cd2Sjpk */ 514*45916cd2Sjpk setdadefent(); 515*45916cd2Sjpk if (device) { 516*45916cd2Sjpk /* 517*45916cd2Sjpk * list default attrs for this device type 518*45916cd2Sjpk */ 519*45916cd2Sjpk da_defs = getdadeftype(device); 520*45916cd2Sjpk if (da_defs == NULL) { 521*45916cd2Sjpk enddadefent(); 522*45916cd2Sjpk dprintf("No default attributes for " 523*45916cd2Sjpk "%s\n", device); 524*45916cd2Sjpk return (DEFATTRSERR); 525*45916cd2Sjpk } 526*45916cd2Sjpk error = print_da_defs(da_defs); 527*45916cd2Sjpk freedadefent(da_defs); 528*45916cd2Sjpk } else { 529*45916cd2Sjpk /* 530*45916cd2Sjpk * list everything in devalloc_defaults 531*45916cd2Sjpk */ 532*45916cd2Sjpk while ((da_defs = getdadefent()) != NULL) { 533*45916cd2Sjpk (void) print_da_defs(da_defs); 534*45916cd2Sjpk freedadefent(da_defs); 535*45916cd2Sjpk } 536*45916cd2Sjpk } 537*45916cd2Sjpk enddadefent(); 538*45916cd2Sjpk return (error); 539*45916cd2Sjpk } 5407c478bd9Sstevel@tonic-gate } 5417c478bd9Sstevel@tonic-gate setdaent(); 5427c478bd9Sstevel@tonic-gate if (device) { 543*45916cd2Sjpk /* 544*45916cd2Sjpk * list this device 545*45916cd2Sjpk */ 546*45916cd2Sjpk if ((da = getdanam(device)) == NULL) { 5477c478bd9Sstevel@tonic-gate enddaent(); 548*45916cd2Sjpk return (NODAERR); 549*45916cd2Sjpk } 550*45916cd2Sjpk error = _list_device(optflag, uid, da, zonename); 551*45916cd2Sjpk freedaent(da); 552*45916cd2Sjpk } else { 553*45916cd2Sjpk /* 554*45916cd2Sjpk * list all devices 555*45916cd2Sjpk */ 556*45916cd2Sjpk while ((da = getdaent()) != NULL) { 557*45916cd2Sjpk (void) _list_device(optflag, uid, da, zonename); 558*45916cd2Sjpk freedaent(da); 559*45916cd2Sjpk } 560*45916cd2Sjpk } 561*45916cd2Sjpk enddaent(); 562*45916cd2Sjpk 563*45916cd2Sjpk return (error); 5647c478bd9Sstevel@tonic-gate } 5657c478bd9Sstevel@tonic-gate 5667c478bd9Sstevel@tonic-gate /* 5677c478bd9Sstevel@tonic-gate * Set the DAC characteristics of the file. 5687c478bd9Sstevel@tonic-gate * This uses a fancy chmod() by setting a minimal ACL which sets the mode 5697c478bd9Sstevel@tonic-gate * and discards any existing ACL. 5707c478bd9Sstevel@tonic-gate */ 571*45916cd2Sjpk int 572*45916cd2Sjpk _newdac(char *file, uid_t owner, gid_t group, o_mode_t mode) 5737c478bd9Sstevel@tonic-gate { 5747c478bd9Sstevel@tonic-gate int err = 0; 5757c478bd9Sstevel@tonic-gate 576*45916cd2Sjpk if (mode == ALLOC_MODE) { 5777c478bd9Sstevel@tonic-gate if (chown(file, owner, group) == -1) { 578*45916cd2Sjpk dperror("newdac: unable to chown"); 579*45916cd2Sjpk err = CHOWNERR; 580*45916cd2Sjpk } 581*45916cd2Sjpk } else do { 582*45916cd2Sjpk if (chown(file, owner, group) == -1) { 583*45916cd2Sjpk dperror("newdac: unable to chown"); 584*45916cd2Sjpk err = CHOWNERR; 5857c478bd9Sstevel@tonic-gate } 5867c478bd9Sstevel@tonic-gate } while (fdetach(file) == 0); 5877c478bd9Sstevel@tonic-gate 588*45916cd2Sjpk if (err) 589*45916cd2Sjpk return (err); 590*45916cd2Sjpk 591*45916cd2Sjpk if (strncmp(file, "/dev/", strlen("/dev/")) != 0) { 592*45916cd2Sjpk /* 593*45916cd2Sjpk * This could be a SunRay device that is in /tmp. 594*45916cd2Sjpk */ 595*45916cd2Sjpk if (chmod(file, mode) == -1) { 596*45916cd2Sjpk dperror("newdac: unable to chmod"); 597*45916cd2Sjpk err = SETACLERR; 598*45916cd2Sjpk } 599*45916cd2Sjpk } else { 600fa9e4066Sahrens err = acl_strip(file, owner, group, (mode_t)mode); 601*45916cd2Sjpk } 602fa9e4066Sahrens 603fa9e4066Sahrens if (err != 0) { 604*45916cd2Sjpk dperror("newdac: unable to setacl"); 605*45916cd2Sjpk err = SETACLERR; 6067c478bd9Sstevel@tonic-gate } 6077c478bd9Sstevel@tonic-gate 6087c478bd9Sstevel@tonic-gate return (err); 6097c478bd9Sstevel@tonic-gate } 6107c478bd9Sstevel@tonic-gate 6117c478bd9Sstevel@tonic-gate static int 6127c478bd9Sstevel@tonic-gate lock_dev(char *file) 6137c478bd9Sstevel@tonic-gate { 614*45916cd2Sjpk int lockfd = -1; 6157c478bd9Sstevel@tonic-gate 616*45916cd2Sjpk if ((file == NULL) || system_labeled) 617*45916cd2Sjpk file = DA_DEV_LOCK; 6187c478bd9Sstevel@tonic-gate dprintf("locking %s\n", file); 619*45916cd2Sjpk if ((lockfd = open(file, O_RDWR | O_CREAT, 0600)) == -1) { 620*45916cd2Sjpk dperror("lock_dev: cannot open lock file"); 621*45916cd2Sjpk return (DEVLKERR); 6227c478bd9Sstevel@tonic-gate } 623*45916cd2Sjpk if (lockf(lockfd, F_TLOCK, 0) == -1) { 624*45916cd2Sjpk dperror("lock_dev: cannot set lock"); 625*45916cd2Sjpk return (DEVLKERR); 6267c478bd9Sstevel@tonic-gate } 6277c478bd9Sstevel@tonic-gate 6287c478bd9Sstevel@tonic-gate return (0); 6297c478bd9Sstevel@tonic-gate } 6307c478bd9Sstevel@tonic-gate 631*45916cd2Sjpk int 632*45916cd2Sjpk mk_alloc(devmap_t *list, uid_t uid, struct zone_path *zpath) 6337c478bd9Sstevel@tonic-gate { 634*45916cd2Sjpk int i; 635*45916cd2Sjpk int error = 0; 636*45916cd2Sjpk char **file; 637*45916cd2Sjpk gid_t gid = getgid(); 638*45916cd2Sjpk mode_t mode = ALLOC_MODE; 6397c478bd9Sstevel@tonic-gate 640*45916cd2Sjpk file = list->dmap_devarray; 641*45916cd2Sjpk if (file == NULL) 642*45916cd2Sjpk return (NODMAPERR); 643*45916cd2Sjpk for (; *file != NULL; file++) { 644*45916cd2Sjpk dprintf("Allocating %s\n", *file); 645*45916cd2Sjpk if ((error = _newdac(*file, uid, gid, mode)) != 0) { 646*45916cd2Sjpk (void) _newdac(*file, ALLOC_ERRID, ALLOC_GID, 6477c478bd9Sstevel@tonic-gate ALLOC_ERR_MODE); 648*45916cd2Sjpk break; 649*45916cd2Sjpk } 650*45916cd2Sjpk } 651*45916cd2Sjpk if (system_labeled && zpath->count && (error == 0)) { 652*45916cd2Sjpk /* 653*45916cd2Sjpk * mark as allocated any new device nodes that we 654*45916cd2Sjpk * created in local zone 655*45916cd2Sjpk */ 656*45916cd2Sjpk for (i = 0; i < zpath->count; i++) { 657*45916cd2Sjpk dprintf("Allocating %s\n", zpath->path[i]); 658*45916cd2Sjpk if ((error = _newdac(zpath->path[i], uid, gid, 659*45916cd2Sjpk mode)) != 0) { 660*45916cd2Sjpk (void) _newdac(zpath->path[i], ALLOC_ERRID, 661*45916cd2Sjpk ALLOC_GID, ALLOC_ERR_MODE); 662*45916cd2Sjpk break; 663*45916cd2Sjpk } 664*45916cd2Sjpk } 6657c478bd9Sstevel@tonic-gate } 6667c478bd9Sstevel@tonic-gate 667*45916cd2Sjpk return (error); 6687c478bd9Sstevel@tonic-gate } 6697c478bd9Sstevel@tonic-gate 6707c478bd9Sstevel@tonic-gate /* 6717c478bd9Sstevel@tonic-gate * mk_revoke() is used instead of system("/usr/sbin/fuser -k file") 6727c478bd9Sstevel@tonic-gate * because "/usr/sbin/fuser -k file" kills all processes 6737c478bd9Sstevel@tonic-gate * working with the file, even "vold" (bug #4095152). 6747c478bd9Sstevel@tonic-gate */ 675*45916cd2Sjpk int 676*45916cd2Sjpk mk_revoke(int optflag, char *file) 6777c478bd9Sstevel@tonic-gate { 6787c478bd9Sstevel@tonic-gate int r = 0, p[2], fp, lock; 679*45916cd2Sjpk int fuserpid; 680*45916cd2Sjpk char buf[MAXPATHLEN]; 6817c478bd9Sstevel@tonic-gate FILE *ptr; 682*45916cd2Sjpk pid_t c_pid; 6837c478bd9Sstevel@tonic-gate prpsinfo_t info; 6847c478bd9Sstevel@tonic-gate 6857c478bd9Sstevel@tonic-gate (void) strcpy(buf, PROCFS); 6867c478bd9Sstevel@tonic-gate /* 687*45916cd2Sjpk * vfork() and execl() just to make the same output 6887c478bd9Sstevel@tonic-gate * as before fixing of bug #4095152. 6897c478bd9Sstevel@tonic-gate * The problem is that the "fuser" command prints 6907c478bd9Sstevel@tonic-gate * one part of output into stderr and another into stdout, 6917c478bd9Sstevel@tonic-gate * but user sees them mixed. Of course, better to change "fuser" 6927c478bd9Sstevel@tonic-gate * or to intercept and not to print its output. 6937c478bd9Sstevel@tonic-gate */ 694*45916cd2Sjpk if (!(optflag & SILENT)) { 6957c478bd9Sstevel@tonic-gate c_pid = vfork(); 6967c478bd9Sstevel@tonic-gate if (c_pid == -1) 6977c478bd9Sstevel@tonic-gate return (-1); 6987c478bd9Sstevel@tonic-gate if (c_pid == 0) { 6997c478bd9Sstevel@tonic-gate dprintf("first exec fuser %s\n", file); 700*45916cd2Sjpk (void) execl("/usr/sbin/fuser", "fuser", file, NULL); 7017c478bd9Sstevel@tonic-gate dperror("first exec fuser"); 7027c478bd9Sstevel@tonic-gate _exit(1); 7037c478bd9Sstevel@tonic-gate } 7047c478bd9Sstevel@tonic-gate 7057c478bd9Sstevel@tonic-gate (void) waitpid(c_pid, &lock, 0); 7067c478bd9Sstevel@tonic-gate dprintf("exit status %x\n", lock); 7077c478bd9Sstevel@tonic-gate if (WEXITSTATUS(lock) != 0) 7087c478bd9Sstevel@tonic-gate return (-1); 7097c478bd9Sstevel@tonic-gate } 710*45916cd2Sjpk dprintf("first continuing c_pid=%d\n", (int)c_pid); 7117c478bd9Sstevel@tonic-gate if (pipe(p)) { 7127c478bd9Sstevel@tonic-gate dperror("pipe"); 7137c478bd9Sstevel@tonic-gate return (-1); 7147c478bd9Sstevel@tonic-gate } 715*45916cd2Sjpk /* vfork() and execl() to catch output and to process it */ 7167c478bd9Sstevel@tonic-gate c_pid = vfork(); 7177c478bd9Sstevel@tonic-gate if (c_pid == -1) { 7187c478bd9Sstevel@tonic-gate dperror("second vfork"); 7197c478bd9Sstevel@tonic-gate return (-1); 7207c478bd9Sstevel@tonic-gate } 721*45916cd2Sjpk dprintf("second continuing c_pid=%d\n", (int)c_pid); 7227c478bd9Sstevel@tonic-gate if (c_pid == 0) { 7237c478bd9Sstevel@tonic-gate (void) close(p[0]); 7247c478bd9Sstevel@tonic-gate (void) close(1); 7257c478bd9Sstevel@tonic-gate (void) fcntl(p[1], F_DUPFD, 1); 7267c478bd9Sstevel@tonic-gate (void) close(p[1]); 7277c478bd9Sstevel@tonic-gate (void) close(2); 7287c478bd9Sstevel@tonic-gate dprintf("second exec fuser %s\n", file); 729*45916cd2Sjpk (void) execl("/usr/sbin/fuser", "fuser", file, NULL); 7307c478bd9Sstevel@tonic-gate dperror("second exec fuser"); 7317c478bd9Sstevel@tonic-gate _exit(1); 7327c478bd9Sstevel@tonic-gate } 7337c478bd9Sstevel@tonic-gate (void) close(p[1]); 7347c478bd9Sstevel@tonic-gate if ((ptr = fdopen(p[0], "r")) != NULL) { 7357c478bd9Sstevel@tonic-gate while (!feof(ptr)) { 736*45916cd2Sjpk if (fscanf(ptr, "%d", &fuserpid) > 0) { 737*45916cd2Sjpk (void) sprintf(buf + strlen(PROCFS), "%d", 738*45916cd2Sjpk fuserpid); 7397c478bd9Sstevel@tonic-gate if ((fp = open(buf, O_RDONLY)) == -1) { 7407c478bd9Sstevel@tonic-gate dperror(buf); 7417c478bd9Sstevel@tonic-gate continue; 7427c478bd9Sstevel@tonic-gate } 743*45916cd2Sjpk if (ioctl(fp, PIOCPSINFO, 744*45916cd2Sjpk (char *)&info) == -1) { 745*45916cd2Sjpk dprintf("%d psinfo failed", fuserpid); 7467c478bd9Sstevel@tonic-gate dperror(""); 7477c478bd9Sstevel@tonic-gate (void) close(fp); 7487c478bd9Sstevel@tonic-gate continue; 7497c478bd9Sstevel@tonic-gate } 7507c478bd9Sstevel@tonic-gate (void) close(fp); 7517c478bd9Sstevel@tonic-gate if (strcmp(info.pr_fname, "vold") == NULL) { 752*45916cd2Sjpk dprintf("%d matched vold name\n", 753*45916cd2Sjpk fuserpid); 7547c478bd9Sstevel@tonic-gate continue; 7557c478bd9Sstevel@tonic-gate } 7567c478bd9Sstevel@tonic-gate dprintf("killing %s", info.pr_fname); 757*45916cd2Sjpk dprintf("(%d)\n", fuserpid); 758*45916cd2Sjpk if ((r = 759*45916cd2Sjpk kill((pid_t)fuserpid, SIGKILL)) == -1) { 760*45916cd2Sjpk dprintf("kill %d", fuserpid); 7617c478bd9Sstevel@tonic-gate dperror(""); 7627c478bd9Sstevel@tonic-gate break; 7637c478bd9Sstevel@tonic-gate } 7647c478bd9Sstevel@tonic-gate } 7657c478bd9Sstevel@tonic-gate } 7667c478bd9Sstevel@tonic-gate } else { 767*45916cd2Sjpk dperror("fdopen(p[0], r)"); 7687c478bd9Sstevel@tonic-gate r = -1; 7697c478bd9Sstevel@tonic-gate } 7707c478bd9Sstevel@tonic-gate (void) fclose(ptr); 771*45916cd2Sjpk 7727c478bd9Sstevel@tonic-gate return (r); 7737c478bd9Sstevel@tonic-gate } 7747c478bd9Sstevel@tonic-gate 775*45916cd2Sjpk int 776*45916cd2Sjpk mk_unalloc(int optflag, devmap_t *list) 7777c478bd9Sstevel@tonic-gate { 7787c478bd9Sstevel@tonic-gate int error = 0; 7797c478bd9Sstevel@tonic-gate int status; 780*45916cd2Sjpk char **file; 7817c478bd9Sstevel@tonic-gate 782*45916cd2Sjpk audit_allocate_list(list->dmap_devlist); 783*45916cd2Sjpk file = list->dmap_devarray; 784*45916cd2Sjpk if (file == NULL) 785*45916cd2Sjpk return (NODMAPERR); 786*45916cd2Sjpk for (; *file != NULL; file++) { 787*45916cd2Sjpk dprintf("Deallocating %s\n", *file); 788*45916cd2Sjpk if (mk_revoke(optflag, *file) < 0) { 789*45916cd2Sjpk dprintf("mk_unalloc: unable to revoke %s\n", *file); 790*45916cd2Sjpk dperror(""); 791*45916cd2Sjpk error = CNTFRCERR; 792*45916cd2Sjpk } 793*45916cd2Sjpk status = _newdac(*file, ALLOC_UID, ALLOC_GID, DEALLOC_MODE); 794*45916cd2Sjpk if (error == 0) 795*45916cd2Sjpk error = status; 796*45916cd2Sjpk 797*45916cd2Sjpk } 798*45916cd2Sjpk 799*45916cd2Sjpk return (error); 800*45916cd2Sjpk } 801*45916cd2Sjpk 802*45916cd2Sjpk int 803*45916cd2Sjpk mk_error(devmap_t *list) 804*45916cd2Sjpk { 805*45916cd2Sjpk int status = 0; 806*45916cd2Sjpk char **file; 807*45916cd2Sjpk 808*45916cd2Sjpk audit_allocate_list(list->dmap_devlist); 809*45916cd2Sjpk file = list->dmap_devarray; 810*45916cd2Sjpk if (file == NULL) 811*45916cd2Sjpk return (NODMAPERR); 812*45916cd2Sjpk for (; *file != NULL; file++) { 813*45916cd2Sjpk dprintf("Putting %s in error state\n", *file); 814*45916cd2Sjpk status = _newdac(*file, ALLOC_ERRID, ALLOC_GID, ALLOC_ERR_MODE); 815*45916cd2Sjpk } 816*45916cd2Sjpk 817*45916cd2Sjpk return (status); 818*45916cd2Sjpk } 819*45916cd2Sjpk 820*45916cd2Sjpk int 821*45916cd2Sjpk exec_clean(int optflag, char *devname, char *path, uid_t uid, char *zonename, 822*45916cd2Sjpk char *clean_arg) 823*45916cd2Sjpk { 824*45916cd2Sjpk int c; 825*45916cd2Sjpk int status = 0, exit_status; 826*45916cd2Sjpk char *mode, *cmd, *wdwcmd, *zoneroot; 827*45916cd2Sjpk char *devzone = zonename; 828*45916cd2Sjpk char wdwpath[PATH_MAX]; 829*45916cd2Sjpk char zonepath[MAXPATHLEN]; 830*45916cd2Sjpk char title[100]; 831*45916cd2Sjpk char pw_buf[NSS_BUFLEN_PASSWD]; 832*45916cd2Sjpk struct passwd pw_ent; 833*45916cd2Sjpk 834*45916cd2Sjpk zonepath[0] = '\0'; 835*45916cd2Sjpk if (system_labeled) { 836*45916cd2Sjpk if ((zoneroot = getzonerootbyname(zonename)) == NULL) { 837*45916cd2Sjpk if (strcmp(clean_arg, ALLOC_CLEAN) == 0) { 838*45916cd2Sjpk return (-1); 839*45916cd2Sjpk } else if (optflag & FORCE) { 840*45916cd2Sjpk (void) strcpy(zonepath, "/"); 841*45916cd2Sjpk devzone = GLOBAL_ZONENAME; 842*45916cd2Sjpk } else { 843*45916cd2Sjpk dprintf("unable to get label for %s zone\n", 844*45916cd2Sjpk zonename); 845*45916cd2Sjpk return (-1); 846*45916cd2Sjpk } 847*45916cd2Sjpk } else { 848*45916cd2Sjpk (void) strcpy(zonepath, zoneroot); 849*45916cd2Sjpk free(zoneroot); 850*45916cd2Sjpk } 851*45916cd2Sjpk } 852*45916cd2Sjpk if (getpwuid_r(uid, &pw_ent, pw_buf, sizeof (pw_buf)) == NULL) 853*45916cd2Sjpk return (-1); 854*45916cd2Sjpk if (optflag & FORCE_ALL) 8557c478bd9Sstevel@tonic-gate mode = "-I"; 856*45916cd2Sjpk else if (optflag & FORCE) 8577c478bd9Sstevel@tonic-gate mode = "-f"; 8587c478bd9Sstevel@tonic-gate else 8597c478bd9Sstevel@tonic-gate mode = "-s"; 860*45916cd2Sjpk if (path == NULL) 861*45916cd2Sjpk return (0); 8627c478bd9Sstevel@tonic-gate if ((cmd = strrchr(path, '/')) == NULL) 8637c478bd9Sstevel@tonic-gate cmd = path; 8647c478bd9Sstevel@tonic-gate else 8657c478bd9Sstevel@tonic-gate cmd++; /* skip leading '/' */ 8667c478bd9Sstevel@tonic-gate c = vfork(); 8677c478bd9Sstevel@tonic-gate switch (c) { 8687c478bd9Sstevel@tonic-gate case -1: 8697c478bd9Sstevel@tonic-gate return (-1); 8707c478bd9Sstevel@tonic-gate case 0: 8717c478bd9Sstevel@tonic-gate (void) setuid(0); 872*45916cd2Sjpk if (system_labeled && (optflag & WINDOWING)) { 873*45916cd2Sjpk /* First try .windowing version of script */ 874*45916cd2Sjpk (void) strncpy(wdwpath, path, PATH_MAX); 875*45916cd2Sjpk (void) strncat(wdwpath, ".windowing", PATH_MAX); 876*45916cd2Sjpk if ((wdwcmd = strrchr(wdwpath, '/')) == NULL) 877*45916cd2Sjpk wdwcmd = wdwpath; 878*45916cd2Sjpk (void) execl(wdwpath, wdwcmd, mode, devname, clean_arg, 879*45916cd2Sjpk pw_ent.pw_name, devzone, zonepath, NULL); 880*45916cd2Sjpk /* If that failed, run regular version via dtterm */ 881*45916cd2Sjpk (void) snprintf(title, sizeof (title), 882*45916cd2Sjpk "Device %s for %s", 883*45916cd2Sjpk strcmp(clean_arg, ALLOC_CLEAN) == 0 ? 884*45916cd2Sjpk "allocation" : "deallocation", devname); 885*45916cd2Sjpk (void) execl("/usr/dt/bin/dtterm", "dtterm", 886*45916cd2Sjpk "-title", title, "-geometry", "x10+100+400", 887*45916cd2Sjpk "-e", "/etc/security/lib/wdwwrapper", 888*45916cd2Sjpk path, mode, devname, clean_arg, pw_ent.pw_name, 889*45916cd2Sjpk devzone, zonepath, NULL); 890*45916cd2Sjpk /* 891*45916cd2Sjpk * And if that failed, continue on to try 892*45916cd2Sjpk * running regular version directly. 893*45916cd2Sjpk */ 894*45916cd2Sjpk } 8957c478bd9Sstevel@tonic-gate dprintf("clean script: %s, ", path); 8967c478bd9Sstevel@tonic-gate dprintf("cmd=%s, ", cmd); 8977c478bd9Sstevel@tonic-gate dprintf("mode=%s, ", mode); 898*45916cd2Sjpk if (system_labeled) { 899*45916cd2Sjpk dprintf("devname=%s ", devname); 900*45916cd2Sjpk dprintf("zonename=%s ", devzone); 901*45916cd2Sjpk dprintf("zonepath=%s ", zonepath); 902*45916cd2Sjpk dprintf("username=%s\n", pw_ent.pw_name); 903*45916cd2Sjpk (void) execl(path, cmd, mode, devname, clean_arg, 904*45916cd2Sjpk pw_ent.pw_name, devzone, zonepath, NULL); 905*45916cd2Sjpk } else { 906*45916cd2Sjpk dprintf("devname=%s\n", devname); 907*45916cd2Sjpk (void) execle(path, cmd, mode, devname, NULL, newenv); 908*45916cd2Sjpk } 9097c478bd9Sstevel@tonic-gate dprintf("Unable to execute clean up script %s\n", path); 9107c478bd9Sstevel@tonic-gate dperror(""); 911*45916cd2Sjpk exit(CNTDEXECERR); 9127c478bd9Sstevel@tonic-gate default: 913*45916cd2Sjpk (void) waitpid(c, &status, 0); 914*45916cd2Sjpk dprintf("Child %d", c); 915*45916cd2Sjpk if (WIFEXITED(status)) { 916*45916cd2Sjpk exit_status = WEXITSTATUS(status); 917*45916cd2Sjpk dprintf(" exited, status: %d\n", exit_status); 918*45916cd2Sjpk return (exit_status); 919*45916cd2Sjpk } else if (WIFSIGNALED(status)) { 920*45916cd2Sjpk dprintf(" killed, signal %d\n", WTERMSIG(status)); 921*45916cd2Sjpk } else { 922*45916cd2Sjpk dprintf(": exit status %d\n", status); 923*45916cd2Sjpk } 9247c478bd9Sstevel@tonic-gate return (-1); 9257c478bd9Sstevel@tonic-gate } 9267c478bd9Sstevel@tonic-gate } 9277c478bd9Sstevel@tonic-gate 928*45916cd2Sjpk int 929*45916cd2Sjpk _deallocate_dev(int optflag, devalloc_t *da, devmap_t *dm_in, uid_t uid, 930*45916cd2Sjpk char *zonename) 9317c478bd9Sstevel@tonic-gate { 932*45916cd2Sjpk int bytes = 0; 9337c478bd9Sstevel@tonic-gate int error = 0; 934*45916cd2Sjpk int is_authorized = 0; 935*45916cd2Sjpk uid_t nuid; 936*45916cd2Sjpk char *fname = NULL; 937*45916cd2Sjpk char file_name[MAXPATHLEN]; 938*45916cd2Sjpk char *devzone = NULL; 939*45916cd2Sjpk devmap_t *dm = NULL, *dm_new = NULL; 940*45916cd2Sjpk struct stat stat_buf; 941*45916cd2Sjpk struct state_file sf; 9427c478bd9Sstevel@tonic-gate 943*45916cd2Sjpk if (dm_in == NULL) { 944*45916cd2Sjpk setdmapent(); 945*45916cd2Sjpk if ((dm_new = getdmapnam(da->da_devname)) == NULL) { 946*45916cd2Sjpk enddmapent(); 947*45916cd2Sjpk dprintf("Unable to find %s in device map database\n", 948*45916cd2Sjpk da->da_devname); 949*45916cd2Sjpk return (NODMAPERR); 950*45916cd2Sjpk } 951*45916cd2Sjpk enddmapent(); 952*45916cd2Sjpk dm = dm_new; 953*45916cd2Sjpk } else { 954*45916cd2Sjpk dm = dm_in; 955*45916cd2Sjpk } 956*45916cd2Sjpk if (system_labeled) { 957*45916cd2Sjpk if (_dev_file_name(&sf, dm) != 0) { 958*45916cd2Sjpk if (dm_new) 959*45916cd2Sjpk freedmapent(dm_new); 960*45916cd2Sjpk dprintf("Unable to find %s device files\n", 961*45916cd2Sjpk da->da_devname); 962*45916cd2Sjpk error = NODMAPERR; 963*45916cd2Sjpk goto out; 964*45916cd2Sjpk } 965*45916cd2Sjpk fname = sf.sf_path; 966*45916cd2Sjpk } else { 967*45916cd2Sjpk bytes = snprintf(file_name, MAXPATHLEN, "%s/%s", DAC_DIR, 968*45916cd2Sjpk da->da_devname); 969*45916cd2Sjpk if (bytes <= 0) { 970*45916cd2Sjpk error = DEVNAMEERR; 971*45916cd2Sjpk goto out; 972*45916cd2Sjpk } else if (bytes >= MAXPATHLEN) { 973*45916cd2Sjpk dprintf("device name %s is too long.\n", 974*45916cd2Sjpk da->da_devname); 975*45916cd2Sjpk error = DEVLONGERR; 976*45916cd2Sjpk goto out; 977*45916cd2Sjpk } 978*45916cd2Sjpk fname = file_name; 9797c478bd9Sstevel@tonic-gate } 9807c478bd9Sstevel@tonic-gate 981*45916cd2Sjpk audit_allocate_device(fname); 9827c478bd9Sstevel@tonic-gate 983*45916cd2Sjpk if (stat(fname, &stat_buf) != 0) { 984*45916cd2Sjpk dprintf("Unable to stat %s\n", fname); 985*45916cd2Sjpk error = DACACCERR; 986*45916cd2Sjpk goto out; 987*45916cd2Sjpk } 988*45916cd2Sjpk is_authorized = _is_dev_authorized(da, uid); 989*45916cd2Sjpk if (!(optflag & (FORCE | FORCE_ALL)) && !is_authorized) { 990*45916cd2Sjpk dprintf("User %d is unauthorized to deallocate\n", (int)uid); 991*45916cd2Sjpk error = UAUTHERR; 992*45916cd2Sjpk goto out; 993*45916cd2Sjpk } 994*45916cd2Sjpk if (system_labeled) { 995*45916cd2Sjpk /* 996*45916cd2Sjpk * unless we're here to deallocate by force, check if the 997*45916cd2Sjpk * label at which the device is currently allocated is 998*45916cd2Sjpk * within the user label range. 999*45916cd2Sjpk */ 1000*45916cd2Sjpk if (!(optflag & FORCE) && 1001*45916cd2Sjpk _check_label(da, zonename, uid, CHECK_URANGE) != 0) { 1002*45916cd2Sjpk error = LABELRNGERR; 1003*45916cd2Sjpk goto out; 1004*45916cd2Sjpk } 1005*45916cd2Sjpk } 1006*45916cd2Sjpk if (!(optflag & FORCE) && stat_buf.st_uid != uid && 1007*45916cd2Sjpk DEV_ALLOCATED(stat_buf)) { 1008*45916cd2Sjpk error = ALLOCUERR; 1009*45916cd2Sjpk goto out; 1010*45916cd2Sjpk } 1011*45916cd2Sjpk if (!DEV_ALLOCATED(stat_buf)) { 1012*45916cd2Sjpk if (DEV_ERRORED(stat_buf)) { 1013*45916cd2Sjpk if (!(optflag & FORCE)) { 1014*45916cd2Sjpk error = DEVSTATEERR; 1015*45916cd2Sjpk goto out; 1016*45916cd2Sjpk } 1017*45916cd2Sjpk } else { 1018*45916cd2Sjpk error = DEVNALLOCERR; 1019*45916cd2Sjpk goto out; 1020*45916cd2Sjpk } 1021*45916cd2Sjpk } 1022*45916cd2Sjpk /* All checks passed, time to lock and deallocate */ 1023*45916cd2Sjpk if ((error = lock_dev(fname)) != 0) 1024*45916cd2Sjpk goto out; 1025*45916cd2Sjpk if (system_labeled) { 1026*45916cd2Sjpk devzone = kva_match(da->da_devopts, DAOPT_ZONE); 1027*45916cd2Sjpk if (devzone && (strcmp(devzone, GLOBAL_ZONENAME) != 0)) { 1028*45916cd2Sjpk if ((remove_znode(devzone, dm) != 0) && 1029*45916cd2Sjpk !(optflag & FORCE)) { 1030*45916cd2Sjpk error = ZONEERR; 1031*45916cd2Sjpk goto out; 1032*45916cd2Sjpk } 1033*45916cd2Sjpk } 1034*45916cd2Sjpk } 1035*45916cd2Sjpk if ((error = mk_unalloc(optflag, dm)) != 0) { 1036*45916cd2Sjpk if (!(optflag & FORCE)) 1037*45916cd2Sjpk goto out; 1038*45916cd2Sjpk } 1039*45916cd2Sjpk if (system_labeled == 0) { 1040*45916cd2Sjpk if ((error = _newdac(fname, ALLOC_UID, ALLOC_GID, 1041*45916cd2Sjpk DEALLOC_MODE)) != 0) { 1042*45916cd2Sjpk (void) _newdac(file_name, ALLOC_UID, ALLOC_GID, 1043*45916cd2Sjpk ALLOC_ERR_MODE); 1044*45916cd2Sjpk goto out; 1045*45916cd2Sjpk } 1046*45916cd2Sjpk } 1047*45916cd2Sjpk /* 1048*45916cd2Sjpk * if we are deallocating device owned by someone else, 1049*45916cd2Sjpk * pass the owner's uid to the cleaning script. 1050*45916cd2Sjpk */ 1051*45916cd2Sjpk nuid = (stat_buf.st_uid == uid) ? uid : stat_buf.st_uid; 1052*45916cd2Sjpk error = exec_clean(optflag, da->da_devname, da->da_devexec, nuid, 1053*45916cd2Sjpk devzone, DEALLOC_CLEAN); 1054*45916cd2Sjpk if (error != 0) { 1055*45916cd2Sjpk if (!(optflag & (FORCE | FORCE_ALL))) { 1056*45916cd2Sjpk error = CLEANERR; 1057*45916cd2Sjpk (void) mk_error(dm); 1058*45916cd2Sjpk } else { 1059*45916cd2Sjpk error = 0; 1060*45916cd2Sjpk } 1061*45916cd2Sjpk } 1062*45916cd2Sjpk 1063*45916cd2Sjpk out: 1064*45916cd2Sjpk if (dm_new) 1065*45916cd2Sjpk freedmapent(dm_new); 1066*45916cd2Sjpk return (error); 1067*45916cd2Sjpk } 1068*45916cd2Sjpk 1069*45916cd2Sjpk int 1070*45916cd2Sjpk _allocate_dev(int optflag, uid_t uid, devalloc_t *da, char *zonename) 1071*45916cd2Sjpk { 1072*45916cd2Sjpk int i; 1073*45916cd2Sjpk int bytes = 0; 1074*45916cd2Sjpk int error = 0; 1075*45916cd2Sjpk int is_authorized = 0; 1076*45916cd2Sjpk int dealloc_optflag = 0; 1077*45916cd2Sjpk char *fname = NULL; 1078*45916cd2Sjpk char file_name[MAXPATHLEN]; 1079*45916cd2Sjpk devmap_t *dm; 1080*45916cd2Sjpk struct stat stat_buf; 1081*45916cd2Sjpk struct state_file sf; 1082*45916cd2Sjpk struct zone_path zpath; 1083*45916cd2Sjpk 1084*45916cd2Sjpk zpath.count = 0; 1085*45916cd2Sjpk zpath.path = NULL; 1086*45916cd2Sjpk setdmapent(); 1087*45916cd2Sjpk if ((dm = getdmapnam(da->da_devname)) == NULL) { 1088*45916cd2Sjpk enddmapent(); 1089*45916cd2Sjpk dprintf("Unable to find %s in device map database\n", 1090*45916cd2Sjpk da->da_devname); 1091*45916cd2Sjpk return (NODMAPERR); 1092*45916cd2Sjpk } 1093*45916cd2Sjpk enddmapent(); 1094*45916cd2Sjpk if (system_labeled) { 1095*45916cd2Sjpk if (_dev_file_name(&sf, dm) != 0) { 1096*45916cd2Sjpk freedmapent(dm); 1097*45916cd2Sjpk dprintf("Unable to find %s device files\n", 1098*45916cd2Sjpk da->da_devname); 1099*45916cd2Sjpk error = NODMAPERR; 1100*45916cd2Sjpk goto out; 1101*45916cd2Sjpk } 1102*45916cd2Sjpk fname = sf.sf_path; 1103*45916cd2Sjpk } else { 1104*45916cd2Sjpk bytes = snprintf(file_name, MAXPATHLEN, "%s/%s", DAC_DIR, 1105*45916cd2Sjpk da->da_devname); 1106*45916cd2Sjpk if (bytes <= 0) { 1107*45916cd2Sjpk error = DEVNAMEERR; 1108*45916cd2Sjpk goto out; 1109*45916cd2Sjpk } else if (bytes >= MAXPATHLEN) { 1110*45916cd2Sjpk dprintf("device name %s is too long.\n", 1111*45916cd2Sjpk da->da_devname); 1112*45916cd2Sjpk error = DEVLONGERR; 1113*45916cd2Sjpk goto out; 1114*45916cd2Sjpk } 1115*45916cd2Sjpk fname = file_name; 1116*45916cd2Sjpk } 1117*45916cd2Sjpk 1118*45916cd2Sjpk (void) audit_allocate_device(fname); 1119*45916cd2Sjpk 1120*45916cd2Sjpk if (stat(fname, &stat_buf) != 0) { 1121*45916cd2Sjpk dprintf("Unable to stat %s\n", fname); 11227c478bd9Sstevel@tonic-gate dperror("Error:"); 1123*45916cd2Sjpk error = DACACCERR; 1124*45916cd2Sjpk goto out; 11257c478bd9Sstevel@tonic-gate } 1126*45916cd2Sjpk if (DEV_ERRORED(stat_buf)) { 1127*45916cd2Sjpk error = DEVSTATEERR; 1128*45916cd2Sjpk goto out; 1129*45916cd2Sjpk } 1130*45916cd2Sjpk is_authorized = _is_dev_authorized(da, uid); 1131*45916cd2Sjpk if (is_authorized == ALLOC_BY_NONE) { 1132*45916cd2Sjpk dprintf("Device %s is not allocatable\n", da->da_devname); 1133*45916cd2Sjpk error = UAUTHERR; 1134*45916cd2Sjpk goto out; 1135*45916cd2Sjpk } else if (!is_authorized && !(optflag & USERNAME)) { 1136*45916cd2Sjpk dprintf("User %d is unauthorized to allocate\n", (int)uid); 1137*45916cd2Sjpk error = UAUTHERR; 1138*45916cd2Sjpk goto out; 1139*45916cd2Sjpk } 1140*45916cd2Sjpk if (system_labeled) { 1141*45916cd2Sjpk /* 1142*45916cd2Sjpk * check if label of the zone to which the device is being 1143*45916cd2Sjpk * allocated is within the device label range. 1144*45916cd2Sjpk */ 1145*45916cd2Sjpk if (_check_label(da, zonename, uid, CHECK_DRANGE) != 0) { 1146*45916cd2Sjpk error = LABELRNGERR; 1147*45916cd2Sjpk goto out; 1148*45916cd2Sjpk } 1149*45916cd2Sjpk } 1150*45916cd2Sjpk if (check_devs(dm) == -1) { 1151*45916cd2Sjpk error = DSPMISSERR; 1152*45916cd2Sjpk goto out; 1153*45916cd2Sjpk } 11547c478bd9Sstevel@tonic-gate if (DEV_ALLOCATED(stat_buf)) { 1155*45916cd2Sjpk if (optflag & FORCE) { 1156*45916cd2Sjpk if (optflag & SILENT) 1157*45916cd2Sjpk dealloc_optflag = FORCE|SILENT; 115840e2b7c9Spaulson else 1159*45916cd2Sjpk dealloc_optflag = FORCE; 1160*45916cd2Sjpk if (_deallocate_dev(dealloc_optflag, da, dm, uid, 1161*45916cd2Sjpk zonename)) { 11627c478bd9Sstevel@tonic-gate dprintf("Couldn't force deallocate device %s\n", 1163*45916cd2Sjpk da->da_devname); 1164*45916cd2Sjpk error = CNTFRCERR; 1165*45916cd2Sjpk goto out; 11667c478bd9Sstevel@tonic-gate } 11677c478bd9Sstevel@tonic-gate } else if (stat_buf.st_uid == uid) { 1168*45916cd2Sjpk error = PREALLOCERR; 1169*45916cd2Sjpk goto out; 11707c478bd9Sstevel@tonic-gate } else { 1171*45916cd2Sjpk error = ALLOCUERR; 1172*45916cd2Sjpk goto out; 1173*45916cd2Sjpk } 1174*45916cd2Sjpk } 1175*45916cd2Sjpk /* All checks passed, time to lock and allocate */ 1176*45916cd2Sjpk if ((error = lock_dev(fname)) != 0) 1177*45916cd2Sjpk goto out; 1178*45916cd2Sjpk if (system_labeled) { 1179*45916cd2Sjpk /* 1180*45916cd2Sjpk * Run the cleaning program; it also mounts allocated 1181*45916cd2Sjpk * device if required. 1182*45916cd2Sjpk */ 1183*45916cd2Sjpk error = exec_clean(optflag, da->da_devname, da->da_devexec, uid, 1184*45916cd2Sjpk zonename, ALLOC_CLEAN); 1185*45916cd2Sjpk if ((error != 0) && (error != CLEAN_MOUNT)) { 1186*45916cd2Sjpk error = CLEANERR; 1187*45916cd2Sjpk (void) mk_error(dm); 1188*45916cd2Sjpk goto out; 1189*45916cd2Sjpk } 1190*45916cd2Sjpk /* 1191*45916cd2Sjpk * If not mounted, create zonelinks, if this is not the 1192*45916cd2Sjpk * global zone. 1193*45916cd2Sjpk */ 1194*45916cd2Sjpk if ((strcmp(zonename, GLOBAL_ZONENAME) != 0) && 1195*45916cd2Sjpk (error != CLEAN_MOUNT)) { 1196*45916cd2Sjpk if (create_znode(zonename, &zpath, dm) != 0) { 1197*45916cd2Sjpk error = ZONEERR; 1198*45916cd2Sjpk goto out; 1199*45916cd2Sjpk } 1200*45916cd2Sjpk } 1201*45916cd2Sjpk } 1202*45916cd2Sjpk 1203*45916cd2Sjpk (void) audit_allocate_list(dm->dmap_devlist); 1204*45916cd2Sjpk 1205*45916cd2Sjpk if ((error = mk_alloc(dm, uid, &zpath)) != 0) { 1206*45916cd2Sjpk (void) mk_unalloc(optflag, dm); 1207*45916cd2Sjpk goto out; 1208*45916cd2Sjpk } 1209*45916cd2Sjpk 1210*45916cd2Sjpk if (system_labeled == 0) { 1211*45916cd2Sjpk if ((error = _newdac(file_name, uid, getgid(), 1212*45916cd2Sjpk ALLOC_MODE)) != 0) { 1213*45916cd2Sjpk (void) _newdac(file_name, ALLOC_UID, ALLOC_GID, 1214*45916cd2Sjpk ALLOC_ERR_MODE); 1215*45916cd2Sjpk goto out; 1216*45916cd2Sjpk } 1217*45916cd2Sjpk } 1218*45916cd2Sjpk error = 0; 1219*45916cd2Sjpk out: 1220*45916cd2Sjpk if (zpath.count) { 1221*45916cd2Sjpk for (i = 0; i < zpath.count; i++) 1222*45916cd2Sjpk free(zpath.path[i]); 1223*45916cd2Sjpk free(zpath.path); 1224*45916cd2Sjpk } 1225*45916cd2Sjpk freedmapent(dm); 1226*45916cd2Sjpk return (error); 1227*45916cd2Sjpk } 1228*45916cd2Sjpk 1229*45916cd2Sjpk void 1230*45916cd2Sjpk _store_devnames(int *count, struct devnames *dnms, char *zonename, 1231*45916cd2Sjpk devalloc_t *da, int flag) 1232*45916cd2Sjpk { 1233*45916cd2Sjpk int i; 1234*45916cd2Sjpk 1235*45916cd2Sjpk dnms->dnames = (char **)realloc(dnms->dnames, 1236*45916cd2Sjpk (*count + 1) * sizeof (char *)); 1237*45916cd2Sjpk if (da) { 1238*45916cd2Sjpk dnms->dnames[*count] = strdup(da->da_devname); 1239*45916cd2Sjpk (*count)++; 1240*45916cd2Sjpk } else { 1241*45916cd2Sjpk dnms->dnames[*count] = NULL; 1242*45916cd2Sjpk if (flag == DA_ADD_ZONE) 1243*45916cd2Sjpk (void) update_device(dnms->dnames, zonename, 1244*45916cd2Sjpk DA_ADD_ZONE); 1245*45916cd2Sjpk else if (flag == DA_REMOVE_ZONE) 1246*45916cd2Sjpk (void) update_device(dnms->dnames, NULL, 1247*45916cd2Sjpk DA_REMOVE_ZONE); 1248*45916cd2Sjpk for (i = 0; i < *count; i++) 1249*45916cd2Sjpk free(dnms->dnames[i]); 1250*45916cd2Sjpk free(dnms->dnames); 1251*45916cd2Sjpk } 1252*45916cd2Sjpk } 1253*45916cd2Sjpk 1254*45916cd2Sjpk int 1255*45916cd2Sjpk allocate(int optflag, uid_t uid, char *device, char *zonename) 1256*45916cd2Sjpk { 1257*45916cd2Sjpk int count = 0; 1258*45916cd2Sjpk int error = 0; 1259*45916cd2Sjpk devalloc_t *da; 1260*45916cd2Sjpk struct devnames dnms; 1261*45916cd2Sjpk 1262*45916cd2Sjpk if (optflag & (FORCE | USERID | USERNAME)) { 1263*45916cd2Sjpk if (!_is_authorized(DEVICE_REVOKE_AUTH, getuid())) 1264*45916cd2Sjpk return (UAUTHERR); 1265*45916cd2Sjpk } 1266*45916cd2Sjpk dnms.dnames = NULL; 1267*45916cd2Sjpk setdaent(); 1268*45916cd2Sjpk if (optflag & TYPE) { 1269*45916cd2Sjpk /* 1270*45916cd2Sjpk * allocate devices of this type 1271*45916cd2Sjpk */ 1272*45916cd2Sjpk while ((da = getdatype(device)) != NULL) { 1273*45916cd2Sjpk if (system_labeled && 1274*45916cd2Sjpk da_check_logindevperm(da->da_devname)) { 1275*45916cd2Sjpk freedaent(da); 12767c478bd9Sstevel@tonic-gate continue; 12777c478bd9Sstevel@tonic-gate } 1278*45916cd2Sjpk dprintf("trying to allocate %s\n", da->da_devname); 1279*45916cd2Sjpk error = _allocate_dev(optflag, uid, da, zonename); 1280*45916cd2Sjpk if (system_labeled && (error == 0)) { 1281*45916cd2Sjpk /* 1282*45916cd2Sjpk * we need to record in device_allocate the 1283*45916cd2Sjpk * label (zone name) at which this device is 1284*45916cd2Sjpk * being allocated. store this device entry. 1285*45916cd2Sjpk */ 1286*45916cd2Sjpk _store_devnames(&count, &dnms, zonename, da, 0); 12877c478bd9Sstevel@tonic-gate } 1288*45916cd2Sjpk freedaent(da); 1289*45916cd2Sjpk error = 0; 12907c478bd9Sstevel@tonic-gate } 1291*45916cd2Sjpk } else { 1292*45916cd2Sjpk /* 1293*45916cd2Sjpk * allocate this device 1294*45916cd2Sjpk */ 1295*45916cd2Sjpk if ((da = getdanam(device)) == NULL) { 12967c478bd9Sstevel@tonic-gate enddaent(); 1297*45916cd2Sjpk return (NODAERR); 1298*45916cd2Sjpk } 1299*45916cd2Sjpk if (system_labeled && da_check_logindevperm(device)) { 1300*45916cd2Sjpk freedaent(da); 1301*45916cd2Sjpk return (LOGINDEVPERMERR); 1302*45916cd2Sjpk } 1303*45916cd2Sjpk dprintf("trying to allocate %s\n", da->da_devname); 1304*45916cd2Sjpk error = _allocate_dev(optflag, uid, da, zonename); 1305*45916cd2Sjpk /* 1306*45916cd2Sjpk * we need to record in device_allocate the label (zone name) 1307*45916cd2Sjpk * at which this device is being allocated. store this device 1308*45916cd2Sjpk * entry. 1309*45916cd2Sjpk */ 1310*45916cd2Sjpk if (system_labeled && (error == 0)) 1311*45916cd2Sjpk _store_devnames(&count, &dnms, zonename, da, 0); 1312*45916cd2Sjpk freedaent(da); 1313*45916cd2Sjpk } 1314*45916cd2Sjpk enddaent(); 1315*45916cd2Sjpk /* 1316*45916cd2Sjpk * add to device_allocate labels (zone names) for the devices we 1317*45916cd2Sjpk * allocated. 1318*45916cd2Sjpk */ 1319*45916cd2Sjpk if (dnms.dnames) 1320*45916cd2Sjpk _store_devnames(&count, &dnms, zonename, NULL, DA_ADD_ZONE); 1321*45916cd2Sjpk 13227c478bd9Sstevel@tonic-gate return (error); 13237c478bd9Sstevel@tonic-gate } 1324*45916cd2Sjpk 1325*45916cd2Sjpk /* ARGSUSED */ 1326*45916cd2Sjpk int 1327*45916cd2Sjpk deallocate(int optflag, uid_t uid, char *device, char *zonename) 1328*45916cd2Sjpk { 1329*45916cd2Sjpk int count = 0; 1330*45916cd2Sjpk int error = 0; 1331*45916cd2Sjpk devalloc_t *da; 1332*45916cd2Sjpk struct devnames dnms; 1333*45916cd2Sjpk 1334*45916cd2Sjpk if (optflag & (FORCE | FORCE_ALL)) { 1335*45916cd2Sjpk if (!_is_authorized(DEVICE_REVOKE_AUTH, getuid())) 1336*45916cd2Sjpk return (UAUTHERR); 1337*45916cd2Sjpk } 1338*45916cd2Sjpk if (optflag & FORCE_ALL) 1339*45916cd2Sjpk optflag |= FORCE; 1340*45916cd2Sjpk dnms.dnames = NULL; 1341*45916cd2Sjpk setdaent(); 1342*45916cd2Sjpk if (optflag & FORCE_ALL) { 1343*45916cd2Sjpk /* 1344*45916cd2Sjpk * deallocate all devices 1345*45916cd2Sjpk */ 1346*45916cd2Sjpk while ((da = getdaent()) != NULL) { 1347*45916cd2Sjpk if (system_labeled && 1348*45916cd2Sjpk da_check_logindevperm(da->da_devname)) { 1349*45916cd2Sjpk freedaent(da); 1350*45916cd2Sjpk continue; 1351*45916cd2Sjpk } 1352*45916cd2Sjpk dprintf("trying to deallocate %s\n", da->da_devname); 1353*45916cd2Sjpk error = _deallocate_dev(optflag, da, NULL, uid, 1354*45916cd2Sjpk zonename); 1355*45916cd2Sjpk if (system_labeled && (error == 0)) { 1356*45916cd2Sjpk /* 1357*45916cd2Sjpk * we need to remove this device's allocation 1358*45916cd2Sjpk * label (zone name) from device_allocate. 1359*45916cd2Sjpk * store this device name. 1360*45916cd2Sjpk */ 1361*45916cd2Sjpk _store_devnames(&count, &dnms, zonename, da, 0); 1362*45916cd2Sjpk } 1363*45916cd2Sjpk freedaent(da); 1364*45916cd2Sjpk error = 0; 1365*45916cd2Sjpk } 1366*45916cd2Sjpk } else if (system_labeled && optflag & TYPE) { 1367*45916cd2Sjpk /* 1368*45916cd2Sjpk * deallocate all devices of this type 1369*45916cd2Sjpk */ 1370*45916cd2Sjpk while ((da = getdatype(device)) != NULL) { 1371*45916cd2Sjpk if (da_check_logindevperm(da->da_devname)) { 1372*45916cd2Sjpk freedaent(da); 1373*45916cd2Sjpk continue; 1374*45916cd2Sjpk } 1375*45916cd2Sjpk dprintf("trying to deallocate %s\n", da->da_devname); 1376*45916cd2Sjpk error = _deallocate_dev(optflag, da, NULL, uid, 1377*45916cd2Sjpk zonename); 1378*45916cd2Sjpk if (error == 0) { 1379*45916cd2Sjpk /* 1380*45916cd2Sjpk * we need to remove this device's allocation 1381*45916cd2Sjpk * label (zone name) from device_allocate. 1382*45916cd2Sjpk * store this device name. 1383*45916cd2Sjpk */ 1384*45916cd2Sjpk _store_devnames(&count, &dnms, zonename, da, 0); 1385*45916cd2Sjpk } 1386*45916cd2Sjpk freedaent(da); 1387*45916cd2Sjpk error = 0; 1388*45916cd2Sjpk } 1389*45916cd2Sjpk } else if (!(optflag & TYPE)) { 1390*45916cd2Sjpk /* 1391*45916cd2Sjpk * deallocate this device 1392*45916cd2Sjpk */ 1393*45916cd2Sjpk if ((da = getdanam(device)) == NULL) { 1394*45916cd2Sjpk enddaent(); 1395*45916cd2Sjpk return (NODAERR); 1396*45916cd2Sjpk } 1397*45916cd2Sjpk if (system_labeled && da_check_logindevperm(da->da_devname)) { 1398*45916cd2Sjpk freedaent(da); 1399*45916cd2Sjpk return (LOGINDEVPERMERR); 1400*45916cd2Sjpk } 1401*45916cd2Sjpk dprintf("trying to deallocate %s\n", da->da_devname); 1402*45916cd2Sjpk error = _deallocate_dev(optflag, da, NULL, uid, zonename); 1403*45916cd2Sjpk if (system_labeled && (error == 0)) { 1404*45916cd2Sjpk /* 1405*45916cd2Sjpk * we need to remove this device's allocation label 1406*45916cd2Sjpk * (zone name) from device_allocate. store this 1407*45916cd2Sjpk * device name. 1408*45916cd2Sjpk */ 1409*45916cd2Sjpk _store_devnames(&count, &dnms, zonename, da, 0); 1410*45916cd2Sjpk } 1411*45916cd2Sjpk freedaent(da); 1412*45916cd2Sjpk } 1413*45916cd2Sjpk enddaent(); 1414*45916cd2Sjpk /* 1415*45916cd2Sjpk * remove from device_allocate labels (zone names) for the devices we 1416*45916cd2Sjpk * deallocated. 1417*45916cd2Sjpk */ 1418*45916cd2Sjpk if (dnms.dnames) 1419*45916cd2Sjpk _store_devnames(&count, &dnms, zonename, NULL, DA_REMOVE_ZONE); 1420*45916cd2Sjpk 1421*45916cd2Sjpk return (error); 1422*45916cd2Sjpk } 1423*45916cd2Sjpk 1424*45916cd2Sjpk static int 1425*45916cd2Sjpk _dev_file_name(struct state_file *sfp, devmap_t *dm) 1426*45916cd2Sjpk { 1427*45916cd2Sjpk sfp->sf_flags = 0; 1428*45916cd2Sjpk /* if devlist is generated, never leave device in error state */ 1429*45916cd2Sjpk if (dm->dmap_devlist[0] == '`') 1430*45916cd2Sjpk sfp->sf_flags |= SFF_NO_ERROR; 1431*45916cd2Sjpk if (dm->dmap_devarray == NULL || 1432*45916cd2Sjpk dm->dmap_devarray[0] == NULL) 1433*45916cd2Sjpk return (NODMAPERR); 1434*45916cd2Sjpk (void) strncpy(sfp->sf_path, dm->dmap_devarray[0], 1435*45916cd2Sjpk sizeof (sfp->sf_path)); 1436*45916cd2Sjpk sfp->sf_path[sizeof (sfp->sf_path) - 1] = '\0'; 1437*45916cd2Sjpk if (sfp->sf_path[0] == '\0') { 1438*45916cd2Sjpk dprintf("dev_file_name: no device list for %s\n", 1439*45916cd2Sjpk dm->dmap_devname); 1440*45916cd2Sjpk return (NODMAPERR); 1441*45916cd2Sjpk } 1442*45916cd2Sjpk 1443*45916cd2Sjpk return (0); 1444*45916cd2Sjpk } 1445*45916cd2Sjpk 1446*45916cd2Sjpk /* 1447*45916cd2Sjpk * _check_label - 1448*45916cd2Sjpk * checks the device label range against zone label, which is also 1449*45916cd2Sjpk * user's current label. 1450*45916cd2Sjpk * returns 0 if in range, -1 for all other conditions. 1451*45916cd2Sjpk * 1452*45916cd2Sjpk */ 1453*45916cd2Sjpk 1454*45916cd2Sjpk static int 1455*45916cd2Sjpk _check_label(devalloc_t *da, char *zonename, uid_t uid, int flag) 1456*45916cd2Sjpk { 1457*45916cd2Sjpk int err; 1458*45916cd2Sjpk int in_range = 0; 1459*45916cd2Sjpk char *alloczone, *lstr; 1460*45916cd2Sjpk char pw_buf[NSS_BUFLEN_PASSWD]; 1461*45916cd2Sjpk blrange_t *range; 1462*45916cd2Sjpk m_label_t *zlabel; 1463*45916cd2Sjpk struct passwd pw_ent; 1464*45916cd2Sjpk 1465*45916cd2Sjpk if ((da == NULL) || (zonename == NULL)) 1466*45916cd2Sjpk return (-1); 1467*45916cd2Sjpk 1468*45916cd2Sjpk if ((zlabel = getzonelabelbyname(zonename)) == NULL) { 1469*45916cd2Sjpk dprintf("unable to get label for %s zone\n", zonename); 1470*45916cd2Sjpk return (-1); 1471*45916cd2Sjpk } 1472*45916cd2Sjpk if (flag == CHECK_DRANGE) { 1473*45916cd2Sjpk blrange_t drange; 1474*45916cd2Sjpk 1475*45916cd2Sjpk drange.lower_bound = blabel_alloc(); 1476*45916cd2Sjpk lstr = kva_match(da->da_devopts, DAOPT_MINLABEL); 1477*45916cd2Sjpk if (lstr == NULL) { 1478*45916cd2Sjpk bsllow(drange.lower_bound); 1479*45916cd2Sjpk } else if (stobsl(lstr, drange.lower_bound, NO_CORRECTION, 1480*45916cd2Sjpk &err) == 0) { 1481*45916cd2Sjpk dprintf("bad min_label for device %s\n", 1482*45916cd2Sjpk da->da_devname); 1483*45916cd2Sjpk free(zlabel); 1484*45916cd2Sjpk blabel_free(drange.lower_bound); 1485*45916cd2Sjpk return (-1); 1486*45916cd2Sjpk } 1487*45916cd2Sjpk drange.upper_bound = blabel_alloc(); 1488*45916cd2Sjpk lstr = kva_match(da->da_devopts, DAOPT_MAXLABEL); 1489*45916cd2Sjpk if (lstr == NULL) { 1490*45916cd2Sjpk bslhigh(drange.upper_bound); 1491*45916cd2Sjpk } else if (stobsl(lstr, drange.upper_bound, NO_CORRECTION, 1492*45916cd2Sjpk &err) == 0) { 1493*45916cd2Sjpk dprintf("bad max_label for device %s\n", 1494*45916cd2Sjpk da->da_devname); 1495*45916cd2Sjpk free(zlabel); 1496*45916cd2Sjpk blabel_free(drange.lower_bound); 1497*45916cd2Sjpk blabel_free(drange.upper_bound); 1498*45916cd2Sjpk return (-1); 1499*45916cd2Sjpk } 1500*45916cd2Sjpk if (blinrange(zlabel, &drange) == 0) { 1501*45916cd2Sjpk char *zlbl = NULL, *min = NULL, *max = NULL; 1502*45916cd2Sjpk 1503*45916cd2Sjpk (void) bsltos(zlabel, &zlbl, 0, 0); 1504*45916cd2Sjpk (void) bsltos(drange.lower_bound, &min, 0, 0); 1505*45916cd2Sjpk (void) bsltos(drange.upper_bound, &max, 0, 0); 1506*45916cd2Sjpk dprintf("%s zone label ", zonename); 1507*45916cd2Sjpk dprintf("%s outside device label range: ", zlbl); 1508*45916cd2Sjpk dprintf("min - %s, ", min); 1509*45916cd2Sjpk dprintf("max - %s\n", max); 1510*45916cd2Sjpk free(zlabel); 1511*45916cd2Sjpk blabel_free(drange.lower_bound); 1512*45916cd2Sjpk blabel_free(drange.upper_bound); 1513*45916cd2Sjpk return (-1); 1514*45916cd2Sjpk } 1515*45916cd2Sjpk } else if (flag == CHECK_URANGE) { 1516*45916cd2Sjpk if (getpwuid_r(uid, &pw_ent, pw_buf, sizeof (pw_buf)) == NULL) { 1517*45916cd2Sjpk dprintf("Unable to get passwd entry for userid %d\n", 1518*45916cd2Sjpk (int)uid); 1519*45916cd2Sjpk free(zlabel); 1520*45916cd2Sjpk return (-1); 1521*45916cd2Sjpk } 1522*45916cd2Sjpk if ((range = getuserrange(pw_ent.pw_name)) == NULL) { 1523*45916cd2Sjpk dprintf("Unable to get label range for userid %d\n", 1524*45916cd2Sjpk (int)uid); 1525*45916cd2Sjpk free(zlabel); 1526*45916cd2Sjpk return (-1); 1527*45916cd2Sjpk } 1528*45916cd2Sjpk in_range = blinrange(zlabel, range); 1529*45916cd2Sjpk free(zlabel); 1530*45916cd2Sjpk blabel_free(range->lower_bound); 1531*45916cd2Sjpk blabel_free(range->upper_bound); 1532*45916cd2Sjpk free(range); 1533*45916cd2Sjpk if (in_range == 0) { 1534*45916cd2Sjpk dprintf("%s device label ", da->da_devname); 1535*45916cd2Sjpk dprintf("out of user %d label range\n", (int)uid); 1536*45916cd2Sjpk return (-1); 1537*45916cd2Sjpk } 1538*45916cd2Sjpk } else if (flag == CHECK_ZLABEL) { 1539*45916cd2Sjpk alloczone = kva_match(da->da_devopts, DAOPT_ZONE); 1540*45916cd2Sjpk if (alloczone == NULL) { 1541*45916cd2Sjpk free(zlabel); 1542*45916cd2Sjpk return (-1); 1543*45916cd2Sjpk } 1544*45916cd2Sjpk if (strcmp(zonename, alloczone) != 0) { 1545*45916cd2Sjpk dprintf("%s zone is different than ", zonename); 1546*45916cd2Sjpk dprintf("%s zone to which the device ", alloczone); 1547*45916cd2Sjpk dprintf("%s is allocated\n", da->da_devname); 1548*45916cd2Sjpk free(zlabel); 1549*45916cd2Sjpk return (-1); 1550*45916cd2Sjpk } 1551*45916cd2Sjpk } 1552*45916cd2Sjpk free(zlabel); 1553*45916cd2Sjpk 1554*45916cd2Sjpk return (0); 1555*45916cd2Sjpk } 1556*45916cd2Sjpk 1557*45916cd2Sjpk int 1558*45916cd2Sjpk create_znode(char *zonename, struct zone_path *zpath, devmap_t *list) 1559*45916cd2Sjpk { 1560*45916cd2Sjpk int i; 1561*45916cd2Sjpk int size; 1562*45916cd2Sjpk int len = 0; 1563*45916cd2Sjpk int fcount = 0; 1564*45916cd2Sjpk char *p, *tmpfile, *zoneroot; 1565*45916cd2Sjpk char **file; 1566*45916cd2Sjpk char zonepath[MAXPATHLEN]; 1567*45916cd2Sjpk struct stat statb; 1568*45916cd2Sjpk 1569*45916cd2Sjpk file = list->dmap_devarray; 1570*45916cd2Sjpk if (file == NULL) 1571*45916cd2Sjpk return (NODMAPERR); 1572*45916cd2Sjpk if ((zoneroot = getzonerootbyname(zonename)) == NULL) { 1573*45916cd2Sjpk dprintf("unable to get label for %s zone\n", zonename); 1574*45916cd2Sjpk return (1); 1575*45916cd2Sjpk } 1576*45916cd2Sjpk (void) strcpy(zonepath, zoneroot); 1577*45916cd2Sjpk free(zoneroot); 1578*45916cd2Sjpk if ((p = strstr(zonepath, "/root")) == NULL) 1579*45916cd2Sjpk return (1); 1580*45916cd2Sjpk *p = '\0'; 1581*45916cd2Sjpk len = strlen(zonepath); 1582*45916cd2Sjpk size = sizeof (zonepath); 1583*45916cd2Sjpk for (; *file != NULL; file++) { 1584*45916cd2Sjpk if (stat(*file, &statb) == -1) { 1585*45916cd2Sjpk dprintf("Couldn't stat the file %s\n", *file); 1586*45916cd2Sjpk return (1); 1587*45916cd2Sjpk } 1588*45916cd2Sjpk /* 1589*45916cd2Sjpk * First time initialization 1590*45916cd2Sjpk */ 1591*45916cd2Sjpk tmpfile = strdup(*file); 1592*45916cd2Sjpk 1593*45916cd2Sjpk /* 1594*45916cd2Sjpk * Most devices have pathnames starting in /dev 1595*45916cd2Sjpk * but SunRay devices do not. In SRRS 3.1 they use /tmp. 1596*45916cd2Sjpk * 1597*45916cd2Sjpk * If the device pathname is not in /dev then create 1598*45916cd2Sjpk * a symbolic link to it and put the device in /dev 1599*45916cd2Sjpk */ 1600*45916cd2Sjpk if (strncmp(tmpfile, "/dev/", strlen("/dev/")) != 0) { 1601*45916cd2Sjpk char *linkdir; 1602*45916cd2Sjpk char srclinkdir[MAXPATHLEN]; 1603*45916cd2Sjpk char dstlinkdir[MAXPATHLEN]; 1604*45916cd2Sjpk 1605*45916cd2Sjpk linkdir = strchr(tmpfile + 1, '/'); 1606*45916cd2Sjpk p = strchr(linkdir + 1, '/'); 1607*45916cd2Sjpk *p = '\0'; 1608*45916cd2Sjpk (void) strcpy(dstlinkdir, "/dev"); 1609*45916cd2Sjpk (void) strncat(dstlinkdir, linkdir, MAXPATHLEN); 1610*45916cd2Sjpk (void) snprintf(srclinkdir, MAXPATHLEN, "%s/root%s", 1611*45916cd2Sjpk zonepath, tmpfile); 1612*45916cd2Sjpk (void) symlink(dstlinkdir, srclinkdir); 1613*45916cd2Sjpk *p = '/'; 1614*45916cd2Sjpk (void) strncat(dstlinkdir, p, MAXPATHLEN); 1615*45916cd2Sjpk free(tmpfile); 1616*45916cd2Sjpk tmpfile = strdup(dstlinkdir); 1617*45916cd2Sjpk } 1618*45916cd2Sjpk if ((p = rindex(tmpfile, '/')) == NULL) { 1619*45916cd2Sjpk dprintf("bad path in create_znode for %s\n", 1620*45916cd2Sjpk tmpfile); 1621*45916cd2Sjpk return (1); 1622*45916cd2Sjpk } 1623*45916cd2Sjpk *p = '\0'; 1624*45916cd2Sjpk (void) strcat(zonepath, tmpfile); 1625*45916cd2Sjpk *p = '/'; 1626*45916cd2Sjpk if ((mkdirp(zonepath, 0755) != 0) && (errno != EEXIST)) { 1627*45916cd2Sjpk dprintf("Unable to create directory %s\n", zonepath); 1628*45916cd2Sjpk return (1); 1629*45916cd2Sjpk } 1630*45916cd2Sjpk zonepath[len] = '\0'; 1631*45916cd2Sjpk if (strlcat(zonepath, tmpfile, size) >= size) { 1632*45916cd2Sjpk dprintf("Buffer overflow in create_znode for %s\n", 1633*45916cd2Sjpk *file); 1634*45916cd2Sjpk free(tmpfile); 1635*45916cd2Sjpk return (1); 1636*45916cd2Sjpk } 1637*45916cd2Sjpk free(tmpfile); 1638*45916cd2Sjpk fcount++; 1639*45916cd2Sjpk if ((zpath->path = (char **)realloc(zpath->path, 1640*45916cd2Sjpk (fcount * sizeof (char *)))) == NULL) 1641*45916cd2Sjpk return (1); 1642*45916cd2Sjpk zpath->path[zpath->count] = strdup(zonepath); 1643*45916cd2Sjpk zpath->count = fcount; 1644*45916cd2Sjpk if (mknod(zonepath, statb.st_mode, statb.st_rdev) == -1) { 1645*45916cd2Sjpk switch (errno) { 1646*45916cd2Sjpk case EEXIST: 1647*45916cd2Sjpk break; 1648*45916cd2Sjpk default: 1649*45916cd2Sjpk dprintf("mknod error: %s\n", 1650*45916cd2Sjpk strerror(errno)); 1651*45916cd2Sjpk for (i = 0; i <= fcount; i++) 1652*45916cd2Sjpk free(zpath->path[i]); 1653*45916cd2Sjpk free(zpath->path); 1654*45916cd2Sjpk return (1); 1655*45916cd2Sjpk } 1656*45916cd2Sjpk } 1657*45916cd2Sjpk zonepath[len] = '\0'; 1658*45916cd2Sjpk } 1659*45916cd2Sjpk 1660*45916cd2Sjpk return (0); 1661*45916cd2Sjpk } 1662*45916cd2Sjpk 1663*45916cd2Sjpk int 1664*45916cd2Sjpk remove_znode(char *zonename, devmap_t *dm) 1665*45916cd2Sjpk { 1666*45916cd2Sjpk int len = 0; 1667*45916cd2Sjpk char *zoneroot; 1668*45916cd2Sjpk char **file; 1669*45916cd2Sjpk char zonepath[MAXPATHLEN]; 1670*45916cd2Sjpk 1671*45916cd2Sjpk file = dm->dmap_devarray; 1672*45916cd2Sjpk if (file == NULL) 1673*45916cd2Sjpk return (NODMAPERR); 1674*45916cd2Sjpk if ((zoneroot = getzonerootbyname(zonename)) == NULL) { 1675*45916cd2Sjpk (void) snprintf(zonepath, MAXPATHLEN, "/zone/%s", zonename); 1676*45916cd2Sjpk } else { 1677*45916cd2Sjpk char *p; 1678*45916cd2Sjpk 1679*45916cd2Sjpk if ((p = strstr(zoneroot, "/root")) == NULL) 1680*45916cd2Sjpk return (1); 1681*45916cd2Sjpk *p = '\0'; 1682*45916cd2Sjpk (void) strcpy(zonepath, zoneroot); 1683*45916cd2Sjpk free(zoneroot); 1684*45916cd2Sjpk } 1685*45916cd2Sjpk /* 1686*45916cd2Sjpk * To support SunRay we will just deal with the 1687*45916cd2Sjpk * file in /dev, not the symlinks. 1688*45916cd2Sjpk */ 1689*45916cd2Sjpk (void) strncat(zonepath, "/dev", MAXPATHLEN); 1690*45916cd2Sjpk len = strlen(zonepath); 1691*45916cd2Sjpk for (; *file != NULL; file++) { 1692*45916cd2Sjpk char *devrelpath; 1693*45916cd2Sjpk 1694*45916cd2Sjpk /* 1695*45916cd2Sjpk * remove device node from zone. 1696*45916cd2Sjpk * 1697*45916cd2Sjpk * SunRay devices don't start with /dev 1698*45916cd2Sjpk * so skip over first directory to make 1699*45916cd2Sjpk * sure it is /dev. SunRay devices in zones 1700*45916cd2Sjpk * will have a symlink into /dev but 1701*45916cd2Sjpk * we don't ever delete it. 1702*45916cd2Sjpk */ 1703*45916cd2Sjpk devrelpath = strchr(*file + 1, '/'); 1704*45916cd2Sjpk 1705*45916cd2Sjpk if (strlcat(zonepath, devrelpath, MAXPATHLEN) >= MAXPATHLEN) { 1706*45916cd2Sjpk dprintf("Buffer overflow in remove_znode for %s\n", 1707*45916cd2Sjpk *file); 1708*45916cd2Sjpk return (1); 1709*45916cd2Sjpk } 1710*45916cd2Sjpk errno = 0; 1711*45916cd2Sjpk if ((unlink(zonepath) == -1) && (errno != ENOENT)) { 1712*45916cd2Sjpk perror(zonepath); 1713*45916cd2Sjpk return (1); 1714*45916cd2Sjpk } 1715*45916cd2Sjpk zonepath[len] = '\0'; 1716*45916cd2Sjpk } 1717*45916cd2Sjpk 1718*45916cd2Sjpk return (0); 1719*45916cd2Sjpk } 1720*45916cd2Sjpk 1721*45916cd2Sjpk int 1722*45916cd2Sjpk update_device(char **devnames, char *zonename, int flag) 1723*45916cd2Sjpk { 1724*45916cd2Sjpk int len, rc; 1725*45916cd2Sjpk char *optstr = NULL; 1726*45916cd2Sjpk da_args dargs; 1727*45916cd2Sjpk devinfo_t devinfo; 1728*45916cd2Sjpk 1729*45916cd2Sjpk dargs.optflag = flag; 1730*45916cd2Sjpk dargs.optflag |= DA_UPDATE|DA_ALLOC_ONLY; 1731*45916cd2Sjpk dargs.rootdir = NULL; 1732*45916cd2Sjpk dargs.devnames = devnames; 1733*45916cd2Sjpk devinfo.devname = devinfo.devtype = devinfo.devauths = devinfo.devexec = 1734*45916cd2Sjpk devinfo.devlist = NULL; 1735*45916cd2Sjpk if (dargs.optflag & DA_ADD_ZONE) { 1736*45916cd2Sjpk len = strlen(DAOPT_ZONE) + strlen(zonename) + 3; 1737*45916cd2Sjpk if ((optstr = (char *)malloc(len)) == NULL) 1738*45916cd2Sjpk return (-1); 1739*45916cd2Sjpk (void) snprintf(optstr, len, "%s%s%s", DAOPT_ZONE, KV_ASSIGN, 1740*45916cd2Sjpk zonename); 1741*45916cd2Sjpk devinfo.devopts = optstr; 1742*45916cd2Sjpk } 1743*45916cd2Sjpk dargs.devinfo = &devinfo; 1744*45916cd2Sjpk 1745*45916cd2Sjpk rc = da_update_device(&dargs); 1746*45916cd2Sjpk 1747*45916cd2Sjpk if (optstr) 1748*45916cd2Sjpk free(optstr); 1749*45916cd2Sjpk 1750*45916cd2Sjpk return (rc); 1751*45916cd2Sjpk } 1752