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 (