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