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