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
65 extern 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
93 extern void audit_allocate_list(char *);
94 extern void audit_allocate_device(char *);
95
96 extern int system_labeled;
97 extern char *newenv[];
98
99 struct state_file {
100 int sf_flags;
101 char sf_path[MAXPATHLEN];
102 };
103
104 struct file_info {
105 struct stat fi_stat;
106 char *fi_message;
107 };
108
109 struct zone_path {
110 int count;
111 char **path;
112 };
113
114 struct dev_names {
115 char **dnames;
116 };
117
118 static int _dev_file_name(struct state_file *, devmap_t *);
119 static int lock_dev(char *, struct stat *);
120 static int _check_label(devalloc_t *, char *, uid_t, int);
121 static int create_znode(char *, struct zone_path *, devmap_t *);
122 static int remove_znode(char *, devmap_t *);
123 static int update_device(char **, char *, int);
124
125 /*
126 * checks if the invoking user is local to the device
127 */
128 /*ARGSUSED*/
129 int
_is_local(uid_t uid)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 */
144 int
_is_authorized(char * auths,uid_t uid)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 */
179 int
_is_dev_authorized(devalloc_t * da,uid_t uid)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
208 int
check_devs(devmap_t * dm)209 check_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
226 int
print_da_defs(da_defs_t * da_defs)227 print_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
247 void
print_dev_attrs(int optflag,devalloc_t * da,devmap_t * dm,struct file_info * fip)248 print_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
285 void
print_dev(devmap_t * dm)286 print_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 */
302 int
_list_device(int optflag,uid_t uid,devalloc_t * da,char * zonename)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
481 out:
482 freedmapent(dm);
483 return (error);
484 }
485
486 /* ARGSUSED */
487 int
list_devices(int optflag,uid_t uid,char * device,char * zonename)488 list_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 */
596 int
_newdac(char * file,uid_t owner,gid_t group,o_mode_t mode)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 */
641 static int
lock_dev(char * file,struct stat * statbuf)642 lock_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
695 int
mk_alloc(devmap_t * list,uid_t uid,struct zone_path * zpath)696 mk_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 */
739 int
mk_revoke(int optflag,char * file)740 mk_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
844 int
mk_unalloc(int optflag,devmap_t * list)845 mk_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
871 int
mk_error(devmap_t * list)872 mk_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
889 int
exec_clean(int optflag,char * devname,char * path,uid_t uid,char * zonename,char * clean_arg)890 exec_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
997 int
_deallocate_dev(int optflag,devalloc_t * da,devmap_t * dm_in,uid_t uid,char * zonename,int * lock_fd)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
1141 out:
1142 if (dm_new)
1143 freedmapent(dm_new);
1144 return (error);
1145 }
1146
1147 int
_allocate_dev(int optflag,uid_t uid,devalloc_t * da,char * zonename,int * lock_fd)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;
1316 out:
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
1326 void
_store_devnames(int * count,struct dev_names * dnms,char * zonename,devalloc_t * da,int flag)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
1351 int
allocate(int optflag,uid_t uid,char * device,char * zonename)1352 allocate(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 */
1429 int
deallocate(int optflag,uid_t uid,char * device,char * zonename)1430 deallocate(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
1559 static int
_dev_file_name(struct state_file * sfp,devmap_t * dm)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
1589 static int
_check_label(devalloc_t * da,char * zonename,uid_t uid,int flag)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
1692 int
create_znode(char * zonename,struct zone_path * zpath,devmap_t * list)1693 create_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
1782 int
remove_znode(char * zonename,devmap_t * dm)1783 remove_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
1838 int
update_device(char ** devnames,char * zonename,int flag)1839 update_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