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