xref: /illumos-gate/usr/src/cmd/allocate/allocate3.c (revision f48205be61a214698b763ff550ab9e657525104c)
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_INVALID(sbuf)	(((sbuf).st_mode & ~S_IFMT) == ALLOC_INVALID)
80 #define	DEV_ALLOCATED(sbuf)	((sbuf).st_uid != ALLOC_UID || \
81 			!(((sbuf).st_mode & ~S_IFMT) == DEALLOC_MODE || \
82 			DEV_ERRORED(sbuf) || DEV_INVALID(sbuf)))
83 
84 #define	ALLOC_CLEAN		"-A"
85 #define	DEALLOC_CLEAN		"-D"
86 #define	DAC_DIR			"/etc/security/dev"
87 #define	DEVICE_AUTH_SEPARATOR	","
88 #define	LOCALDEVICE		"/dev/console"
89 #define	PROCFS			"/proc/"
90 #define	SFF_NO_ERROR		0x1
91 
92 #define	ALLOC_BY_NONE		-1
93 #define	CHECK_DRANGE		1
94 #define	CHECK_URANGE		2
95 #define	CHECK_ZLABEL		3
96 
97 extern void audit_allocate_list(char *);
98 extern void audit_allocate_device(char *);
99 
100 extern int	system_labeled;
101 extern char	*newenv[];
102 
103 struct state_file {
104 	int	sf_flags;
105 	char	sf_path[MAXPATHLEN];
106 };
107 
108 struct file_info {
109 	struct stat	fi_stat;
110 	char		*fi_message;
111 };
112 
113 struct zone_path {
114 	int	count;
115 	char	**path;
116 };
117 
118 struct dev_names {
119 	char **dnames;
120 };
121 
122 static int _dev_file_name(struct state_file *, devmap_t *);
123 static int lock_dev(char *);
124 static int _check_label(devalloc_t *, char *, uid_t, int);
125 static int create_znode(char *, struct zone_path *, devmap_t *);
126 static int remove_znode(char *, devmap_t *);
127 static int update_device(char **, char *, int);
128 
129 /*
130  * checks if the invoking user is local to the device
131  */
132 /*ARGSUSED*/
133 int
134 _is_local(uid_t uid)
135 {
136 	struct stat	statbuf;
137 
138 	if (stat(LOCALDEVICE, &statbuf) == 0 &&
139 	    statbuf.st_uid == uid)
140 		return (1);
141 
142 	return (0);
143 }
144 
145 /*
146  * Checks if the user with the specified uid has the specified authorization
147  */
148 int
149 _is_authorized(char *auths, uid_t uid)
150 {
151 	char		*dcp, *authlist, *lasts;
152 	char		pw_buf[NSS_BUFLEN_PASSWD];
153 	struct passwd	pw_ent;
154 
155 	/*
156 	 * first, the easy cases
157 	 */
158 	if (strcmp(auths, "@") == 0)
159 		return (1);
160 	if (strcmp(auths, "*") == 0)
161 		return (ALLOC_BY_NONE);
162 	if (getpwuid_r(uid, &pw_ent, pw_buf, sizeof (pw_buf)) == NULL)
163 		return (0);
164 	if (strpbrk(auths, DEVICE_AUTH_SEPARATOR) == NULL)
165 		return (chkauthattr(auths, pw_ent.pw_name));
166 	authlist = strdup(auths);
167 	if (authlist == NULL)
168 		return (0);
169 	for (dcp = authlist;
170 	    (dcp = strtok_r(dcp, DEVICE_AUTH_SEPARATOR, &lasts)) != NULL;
171 	    dcp = NULL) {
172 		if (chkauthattr(dcp, pw_ent.pw_name))
173 			break;
174 	}
175 	free(authlist);
176 
177 	return (dcp != NULL);
178 }
179 
180 /*
181  * Checks if the specified user has authorization for the device
182  */
183 int
184 _is_dev_authorized(devalloc_t *da, uid_t uid)
185 {
186 	int	ares;
187 	char	*auth_list, *dcp, *subauth = NULL;
188 
189 	auth_list = da->da_devauth;
190 	if (auth_list == NULL)
191 		return (0);
192 	dcp = strpbrk(auth_list, KV_TOKEN_DELIMIT);
193 	if (dcp == NULL)
194 		return (_is_authorized(auth_list, uid));
195 	if (_is_local(uid)) {
196 		/* the local authorization is before the separator */
197 		ares = dcp - auth_list;
198 		subauth = malloc(ares + 1);
199 		if (subauth == NULL)
200 			return (0);
201 		(void) strlcpy(subauth, auth_list, (ares + 1));
202 		auth_list = subauth;
203 	} else
204 		auth_list = dcp + 1;
205 	ares = _is_authorized(auth_list, uid);
206 	if (subauth != NULL)
207 		free(subauth);
208 
209 	return (ares);
210 }
211 
212 int
213 check_devs(devmap_t *dm)
214 {
215 	int	status = 0;
216 	char	**file;
217 
218 	if (dm->dmap_devarray == NULL)
219 		return (NODMAPERR);
220 	for (file = dm->dmap_devarray; *file != NULL; file++) {
221 		if ((status = access(*file, F_OK)) == -1) {
222 			dprintf("Unable to access file %s\n", *file);
223 			break;
224 		}
225 	}
226 
227 	return (status);
228 }
229 
230 int
231 print_da_defs(da_defs_t *da_defs)
232 {
233 	char	optbuf[BUFSIZ];
234 	char	*p = NULL;
235 
236 	if (da_defs->devopts == NULL) {
237 		dprintf("No default attributes for %s\n", da_defs->devtype);
238 		return (DEFATTRSERR);
239 	}
240 	(void) printf("dev_type=%s\n", da_defs->devtype);
241 	if (_kva2str(da_defs->devopts, optbuf, sizeof (optbuf), KV_ASSIGN,
242 	    KV_TOKEN_DELIMIT) == 0) {
243 		if (p = rindex(optbuf, ':'))
244 			*p = '\0';
245 		(void) printf("\t%s\n", optbuf);
246 	}
247 
248 	return (0);
249 }
250 
251 void
252 print_dev_attrs(int optflag, devalloc_t *da, devmap_t *dm,
253     struct file_info *fip)
254 {
255 	char	*p = NULL;
256 	char	optbuf[BUFSIZ];
257 
258 	(void) printf("device=%s%s", dm->dmap_devname, KV_DELIMITER);
259 	(void) printf("type=%s%s", dm->dmap_devtype, KV_DELIMITER);
260 	(void) printf("auths=%s%s",
261 	    (da->da_devauth ? da->da_devauth : ""), KV_DELIMITER);
262 	(void) printf("clean=%s%s",
263 	    (da->da_devexec ? da->da_devexec : ""), KV_DELIMITER);
264 	if (da->da_devopts != NULL) {
265 		if (_kva2str(da->da_devopts, optbuf, sizeof (optbuf),
266 		    KV_ASSIGN, KV_TOKEN_DELIMIT) == 0) {
267 			if (p = rindex(optbuf, ':'))
268 				*p = '\0';
269 			(void) printf("%s", optbuf);
270 		}
271 	}
272 	(void) printf("%s", KV_DELIMITER);
273 	if (optflag & WINDOWING) {
274 		if (DEV_INVALID(fip->fi_stat))
275 			(void) printf("owner=/INVALID:%s%s", fip->fi_message,
276 			    KV_DELIMITER);
277 		else if (DEV_ERRORED(fip->fi_stat))
278 			(void) printf("owner=/ERROR%s", KV_DELIMITER);
279 		else if (!DEV_ALLOCATED(fip->fi_stat))
280 			(void) printf("owner=/FREE%s", KV_DELIMITER);
281 		else
282 			(void) printf("owner=%u%s", fip->fi_stat.st_uid,
283 			    KV_DELIMITER);
284 	}
285 	(void) printf("files=%s", dm->dmap_devlist);
286 	(void) printf("\n");
287 }
288 
289 void
290 print_dev(devmap_t *dm)
291 {
292 	char	**file;
293 
294 	(void) printf(gettext("device: %s "), dm->dmap_devname);
295 	(void) printf(gettext("type: %s "), dm->dmap_devtype);
296 	(void) printf(gettext("files:"));
297 	file = dm->dmap_devarray;
298 	if (file != NULL) {
299 		for (; *file != NULL; file++)
300 			(void) printf(" %s", *file);
301 	}
302 	(void) printf("\n");
303 }
304 
305 /* ARGSUSED */
306 int
307 _list_device(int optflag, uid_t uid, devalloc_t *da, char *zonename)
308 {
309 	int			bytes = 0;
310 	int			error = 0;
311 	int			is_authorized = 0;
312 	char			*fname = NULL;
313 	char			file_name[MAXPATHLEN];
314 	devmap_t		*dm;
315 	struct file_info	fi;
316 	struct state_file	sf;
317 
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 	if (system_labeled) {
327 		if ((error = _dev_file_name(&sf, dm)) != 0) {
328 			freedmapent(dm);
329 			dprintf("Unable to find %s device files\n",
330 			    da->da_devname);
331 			error = NODMAPERR;
332 			goto out;
333 		}
334 		fname = sf.sf_path;
335 	} else {
336 		bytes = snprintf(file_name, MAXPATHLEN, "%s/%s", DAC_DIR,
337 		    da->da_devname);
338 		if (bytes <= 0) {
339 			error = DEVNAMEERR;
340 			goto out;
341 		} else if (bytes >= MAXPATHLEN) {
342 			dprintf("device name %s is too long.\n",
343 			    da->da_devname);
344 			error = DEVLONGERR;
345 			goto out;
346 		}
347 		fname = file_name;
348 	}
349 	if (stat(fname, &fi.fi_stat) != 0) {
350 		dprintf("Unable to stat %s\n", fname);
351 		dperror("Error:");
352 		error = DACACCERR;
353 		goto out;
354 	}
355 	if (optflag & USERID)
356 		is_authorized = 1;
357 	else
358 		is_authorized = _is_dev_authorized(da, uid);
359 	if (optflag & LISTFREE) {	/* list_devices -n */
360 		/*
361 		 * list all free devices
362 		 */
363 		if (DEV_ALLOCATED(fi.fi_stat)) {
364 				error = PREALLOCERR;
365 				goto out;
366 		}
367 		if (system_labeled) {
368 			/*
369 			 * for this free device, check if -
370 			 * 1. user has authorization to allocate
371 			 * 2. the zone label is within the label range of the
372 			 *    device
373 			 */
374 			if (is_authorized == ALLOC_BY_NONE) {
375 				error = DAUTHERR;
376 				goto out;
377 			} else if (is_authorized == 0) {
378 				error = UAUTHERR;
379 				goto out;
380 			}
381 			if (_check_label(da, zonename, uid,
382 			    CHECK_DRANGE) != 0) {
383 				error = LABELRNGERR;
384 				goto out;
385 			}
386 		}
387 	} else if (optflag & LISTALLOC) {	/*  list_devices -u */
388 		/*
389 		 * list all allocated devices
390 		 */
391 		if (!DEV_ALLOCATED(fi.fi_stat)) {
392 			error = DEVNALLOCERR;
393 			goto out;
394 		}
395 		if (fi.fi_stat.st_uid != uid) {
396 			error = DEVSTATEERR;
397 			goto out;
398 		}
399 		if (system_labeled) {
400 			/*
401 			 * check if the zone label equals the label at which
402 			 * the device is allocated.
403 			 */
404 			if (_check_label(da, zonename, uid,
405 			    CHECK_ZLABEL) != 0) {
406 				error = LABELRNGERR;
407 				goto out;
408 			}
409 		}
410 	} else if (optflag & LISTALL) {		/* list_devices -l */
411 		/*
412 		 * list all devices - free and allocated - available
413 		 */
414 		if (DEV_ALLOCATED(fi.fi_stat)) {
415 			if (optflag & WINDOWING &&
416 			    (is_authorized == ALLOC_BY_NONE)) {
417 				/*
418 				 * don't complain if we're here for the GUI.
419 				 */
420 				error = 0;
421 			} else if (fi.fi_stat.st_uid != uid) {
422 				if (!(optflag & WINDOWING)) {
423 					error = ALLOCUERR;
424 					goto out;
425 				}
426 			}
427 			if (system_labeled && !(optflag & WINDOWING)) {
428 				/*
429 				 * if we're not displaying in the GUI,
430 				 * check if the zone label equals the label
431 				 * at which the device is allocated.
432 				 */
433 				if (_check_label(da, zonename, uid,
434 				    CHECK_ZLABEL) != 0) {
435 					error = LABELRNGERR;
436 					goto out;
437 				}
438 			}
439 		} else if (system_labeled && !(optflag & WINDOWING)) {
440 			/*
441 			 * if we're not displaying in the GUI,
442 			 * for this free device, check if -
443 			 * 1. user has authorization to allocate
444 			 * 2. the zone label is within the label range of the
445 			 *    device
446 			 */
447 			if (is_authorized == ALLOC_BY_NONE) {
448 				error = DAUTHERR;
449 				goto out;
450 			} else if (is_authorized == 0) {
451 				error = UAUTHERR;
452 				goto out;
453 			}
454 			if (_check_label(da, zonename, uid,
455 			    CHECK_DRANGE) != 0) {
456 				error = LABELRNGERR;
457 				goto out;
458 			}
459 		}
460 	}
461 	if (system_labeled && DEV_ERRORED(fi.fi_stat) && !(optflag & LISTALL)) {
462 		error = DEVSTATEERR;
463 		goto out;
464 	}
465 	if (check_devs(dm) == -1) {
466 		error = DSPMISSERR;
467 		goto out;
468 	}
469 	if (optflag & LISTATTRS)
470 		print_dev_attrs(optflag, da, dm, &fi);
471 	else
472 		print_dev(dm);
473 
474 	error = 0;
475 
476 out:
477 	freedmapent(dm);
478 	return (error);
479 }
480 
481 /* ARGSUSED */
482 int
483 list_devices(int optflag, uid_t uid, char *device, char *zonename)
484 {
485 	int		error = 0;
486 	da_defs_t	*da_defs;
487 	devalloc_t	*da;
488 
489 	if (system_labeled && optflag & WINDOWING && !(optflag & LISTATTRS)) {
490 		/*
491 		 * Private interface for GUI.
492 		 */
493 		(void) lock_dev(NULL);
494 		(void) puts(DA_DB_LOCK);
495 		return (0);
496 	}
497 	if (optflag & USERID) {
498 		/*
499 		 * we need device.revoke to list someone else's devices
500 		 */
501 		if (!_is_authorized(DEVICE_REVOKE_AUTH, getuid()))
502 			return (UAUTHERR);
503 	}
504 	if (system_labeled) {
505 		if (!(optflag & USERID) &&
506 		    !_is_authorized(DEFAULT_DEV_ALLOC_AUTH, uid))
507 			/*
508 			 * we need device.allocate to list our devices
509 			 */
510 			return (UAUTHERR);
511 		if (optflag & LISTDEFS) {
512 			/*
513 			 * list default attrs from devalloc_defaults
514 			 */
515 			setdadefent();
516 			if (device) {
517 				/*
518 				 * list default attrs for this device type
519 				 */
520 				da_defs = getdadeftype(device);
521 				if (da_defs == NULL) {
522 					enddadefent();
523 					dprintf("No default attributes for "
524 					    "%s\n", device);
525 					return (DEFATTRSERR);
526 				}
527 				error = print_da_defs(da_defs);
528 				freedadefent(da_defs);
529 			} else {
530 				/*
531 				 * list everything in devalloc_defaults
532 				 */
533 				while ((da_defs = getdadefent()) != NULL) {
534 					(void) print_da_defs(da_defs);
535 					freedadefent(da_defs);
536 				}
537 			}
538 			enddadefent();
539 			return (error);
540 		}
541 	}
542 	setdaent();
543 	if (device) {
544 		/*
545 		 * list this device
546 		 */
547 		if ((da = getdanam(device)) == NULL) {
548 			enddaent();
549 			return (NODAERR);
550 		}
551 		error = _list_device(optflag, uid, da, zonename);
552 		freedaent(da);
553 	} else {
554 		/*
555 		 * list all devices
556 		 */
557 		while ((da = getdaent()) != NULL) {
558 			(void) _list_device(optflag, uid, da, zonename);
559 			freedaent(da);
560 		}
561 	}
562 	enddaent();
563 
564 	return (error);
565 }
566 
567 /*
568  * Set the DAC characteristics of the file.
569  * This uses a fancy chmod() by setting a minimal ACL which sets the mode
570  * and discards any existing ACL.
571  */
572 int
573 _newdac(char *file, uid_t owner, gid_t group, o_mode_t mode)
574 {
575 	int	err = 0;
576 
577 	if (mode == ALLOC_MODE) {
578 		if (chown(file, owner, group) == -1) {
579 			dperror("newdac: unable to chown");
580 			err = CHOWNERR;
581 		}
582 	} else do {
583 		if (chown(file, owner, group) == -1) {
584 			dperror("newdac: unable to chown");
585 			err = CHOWNERR;
586 		}
587 	} while (fdetach(file) == 0);
588 
589 	if (err)
590 		return (err);
591 
592 	if (strncmp(file, "/dev/", strlen("/dev/")) != 0) {
593 		/*
594 		 * This could be a SunRay device that is in /tmp.
595 		 */
596 		if (chmod(file, mode) == -1) {
597 			dperror("newdac: unable to chmod");
598 			err = SETACLERR;
599 		}
600 	} else {
601 		err = acl_strip(file, owner, group, (mode_t)mode);
602 	}
603 
604 	if (err != 0) {
605 		dperror("newdac: unable to setacl");
606 		err = SETACLERR;
607 	}
608 
609 	return (err);
610 }
611 
612 static int
613 lock_dev(char *file)
614 {
615 	int	lockfd = -1;
616 
617 	if ((file == NULL) || system_labeled)
618 		file = DA_DEV_LOCK;
619 	dprintf("locking %s\n", file);
620 	if ((lockfd = open(file, O_RDWR | O_CREAT, 0600)) == -1) {
621 		dperror("lock_dev: cannot open lock file");
622 		return (DEVLKERR);
623 	}
624 	if (lockf(lockfd, F_TLOCK, 0) == -1) {
625 		dperror("lock_dev: cannot set lock");
626 		return (DEVLKERR);
627 	}
628 
629 	return (0);
630 }
631 
632 int
633 mk_alloc(devmap_t *list, uid_t uid, struct zone_path *zpath)
634 {
635 	int	i;
636 	int	error = 0;
637 	char	**file;
638 	gid_t	gid = getgid();
639 	mode_t	mode = ALLOC_MODE;
640 
641 	file = list->dmap_devarray;
642 	if (file == NULL)
643 		return (NODMAPERR);
644 	for (; *file != NULL; file++) {
645 		dprintf("Allocating %s\n", *file);
646 		if ((error = _newdac(*file, uid, gid, mode)) != 0) {
647 			(void) _newdac(*file, ALLOC_ERRID, ALLOC_GID,
648 			    ALLOC_ERR_MODE);
649 			break;
650 		}
651 	}
652 	if (system_labeled && zpath->count && (error == 0)) {
653 		/*
654 		 * mark as allocated any new device nodes that we
655 		 * created in local zone
656 		 */
657 		for (i = 0; i < zpath->count; i++) {
658 			dprintf("Allocating %s\n", zpath->path[i]);
659 			if ((error = _newdac(zpath->path[i], uid, gid,
660 			    mode)) != 0) {
661 				(void) _newdac(zpath->path[i], ALLOC_ERRID,
662 				    ALLOC_GID, ALLOC_ERR_MODE);
663 				break;
664 			}
665 		}
666 	}
667 
668 	return (error);
669 }
670 
671 /*
672  * mk_revoke() is used instead of system("/usr/sbin/fuser -k file")
673  * because "/usr/sbin/fuser -k file" kills all processes
674  * working with the file, even "vold" (bug #4095152).
675  */
676 int
677 mk_revoke(int optflag, char *file)
678 {
679 	int		r = 0, p[2], fp, lock;
680 	int		fuserpid;
681 	char		buf[MAXPATHLEN];
682 	FILE		*ptr;
683 	pid_t		c_pid;
684 	prpsinfo_t	info;
685 
686 	(void) strcpy(buf, PROCFS);
687 	/*
688 	 * vfork() and execl() just to make the same output
689 	 * as before fixing of bug #4095152.
690 	 * The problem is that the "fuser" command prints
691 	 * one part of output into stderr and another into stdout,
692 	 * but user sees them mixed. Of course, better to change "fuser"
693 	 * or to intercept and not to print its output.
694 	 */
695 	if (!(optflag & SILENT)) {
696 		c_pid = vfork();
697 		if (c_pid == -1)
698 			return (-1);
699 		if (c_pid == 0) {
700 			dprintf("first exec fuser %s\n", file);
701 			(void) execl("/usr/sbin/fuser", "fuser", file, NULL);
702 			dperror("first exec fuser");
703 			_exit(1);
704 		}
705 
706 		(void) waitpid(c_pid, &lock, 0);
707 		dprintf("exit status %x\n", lock);
708 		if (WEXITSTATUS(lock) != 0)
709 			return (-1);
710 	}
711 	dprintf("first continuing c_pid=%d\n", (int)c_pid);
712 	if (pipe(p)) {
713 		dperror("pipe");
714 		return (-1);
715 	}
716 	/* vfork() and execl() to catch output and to process it */
717 	c_pid = vfork();
718 	if (c_pid == -1) {
719 		dperror("second vfork");
720 		return (-1);
721 	}
722 	dprintf("second continuing c_pid=%d\n", (int)c_pid);
723 	if (c_pid == 0) {
724 		(void) close(p[0]);
725 		(void) close(1);
726 		(void) fcntl(p[1], F_DUPFD, 1);
727 		(void) close(p[1]);
728 		(void) close(2);
729 		dprintf("second exec fuser %s\n", file);
730 		(void) execl("/usr/sbin/fuser", "fuser", file, NULL);
731 		dperror("second exec fuser");
732 		_exit(1);
733 	}
734 	(void) close(p[1]);
735 	if ((ptr = fdopen(p[0], "r")) != NULL) {
736 		while (!feof(ptr)) {
737 			if (fscanf(ptr, "%d", &fuserpid) > 0) {
738 				(void) sprintf(buf + strlen(PROCFS), "%d",
739 				    fuserpid);
740 				if ((fp = open(buf, O_RDONLY)) == -1) {
741 					dperror(buf);
742 					continue;
743 				}
744 				if (ioctl(fp, PIOCPSINFO,
745 				    (char *)&info) == -1) {
746 					dprintf("%d psinfo failed", fuserpid);
747 					dperror("");
748 					(void) close(fp);
749 					continue;
750 				}
751 				(void) close(fp);
752 				if (strcmp(info.pr_fname, "vold") == NULL) {
753 					dprintf("%d matched vold name\n",
754 					    fuserpid);
755 					continue;
756 				}
757 				dprintf("killing %s", info.pr_fname);
758 				dprintf("(%d)\n", fuserpid);
759 				if ((r =
760 				    kill((pid_t)fuserpid, SIGKILL)) == -1) {
761 					dprintf("kill %d", fuserpid);
762 					dperror("");
763 					break;
764 				}
765 			}
766 		}
767 	} else {
768 		dperror("fdopen(p[0], r)");
769 		r = -1;
770 	}
771 	(void) fclose(ptr);
772 
773 	return (r);
774 }
775 
776 int
777 mk_unalloc(int optflag, devmap_t *list)
778 {
779 	int	error = 0;
780 	int	status;
781 	char	**file;
782 
783 	audit_allocate_list(list->dmap_devlist);
784 	file = list->dmap_devarray;
785 	if (file == NULL)
786 		return (NODMAPERR);
787 	for (; *file != NULL; file++) {
788 		dprintf("Deallocating %s\n", *file);
789 		if (mk_revoke(optflag, *file) < 0) {
790 			dprintf("mk_unalloc: unable to revoke %s\n", *file);
791 			dperror("");
792 			error = CNTFRCERR;
793 		}
794 		status = _newdac(*file, ALLOC_UID, ALLOC_GID, DEALLOC_MODE);
795 		if (error == 0)
796 			error = status;
797 
798 	}
799 
800 	return (error);
801 }
802 
803 int
804 mk_error(devmap_t *list)
805 {
806 	int	status = 0;
807 	char	**file;
808 
809 	audit_allocate_list(list->dmap_devlist);
810 	file = list->dmap_devarray;
811 	if (file == NULL)
812 		return (NODMAPERR);
813 	for (; *file != NULL; file++) {
814 		dprintf("Putting %s in error state\n", *file);
815 		status = _newdac(*file, ALLOC_ERRID, ALLOC_GID, ALLOC_ERR_MODE);
816 	}
817 
818 	return (status);
819 }
820 
821 int
822 exec_clean(int optflag, char *devname, char *path, uid_t uid, char *zonename,
823     char *clean_arg)
824 {
825 	int		c;
826 	int		status = 0, exit_status;
827 	char		*mode, *cmd, *wdwcmd, *zoneroot;
828 	char		*devzone = zonename;
829 	char		wdwpath[PATH_MAX];
830 	char		zonepath[MAXPATHLEN];
831 	char		title[100];
832 	char		pw_buf[NSS_BUFLEN_PASSWD];
833 	struct passwd	pw_ent;
834 
835 	zonepath[0] = '\0';
836 	if (system_labeled) {
837 		if ((zoneroot = getzonerootbyname(zonename)) == NULL) {
838 			if (strcmp(clean_arg, ALLOC_CLEAN) == 0) {
839 				return (-1);
840 			} else if (optflag & FORCE) {
841 				(void) strcpy(zonepath, "/");
842 				devzone = GLOBAL_ZONENAME;
843 			} else {
844 				dprintf("unable to get label for %s zone\n",
845 				    zonename);
846 				return (-1);
847 			}
848 		} else {
849 			(void) strcpy(zonepath, zoneroot);
850 			free(zoneroot);
851 		}
852 	}
853 	if (getpwuid_r(uid, &pw_ent, pw_buf, sizeof (pw_buf)) == NULL)
854 		return (-1);
855 	if (optflag & FORCE_ALL)
856 		mode = "-I";
857 	else if (optflag & FORCE)
858 		mode = "-f";
859 	else
860 		mode = "-s";
861 	if (path == NULL)
862 		return (0);
863 	if ((cmd = strrchr(path, '/')) == NULL)
864 		cmd = path;
865 	else
866 		cmd++;	/* skip leading '/' */
867 	c = vfork();
868 	switch (c) {
869 	case -1:
870 		return (-1);
871 	case 0:
872 		(void) setuid(0);
873 		if (system_labeled && (optflag & WINDOWING)) {
874 			/* First try .windowing version of script */
875 			(void) strncpy(wdwpath, path, PATH_MAX);
876 			(void) strncat(wdwpath, ".windowing", PATH_MAX);
877 			if ((wdwcmd = strrchr(wdwpath, '/')) == NULL)
878 				wdwcmd = wdwpath;
879 			(void) execl(wdwpath, wdwcmd, mode, devname, clean_arg,
880 			    pw_ent.pw_name, devzone, zonepath, NULL);
881 			/* If that failed, run regular version via dtterm */
882 			(void) snprintf(title, sizeof (title),
883 			    "Device %s for %s",
884 			    strcmp(clean_arg, ALLOC_CLEAN) == 0 ?
885 			    "allocation" : "deallocation", devname);
886 			(void) execl("/usr/dt/bin/dtterm", "dtterm",
887 			    "-title", title, "-geometry", "x10+100+400",
888 			    "-e", "/etc/security/lib/wdwwrapper",
889 			    path, mode, devname, clean_arg, pw_ent.pw_name,
890 			    devzone, zonepath, NULL);
891 			/*
892 			 * And if that failed, continue on to try
893 			 * running regular version directly.
894 			 */
895 		}
896 		dprintf("clean script: %s, ", path);
897 		dprintf("cmd=%s, ", cmd);
898 		dprintf("mode=%s, ", mode);
899 		if (system_labeled) {
900 			dprintf("devname=%s ", devname);
901 			dprintf("zonename=%s ", devzone);
902 			dprintf("zonepath=%s ", zonepath);
903 			dprintf("username=%s\n", pw_ent.pw_name);
904 			(void) execl(path, cmd, mode, devname, clean_arg,
905 			    pw_ent.pw_name, devzone, zonepath, NULL);
906 		} else {
907 			dprintf("devname=%s\n", devname);
908 			(void) execle(path, cmd, mode, devname, NULL, newenv);
909 		}
910 		dprintf("Unable to execute clean up script %s\n", path);
911 		dperror("");
912 		exit(CNTDEXECERR);
913 	default:
914 		(void) waitpid(c, &status, 0);
915 		dprintf("Child %d", c);
916 		if (WIFEXITED(status)) {
917 			exit_status = WEXITSTATUS(status);
918 			dprintf(" exited, status: %d\n", exit_status);
919 			return (exit_status);
920 		} else if (WIFSIGNALED(status)) {
921 			dprintf(" killed, signal %d\n", WTERMSIG(status));
922 		} else {
923 			dprintf(": exit status %d\n", status);
924 		}
925 		return (-1);
926 	}
927 }
928 
929 int
930 _deallocate_dev(int optflag, devalloc_t *da, devmap_t *dm_in, uid_t uid,
931     char *zonename)
932 {
933 	int			bytes = 0;
934 	int			error = 0;
935 	int			is_authorized = 0;
936 	uid_t			nuid;
937 	char			*fname = NULL;
938 	char			file_name[MAXPATHLEN];
939 	char			*devzone = NULL;
940 	devmap_t		*dm = NULL, *dm_new = NULL;
941 	struct stat		stat_buf;
942 	struct state_file	sf;
943 
944 	if (dm_in == NULL) {
945 		setdmapent();
946 		if ((dm_new = getdmapnam(da->da_devname)) == NULL) {
947 			enddmapent();
948 			dprintf("Unable to find %s in device map database\n",
949 			    da->da_devname);
950 			return (NODMAPERR);
951 		}
952 		enddmapent();
953 		dm = dm_new;
954 	} else {
955 		dm = dm_in;
956 	}
957 	if (system_labeled) {
958 		if (_dev_file_name(&sf, dm) != 0) {
959 			if (dm_new)
960 				freedmapent(dm_new);
961 			dprintf("Unable to find %s device files\n",
962 			    da->da_devname);
963 			error = NODMAPERR;
964 			goto out;
965 		}
966 		fname = sf.sf_path;
967 	} else {
968 		bytes = snprintf(file_name,  MAXPATHLEN, "%s/%s", DAC_DIR,
969 		    da->da_devname);
970 		if (bytes <= 0) {
971 			error = DEVNAMEERR;
972 			goto out;
973 		} else if (bytes >= MAXPATHLEN) {
974 			dprintf("device name %s is too long.\n",
975 			    da->da_devname);
976 			error = DEVLONGERR;
977 			goto out;
978 		}
979 		fname = file_name;
980 	}
981 
982 	audit_allocate_device(fname);
983 
984 	if (stat(fname, &stat_buf) != 0) {
985 		dprintf("Unable to stat %s\n", fname);
986 		error = DACACCERR;
987 		goto out;
988 	}
989 	is_authorized = _is_dev_authorized(da, uid);
990 	if (!(optflag & (FORCE | FORCE_ALL)) && !is_authorized) {
991 		dprintf("User %d is unauthorized to deallocate\n", (int)uid);
992 		error = UAUTHERR;
993 		goto out;
994 	}
995 	if (system_labeled) {
996 		/*
997 		 * unless we're here to deallocate by force, check if the
998 		 * label at which the device is currently allocated is
999 		 * within the user label range.
1000 		 */
1001 		if (!(optflag & FORCE) &&
1002 		    _check_label(da, zonename, uid, CHECK_URANGE) != 0) {
1003 			error = LABELRNGERR;
1004 			goto out;
1005 		}
1006 	}
1007 	if (!(optflag & FORCE) && stat_buf.st_uid != uid &&
1008 	    DEV_ALLOCATED(stat_buf)) {
1009 		error = ALLOCUERR;
1010 		goto out;
1011 	}
1012 	if (!DEV_ALLOCATED(stat_buf)) {
1013 		if (DEV_ERRORED(stat_buf)) {
1014 			if (!(optflag & FORCE)) {
1015 				error = DEVSTATEERR;
1016 				goto out;
1017 			}
1018 		} else {
1019 			error = DEVNALLOCERR;
1020 			goto out;
1021 		}
1022 	}
1023 	/* All checks passed, time to lock and deallocate */
1024 	if ((error = lock_dev(fname)) != 0)
1025 		goto out;
1026 	if (system_labeled) {
1027 		devzone = kva_match(da->da_devopts, DAOPT_ZONE);
1028 		if (devzone && (strcmp(devzone, GLOBAL_ZONENAME) != 0)) {
1029 			if ((remove_znode(devzone, dm) != 0) &&
1030 			    !(optflag & FORCE)) {
1031 				error = ZONEERR;
1032 				goto out;
1033 			}
1034 		}
1035 	}
1036 	if ((error = mk_unalloc(optflag, dm)) != 0) {
1037 		if (!(optflag & FORCE))
1038 			goto out;
1039 	}
1040 	if (system_labeled == 0) {
1041 		if ((error = _newdac(fname, ALLOC_UID, ALLOC_GID,
1042 		    DEALLOC_MODE)) != 0) {
1043 			(void) _newdac(file_name, ALLOC_UID, ALLOC_GID,
1044 			    ALLOC_ERR_MODE);
1045 			goto out;
1046 		}
1047 	}
1048 	/*
1049 	 * if we are deallocating device owned by someone else,
1050 	 * pass the owner's uid to the cleaning script.
1051 	 */
1052 	nuid = (stat_buf.st_uid == uid) ? uid : stat_buf.st_uid;
1053 	error = exec_clean(optflag, da->da_devname, da->da_devexec, nuid,
1054 	    devzone, DEALLOC_CLEAN);
1055 	if (error != 0) {
1056 		if (!(optflag & (FORCE | FORCE_ALL))) {
1057 			error = CLEANERR;
1058 			(void) mk_error(dm);
1059 		} else {
1060 			error = 0;
1061 		}
1062 	}
1063 
1064 out:
1065 	if (dm_new)
1066 		freedmapent(dm_new);
1067 	return (error);
1068 }
1069 
1070 int
1071 _allocate_dev(int optflag, uid_t uid, devalloc_t *da, char *zonename)
1072 {
1073 	int			i;
1074 	int			bytes = 0;
1075 	int			error = 0;
1076 	int			is_authorized = 0;
1077 	int			dealloc_optflag = 0;
1078 	char			*fname = NULL;
1079 	char			file_name[MAXPATHLEN];
1080 	devmap_t 		*dm;
1081 	struct stat 		stat_buf;
1082 	struct state_file	sf;
1083 	struct zone_path	zpath;
1084 
1085 	zpath.count = 0;
1086 	zpath.path = NULL;
1087 	setdmapent();
1088 	if ((dm = getdmapnam(da->da_devname)) == NULL) {
1089 		enddmapent();
1090 		dprintf("Unable to find %s in device map database\n",
1091 		    da->da_devname);
1092 		return (NODMAPERR);
1093 	}
1094 	enddmapent();
1095 	if (system_labeled) {
1096 		if (_dev_file_name(&sf, dm) != 0) {
1097 			freedmapent(dm);
1098 			dprintf("Unable to find %s device files\n",
1099 			    da->da_devname);
1100 			error = NODMAPERR;
1101 			goto out;
1102 		}
1103 		fname = sf.sf_path;
1104 	} else {
1105 		bytes = snprintf(file_name,  MAXPATHLEN, "%s/%s", DAC_DIR,
1106 		    da->da_devname);
1107 		if (bytes <= 0) {
1108 			error = DEVNAMEERR;
1109 			goto out;
1110 		} else if (bytes >= MAXPATHLEN) {
1111 			dprintf("device name %s is too long.\n",
1112 			    da->da_devname);
1113 			error = DEVLONGERR;
1114 			goto out;
1115 		}
1116 		fname = file_name;
1117 	}
1118 
1119 	(void) audit_allocate_device(fname);
1120 
1121 	if (stat(fname, &stat_buf) != 0) {
1122 		dprintf("Unable to stat %s\n", fname);
1123 		dperror("Error:");
1124 		error = DACACCERR;
1125 		goto out;
1126 	}
1127 	if (DEV_ERRORED(stat_buf)) {
1128 		error = DEVSTATEERR;
1129 		goto out;
1130 	}
1131 	is_authorized = _is_dev_authorized(da, uid);
1132 	if (is_authorized == ALLOC_BY_NONE) {
1133 		dprintf("Device %s is not allocatable\n", da->da_devname);
1134 		error = UAUTHERR;
1135 		goto out;
1136 	} else if (!is_authorized && !(optflag & USERNAME)) {
1137 		dprintf("User %d is unauthorized to allocate\n", (int)uid);
1138 		error = UAUTHERR;
1139 		goto out;
1140 	}
1141 	if (system_labeled) {
1142 		/*
1143 		 * check if label of the zone to which the device is being
1144 		 * allocated is within the device label range.
1145 		 */
1146 		if (_check_label(da, zonename, uid, CHECK_DRANGE) != 0) {
1147 			error = LABELRNGERR;
1148 			goto out;
1149 		}
1150 	}
1151 	if (check_devs(dm) == -1) {
1152 		error = DSPMISSERR;
1153 		goto out;
1154 	}
1155 	if (DEV_ALLOCATED(stat_buf)) {
1156 		if (optflag & FORCE) {
1157 			if (optflag & SILENT)
1158 				dealloc_optflag = FORCE|SILENT;
1159 			else
1160 				dealloc_optflag = FORCE;
1161 			if (_deallocate_dev(dealloc_optflag, da, dm, uid,
1162 			    zonename)) {
1163 				dprintf("Couldn't force deallocate device %s\n",
1164 				    da->da_devname);
1165 				error = CNTFRCERR;
1166 				goto out;
1167 			}
1168 		} else if (stat_buf.st_uid == uid) {
1169 			error = PREALLOCERR;
1170 			goto out;
1171 		} else {
1172 			error = ALLOCUERR;
1173 			goto out;
1174 		}
1175 	}
1176 	/* All checks passed, time to lock and allocate */
1177 	if ((error = lock_dev(fname)) != 0)
1178 		goto out;
1179 	if (system_labeled) {
1180 		/*
1181 		 * Run the cleaning program; it also mounts allocated
1182 		 * device if required.
1183 		 */
1184 		error = exec_clean(optflag, da->da_devname, da->da_devexec, uid,
1185 		    zonename, ALLOC_CLEAN);
1186 		if ((error != 0) && (error != CLEAN_MOUNT)) {
1187 			error = CLEANERR;
1188 			(void) mk_error(dm);
1189 			goto out;
1190 		}
1191 		/*
1192 		 * If not mounted, create zonelinks, if this is not the
1193 		 * global zone.
1194 		 */
1195 		if ((strcmp(zonename, GLOBAL_ZONENAME) != 0) &&
1196 		    (error != CLEAN_MOUNT)) {
1197 			if (create_znode(zonename, &zpath, dm) != 0) {
1198 				error = ZONEERR;
1199 				goto out;
1200 			}
1201 		}
1202 	}
1203 
1204 	(void) audit_allocate_list(dm->dmap_devlist);
1205 
1206 	if ((error = mk_alloc(dm, uid, &zpath)) != 0) {
1207 		(void) mk_unalloc(optflag, dm);
1208 		goto out;
1209 	}
1210 
1211 	if (system_labeled == 0) {
1212 		if ((error = _newdac(file_name, uid, getgid(),
1213 		    ALLOC_MODE)) != 0) {
1214 			(void) _newdac(file_name, ALLOC_UID, ALLOC_GID,
1215 			    ALLOC_ERR_MODE);
1216 			goto out;
1217 		}
1218 	}
1219 	error = 0;
1220 out:
1221 	if (zpath.count) {
1222 		for (i = 0; i < zpath.count; i++)
1223 			free(zpath.path[i]);
1224 		free(zpath.path);
1225 	}
1226 	freedmapent(dm);
1227 	return (error);
1228 }
1229 
1230 void
1231 _store_devnames(int *count, struct dev_names *dnms, char *zonename,
1232     devalloc_t *da, int flag)
1233 {
1234 	int i;
1235 
1236 	dnms->dnames = (char **)realloc(dnms->dnames,
1237 	    (*count + 1) * sizeof (char *));
1238 	if (da) {
1239 		dnms->dnames[*count] = strdup(da->da_devname);
1240 		(*count)++;
1241 	} else {
1242 		dnms->dnames[*count] = NULL;
1243 		if (flag == DA_ADD_ZONE)
1244 			(void) update_device(dnms->dnames, zonename,
1245 			    DA_ADD_ZONE);
1246 		else if (flag == DA_REMOVE_ZONE)
1247 			(void) update_device(dnms->dnames, NULL,
1248 			    DA_REMOVE_ZONE);
1249 		for (i = 0; i < *count; i++)
1250 			free(dnms->dnames[i]);
1251 		free(dnms->dnames);
1252 	}
1253 }
1254 
1255 int
1256 allocate(int optflag, uid_t uid, char *device, char *zonename)
1257 {
1258 	int		count = 0;
1259 	int		error = 0;
1260 	devalloc_t	*da;
1261 	struct dev_names dnms;
1262 
1263 	if (optflag & (FORCE | USERID | USERNAME)) {
1264 		if (!_is_authorized(DEVICE_REVOKE_AUTH, getuid()))
1265 			return (UAUTHERR);
1266 	}
1267 	dnms.dnames = NULL;
1268 	setdaent();
1269 	if (optflag & TYPE) {
1270 		/*
1271 		 * allocate devices of this type
1272 		 */
1273 		while ((da = getdatype(device)) != NULL) {
1274 			if (system_labeled &&
1275 			    da_check_logindevperm(da->da_devname)) {
1276 				freedaent(da);
1277 				continue;
1278 			}
1279 			dprintf("trying to allocate %s\n", da->da_devname);
1280 			error = _allocate_dev(optflag, uid, da, zonename);
1281 			if (system_labeled && (error == 0)) {
1282 				/*
1283 				 * we need to record in device_allocate the
1284 				 * label (zone name) at which this device is
1285 				 * being allocated. store this device entry.
1286 				 */
1287 				_store_devnames(&count, &dnms, zonename, da, 0);
1288 			}
1289 			freedaent(da);
1290 			error = 0;
1291 		}
1292 	} else {
1293 		/*
1294 		 * allocate this device
1295 		 */
1296 		if ((da = getdanam(device)) == NULL) {
1297 			enddaent();
1298 			return (NODAERR);
1299 		}
1300 		if (system_labeled && da_check_logindevperm(device)) {
1301 			freedaent(da);
1302 			return (LOGINDEVPERMERR);
1303 		}
1304 		dprintf("trying to allocate %s\n", da->da_devname);
1305 		error = _allocate_dev(optflag, uid, da, zonename);
1306 		/*
1307 		 * we need to record in device_allocate the label (zone name)
1308 		 * at which this device is being allocated. store this device
1309 		 * entry.
1310 		 */
1311 		if (system_labeled && (error == 0))
1312 			_store_devnames(&count, &dnms, zonename, da, 0);
1313 		freedaent(da);
1314 	}
1315 	enddaent();
1316 	/*
1317 	 * add to device_allocate labels (zone names) for the devices we
1318 	 * allocated.
1319 	 */
1320 	if (dnms.dnames)
1321 		_store_devnames(&count, &dnms, zonename, NULL, DA_ADD_ZONE);
1322 
1323 	return (error);
1324 }
1325 
1326 /* ARGSUSED */
1327 int
1328 deallocate(int optflag, uid_t uid, char *device, char *zonename)
1329 {
1330 	int		count = 0;
1331 	int		error = 0;
1332 	devalloc_t	*da;
1333 	struct dev_names dnms;
1334 
1335 	if (optflag & (FORCE | FORCE_ALL)) {
1336 		if (!_is_authorized(DEVICE_REVOKE_AUTH, getuid()))
1337 		return (UAUTHERR);
1338 	}
1339 	if (optflag & FORCE_ALL)
1340 		optflag |= FORCE;
1341 	dnms.dnames = NULL;
1342 	setdaent();
1343 	if (optflag & FORCE_ALL) {
1344 		/*
1345 		 * deallocate all devices
1346 		 */
1347 		while ((da = getdaent()) != NULL) {
1348 			if (system_labeled &&
1349 			    da_check_logindevperm(da->da_devname)) {
1350 				freedaent(da);
1351 				continue;
1352 			}
1353 			dprintf("trying to deallocate %s\n", da->da_devname);
1354 			error = _deallocate_dev(optflag, da, NULL, uid,
1355 			    zonename);
1356 			if (system_labeled && (error == 0)) {
1357 				/*
1358 				 * we need to remove this device's allocation
1359 				 * label (zone name) from device_allocate.
1360 				 * store this device name.
1361 				 */
1362 				_store_devnames(&count, &dnms, zonename, da, 0);
1363 			}
1364 			freedaent(da);
1365 			error = 0;
1366 		}
1367 	} else if (system_labeled && optflag & TYPE) {
1368 		/*
1369 		 * deallocate all devices of this type
1370 		 */
1371 		while ((da = getdatype(device)) != NULL) {
1372 			if (da_check_logindevperm(da->da_devname)) {
1373 				freedaent(da);
1374 				continue;
1375 			}
1376 			dprintf("trying to deallocate %s\n", da->da_devname);
1377 			error = _deallocate_dev(optflag, da, NULL, uid,
1378 			    zonename);
1379 			if (error == 0) {
1380 				/*
1381 				 * we need to remove this device's allocation
1382 				 * label (zone name) from device_allocate.
1383 				 * store this device name.
1384 				 */
1385 				_store_devnames(&count, &dnms, zonename, da, 0);
1386 			}
1387 			freedaent(da);
1388 			error = 0;
1389 		}
1390 	} else if (!(optflag & TYPE)) {
1391 		/*
1392 		 * deallocate this device
1393 		 */
1394 		if ((da = getdanam(device)) == NULL) {
1395 			enddaent();
1396 			return (NODAERR);
1397 		}
1398 		if (system_labeled && da_check_logindevperm(da->da_devname)) {
1399 			freedaent(da);
1400 			return (LOGINDEVPERMERR);
1401 		}
1402 		dprintf("trying to deallocate %s\n", da->da_devname);
1403 		error = _deallocate_dev(optflag, da, NULL, uid, zonename);
1404 		if (system_labeled && (error == 0)) {
1405 			/*
1406 			 * we need to remove this device's allocation label
1407 			 * (zone name) from device_allocate. store this
1408 			 * device name.
1409 			 */
1410 			_store_devnames(&count, &dnms, zonename, da, 0);
1411 		}
1412 		freedaent(da);
1413 	}
1414 	enddaent();
1415 	/*
1416 	 * remove from device_allocate labels (zone names) for the devices we
1417 	 * deallocated.
1418 	 */
1419 	if (dnms.dnames)
1420 		_store_devnames(&count, &dnms, zonename, NULL, DA_REMOVE_ZONE);
1421 
1422 	return (error);
1423 }
1424 
1425 static int
1426 _dev_file_name(struct state_file *sfp, devmap_t *dm)
1427 {
1428 	sfp->sf_flags = 0;
1429 	/* if devlist is generated, never leave device in error state */
1430 	if (dm->dmap_devlist[0] == '`')
1431 		sfp->sf_flags |= SFF_NO_ERROR;
1432 	if (dm->dmap_devarray == NULL ||
1433 	    dm->dmap_devarray[0] == NULL)
1434 		return (NODMAPERR);
1435 	(void) strncpy(sfp->sf_path, dm->dmap_devarray[0],
1436 	    sizeof (sfp->sf_path));
1437 	sfp->sf_path[sizeof (sfp->sf_path) - 1] = '\0';
1438 	if (sfp->sf_path[0] == '\0') {
1439 		dprintf("dev_file_name: no device list for %s\n",
1440 		    dm->dmap_devname);
1441 		return (NODMAPERR);
1442 	}
1443 
1444 	return (0);
1445 }
1446 
1447 /*
1448  * _check_label -
1449  *	checks the device label range against zone label, which is also
1450  *	user's current label.
1451  *	returns 0 if in range, -1 for all other conditions.
1452  *
1453  */
1454 
1455 static int
1456 _check_label(devalloc_t *da, char *zonename, uid_t uid, int flag)
1457 {
1458 	int		err;
1459 	int		in_range = 0;
1460 	char		*alloczone, *lstr;
1461 	char		pw_buf[NSS_BUFLEN_PASSWD];
1462 	blrange_t	*range;
1463 	m_label_t	*zlabel;
1464 	struct passwd	pw_ent;
1465 
1466 	if ((da == NULL) || (zonename == NULL))
1467 		return (-1);
1468 
1469 	if ((zlabel = getzonelabelbyname(zonename)) == NULL) {
1470 		dprintf("unable to get label for %s zone\n", zonename);
1471 		return (-1);
1472 	}
1473 	if (flag == CHECK_DRANGE) {
1474 		blrange_t	drange;
1475 
1476 		drange.lower_bound = blabel_alloc();
1477 		lstr = kva_match(da->da_devopts, DAOPT_MINLABEL);
1478 		if (lstr == NULL) {
1479 			bsllow(drange.lower_bound);
1480 		} else if (stobsl(lstr, drange.lower_bound, NO_CORRECTION,
1481 		    &err) == 0) {
1482 			dprintf("bad min_label for device %s\n",
1483 			    da->da_devname);
1484 			free(zlabel);
1485 			blabel_free(drange.lower_bound);
1486 			return (-1);
1487 		}
1488 		drange.upper_bound = blabel_alloc();
1489 		lstr = kva_match(da->da_devopts, DAOPT_MAXLABEL);
1490 		if (lstr == NULL) {
1491 			bslhigh(drange.upper_bound);
1492 		} else if (stobsl(lstr, drange.upper_bound, NO_CORRECTION,
1493 		    &err) == 0) {
1494 			dprintf("bad max_label for device %s\n",
1495 			    da->da_devname);
1496 			free(zlabel);
1497 			blabel_free(drange.lower_bound);
1498 			blabel_free(drange.upper_bound);
1499 			return (-1);
1500 		}
1501 		if (blinrange(zlabel, &drange) == 0) {
1502 			char	*zlbl = NULL, *min = NULL, *max = NULL;
1503 
1504 			(void) bsltos(zlabel, &zlbl, 0, 0);
1505 			(void) bsltos(drange.lower_bound, &min, 0, 0);
1506 			(void) bsltos(drange.upper_bound, &max, 0, 0);
1507 			dprintf("%s zone label ", zonename);
1508 			dprintf("%s outside device label range: ", zlbl);
1509 			dprintf("min - %s, ", min);
1510 			dprintf("max - %s\n", max);
1511 			free(zlabel);
1512 			blabel_free(drange.lower_bound);
1513 			blabel_free(drange.upper_bound);
1514 			return (-1);
1515 		}
1516 	} else if (flag == CHECK_URANGE) {
1517 		if (getpwuid_r(uid, &pw_ent, pw_buf, sizeof (pw_buf)) == NULL) {
1518 			dprintf("Unable to get passwd entry for userid %d\n",
1519 			    (int)uid);
1520 			free(zlabel);
1521 			return (-1);
1522 		}
1523 		if ((range = getuserrange(pw_ent.pw_name)) == NULL) {
1524 			dprintf("Unable to get label range for userid %d\n",
1525 			    (int)uid);
1526 			free(zlabel);
1527 			return (-1);
1528 		}
1529 		in_range = blinrange(zlabel, range);
1530 		free(zlabel);
1531 		blabel_free(range->lower_bound);
1532 		blabel_free(range->upper_bound);
1533 		free(range);
1534 		if (in_range == 0) {
1535 			dprintf("%s device label ", da->da_devname);
1536 			dprintf("out of user %d label range\n", (int)uid);
1537 			return (-1);
1538 		}
1539 	} else if (flag == CHECK_ZLABEL) {
1540 		alloczone = kva_match(da->da_devopts, DAOPT_ZONE);
1541 		if (alloczone == NULL) {
1542 			free(zlabel);
1543 			return (-1);
1544 		}
1545 		if (strcmp(zonename, alloczone) != 0) {
1546 			dprintf("%s zone is different than ", zonename);
1547 			dprintf("%s zone to which the device ", alloczone);
1548 			dprintf("%s is allocated\n", da->da_devname);
1549 			free(zlabel);
1550 			return (-1);
1551 		}
1552 	}
1553 	free(zlabel);
1554 
1555 	return (0);
1556 }
1557 
1558 int
1559 create_znode(char *zonename, struct zone_path *zpath, devmap_t *list)
1560 {
1561 	int		size;
1562 	int		len = 0;
1563 	int		fcount = 0;
1564 	char		*p, *tmpfile, *zoneroot;
1565 	char		**file;
1566 	char		zonepath[MAXPATHLEN];
1567 	di_prof_t	prof = NULL;
1568 
1569 	file = list->dmap_devarray;
1570 	if (file == NULL)
1571 		return (NODMAPERR);
1572 	if ((zoneroot = getzonerootbyname(zonename)) == NULL) {
1573 		dprintf("unable to get label for %s zone\n", zonename);
1574 		return (1);
1575 	}
1576 	(void) strcpy(zonepath, zoneroot);
1577 	free(zoneroot);
1578 	len = strlen(zonepath);
1579 	size = sizeof (zonepath);
1580 	(void) strlcat(zonepath, "/dev", size);
1581 	if (di_prof_init(zonepath, &prof)) {
1582 		dprintf("failed to initialize dev profile at %s\n", zonepath);
1583 		return (1);
1584 	}
1585 	zonepath[len] = '\0';
1586 	for (; *file != NULL; file++) {
1587 		/*
1588 		 * First time initialization
1589 		 */
1590 		tmpfile = strdup(*file);
1591 
1592 		/*
1593 		 * Most devices have pathnames starting in /dev
1594 		 * but SunRay devices do not. In SRRS 3.1 they use /tmp.
1595 		 *
1596 		 * If the device pathname is not in /dev then create
1597 		 * a symbolic link to it and put the device in /dev
1598 		 */
1599 		if (strncmp(tmpfile, "/dev/", strlen("/dev/")) != 0) {
1600 			char	*linkdir;
1601 			char	srclinkdir[MAXPATHLEN];
1602 			char	dstlinkdir[MAXPATHLEN];
1603 
1604 			linkdir = strchr(tmpfile + 1, '/');
1605 			p = strchr(linkdir + 1, '/');
1606 			*p = '\0';
1607 			(void) strcpy(dstlinkdir, "/dev");
1608 			(void) strncat(dstlinkdir, linkdir, MAXPATHLEN);
1609 			(void) snprintf(srclinkdir, MAXPATHLEN, "%s/root%s",
1610 				zonepath, tmpfile);
1611 			(void) symlink(dstlinkdir, srclinkdir);
1612 			*p = '/';
1613 			(void) strncat(dstlinkdir, p, MAXPATHLEN);
1614 			free(tmpfile);
1615 			tmpfile = strdup(dstlinkdir);
1616 		}
1617 		if (di_prof_add_dev(prof, tmpfile)) {
1618 			dprintf("failed to add %s to profile\n", tmpfile);
1619 			di_prof_fini(prof);
1620 			return (1);
1621 		}
1622 		if (strlcat(zonepath, tmpfile, size) >= size) {
1623 			dprintf("Buffer overflow in create_znode for %s\n",
1624 			    *file);
1625 			free(tmpfile);
1626 			di_prof_fini(prof);
1627 			return (1);
1628 		}
1629 		free(tmpfile);
1630 		fcount++;
1631 		if ((zpath->path = (char **)realloc(zpath->path,
1632 		    (fcount * sizeof (char *)))) == NULL) {
1633 			di_prof_fini(prof);
1634 			return (1);
1635 		}
1636 		zpath->path[zpath->count] = strdup(zonepath);
1637 		zpath->count = fcount;
1638 		zonepath[len] = '\0';
1639 	}
1640 
1641 	if (di_prof_commit(prof))
1642 		dprintf("failed to add devices to zone %s\n", zonename);
1643 	di_prof_fini(prof);
1644 
1645 	return (0);
1646 }
1647 
1648 int
1649 remove_znode(char *zonename, devmap_t *dm)
1650 {
1651 	int		len = 0;
1652 	char		*zoneroot;
1653 	char		**file;
1654 	char		zonepath[MAXPATHLEN];
1655 	di_prof_t	prof = NULL;
1656 
1657 	file = dm->dmap_devarray;
1658 	if (file == NULL)
1659 		return (NODMAPERR);
1660 	if ((zoneroot = getzonerootbyname(zonename)) == NULL) {
1661 		(void) snprintf(zonepath, MAXPATHLEN, "/zone/%s", zonename);
1662 	} else {
1663 		(void)  strcpy(zonepath, zoneroot);
1664 		free(zoneroot);
1665 	}
1666 	/*
1667 	 * To support SunRay we will just deal with the
1668 	 * file in /dev, not the symlinks.
1669 	 */
1670 	(void) strncat(zonepath, "/dev", MAXPATHLEN);
1671 	len = strlen(zonepath);
1672 	if (di_prof_init(zonepath, &prof)) {
1673 		dprintf("failed to initialize dev profile at %s\n", zonepath);
1674 		return (1);
1675 	}
1676 	for (; *file != NULL; file++) {
1677 		char *devrelpath;
1678 
1679 		/*
1680 		 * remove device node from zone.
1681 		 *
1682 		 * SunRay devices don't start with /dev
1683 		 * so skip over first directory to make
1684 		 * sure it is /dev. SunRay devices in zones
1685 		 * will have a symlink into /dev but
1686 		 * we don't ever delete it.
1687 		 */
1688 		devrelpath = strchr(*file + 1, '/');
1689 
1690 		if (di_prof_add_exclude(prof, devrelpath + 1)) {
1691 			dprintf("Failed exclude %s in dev profile\n", *file);
1692 			di_prof_fini(prof);
1693 			return (1);
1694 		}
1695 		zonepath[len] = '\0';
1696 	}
1697 
1698 	if (di_prof_commit(prof))
1699 		dprintf("failed to remove devices from zone %s\n", zonename);
1700 	di_prof_fini(prof);
1701 	return (0);
1702 }
1703 
1704 int
1705 update_device(char **devnames, char *zonename, int flag)
1706 {
1707 	int		len, rc;
1708 	char		*optstr = NULL;
1709 	da_args		dargs;
1710 	devinfo_t	devinfo;
1711 
1712 	dargs.optflag = flag;
1713 	dargs.optflag |= DA_UPDATE|DA_ALLOC_ONLY;
1714 	dargs.rootdir = NULL;
1715 	dargs.devnames = devnames;
1716 	devinfo.devname = devinfo.devtype = devinfo.devauths = devinfo.devexec =
1717 	    devinfo.devlist = NULL;
1718 	if (dargs.optflag & DA_ADD_ZONE) {
1719 		len = strlen(DAOPT_ZONE) + strlen(zonename) + 3;
1720 		if ((optstr = (char *)malloc(len)) == NULL)
1721 			return (-1);
1722 		(void) snprintf(optstr, len, "%s%s%s", DAOPT_ZONE, KV_ASSIGN,
1723 		    zonename);
1724 		devinfo.devopts = optstr;
1725 	}
1726 	dargs.devinfo = &devinfo;
1727 
1728 	rc = da_update_device(&dargs);
1729 
1730 	if (optstr)
1731 		free(optstr);
1732 
1733 	return (rc);
1734 }
1735