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