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