Home | History | Annotate | Download | only in allocate
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 
     22 /*
     23  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
     24  * Use is subject to license terms.
     25  */
     26 
     27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
     28 
     29 #include <auth_attr.h>
     30 #include <auth_list.h>
     31 #include <dirent.h>
     32 #include <errno.h>
     33 #include <fcntl.h>
     34 #include <libintl.h>
     35 #include <locale.h>
     36 #include <pwd.h>
     37 #include <signal.h>
     38 #include <stdio.h>
     39 #include <stdlib.h>
     40 #include <string.h>
     41 #include <strings.h>
     42 #include <unistd.h>
     43 #include <bsm/devices.h>
     44 #include <sys/acl.h>
     45 #include <tsol/label.h>
     46 #include <syslog.h>
     47 #include <limits.h>
     48 #include <user_attr.h>
     49 #include <secdb.h>
     50 #include <sys/mkdev.h>
     51 #include <sys/acl.h>
     52 #include <sys/file.h>
     53 #include <sys/procfs.h>
     54 #include <sys/param.h>
     55 #include <sys/resource.h>
     56 #include <sys/stat.h>
     57 #include <sys/time.h>
     58 #include <sys/types.h>
     59 #include <sys/wait.h>
     60 #include <utime.h>
     61 #include <libgen.h>
     62 #include <zone.h>
     63 #include <nss_dbdefs.h>
     64 #include <bsm/devalloc.h>
     65 #include <libdevinfo.h>
     66 #include "allocate.h"
     67 
     68 extern void print_error(int, char *);
     69 
     70 #if	defined(DEBUG) || defined(lint)
     71 #define	dprintf(s, a) (void) fprintf(stderr, s, a)
     72 #define	dperror(s) perror(s)
     73 #else	/* !DEBUG */
     74 #define	dprintf(s, a)	0
     75 #define	dperror(s)	0
     76 #endif	/* DEBUG */
     77 
     78 #define	DEV_ERRORED(sbuf)	(((sbuf).st_mode & ~S_IFMT) == ALLOC_ERR_MODE)
     79 #define	DEV_ALLOCATED(sbuf)	((sbuf).st_uid != DA_UID || \
     80 			!(((sbuf).st_mode & ~S_IFMT) == DEALLOC_MODE || \
     81 			DEV_ERRORED(sbuf)))
     82 
     83 #define	ALLOC_CLEAN		"-A"
     84 #define	DEALLOC_CLEAN		"-D"
     85 #define	DAC_DIR			"/etc/security/dev"
     86 #define	DEVICE_AUTH_SEPARATOR	","
     87 #define	LOCALDEVICE		"/dev/console"
     88 #define	PROCFS			"/proc/"
     89 #define	SFF_NO_ERROR		0x1
     90 
     91 #define	ALLOC_BY_NONE		-1
     92 #define	CHECK_DRANGE		1
     93 #define	CHECK_URANGE		2
     94 #define	CHECK_ZLABEL		3
     95 
     96 extern void audit_allocate_list(char *);
     97 extern void audit_allocate_device(char *);
     98 
     99 extern int	system_labeled;
    100 extern char	*newenv[];
    101 
    102 struct state_file {
    103 	int	sf_flags;
    104 	char	sf_path[MAXPATHLEN];
    105 };
    106 
    107 struct file_info {
    108 	struct stat	fi_stat;
    109 	char		*fi_message;
    110 };
    111 
    112 struct zone_path {
    113 	int	count;
    114 	char	**path;
    115 };
    116 
    117 struct dev_names {
    118 	char **dnames;
    119 };
    120 
    121 static int _dev_file_name(struct state_file *, devmap_t *);
    122 static int lock_dev(char *, struct stat *);
    123 static int _check_label(devalloc_t *, char *, uid_t, int);
    124 static int create_znode(char *, struct zone_path *, devmap_t *);
    125 static int remove_znode(char *, devmap_t *);
    126 static int update_device(char **, char *, int);
    127 
    128 /*
    129  * checks if the invoking user is local to the device
    130  */
    131 /*ARGSUSED*/
    132 int
    133 _is_local(uid_t uid)
    134 {
    135 	struct stat	statbuf;
    136 
    137 	if (stat(LOCALDEVICE, &statbuf) == 0 &&
    138 	    statbuf.st_uid == uid)
    139 		return (1);
    140 
    141 	return (0);
    142 }
    143 
    144 /*
    145  * Checks if the user with the specified uid has the specified authorization
    146  */
    147 int
    148 _is_authorized(char *auths, uid_t uid)
    149 {
    150 	char		*dcp, *authlist, *lasts;
    151 	char		pw_buf[NSS_BUFLEN_PASSWD];
    152 	struct passwd	pw_ent;
    153 
    154 	/*
    155 	 * first, the easy cases
    156 	 */
    157 	if (strcmp(auths, "@") == 0)
    158 		return (1);
    159 	if (strcmp(auths, "*") == 0)
    160 		return (ALLOC_BY_NONE);
    161 	if (getpwuid_r(uid, &pw_ent, pw_buf, sizeof (pw_buf)) == NULL)
    162 		return (0);
    163 	if (strpbrk(auths, DEVICE_AUTH_SEPARATOR) == NULL)
    164 		return (chkauthattr(auths, pw_ent.pw_name));
    165 	authlist = strdup(auths);
    166 	if (authlist == NULL)
    167 		return (0);
    168 	for (dcp = authlist;
    169 	    (dcp = strtok_r(dcp, DEVICE_AUTH_SEPARATOR, &lasts)) != NULL;
    170 	    dcp = NULL) {
    171 		if (chkauthattr(dcp, pw_ent.pw_name))
    172 			break;
    173 	}
    174 	free(authlist);
    175 
    176 	return (dcp != NULL);
    177 }
    178 
    179 /*
    180  * Checks if the specified user has authorization for the device
    181  */
    182 int
    183 _is_dev_authorized(devalloc_t *da, uid_t uid)
    184 {
    185 	int	ares;
    186 	char	*auth_list, *dcp, *subauth = NULL;
    187 
    188 	auth_list = da->da_devauth;
    189 	if (auth_list == NULL)
    190 		return (0);
    191 	dcp = strpbrk(auth_list, KV_TOKEN_DELIMIT);
    192 	if (dcp == NULL)
    193 		return (_is_authorized(auth_list, uid));
    194 	if (_is_local(uid)) {
    195 		/* the local authorization is before the separator */
    196 		ares = dcp - auth_list;
    197 		subauth = malloc(ares + 1);
    198 		if (subauth == NULL)
    199 			return (0);
    200 		(void) strlcpy(subauth, auth_list, (ares + 1));
    201 		auth_list = subauth;
    202 	} else
    203 		auth_list = dcp + 1;
    204 	ares = _is_authorized(auth_list, uid);
    205 	if (subauth != NULL)
    206 		free(subauth);
    207 
    208 	return (ares);
    209 }
    210 
    211 int
    212 check_devs(devmap_t *dm)
    213 {
    214 	int	status = 0;
    215 	char	**file;
    216 
    217 	if (dm->dmap_devarray == NULL)
    218 		return (NODMAPERR);
    219 	for (file = dm->dmap_devarray; *file != NULL; file++) {
    220 		if ((status = access(*file, F_OK)) == -1) {
    221 			dprintf("Unable to access file %s\n", *file);
    222 			break;
    223 		}
    224 	}
    225 
    226 	return (status);
    227 }
    228 
    229 int
    230 print_da_defs(da_defs_t *da_defs)
    231 {
    232 	char	optbuf[BUFSIZ];
    233 	char	*p = NULL;
    234 
    235 	if (da_defs->devopts == NULL) {
    236 		dprintf("No default attributes for %s\n", da_defs->devtype);
    237 		return (DEFATTRSERR);
    238 	}
    239 	(void) printf("dev_type=%s\n", da_defs->devtype);
    240 	if (_kva2str(da_defs->devopts, optbuf, sizeof (optbuf), KV_ASSIGN,
    241 	    KV_TOKEN_DELIMIT) == 0) {
    242 		if (p = rindex(optbuf, ':'))
    243 			*p = '\0';
    244 		(void) printf("\t%s\n", optbuf);
    245 	}
    246 
    247 	return (0);
    248 }
    249 
    250 void
    251 print_dev_attrs(int optflag, devalloc_t *da, devmap_t *dm,
    252     struct file_info *fip)
    253 {
    254 	char	*p = NULL;
    255 	char	optbuf[BUFSIZ];
    256 
    257 	(void) printf("device=%s%s", dm->dmap_devname, KV_DELIMITER);
    258 	(void) printf("type=%s%s", dm->dmap_devtype, KV_DELIMITER);
    259 	(void) printf("auths=%s%s",
    260 	    (da->da_devauth ? da->da_devauth : ""), KV_DELIMITER);
    261 	(void) printf("clean=%s%s",
    262 	    (da->da_devexec ? da->da_devexec : ""), KV_DELIMITER);
    263 	if (da->da_devopts != NULL) {
    264 		if (_kva2str(da->da_devopts, optbuf, sizeof (optbuf),
    265 		    KV_ASSIGN, KV_TOKEN_DELIMIT) == 0) {
    266 			if (p = rindex(optbuf, ':'))
    267 				*p = '\0';
    268 			(void) printf("%s", optbuf);
    269 		}
    270 	}
    271 	(void) printf("%s", KV_DELIMITER);
    272 	if (optflag & WINDOWING) {
    273 		if ((fip->fi_message != NULL) &&
    274 		    (strcmp(fip->fi_message, DAOPT_CLASS) == 0))
    275 			(void) printf("owner=/FREE%s", KV_DELIMITER);
    276 		else if (DEV_ERRORED(fip->fi_stat))
    277 			(void) printf("owner=/ERROR%s", KV_DELIMITER);
    278 		else if (!DEV_ALLOCATED(fip->fi_stat))
    279 			(void) printf("owner=/FREE%s", KV_DELIMITER);
    280 		else
    281 			(void) printf("owner=%u%s", fip->fi_stat.st_uid,
    282 			    KV_DELIMITER);
    283 	}
    284 	(void) printf("files=%s", dm->dmap_devlist);
    285 	(void) printf("\n");
    286 }
    287 
    288 void
    289 print_dev(devmap_t *dm)
    290 {
    291 	char	**file;
    292 
    293 	(void) printf(gettext("device: %s "), dm->dmap_devname);
    294 	(void) printf(gettext("type: %s "), dm->dmap_devtype);
    295 	(void) printf(gettext("files:"));
    296 	file = dm->dmap_devarray;
    297 	if (file != NULL) {
    298 		for (; *file != NULL; file++)
    299 			(void) printf(" %s", *file);
    300 	}
    301 	(void) printf("\n");
    302 }
    303 
    304 /* ARGSUSED */
    305 int
    306 _list_device(int optflag, uid_t uid, devalloc_t *da, char *zonename)
    307 {
    308 	int			bytes = 0;
    309 	int			error = 0;
    310 	int			is_authorized = 0;
    311 	char			*fname = NULL;
    312 	char			file_name[MAXPATHLEN];
    313 	devmap_t		*dm;
    314 	struct file_info	fi;
    315 	struct state_file	sf;
    316 
    317 	fi.fi_message = NULL;
    318 	setdmapent();
    319 	if ((dm = getdmapnam(da->da_devname)) == NULL) {
    320 		enddmapent();
    321 		dprintf("Unable to find %s in the maps database\n",
    322 		    da->da_devname);
    323 		return (NODMAPERR);
    324 	}
    325 	enddmapent();
    326 
    327 	if ((optflag & CLASS) &&
    328 	    (!(optflag & (LISTALL | LISTFREE | LISTALLOC)))) {
    329 		fi.fi_message = DAOPT_CLASS;
    330 		if (optflag & LISTATTRS)
    331 			print_dev_attrs(optflag, da, dm, &fi);
    332 		else
    333 			print_dev(dm);
    334 		goto out;
    335 	}
    336 
    337 	if (system_labeled) {
    338 		if ((error = _dev_file_name(&sf, dm)) != 0) {
    339 			freedmapent(dm);
    340 			dprintf("Unable to find %s device files\n",
    341 			    da->da_devname);
    342 			error = NODMAPERR;
    343 			goto out;
    344 		}
    345 		fname = sf.sf_path;
    346 	} else {
    347 		bytes = snprintf(file_name, MAXPATHLEN, "%s/%s", DAC_DIR,
    348 		    da->da_devname);
    349 		if (bytes <= 0) {
    350 			error = DEVNAMEERR;
    351 			goto out;
    352 		} else if (bytes >= MAXPATHLEN) {
    353 			dprintf("device name %s is too long.\n",
    354 			    da->da_devname);
    355 			error = DEVLONGERR;
    356 			goto out;
    357 		}
    358 		fname = file_name;
    359 	}
    360 	if (stat(fname, &fi.fi_stat) != 0) {
    361 		dprintf("Unable to stat %s\n", fname);
    362 		dperror("Error:");
    363 		error = DACACCERR;
    364 		goto out;
    365 	}
    366 	if (optflag & USERID)
    367 		is_authorized = 1;
    368 	else
    369 		is_authorized = _is_dev_authorized(da, uid);
    370 	if (optflag & LISTFREE) {	/* list_devices -n */
    371 		/*
    372 		 * list all free devices
    373 		 */
    374 		if (DEV_ALLOCATED(fi.fi_stat)) {
    375 				error = PREALLOCERR;
    376 				goto out;
    377 		}
    378 		if (system_labeled) {
    379 			/*
    380 			 * for this free device, check if -
    381 			 * 1. user has authorization to allocate
    382 			 * 2. the zone label is within the label range of the
    383 			 *    device
    384 			 */
    385 			if (is_authorized == ALLOC_BY_NONE) {
    386 				error = DAUTHERR;
    387 				goto out;
    388 			} else if (is_authorized == 0) {
    389 				error = UAUTHERR;
    390 				goto out;
    391 			}
    392 			if (_check_label(da, zonename, uid,
    393 			    CHECK_DRANGE) != 0) {
    394 				error = LABELRNGERR;
    395 				goto out;
    396 			}
    397 		}
    398 	} else if (optflag & LISTALLOC) {	/*  list_devices -u */
    399 		/*
    400 		 * list all allocated devices
    401 		 */
    402 		if (!DEV_ALLOCATED(fi.fi_stat)) {
    403 			error = DEVNALLOCERR;
    404 			goto out;
    405 		}
    406 		if (fi.fi_stat.st_uid != uid) {
    407 			error = DEVSTATEERR;
    408 			goto out;
    409 		}
    410 		if (system_labeled) {
    411 			/*
    412 			 * check if the zone label equals the label at which
    413 			 * the device is allocated.
    414 			 */
    415 			if (_check_label(da, zonename, uid,
    416 			    CHECK_ZLABEL) != 0) {
    417 				error = LABELRNGERR;
    418 				goto out;
    419 			}
    420 		}
    421 	} else if (optflag & LISTALL) {		/* list_devices -l */
    422 		/*
    423 		 * list all devices - free and allocated - available
    424 		 */
    425 		if (DEV_ALLOCATED(fi.fi_stat)) {
    426 			if (optflag & WINDOWING &&
    427 			    (is_authorized == ALLOC_BY_NONE)) {
    428 				/*
    429 				 * don't complain if we're here for the GUI.
    430 				 */
    431 				error = 0;
    432 			} else if (fi.fi_stat.st_uid != uid) {
    433 				if (!(optflag & WINDOWING)) {
    434 					error = ALLOCUERR;
    435 					goto out;
    436 				}
    437 			}
    438 			if (system_labeled && !(optflag & WINDOWING)) {
    439 				/*
    440 				 * if we're not displaying in the GUI,
    441 				 * check if the zone label equals the label
    442 				 * at which the device is allocated.
    443 				 */
    444 				if (_check_label(da, zonename, uid,
    445 				    CHECK_ZLABEL) != 0) {
    446 					error = LABELRNGERR;
    447 					goto out;
    448 				}
    449 			}
    450 		} else if (system_labeled && !(optflag & WINDOWING)) {
    451 			/*
    452 			 * if we're not displaying in the GUI,
    453 			 * for this free device, check if -
    454 			 * 1. user has authorization to allocate
    455 			 * 2. the zone label is within the label range of the
    456 			 *    device
    457 			 */
    458 			if (is_authorized == ALLOC_BY_NONE) {
    459 				error = DAUTHERR;
    460 				goto out;
    461 			} else if (is_authorized == 0) {
    462 				error = UAUTHERR;
    463 				goto out;
    464 			}
    465 			if (_check_label(da, zonename, uid,
    466 			    CHECK_DRANGE) != 0) {
    467 				error = LABELRNGERR;
    468 				goto out;
    469 			}
    470 		}
    471 	}
    472 	if (system_labeled && DEV_ERRORED(fi.fi_stat) && !(optflag & LISTALL)) {
    473 		error = DEVSTATEERR;
    474 		goto out;
    475 	}
    476 	if (check_devs(dm) == -1) {
    477 		error = DSPMISSERR;
    478 		goto out;
    479 	}
    480 	if (optflag & LISTATTRS)
    481 		print_dev_attrs(optflag, da, dm, &fi);
    482 	else
    483 		print_dev(dm);
    484 
    485 	error = 0;
    486 
    487 out:
    488 	freedmapent(dm);
    489 	return (error);
    490 }
    491 
    492 /* ARGSUSED */
    493 int
    494 list_devices(int optflag, uid_t uid, char *device, char *zonename)
    495 {
    496 	int		error = 0;
    497 	char		*class = NULL;
    498 	da_defs_t	*da_defs;
    499 	devalloc_t	*da;
    500 
    501 	if (system_labeled && optflag & WINDOWING && !(optflag & LISTATTRS)) {
    502 		/*
    503 		 * Private interface for GUI.
    504 		 */
    505 		(void) puts(DA_DB_LOCK);
    506 		return (0);
    507 	}
    508 	if (optflag & USERID) {
    509 		/*
    510 		 * we need device.revoke to list someone else's devices
    511 		 */
    512 		if (!_is_authorized(DEVICE_REVOKE_AUTH, getuid()))
    513 			return (UAUTHERR);
    514 	}
    515 	if (system_labeled) {
    516 		if (!(optflag & USERID) &&
    517 		    !_is_authorized(DEFAULT_DEV_ALLOC_AUTH, uid))
    518 			/*
    519 			 * we need device.allocate to list our devices
    520 			 */
    521 			return (UAUTHERR);
    522 		if (optflag & LISTDEFS) {
    523 			/*
    524 			 * list default attrs from devalloc_defaults
    525 			 */
    526 			setdadefent();
    527 			if (device) {
    528 				/*
    529 				 * list default attrs for this device type
    530 				 */
    531 				da_defs = getdadeftype(device);
    532 				if (da_defs == NULL) {
    533 					enddadefent();
    534 					dprintf("No default attributes for "
    535 					    "%s\n", device);
    536 					return (DEFATTRSERR);
    537 				}
    538 				error = print_da_defs(da_defs);
    539 				freedadefent(da_defs);
    540 			} else {
    541 				/*
    542 				 * list everything in devalloc_defaults
    543 				 */
    544 				while ((da_defs = getdadefent()) != NULL) {
    545 					(void) print_da_defs(da_defs);
    546 					freedadefent(da_defs);
    547 				}
    548 			}
    549 			enddadefent();
    550 			return (error);
    551 		}
    552 	}
    553 	/*
    554 	 * Lock the database to make sure no body writes to it while we are
    555 	 * reading.
    556 	 */
    557 	(void) lock_dev(NULL, NULL);
    558 	setdaent();
    559 	if (device) {
    560 		if (optflag & CLASS) {
    561 			/*
    562 			 * list all devices of this class.
    563 			 */
    564 			while ((da = getdaent()) != NULL) {
    565 				class =	 kva_match(da->da_devopts, DAOPT_CLASS);
    566 				if (class && (strcmp(class, device) == 0)) {
    567 					(void) _list_device(optflag, uid, da,
    568 					    zonename);
    569 				}
    570 				freedaent(da);
    571 			}
    572 		} else {
    573 			/*
    574 			 * list this device
    575 			 */
    576 			if ((da = getdanam(device)) == NULL) {
    577 				enddaent();
    578 				return (NODAERR);
    579 			}
    580 			error = _list_device(optflag, uid, da, zonename);
    581 			freedaent(da);
    582 		}
    583 	} else {
    584 		/*
    585 		 * list all devices
    586 		 */
    587 		while ((da = getdaent()) != NULL) {
    588 			(void) _list_device(optflag, uid, da, zonename);
    589 			freedaent(da);
    590 		}
    591 	}
    592 	enddaent();
    593 
    594 	return (error);
    595 }
    596 
    597 /*
    598  * Set the DAC characteristics of the file.
    599  * This uses a fancy chmod() by setting a minimal ACL which sets the mode
    600  * and discards any existing ACL.
    601  */
    602 int
    603 _newdac(char *file, uid_t owner, gid_t group, o_mode_t mode)
    604 {
    605 	int	err = 0;
    606 
    607 	if (mode == ALLOC_MODE) {
    608 		if (chown(file, owner, group) == -1) {
    609 			dperror("newdac: unable to chown");
    610 			err = CHOWNERR;
    611 		}
    612 	} else do {
    613 		if (chown(file, owner, group) == -1) {
    614 			dperror("newdac: unable to chown");
    615 			err = CHOWNERR;
    616 		}
    617 	} while (fdetach(file) == 0);
    618 
    619 	if (err)
    620 		return (err);
    621 
    622 	if (strncmp(file, "/dev/", strlen("/dev/")) != 0) {
    623 		/*
    624 		 * This could be a SunRay device that is in /tmp.
    625 		 */
    626 		if (chmod(file, mode) == -1) {
    627 			dperror("newdac: unable to chmod");
    628 			err = SETACLERR;
    629 		}
    630 	} else {
    631 		err = acl_strip(file, owner, group, (mode_t)mode);
    632 	}
    633 
    634 	if (err != 0) {
    635 		dperror("newdac: unable to setacl");
    636 		err = SETACLERR;
    637 	}
    638 
    639 	return (err);
    640 }
    641 
    642 /*
    643  * lock_dev -
    644  *	locks a section of DA_DB_LOCK.
    645  *	returns lock fd if successful, else -1 on error.
    646  */
    647 static int
    648 lock_dev(char *file, struct stat *statbuf)
    649 {
    650 	static int	lockfd = -1;
    651 	int		ret;
    652 	int		count = 0;
    653 	int		retry = 10;
    654 	off_t		size = 0;
    655 	off_t		offset;
    656 	char		*lockfile;
    657 
    658 	if (system_labeled)
    659 		lockfile = DA_DB_LOCK;
    660 	else
    661 		lockfile = file;
    662 
    663 	if (statbuf) {
    664 		offset = statbuf->st_rdev;
    665 		dprintf("locking %s\n", file);
    666 	} else {
    667 		offset = 0;
    668 		dprintf("locking %s\n", lockfile);
    669 	}
    670 	if ((lockfd == -1) &&
    671 	    (lockfd = open(lockfile, O_RDWR | O_CREAT, 0600)) == -1) {
    672 		dperror("lock_dev: cannot open lock file");
    673 		return (-1);
    674 	}
    675 	if (system_labeled) {
    676 		(void) _newdac(lockfile, DA_UID, DA_GID, 0600);
    677 		if (lseek(lockfd, offset, SEEK_SET) == -1) {
    678 			dperror("lock_dev: cannot position lock file");
    679 			return (-1);
    680 		}
    681 		size = 1;
    682 	}
    683 	errno = 0;
    684 	while (retry) {
    685 		count++;
    686 		ret = lockf(lockfd, F_TLOCK, size);
    687 		if (ret == 0)
    688 			return (lockfd);
    689 		if ((errno != EACCES) && (errno != EAGAIN)) {
    690 			dperror("lock_dev: cannot set lock");
    691 			return (-1);
    692 		}
    693 		retry--;
    694 		(void) sleep(count);
    695 		errno = 0;
    696 	}
    697 
    698 	return (-1);
    699 }
    700 
    701 int
    702 mk_alloc(devmap_t *list, uid_t uid, struct zone_path *zpath)
    703 {
    704 	int	i;
    705 	int	error = 0;
    706 	char	**file;
    707 	gid_t	gid = getgid();
    708 	mode_t	mode = ALLOC_MODE;
    709 
    710 	file = list->dmap_devarray;
    711 	if (file == NULL)
    712 		return (NODMAPERR);
    713 	for (; *file != NULL; file++) {
    714 		dprintf("Allocating %s\n", *file);
    715 		if ((error = _newdac(*file, uid, gid, mode)) != 0) {
    716 			(void) _newdac(*file, ALLOC_ERRID, DA_GID,
    717 			    ALLOC_ERR_MODE);
    718 			break;
    719 		}
    720 	}
    721 	if (system_labeled && zpath->count && (error == 0)) {
    722 		/*
    723 		 * mark as allocated any new device nodes that we
    724 		 * created in local zone
    725 		 */
    726 		for (i = 0; i < zpath->count; i++) {
    727 			dprintf("Allocating %s\n", zpath->path[i]);
    728 			if ((error = _newdac(zpath->path[i], uid, gid,
    729 			    mode)) != 0) {
    730 				(void) _newdac(zpath->path[i], ALLOC_ERRID,
    731 				    DA_GID, ALLOC_ERR_MODE);
    732 				break;
    733 			}
    734 		}
    735 	}
    736 
    737 	return (error);
    738 }
    739 
    740 /*
    741  * mk_revoke() is used instead of system("/usr/sbin/fuser -k file")
    742  * because "/usr/sbin/fuser -k file" kills all processes
    743  * working with the file, even "vold" (bug #4095152).
    744  */
    745 int
    746 mk_revoke(int optflag, char *file)
    747 {
    748 	int		r = 0, p[2], fp, lock;
    749 	int		fuserpid;
    750 	char		buf[MAXPATHLEN];
    751 	FILE		*ptr;
    752 	pid_t		c_pid;
    753 	prpsinfo_t	info;
    754 
    755 	(void) strcpy(buf, PROCFS);
    756 	/*
    757 	 * vfork() and execl() just to make the same output
    758 	 * as before fixing of bug #4095152.
    759 	 * The problem is that the "fuser" command prints
    760 	 * one part of output into stderr and another into stdout,
    761 	 * but user sees them mixed. Of course, better to change "fuser"
    762 	 * or to intercept and not to print its output.
    763 	 */
    764 	if (!(optflag & SILENT)) {
    765 		c_pid = vfork();
    766 		if (c_pid == -1)
    767 			return (-1);
    768 		if (c_pid == 0) {
    769 			dprintf("first exec fuser %s\n", file);
    770 			(void) execl("/usr/sbin/fuser", "fuser", file, NULL);
    771 			dperror("first exec fuser");
    772 			_exit(1);
    773 		}
    774 
    775 		(void) waitpid(c_pid, &lock, 0);
    776 		dprintf("exit status %x\n", lock);
    777 		if (WEXITSTATUS(lock) != 0)
    778 			return (-1);
    779 	}
    780 	dprintf("first continuing c_pid=%d\n", (int)c_pid);
    781 	if (pipe(p)) {
    782 		dperror("pipe");
    783 		return (-1);
    784 	}
    785 	/* vfork() and execl() to catch output and to process it */
    786 	c_pid = vfork();
    787 	if (c_pid == -1) {
    788 		dperror("second vfork");
    789 		return (-1);
    790 	}
    791 	dprintf("second continuing c_pid=%d\n", (int)c_pid);
    792 	if (c_pid == 0) {
    793 		(void) close(p[0]);
    794 		(void) close(1);
    795 		(void) fcntl(p[1], F_DUPFD, 1);
    796 		(void) close(p[1]);
    797 		(void) close(2);
    798 		dprintf("second exec fuser %s\n", file);
    799 		(void) execl("/usr/sbin/fuser", "fuser", file, NULL);
    800 		dperror("second exec fuser");
    801 		_exit(1);
    802 	}
    803 	(void) close(p[1]);
    804 	if ((ptr = fdopen(p[0], "r")) != NULL) {
    805 		while (!feof(ptr)) {
    806 			if (fscanf(ptr, "%d", &fuserpid) > 0) {
    807 				(void) sprintf(buf + strlen(PROCFS), "%d",
    808 				    fuserpid);
    809 				if ((fp = open(buf, O_RDONLY)) == -1) {
    810 					dperror(buf);
    811 					continue;
    812 				}
    813 				if (ioctl(fp, PIOCPSINFO,
    814 				    (char *)&info) == -1) {
    815 					dprintf("%d psinfo failed", fuserpid);
    816 					dperror("");
    817 					(void) close(fp);
    818 					continue;
    819 				}
    820 				(void) close(fp);
    821 				if (strcmp(info.pr_fname, "vold") == NULL) {
    822 					dprintf("%d matched vold name\n",
    823 					    fuserpid);
    824 					continue;
    825 				}
    826 				dprintf("killing %s", info.pr_fname);
    827 				dprintf("(%d)\n", fuserpid);
    828 				if ((r =
    829 				    kill((pid_t)fuserpid, SIGKILL)) == -1) {
    830 					dprintf("kill %d", fuserpid);
    831 					dperror("");
    832 					break;
    833 				}
    834 			}
    835 		}
    836 	} else {
    837 		dperror("fdopen(p[0], r)");
    838 		r = -1;
    839 	}
    840 	(void) fclose(ptr);
    841 
    842 	return (r);
    843 }
    844 
    845 int
    846 mk_unalloc(int optflag, devmap_t *list)
    847 {
    848 	int	error = 0;
    849 	int	status;
    850 	char	**file;
    851 
    852 	audit_allocate_list(list->dmap_devlist);
    853 	file = list->dmap_devarray;
    854 	if (file == NULL)
    855 		return (NODMAPERR);
    856 	for (; *file != NULL; file++) {
    857 		dprintf("Deallocating %s\n", *file);
    858 		if (mk_revoke(optflag, *file) < 0) {
    859 			dprintf("mk_unalloc: unable to revoke %s\n", *file);
    860 			dperror("");
    861 			error = CNTFRCERR;
    862 		}
    863 		status = _newdac(*file, DA_UID, DA_GID, DEALLOC_MODE);
    864 		if (error == 0)
    865 			error = status;
    866 
    867 	}
    868 
    869 	return (error);
    870 }
    871 
    872 int
    873 mk_error(devmap_t *list)
    874 {
    875 	int	status = 0;
    876 	char	**file;
    877 
    878 	audit_allocate_list(list->dmap_devlist);
    879 	file = list->dmap_devarray;
    880 	if (file == NULL)
    881 		return (NODMAPERR);
    882 	for (; *file != NULL; file++) {
    883 		dprintf("Putting %s in error state\n", *file);
    884 		status = _newdac(*file, ALLOC_ERRID, DA_GID, ALLOC_ERR_MODE);
    885 	}
    886 
    887 	return (status);
    888 }
    889 
    890 int
    891 exec_clean(int optflag, char *devname, char *path, uid_t uid, char *zonename,
    892     char *clean_arg)
    893 {
    894 	int		c;
    895 	int		status = 0, exit_status;
    896 	char		*mode, *cmd, *wdwcmd, *zoneroot;
    897 	char		*devzone = zonename;
    898 	char		wdwpath[PATH_MAX];
    899 	char		zonepath[MAXPATHLEN];
    900 	char		title[100];
    901 	char		pw_buf[NSS_BUFLEN_PASSWD];
    902 	struct passwd	pw_ent;
    903 
    904 	zonepath[0] = '\0';
    905 	if (system_labeled) {
    906 		if ((zoneroot = getzonerootbyname(zonename)) == NULL) {
    907 			if (strcmp(clean_arg, ALLOC_CLEAN) == 0) {
    908 				return (-1);
    909 			} else if (optflag & FORCE) {
    910 				(void) strcpy(zonepath, "/");
    911 				devzone = GLOBAL_ZONENAME;
    912 			} else {
    913 				dprintf("unable to get label for %s zone\n",
    914 				    zonename);
    915 				return (-1);
    916 			}
    917 		} else {
    918 			(void) strcpy(zonepath, zoneroot);
    919 			free(zoneroot);
    920 		}
    921 	}
    922 	if (getpwuid_r(uid, &pw_ent, pw_buf, sizeof (pw_buf)) == NULL)
    923 		return (-1);
    924 	if (optflag & FORCE_ALL)
    925 		mode = "-I";
    926 	else if (optflag & FORCE)
    927 		mode = "-f";
    928 	else
    929 		mode = "-s";
    930 	if (path == NULL)
    931 		return (0);
    932 	if ((cmd = strrchr(path, '/')) == NULL)
    933 		cmd = path;
    934 	else
    935 		cmd++;	/* skip leading '/' */
    936 	c = vfork();
    937 	switch (c) {
    938 	case -1:
    939 		return (-1);
    940 	case 0:
    941 		(void) setuid(0);
    942 		if (system_labeled && (optflag & WINDOWING)) {
    943 			/* First try .windowing version of script */
    944 			(void) strncpy(wdwpath, path, PATH_MAX);
    945 			(void) strncat(wdwpath, ".windowing", PATH_MAX);
    946 			if ((wdwcmd = strrchr(wdwpath, '/')) == NULL)
    947 				wdwcmd = wdwpath;
    948 			(void) execl(wdwpath, wdwcmd, mode, devname, clean_arg,
    949 			    pw_ent.pw_name, devzone, zonepath, NULL);
    950 			/* If that failed, run regular version via dtterm */
    951 			(void) snprintf(title, sizeof (title),
    952 			    "Device %s for %s",
    953 			    strcmp(clean_arg, ALLOC_CLEAN) == 0 ?
    954 			    "allocation" : "deallocation", devname);
    955 			(void) execl("/usr/dt/bin/dtterm", "dtterm",
    956 			    "-title", title, "-geometry", "x10+100+400",
    957 			    "-e", "/etc/security/lib/wdwwrapper",
    958 			    path, mode, devname, clean_arg, pw_ent.pw_name,
    959 			    devzone, zonepath, NULL);
    960 			/*
    961 			 * And if that failed, continue on to try
    962 			 * running regular version directly.
    963 			 */
    964 		}
    965 		dprintf("clean script: %s, ", path);
    966 		dprintf("cmd=%s, ", cmd);
    967 		dprintf("mode=%s, ", mode);
    968 		if (system_labeled) {
    969 			dprintf("devname=%s ", devname);
    970 			dprintf("zonename=%s ", devzone);
    971 			dprintf("zonepath=%s ", zonepath);
    972 			dprintf("username=%s\n", pw_ent.pw_name);
    973 			(void) execl(path, cmd, mode, devname, clean_arg,
    974 			    pw_ent.pw_name, devzone, zonepath, NULL);
    975 		} else {
    976 			dprintf("devname=%s\n", devname);
    977 			(void) execle(path, cmd, mode, devname, NULL, newenv);
    978 		}
    979 		dprintf("Unable to execute clean up script %s\n", path);
    980 		dperror("");
    981 		exit(CNTDEXECERR);
    982 	default:
    983 		(void) waitpid(c, &status, 0);
    984 		dprintf("Child %d", c);
    985 		if (WIFEXITED(status)) {
    986 			exit_status = WEXITSTATUS(status);
    987 			dprintf(" exited, status: %d\n", exit_status);
    988 			return (exit_status);
    989 		} else if (WIFSIGNALED(status)) {
    990 			dprintf(" killed, signal %d\n", WTERMSIG(status));
    991 		} else {
    992 			dprintf(": exit status %d\n", status);
    993 		}
    994 		return (-1);
    995 	}
    996 }
    997 
    998 int
    999 _deallocate_dev(int optflag, devalloc_t *da, devmap_t *dm_in, uid_t uid,
   1000     char *zonename, int *lock_fd)
   1001 {
   1002 	int			bytes = 0;
   1003 	int			error = 0;
   1004 	int			is_authorized = 0;
   1005 	uid_t			nuid;
   1006 	char			*fname = NULL;
   1007 	char			file_name[MAXPATHLEN];
   1008 	char			*devzone = NULL;
   1009 	devmap_t		*dm = NULL, *dm_new = NULL;
   1010 	struct stat		stat_buf;
   1011 	struct state_file	sf;
   1012 
   1013 	if (dm_in == NULL) {
   1014 		setdmapent();
   1015 		if ((dm_new = getdmapnam(da->da_devname)) == NULL) {
   1016 			enddmapent();
   1017 			dprintf("Unable to find %s in device map database\n",
   1018 			    da->da_devname);
   1019 			return (NODMAPERR);
   1020 		}
   1021 		enddmapent();
   1022 		dm = dm_new;
   1023 	} else {
   1024 		dm = dm_in;
   1025 	}
   1026 	if (system_labeled) {
   1027 		if (_dev_file_name(&sf, dm) != 0) {
   1028 			if (dm_new)
   1029 				freedmapent(dm_new);
   1030 			dprintf("Unable to find %s device files\n",
   1031 			    da->da_devname);
   1032 			error = NODMAPERR;
   1033 			goto out;
   1034 		}
   1035 		fname = sf.sf_path;
   1036 	} else {
   1037 		bytes = snprintf(file_name,  MAXPATHLEN, "%s/%s", DAC_DIR,
   1038 		    da->da_devname);
   1039 		if (bytes <= 0) {
   1040 			error = DEVNAMEERR;
   1041 			goto out;
   1042 		} else if (bytes >= MAXPATHLEN) {
   1043 			dprintf("device name %s is too long.\n",
   1044 			    da->da_devname);
   1045 			error = DEVLONGERR;
   1046 			goto out;
   1047 		}
   1048 		fname = file_name;
   1049 	}
   1050 
   1051 	audit_allocate_device(fname);
   1052 
   1053 	if (stat(fname, &stat_buf) != 0) {
   1054 		dprintf("Unable to stat %s\n", fname);
   1055 		error = DACACCERR;
   1056 		goto out;
   1057 	}
   1058 	is_authorized = _is_dev_authorized(da, uid);
   1059 	if (!(optflag & (FORCE | FORCE_ALL)) && !is_authorized) {
   1060 		dprintf("User %d is unauthorized to deallocate\n", (int)uid);
   1061 		error = UAUTHERR;
   1062 		goto out;
   1063 	}
   1064 	if (system_labeled) {
   1065 		/*
   1066 		 * unless we're here to deallocate by force, check if the
   1067 		 * label at which the device is currently allocated is
   1068 		 * within the user label range.
   1069 		 */
   1070 		if (!(optflag & FORCE) &&
   1071 		    _check_label(da, zonename, uid, CHECK_URANGE) != 0) {
   1072 			error = LABELRNGERR;
   1073 			goto out;
   1074 		}
   1075 	}
   1076 	if (!(optflag & FORCE) && stat_buf.st_uid != uid &&
   1077 	    DEV_ALLOCATED(stat_buf)) {
   1078 		error = ALLOCUERR;
   1079 		goto out;
   1080 	}
   1081 	if (!DEV_ALLOCATED(stat_buf)) {
   1082 		if (