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 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 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 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 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 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 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 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 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 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 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 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 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 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") == NULL) { 816 dprintf("%d matched vold name\n", 817 fuserpid); 818 continue; 819 } 820 if (strcmp(info.pr_fname, "deallocate") 821 == NULL) { 822 dprintf("%d matched deallocate name\n", 823 fuserpid); 824 continue; 825 } 826 dprintf("killing %s", info.pr_fname); 827 dprintf("(%d)\n", fuserpid); 828 if ((r = 829 kill((pid_t)fuserpid, SIGKILL)) == -1) { 830 dprintf("kill %d", fuserpid); 831 dperror(""); 832 break; 833 } 834 } 835 } 836 } else { 837 dperror("fdopen(p[0], r)"); 838 r = -1; 839 } 840 (void) fclose(ptr); 841 842 return (r); 843 } 844 845 int 846 mk_unalloc(int optflag, devmap_t *list) 847 { 848 int error = 0; 849 int status; 850 char **file; 851 852 audit_allocate_list(list->dmap_devlist); 853 file = list->dmap_devarray; 854 if (file == NULL) 855 return (NODMAPERR); 856 for (; *file != NULL; file++) { 857 dprintf("Deallocating %s\n", *file); 858 if (mk_revoke(optflag, *file) < 0) { 859 dprintf("mk_unalloc: unable to revoke %s\n", *file); 860 dperror(""); 861 error = CNTFRCERR; 862 } 863 status = _newdac(*file, DA_UID, DA_GID, DEALLOC_MODE); 864 if (error == 0) 865 error = status; 866 867 } 868 869 return (error); 870 } 871 872 int 873 mk_error(devmap_t *list) 874 { 875 int status = 0; 876 char **file; 877 878 audit_allocate_list(list->dmap_devlist); 879 file = list->dmap_devarray; 880 if (file == NULL) 881 return (NODMAPERR); 882 for (; *file != NULL; file++) { 883 dprintf("Putting %s in error state\n", *file); 884 status = _newdac(*file, ALLOC_ERRID, DA_GID, ALLOC_ERR_MODE); 885 } 886 887 return (status); 888 } 889 890 int 891 exec_clean(int optflag, char *devname, char *path, uid_t uid, char *zonename, 892 char *clean_arg) 893 { 894 int c; 895 int status = 0, exit_status; 896 char *mode, *cmd, *wdwcmd, *zoneroot; 897 char *devzone = zonename; 898 char wdwpath[PATH_MAX]; 899 char zonepath[MAXPATHLEN]; 900 char title[100]; 901 char pw_buf[NSS_BUFLEN_PASSWD]; 902 struct passwd pw_ent; 903 904 zonepath[0] = '\0'; 905 if (system_labeled) { 906 if ((zoneroot = getzonerootbyname(zonename)) == NULL) { 907 if (strcmp(clean_arg, ALLOC_CLEAN) == 0) { 908 return (-1); 909 } else if (optflag & FORCE) { 910 (void) strcpy(zonepath, "/"); 911 devzone = GLOBAL_ZONENAME; 912 } else { 913 dprintf("unable to get label for %s zone\n", 914 zonename); 915 return (-1); 916 } 917 } else { 918 (void) strcpy(zonepath, zoneroot); 919 free(zoneroot); 920 } 921 } 922 if (getpwuid_r(uid, &pw_ent, pw_buf, sizeof (pw_buf)) == NULL) 923 return (-1); 924 if (optflag & FORCE_ALL) 925 mode = "-I"; 926 else if (optflag & FORCE) 927 mode = "-f"; 928 else 929 mode = "-s"; 930 if (path == NULL) 931 return (0); 932 if ((cmd = strrchr(path, '/')) == NULL) 933 cmd = path; 934 else 935 cmd++; /* skip leading '/' */ 936 c = vfork(); 937 switch (c) { 938 case -1: 939 return (-1); 940 case 0: 941 (void) setuid(0); 942 if (system_labeled && (optflag & WINDOWING)) { 943 /* First try .windowing version of script */ 944 (void) strncpy(wdwpath, path, PATH_MAX); 945 (void) strncat(wdwpath, ".windowing", PATH_MAX); 946 if ((wdwcmd = strrchr(wdwpath, '/')) == NULL) 947 wdwcmd = wdwpath; 948 (void) execl(wdwpath, wdwcmd, mode, devname, clean_arg, 949 pw_ent.pw_name, devzone, zonepath, NULL); 950 /* If that failed, run regular version via dtterm */ 951 (void) snprintf(title, sizeof (title), 952 "Device %s for %s", 953 strcmp(clean_arg, ALLOC_CLEAN) == 0 ? 954 "allocation" : "deallocation", devname); 955 (void) execl("/usr/dt/bin/dtterm", "dtterm", 956 "-title", title, "-geometry", "x10+100+400", 957 "-e", "/etc/security/lib/wdwwrapper", 958 path, mode, devname, clean_arg, pw_ent.pw_name, 959 devzone, zonepath, NULL); 960 /* 961 * And if that failed, continue on to try 962 * running regular version directly. 963 */ 964 } 965 dprintf("clean script: %s, ", path); 966 dprintf("cmd=%s, ", cmd); 967 dprintf("mode=%s, ", mode); 968 if (system_labeled) { 969 dprintf("devname=%s ", devname); 970 dprintf("zonename=%s ", devzone); 971 dprintf("zonepath=%s ", zonepath); 972 dprintf("username=%s\n", pw_ent.pw_name); 973 (void) execl(path, cmd, mode, devname, clean_arg, 974 pw_ent.pw_name, devzone, zonepath, NULL); 975 } else { 976 dprintf("devname=%s\n", devname); 977 (void) execle(path, cmd, mode, devname, NULL, newenv); 978 } 979 dprintf("Unable to execute clean up script %s\n", path); 980 dperror(""); 981 exit(CNTDEXECERR); 982 default: 983 (void) waitpid(c, &status, 0); 984 dprintf("Child %d", c); 985 if (WIFEXITED(status)) { 986 exit_status = WEXITSTATUS(status); 987 dprintf(" exited, status: %d\n", exit_status); 988 return (exit_status); 989 } else if (WIFSIGNALED(status)) { 990 dprintf(" killed, signal %d\n", WTERMSIG(status)); 991 } else { 992 dprintf(": exit status %d\n", status); 993 } 994 return (-1); 995 } 996 } 997 998 int 999 _deallocate_dev(int optflag, devalloc_t *da, devmap_t *dm_in, uid_t uid, 1000 char *zonename, int *lock_fd) 1001 { 1002 int bytes = 0; 1003 int error = 0; 1004 int is_authorized = 0; 1005 uid_t nuid; 1006 char *fname = NULL; 1007 char file_name[MAXPATHLEN]; 1008 char *devzone = NULL; 1009 devmap_t *dm = NULL, *dm_new = NULL; 1010 struct stat stat_buf; 1011 struct state_file sf; 1012 1013 if (dm_in == NULL) { 1014 setdmapent(); 1015 if ((dm_new = getdmapnam(da->da_devname)) == NULL) { 1016 enddmapent(); 1017 dprintf("Unable to find %s in device map database\n", 1018 da->da_devname); 1019 return (NODMAPERR); 1020 } 1021 enddmapent(); 1022 dm = dm_new; 1023 } else { 1024 dm = dm_in; 1025 } 1026 if (system_labeled) { 1027 if (_dev_file_name(&sf, dm) != 0) { 1028 if (dm_new) 1029 freedmapent(dm_new); 1030 dprintf("Unable to find %s device files\n", 1031 da->da_devname); 1032 error = NODMAPERR; 1033 goto out; 1034 } 1035 fname = sf.sf_path; 1036 } else { 1037 bytes = snprintf(file_name, MAXPATHLEN, "%s/%s", DAC_DIR, 1038 da->da_devname); 1039 if (bytes <= 0) { 1040 error = DEVNAMEERR; 1041 goto out; 1042 } else if (bytes >= MAXPATHLEN) { 1043 dprintf("device name %s is too long.\n", 1044 da->da_devname); 1045 error = DEVLONGERR; 1046 goto out; 1047 } 1048 fname = file_name; 1049 } 1050 1051 audit_allocate_device(fname); 1052 1053 if (stat(fname, &stat_buf) != 0) { 1054 dprintf("Unable to stat %s\n", fname); 1055 error = DACACCERR; 1056 goto out; 1057 } 1058 is_authorized = _is_dev_authorized(da, uid); 1059 if (is_authorized == ALLOC_BY_NONE) { 1060 dprintf("Not deallocating %s, not allocatable\n", 1061 da->da_devname); 1062 goto out; 1063 } 1064 if (!(optflag & (FORCE | FORCE_ALL)) && !is_authorized) { 1065 dprintf("User %d is unauthorized to deallocate\n", (int)uid); 1066 error = UAUTHERR; 1067 goto out; 1068 } 1069 if (system_labeled) { 1070 /* 1071 * unless we're here to deallocate by force, check if the 1072 * label at which the device is currently allocated is 1073 * within the user label range. 1074 */ 1075 if (!(optflag & FORCE) && 1076 _check_label(da, zonename, uid, CHECK_URANGE) != 0) { 1077 error = LABELRNGERR; 1078 goto out; 1079 } 1080 } 1081 if (!(optflag & FORCE) && stat_buf.st_uid != uid && 1082 DEV_ALLOCATED(stat_buf)) { 1083 error = ALLOCUERR; 1084 goto out; 1085 } 1086 if (!DEV_ALLOCATED(stat_buf)) { 1087 if (DEV_ERRORED(stat_buf)) { 1088 if (!(optflag & FORCE)) { 1089 error = DEVSTATEERR; 1090 goto out; 1091 } 1092 } else { 1093 error = DEVNALLOCERR; 1094 goto out; 1095 } 1096 } 1097 /* All checks passed, time to lock and deallocate */ 1098 if ((*lock_fd = lock_dev(fname, &stat_buf)) == -1) { 1099 error = DEVLKERR; 1100 goto out; 1101 } 1102 if (system_labeled) { 1103 devzone = kva_match(da->da_devopts, DAOPT_ZONE); 1104 if (devzone == NULL) { 1105 devzone = GLOBAL_ZONENAME; 1106 } else if (strcmp(devzone, GLOBAL_ZONENAME) != 0) { 1107 if ((remove_znode(devzone, dm) != 0) && 1108 !(optflag & FORCE)) { 1109 error = ZONEERR; 1110 goto out; 1111 } 1112 } 1113 } 1114 if ((error = mk_unalloc(optflag, dm)) != 0) { 1115 if (!(optflag & FORCE)) 1116 goto out; 1117 } 1118 if (system_labeled == 0) { 1119 if ((error = _newdac(fname, DA_UID, DA_GID, 1120 DEALLOC_MODE)) != 0) { 1121 (void) _newdac(file_name, DA_UID, DA_GID, 1122 ALLOC_ERR_MODE); 1123 goto out; 1124 } 1125 } 1126 /* 1127 * if we are deallocating device owned by someone else, 1128 * pass the owner's uid to the cleaning script. 1129 */ 1130 nuid = (stat_buf.st_uid == uid) ? uid : stat_buf.st_uid; 1131 error = exec_clean(optflag, da->da_devname, da->da_devexec, nuid, 1132 devzone, DEALLOC_CLEAN); 1133 if (error != 0) { 1134 if (!(optflag & (FORCE | FORCE_ALL))) { 1135 error = CLEANERR; 1136 (void) mk_error(dm); 1137 } else { 1138 error = 0; 1139 } 1140 } 1141 1142 out: 1143 if (dm_new) 1144 freedmapent(dm_new); 1145 return (error); 1146 } 1147 1148 int 1149 _allocate_dev(int optflag, uid_t uid, devalloc_t *da, char *zonename, 1150 int *lock_fd) 1151 { 1152 int i; 1153 int bytes = 0; 1154 int error = 0; 1155 int is_authorized = 0; 1156 int dealloc_optflag = 0; 1157 char *fname = NULL; 1158 char file_name[MAXPATHLEN]; 1159 devmap_t *dm; 1160 struct stat stat_buf; 1161 struct state_file sf; 1162 struct zone_path zpath; 1163 1164 zpath.count = 0; 1165 zpath.path = NULL; 1166 setdmapent(); 1167 if ((dm = getdmapnam(da->da_devname)) == NULL) { 1168 enddmapent(); 1169 dprintf("Unable to find %s in device map database\n", 1170 da->da_devname); 1171 return (NODMAPERR); 1172 } 1173 enddmapent(); 1174 if (system_labeled) { 1175 if (_dev_file_name(&sf, dm) != 0) { 1176 freedmapent(dm); 1177 dprintf("Unable to find %s device files\n", 1178 da->da_devname); 1179 error = NODMAPERR; 1180 goto out; 1181 } 1182 fname = sf.sf_path; 1183 } else { 1184 bytes = snprintf(file_name, MAXPATHLEN, "%s/%s", DAC_DIR, 1185 da->da_devname); 1186 if (bytes <= 0) { 1187 error = DEVNAMEERR; 1188 goto out; 1189 } else if (bytes >= MAXPATHLEN) { 1190 dprintf("device name %s is too long.\n", 1191 da->da_devname); 1192 error = DEVLONGERR; 1193 goto out; 1194 } 1195 fname = file_name; 1196 } 1197 1198 (void) audit_allocate_device(fname); 1199 1200 if (stat(fname, &stat_buf) != 0) { 1201 dprintf("Unable to stat %s\n", fname); 1202 dperror("Error:"); 1203 error = DACACCERR; 1204 goto out; 1205 } 1206 if (DEV_ERRORED(stat_buf)) { 1207 error = DEVSTATEERR; 1208 goto out; 1209 } 1210 is_authorized = _is_dev_authorized(da, uid); 1211 if (is_authorized == ALLOC_BY_NONE) { 1212 dprintf("Device %s is not allocatable\n", da->da_devname); 1213 error = UAUTHERR; 1214 goto out; 1215 } else if (!is_authorized && !(optflag & USERNAME)) { 1216 dprintf("User %d is unauthorized to allocate\n", (int)uid); 1217 error = UAUTHERR; 1218 goto out; 1219 } 1220 if (system_labeled) { 1221 /* 1222 * check if label of the zone to which the device is being 1223 * allocated is within the device label range. 1224 */ 1225 if (_check_label(da, zonename, uid, CHECK_DRANGE) != 0) { 1226 error = LABELRNGERR; 1227 goto out; 1228 } 1229 } 1230 if (check_devs(dm) == -1) { 1231 error = DSPMISSERR; 1232 goto out; 1233 } 1234 if (DEV_ALLOCATED(stat_buf)) { 1235 if (optflag & FORCE) { 1236 if (optflag & SILENT) 1237 dealloc_optflag = FORCE|SILENT; 1238 else 1239 dealloc_optflag = FORCE; 1240 if (_deallocate_dev(dealloc_optflag, da, dm, uid, 1241 zonename, lock_fd)) { 1242 dprintf("Couldn't force deallocate device %s\n", 1243 da->da_devname); 1244 error = CNTFRCERR; 1245 goto out; 1246 } 1247 } else if (stat_buf.st_uid == uid) { 1248 error = PREALLOCERR; 1249 goto out; 1250 } else { 1251 error = ALLOCUERR; 1252 goto out; 1253 } 1254 } 1255 /* All checks passed, time to lock and allocate */ 1256 if ((*lock_fd = lock_dev(fname, &stat_buf)) == -1) { 1257 error = DEVLKERR; 1258 goto out; 1259 } 1260 if (system_labeled) { 1261 /* 1262 * Run the cleaning program; it also mounts allocated 1263 * device if required. 1264 */ 1265 error = exec_clean(optflag, da->da_devname, da->da_devexec, uid, 1266 zonename, ALLOC_CLEAN); 1267 if (error != DEVCLEAN_OK) { 1268 switch (error) { 1269 case DEVCLEAN_ERROR: 1270 case DEVCLEAN_SYSERR: 1271 dprintf("allocate: " 1272 "Error in device clean program %s\n", 1273 da->da_devexec); 1274 error = CLEANERR; 1275 (void) mk_error(dm); 1276 goto out; 1277 case DEVCLEAN_BADMOUNT: 1278 dprintf("allocate: Failed to mount device %s\n", 1279 da->da_devexec); 1280 goto out; 1281 case DEVCLEAN_MOUNTOK: 1282 break; 1283 default: 1284 error = 0; 1285 goto out; 1286 } 1287 } 1288 /* 1289 * If not mounted, create zonelinks, if this is not the 1290 * global zone. 1291 */ 1292 if ((strcmp(zonename, GLOBAL_ZONENAME) != 0) && 1293 (error != DEVCLEAN_MOUNTOK)) { 1294 if (create_znode(zonename, &zpath, dm) != 0) { 1295 error = ZONEERR; 1296 goto out; 1297 } 1298 } 1299 } 1300 1301 (void) audit_allocate_list(dm->dmap_devlist); 1302 1303 if ((error = mk_alloc(dm, uid, &zpath)) != 0) { 1304 (void) mk_unalloc(optflag, dm); 1305 goto out; 1306 } 1307 1308 if (system_labeled == 0) { 1309 if ((error = _newdac(file_name, uid, getgid(), 1310 ALLOC_MODE)) != 0) { 1311 (void) _newdac(file_name, DA_UID, DA_GID, 1312 ALLOC_ERR_MODE); 1313 goto out; 1314 } 1315 } 1316 error = 0; 1317 out: 1318 if (zpath.count) { 1319 for (i = 0; i < zpath.count; i++) 1320 free(zpath.path[i]); 1321 free(zpath.path); 1322 } 1323 freedmapent(dm); 1324 return (error); 1325 } 1326 1327 void 1328 _store_devnames(int *count, struct dev_names *dnms, char *zonename, 1329 devalloc_t *da, int flag) 1330 { 1331 int i; 1332 1333 dnms->dnames = (char **)realloc(dnms->dnames, 1334 (*count + 1) * sizeof (char *)); 1335 if (da) { 1336 dnms->dnames[*count] = strdup(da->da_devname); 1337 (*count)++; 1338 } else { 1339 dnms->dnames[*count] = NULL; 1340 if (flag == DA_ADD_ZONE) 1341 (void) update_device(dnms->dnames, zonename, 1342 DA_ADD_ZONE); 1343 else if (flag == DA_REMOVE_ZONE) 1344 (void) update_device(dnms->dnames, NULL, 1345 DA_REMOVE_ZONE); 1346 for (i = 0; i < *count; i++) 1347 free(dnms->dnames[i]); 1348 free(dnms->dnames); 1349 } 1350 } 1351 1352 int 1353 allocate(int optflag, uid_t uid, char *device, char *zonename) 1354 { 1355 int count = 0; 1356 int error = 0; 1357 int lock_fd = -1; 1358 devalloc_t *da; 1359 struct dev_names dnms; 1360 1361 if (optflag & (FORCE | USERID | USERNAME)) { 1362 if (!_is_authorized(DEVICE_REVOKE_AUTH, getuid())) 1363 return (UAUTHERR); 1364 } 1365 dnms.dnames = NULL; 1366 setdaent(); 1367 if (optflag & TYPE) { 1368 /* 1369 * allocate devices of this type 1370 */ 1371 while ((da = getdatype(device)) != NULL) { 1372 if (system_labeled && 1373 da_check_logindevperm(da->da_devname)) { 1374 freedaent(da); 1375 continue; 1376 } 1377 dprintf("trying to allocate %s\n", da->da_devname); 1378 error = _allocate_dev(optflag, uid, da, zonename, 1379 &lock_fd); 1380 if (system_labeled && (error == 0)) { 1381 /* 1382 * we need to record in device_allocate the 1383 * label (zone name) at which this device is 1384 * being allocated. store this device entry. 1385 */ 1386 _store_devnames(&count, &dnms, zonename, da, 0); 1387 } 1388 freedaent(da); 1389 error = 0; 1390 } 1391 } else { 1392 /* 1393 * allocate this device 1394 */ 1395 if ((da = getdanam(device)) == NULL) { 1396 enddaent(); 1397 return (NODAERR); 1398 } 1399 if (system_labeled && da_check_logindevperm(device)) { 1400 freedaent(da); 1401 return (LOGINDEVPERMERR); 1402 } 1403 dprintf("trying to allocate %s\n", da->da_devname); 1404 error = _allocate_dev(optflag, uid, da, zonename, &lock_fd); 1405 /* 1406 * we need to record in device_allocate the label (zone name) 1407 * at which this device is being allocated. store this device 1408 * entry. 1409 */ 1410 if (system_labeled && (error == 0)) 1411 _store_devnames(&count, &dnms, zonename, da, 0); 1412 freedaent(da); 1413 if (error == DEVCLEAN_BADMOUNT) 1414 error = 0; 1415 } 1416 enddaent(); 1417 if (lock_fd != -1) 1418 (void) close(lock_fd); 1419 /* 1420 * add to device_allocate labels (zone names) for the devices we 1421 * allocated. 1422 */ 1423 if (dnms.dnames) 1424 _store_devnames(&count, &dnms, zonename, NULL, DA_ADD_ZONE); 1425 1426 return (error); 1427 } 1428 1429 /* ARGSUSED */ 1430 int 1431 deallocate(int optflag, uid_t uid, char *device, char *zonename) 1432 { 1433 int count = 0; 1434 int error = 0; 1435 int lock_fd = -1; 1436 char *class = NULL; 1437 devalloc_t *da; 1438 struct dev_names dnms; 1439 1440 if (optflag & (FORCE | FORCE_ALL)) { 1441 if (!_is_authorized(DEVICE_REVOKE_AUTH, getuid())) 1442 return (UAUTHERR); 1443 } 1444 if (optflag & FORCE_ALL) 1445 optflag |= FORCE; 1446 dnms.dnames = NULL; 1447 setdaent(); 1448 if (optflag & FORCE_ALL) { 1449 /* 1450 * deallocate all devices 1451 */ 1452 while ((da = getdaent()) != NULL) { 1453 if (system_labeled && 1454 da_check_logindevperm(da->da_devname)) { 1455 freedaent(da); 1456 continue; 1457 } 1458 dprintf("trying to deallocate %s\n", da->da_devname); 1459 error = _deallocate_dev(optflag, da, NULL, uid, 1460 zonename, &lock_fd); 1461 if (system_labeled && (error == 0)) { 1462 /* 1463 * we need to remove this device's allocation 1464 * label (zone name) from device_allocate. 1465 * store this device name. 1466 */ 1467 _store_devnames(&count, &dnms, zonename, da, 0); 1468 } 1469 freedaent(da); 1470 error = 0; 1471 } 1472 } else if (system_labeled && (optflag & TYPE)) { 1473 /* 1474 * deallocate all devices of this type 1475 */ 1476 while ((da = getdatype(device)) != NULL) { 1477 if (da_check_logindevperm(da->da_devname)) { 1478 freedaent(da); 1479 continue; 1480 } 1481 dprintf("trying to deallocate %s\n", da->da_devname); 1482 error = _deallocate_dev(optflag, da, NULL, uid, 1483 zonename, &lock_fd); 1484 if (error == 0) { 1485 /* 1486 * we need to remove this device's allocation 1487 * label (zone name) from device_allocate. 1488 * store this device name. 1489 */ 1490 _store_devnames(&count, &dnms, zonename, da, 0); 1491 } 1492 freedaent(da); 1493 error = 0; 1494 } 1495 } else if (system_labeled && (optflag & CLASS)) { 1496 /* 1497 * deallocate all devices of this class (for sunray) 1498 */ 1499 while ((da = getdaent()) != NULL) { 1500 class = kva_match(da->da_devopts, DAOPT_CLASS); 1501 if (class && (strcmp(class, device) == 0)) { 1502 dprintf("trying to deallocate %s\n", 1503 da->da_devname); 1504 error = _deallocate_dev(optflag, da, NULL, uid, 1505 zonename, &lock_fd); 1506 if (error == 0) { 1507 /* 1508 * we need to remove this device's 1509 * allocation label (zone name) from 1510 * device_allocate. store this device 1511 * name. 1512 */ 1513 _store_devnames(&count, &dnms, zonename, 1514 da, 0); 1515 } 1516 error = 0; 1517 } 1518 freedaent(da); 1519 } 1520 } else if (!(optflag & TYPE)) { 1521 /* 1522 * deallocate this device 1523 */ 1524 if ((da = getdanam(device)) == NULL) { 1525 enddaent(); 1526 return (NODAERR); 1527 } 1528 if (system_labeled && da_check_logindevperm(da->da_devname)) { 1529 freedaent(da); 1530 return (LOGINDEVPERMERR); 1531 } 1532 dprintf("trying to deallocate %s\n", da->da_devname); 1533 error = _deallocate_dev(optflag, da, NULL, uid, zonename, 1534 &lock_fd); 1535 if (system_labeled && (error == 0)) { 1536 /* 1537 * we need to remove this device's allocation label 1538 * (zone name) from device_allocate. store this 1539 * device name. 1540 */ 1541 _store_devnames(&count, &dnms, zonename, da, 0); 1542 } 1543 freedaent(da); 1544 if (error == DEVCLEAN_BADMOUNT) 1545 error = 0; 1546 } 1547 enddaent(); 1548 if (lock_fd != -1) 1549 (void) close(lock_fd); 1550 /* 1551 * remove from device_allocate labels (zone names) for the devices we 1552 * deallocated. 1553 */ 1554 if (dnms.dnames) 1555 _store_devnames(&count, &dnms, zonename, NULL, DA_REMOVE_ZONE); 1556 1557 return (error); 1558 } 1559 1560 static int 1561 _dev_file_name(struct state_file *sfp, devmap_t *dm) 1562 { 1563 sfp->sf_flags = 0; 1564 /* if devlist is generated, never leave device in error state */ 1565 if (dm->dmap_devlist[0] == '`') 1566 sfp->sf_flags |= SFF_NO_ERROR; 1567 if (dm->dmap_devarray == NULL || 1568 dm->dmap_devarray[0] == NULL) 1569 return (NODMAPERR); 1570 (void) strncpy(sfp->sf_path, dm->dmap_devarray[0], 1571 sizeof (sfp->sf_path)); 1572 sfp->sf_path[sizeof (sfp->sf_path) - 1] = '\0'; 1573 if (sfp->sf_path[0] == '\0') { 1574 dprintf("dev_file_name: no device list for %s\n", 1575 dm->dmap_devname); 1576 return (NODMAPERR); 1577 } 1578 1579 return (0); 1580 } 1581 1582 /* 1583 * _check_label - 1584 * checks the device label range against zone label, which is also 1585 * user's current label. 1586 * returns 0 if in range, -1 for all other conditions. 1587 * 1588 */ 1589 1590 static int 1591 _check_label(devalloc_t *da, char *zonename, uid_t uid, int flag) 1592 { 1593 int err; 1594 int in_range = 0; 1595 char *alloczone, *lstr; 1596 char pw_buf[NSS_BUFLEN_PASSWD]; 1597 blrange_t *range; 1598 m_label_t *zlabel; 1599 struct passwd pw_ent; 1600 1601 if ((da == NULL) || (zonename == NULL)) 1602 return (-1); 1603 1604 if ((zlabel = getzonelabelbyname(zonename)) == NULL) { 1605 dprintf("unable to get label for %s zone\n", zonename); 1606 return (-1); 1607 } 1608 if (flag == CHECK_DRANGE) { 1609 blrange_t drange; 1610 1611 drange.lower_bound = blabel_alloc(); 1612 lstr = kva_match(da->da_devopts, DAOPT_MINLABEL); 1613 if (lstr == NULL) { 1614 bsllow(drange.lower_bound); 1615 } else if (stobsl(lstr, drange.lower_bound, NO_CORRECTION, 1616 &err) == 0) { 1617 dprintf("bad min_label for device %s\n", 1618 da->da_devname); 1619 free(zlabel); 1620 blabel_free(drange.lower_bound); 1621 return (-1); 1622 } 1623 drange.upper_bound = blabel_alloc(); 1624 lstr = kva_match(da->da_devopts, DAOPT_MAXLABEL); 1625 if (lstr == NULL) { 1626 bslhigh(drange.upper_bound); 1627 } else if (stobsl(lstr, drange.upper_bound, NO_CORRECTION, 1628 &err) == 0) { 1629 dprintf("bad max_label for device %s\n", 1630 da->da_devname); 1631 free(zlabel); 1632 blabel_free(drange.lower_bound); 1633 blabel_free(drange.upper_bound); 1634 return (-1); 1635 } 1636 if (blinrange(zlabel, &drange) == 0) { 1637 char *zlbl = NULL, *min = NULL, *max = NULL; 1638 1639 (void) bsltos(zlabel, &zlbl, 0, 0); 1640 (void) bsltos(drange.lower_bound, &min, 0, 0); 1641 (void) bsltos(drange.upper_bound, &max, 0, 0); 1642 dprintf("%s zone label ", zonename); 1643 dprintf("%s outside device label range: ", zlbl); 1644 dprintf("min - %s, ", min); 1645 dprintf("max - %s\n", max); 1646 free(zlabel); 1647 blabel_free(drange.lower_bound); 1648 blabel_free(drange.upper_bound); 1649 return (-1); 1650 } 1651 } else if (flag == CHECK_URANGE) { 1652 if (getpwuid_r(uid, &pw_ent, pw_buf, sizeof (pw_buf)) == NULL) { 1653 dprintf("Unable to get passwd entry for userid %d\n", 1654 (int)uid); 1655 free(zlabel); 1656 return (-1); 1657 } 1658 if ((range = getuserrange(pw_ent.pw_name)) == NULL) { 1659 dprintf("Unable to get label range for userid %d\n", 1660 (int)uid); 1661 free(zlabel); 1662 return (-1); 1663 } 1664 in_range = blinrange(zlabel, range); 1665 free(zlabel); 1666 blabel_free(range->lower_bound); 1667 blabel_free(range->upper_bound); 1668 free(range); 1669 if (in_range == 0) { 1670 dprintf("%s device label ", da->da_devname); 1671 dprintf("out of user %d label range\n", (int)uid); 1672 return (-1); 1673 } 1674 } else if (flag == CHECK_ZLABEL) { 1675 alloczone = kva_match(da->da_devopts, DAOPT_ZONE); 1676 if (alloczone == NULL) { 1677 free(zlabel); 1678 return (-1); 1679 } 1680 if (strcmp(zonename, alloczone) != 0) { 1681 dprintf("%s zone is different than ", zonename); 1682 dprintf("%s zone to which the device ", alloczone); 1683 dprintf("%s is allocated\n", da->da_devname); 1684 free(zlabel); 1685 return (-1); 1686 } 1687 } 1688 free(zlabel); 1689 1690 return (0); 1691 } 1692 1693 int 1694 create_znode(char *zonename, struct zone_path *zpath, devmap_t *list) 1695 { 1696 int size; 1697 int len = 0; 1698 int fcount = 0; 1699 char *p, *tmpfile, *zoneroot; 1700 char **file; 1701 char zonepath[MAXPATHLEN]; 1702 di_prof_t prof = NULL; 1703 1704 file = list->dmap_devarray; 1705 if (file == NULL) 1706 return (NODMAPERR); 1707 if ((zoneroot = getzonerootbyname(zonename)) == NULL) { 1708 dprintf("unable to get label for %s zone\n", zonename); 1709 return (1); 1710 } 1711 (void) strcpy(zonepath, zoneroot); 1712 free(zoneroot); 1713 len = strlen(zonepath); 1714 size = sizeof (zonepath); 1715 (void) strlcat(zonepath, "/dev", size); 1716 if (di_prof_init(zonepath, &prof)) { 1717 dprintf("failed to initialize dev profile at %s\n", zonepath); 1718 return (1); 1719 } 1720 zonepath[len] = '\0'; 1721 for (; *file != NULL; file++) { 1722 /* 1723 * First time initialization 1724 */ 1725 tmpfile = strdup(*file); 1726 1727 /* 1728 * Most devices have pathnames starting in /dev 1729 * but SunRay devices do not. In SRRS 3.1 they use /tmp. 1730 * 1731 * If the device pathname is not in /dev then create 1732 * a symbolic link to it and put the device in /dev 1733 */ 1734 if (strncmp(tmpfile, "/dev/", strlen("/dev/")) != 0) { 1735 char *linkdir; 1736 char srclinkdir[MAXPATHLEN]; 1737 char dstlinkdir[MAXPATHLEN]; 1738 1739 linkdir = strchr(tmpfile + 1, '/'); 1740 p = strchr(linkdir + 1, '/'); 1741 *p = '\0'; 1742 (void) strcpy(dstlinkdir, "/dev"); 1743 (void) strncat(dstlinkdir, linkdir, MAXPATHLEN); 1744 (void) snprintf(srclinkdir, MAXPATHLEN, "%s/root%s", 1745 zonepath, tmpfile); 1746 (void) symlink(dstlinkdir, srclinkdir); 1747 *p = '/'; 1748 (void) strncat(dstlinkdir, p, MAXPATHLEN); 1749 free(tmpfile); 1750 tmpfile = strdup(dstlinkdir); 1751 } 1752 if (di_prof_add_dev(prof, tmpfile)) { 1753 dprintf("failed to add %s to profile\n", tmpfile); 1754 di_prof_fini(prof); 1755 return (1); 1756 } 1757 if (strlcat(zonepath, tmpfile, size) >= size) { 1758 dprintf("Buffer overflow in create_znode for %s\n", 1759 *file); 1760 free(tmpfile); 1761 di_prof_fini(prof); 1762 return (1); 1763 } 1764 free(tmpfile); 1765 fcount++; 1766 if ((zpath->path = (char **)realloc(zpath->path, 1767 (fcount * sizeof (char *)))) == NULL) { 1768 di_prof_fini(prof); 1769 return (1); 1770 } 1771 zpath->path[zpath->count] = strdup(zonepath); 1772 zpath->count = fcount; 1773 zonepath[len] = '\0'; 1774 } 1775 1776 if (di_prof_commit(prof)) 1777 dprintf("failed to add devices to zone %s\n", zonename); 1778 di_prof_fini(prof); 1779 1780 return (0); 1781 } 1782 1783 int 1784 remove_znode(char *zonename, devmap_t *dm) 1785 { 1786 int len = 0; 1787 char *zoneroot; 1788 char **file; 1789 char zonepath[MAXPATHLEN]; 1790 di_prof_t prof = NULL; 1791 1792 file = dm->dmap_devarray; 1793 if (file == NULL) 1794 return (NODMAPERR); 1795 if ((zoneroot = getzonerootbyname(zonename)) == NULL) { 1796 (void) snprintf(zonepath, MAXPATHLEN, "/zone/%s", zonename); 1797 } else { 1798 (void) strcpy(zonepath, zoneroot); 1799 free(zoneroot); 1800 } 1801 /* 1802 * To support SunRay we will just deal with the 1803 * file in /dev, not the symlinks. 1804 */ 1805 (void) strncat(zonepath, "/dev", MAXPATHLEN); 1806 len = strlen(zonepath); 1807 if (di_prof_init(zonepath, &prof)) { 1808 dprintf("failed to initialize dev profile at %s\n", zonepath); 1809 return (1); 1810 } 1811 for (; *file != NULL; file++) { 1812 char *devrelpath; 1813 1814 /* 1815 * remove device node from zone. 1816 * 1817 * SunRay devices don't start with /dev 1818 * so skip over first directory to make 1819 * sure it is /dev. SunRay devices in zones 1820 * will have a symlink into /dev but 1821 * we don't ever delete it. 1822 */ 1823 devrelpath = strchr(*file + 1, '/'); 1824 1825 if (di_prof_add_exclude(prof, devrelpath + 1)) { 1826 dprintf("Failed exclude %s in dev profile\n", *file); 1827 di_prof_fini(prof); 1828 return (1); 1829 } 1830 zonepath[len] = '\0'; 1831 } 1832 1833 if (di_prof_commit(prof)) 1834 dprintf("failed to remove devices from zone %s\n", zonename); 1835 di_prof_fini(prof); 1836 return (0); 1837 } 1838 1839 int 1840 update_device(char **devnames, char *zonename, int flag) 1841 { 1842 int len, rc; 1843 char *optstr = NULL; 1844 da_args dargs; 1845 devinfo_t devinfo; 1846 1847 dargs.optflag = flag; 1848 dargs.optflag |= DA_UPDATE|DA_ALLOC_ONLY; 1849 dargs.rootdir = NULL; 1850 dargs.devnames = devnames; 1851 devinfo.devname = devinfo.devtype = devinfo.devauths = devinfo.devexec = 1852 devinfo.devlist = NULL; 1853 if (dargs.optflag & DA_ADD_ZONE) { 1854 len = strlen(DAOPT_ZONE) + strlen(zonename) + 3; 1855 if ((optstr = (char *)malloc(len)) == NULL) 1856 return (-1); 1857 (void) snprintf(optstr, len, "%s%s%s", DAOPT_ZONE, KV_ASSIGN, 1858 zonename); 1859 devinfo.devopts = optstr; 1860 } 1861 dargs.devinfo = &devinfo; 1862 1863 rc = da_update_device(&dargs); 1864 1865 if (optstr) 1866 free(optstr); 1867 1868 return (rc); 1869 } 1870