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 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 27 /* All Rights Reserved */ 28 29 /* 30 * University Copyright- Copyright (c) 1982, 1986, 1988 31 * The Regents of the University of California 32 * All Rights Reserved 33 * 34 * University Acknowledgment- Portions of this document are derived from 35 * software developed by the University of California, Berkeley, and its 36 * contributors. 37 */ 38 39 40 /* 41 * Common code for halt(1M), poweroff(1M), and reboot(1M). We use 42 * argv[0] to determine which behavior to exhibit. 43 */ 44 45 #include <stdio.h> 46 #include <procfs.h> 47 #include <sys/types.h> 48 #include <sys/elf.h> 49 #include <sys/systeminfo.h> 50 #include <sys/stat.h> 51 #include <sys/uadmin.h> 52 #include <sys/mntent.h> 53 #include <sys/mnttab.h> 54 #include <sys/mount.h> 55 #include <alloca.h> 56 #include <assert.h> 57 #include <errno.h> 58 #include <fcntl.h> 59 #include <libgen.h> 60 #include <libscf.h> 61 #include <limits.h> 62 #include <locale.h> 63 #include <libintl.h> 64 #include <syslog.h> 65 #include <signal.h> 66 #include <strings.h> 67 #include <unistd.h> 68 #include <stdlib.h> 69 #include <stdio.h> 70 #include <strings.h> 71 #include <time.h> 72 #include <wait.h> 73 #include <ctype.h> 74 #include <utmpx.h> 75 #include <pwd.h> 76 #include <zone.h> 77 78 #include <libzfs.h> 79 80 #if !defined(TEXT_DOMAIN) 81 #define TEXT_DOMAIN "SYS_TEST" 82 #endif 83 84 #if defined(__sparc) 85 #define CUR_ELFDATA ELFDATA2MSB 86 #elif defined(__i386) 87 #define CUR_ELFDATA ELFDATA2LSB 88 #endif 89 90 static libzfs_handle_t *g_zfs; 91 92 extern int audit_halt_setup(int, char **); 93 extern int audit_halt_success(void); 94 extern int audit_halt_fail(void); 95 96 extern int audit_reboot_setup(void); 97 extern int audit_reboot_success(void); 98 extern int audit_reboot_fail(void); 99 100 static char *cmdname; /* basename(argv[0]), the name of the command */ 101 102 typedef struct ctidlist_struct { 103 ctid_t ctid; 104 struct ctidlist_struct *next; 105 } ctidlist_t; 106 107 static ctidlist_t *ctidlist = NULL; 108 static ctid_t startdct = -1; 109 110 #define FMRI_STARTD_CONTRACT \ 111 "svc:/system/svc/restarter:default/:properties/restarter/contract" 112 113 #define ZONEADM_PROG "/usr/sbin/zoneadm" 114 115 #define LUUMOUNT_PROG "/usr/sbin/luumount" 116 #define LUMOUNT_PROG "/usr/sbin/lumount" 117 118 /* 119 * The length of FASTBOOT_MOUNTPOINT must be less than MAXPATHLEN. 120 */ 121 #define FASTBOOT_MOUNTPOINT "/tmp/.fastboot.root" 122 123 static char fastboot_mounted[MAXPATHLEN]; 124 125 static int validate_ufs_disk(char *, char *); 126 static int validate_zfs_pool(char *, char *); 127 128 static pid_t 129 get_initpid() 130 { 131 static int init_pid = -1; 132 133 if (init_pid == -1) { 134 if (zone_getattr(getzoneid(), ZONE_ATTR_INITPID, &init_pid, 135 sizeof (init_pid)) != sizeof (init_pid)) { 136 assert(errno == ESRCH); 137 init_pid = -1; 138 } 139 } 140 return (init_pid); 141 } 142 143 /* 144 * Quiesce or resume init using /proc. When stopping init, we can't send 145 * SIGTSTP (since init ignores it) or SIGSTOP (since the kernel won't permit 146 * it). 147 */ 148 static int 149 direct_init(long command) 150 { 151 char ctlfile[MAXPATHLEN]; 152 pid_t pid; 153 int ctlfd; 154 155 assert(command == PCDSTOP || command == PCRUN); 156 if ((pid = get_initpid()) == -1) { 157 return (-1); 158 } 159 160 (void) snprintf(ctlfile, sizeof (ctlfile), "/proc/%d/ctl", pid); 161 if ((ctlfd = open(ctlfile, O_WRONLY)) == -1) 162 return (-1); 163 164 if (command == PCDSTOP) { 165 if (write(ctlfd, &command, sizeof (long)) == -1) { 166 (void) close(ctlfd); 167 return (-1); 168 } 169 } else { /* command == PCRUN */ 170 long cmds[2]; 171 cmds[0] = command; 172 cmds[1] = 0; 173 if (write(ctlfd, cmds, sizeof (cmds)) == -1) { 174 (void) close(ctlfd); 175 return (-1); 176 } 177 } 178 (void) close(ctlfd); 179 return (0); 180 } 181 182 static void 183 stop_startd() 184 { 185 scf_handle_t *h; 186 scf_property_t *prop = NULL; 187 scf_value_t *val = NULL; 188 uint64_t uint64; 189 190 if ((h = scf_handle_create(SCF_VERSION)) == NULL) 191 return; 192 193 if ((scf_handle_bind(h) != 0) || 194 ((prop = scf_property_create(h)) == NULL) || 195 ((val = scf_value_create(h)) == NULL)) 196 goto out; 197 198 if (scf_handle_decode_fmri(h, FMRI_STARTD_CONTRACT, 199 NULL, NULL, NULL, NULL, prop, SCF_DECODE_FMRI_EXACT) != 0) 200 goto out; 201 202 if (scf_property_is_type(prop, SCF_TYPE_COUNT) != 0 || 203 scf_property_get_value(prop, val) != 0 || 204 scf_value_get_count(val, &uint64) != 0) 205 goto out; 206 207 startdct = (ctid_t)uint64; 208 (void) sigsend(P_CTID, startdct, SIGSTOP); 209 210 out: 211 scf_property_destroy(prop); 212 scf_value_destroy(val); 213 scf_handle_destroy(h); 214 } 215 216 static void 217 continue_startd() 218 { 219 if (startdct != -1) 220 (void) sigsend(P_CTID, startdct, SIGCONT); 221 } 222 223 #define FMRI_RESTARTER_PROP "/:properties/general/restarter" 224 #define FMRI_CONTRACT_PROP "/:properties/restarter/contract" 225 226 static int 227 save_ctid(ctid_t ctid) 228 { 229 ctidlist_t *next; 230 231 for (next = ctidlist; next != NULL; next = next->next) 232 if (next->ctid == ctid) 233 return (-1); 234 235 next = (ctidlist_t *)malloc(sizeof (ctidlist_t)); 236 if (next == NULL) 237 return (-1); 238 239 next->ctid = ctid; 240 next->next = ctidlist; 241 ctidlist = next; 242 return (0); 243 } 244 245 static void 246 stop_delegates() 247 { 248 ctid_t ctid; 249 scf_handle_t *h; 250 scf_scope_t *sc = NULL; 251 scf_service_t *svc = NULL; 252 scf_instance_t *inst = NULL; 253 scf_snapshot_t *snap = NULL; 254 scf_snapshot_t *isnap = NULL; 255 scf_propertygroup_t *pg = NULL; 256 scf_property_t *prop = NULL; 257 scf_value_t *val = NULL; 258 scf_iter_t *siter = NULL; 259 scf_iter_t *iiter = NULL; 260 char *fmri; 261 ssize_t length; 262 263 uint64_t uint64; 264 ssize_t bytes; 265 266 length = scf_limit(SCF_LIMIT_MAX_FMRI_LENGTH); 267 if (length <= 0) 268 return; 269 270 length++; 271 fmri = alloca(length * sizeof (char)); 272 273 if ((h = scf_handle_create(SCF_VERSION)) == NULL) 274 return; 275 276 if (scf_handle_bind(h) != 0) { 277 scf_handle_destroy(h); 278 return; 279 } 280 281 if ((sc = scf_scope_create(h)) == NULL || 282 (svc = scf_service_create(h)) == NULL || 283 (inst = scf_instance_create(h)) == NULL || 284 (snap = scf_snapshot_create(h)) == NULL || 285 (pg = scf_pg_create(h)) == NULL || 286 (prop = scf_property_create(h)) == NULL || 287 (val = scf_value_create(h)) == NULL || 288 (siter = scf_iter_create(h)) == NULL || 289 (iiter = scf_iter_create(h)) == NULL) 290 goto out; 291 292 if (scf_handle_get_scope(h, SCF_SCOPE_LOCAL, sc) != 0) 293 goto out; 294 295 if (scf_iter_scope_services(siter, sc) != 0) 296 goto out; 297 298 while (scf_iter_next_service(siter, svc) == 1) { 299 300 if (scf_iter_service_instances(iiter, svc) != 0) 301 continue; 302 303 while (scf_iter_next_instance(iiter, inst) == 1) { 304 305 if ((scf_instance_get_snapshot(inst, "running", 306 snap)) != 0) 307 isnap = NULL; 308 else 309 isnap = snap; 310 311 if (scf_instance_get_pg_composed(inst, isnap, 312 SCF_PG_GENERAL, pg) != 0) 313 continue; 314 315 if (scf_pg_get_property(pg, SCF_PROPERTY_RESTARTER, 316 prop) != 0 || 317 scf_property_get_value(prop, val) != 0) 318 continue; 319 320 bytes = scf_value_get_astring(val, fmri, length); 321 if (bytes <= 0 || bytes >= length) 322 continue; 323 324 if (strlcat(fmri, FMRI_CONTRACT_PROP, length) >= 325 length) 326 continue; 327 328 if (scf_handle_decode_fmri(h, fmri, NULL, NULL, 329 NULL, NULL, prop, SCF_DECODE_FMRI_EXACT) != 0) 330 continue; 331 332 if (scf_property_is_type(prop, SCF_TYPE_COUNT) != 0 || 333 scf_property_get_value(prop, val) != 0 || 334 scf_value_get_count(val, &uint64) != 0) 335 continue; 336 337 ctid = (ctid_t)uint64; 338 if (save_ctid(ctid) == 0) { 339 (void) sigsend(P_CTID, ctid, SIGSTOP); 340 } 341 } 342 } 343 out: 344 scf_scope_destroy(sc); 345 scf_service_destroy(svc); 346 scf_instance_destroy(inst); 347 scf_snapshot_destroy(snap); 348 scf_pg_destroy(pg); 349 scf_property_destroy(prop); 350 scf_value_destroy(val); 351 scf_iter_destroy(siter); 352 scf_iter_destroy(iiter); 353 354 (void) scf_handle_unbind(h); 355 scf_handle_destroy(h); 356 } 357 358 static void 359 continue_delegates() 360 { 361 ctidlist_t *next; 362 for (next = ctidlist; next != NULL; next = next->next) 363 (void) sigsend(P_CTID, next->ctid, SIGCONT); 364 } 365 366 static void 367 stop_restarters() 368 { 369 stop_startd(); 370 stop_delegates(); 371 } 372 373 static void 374 continue_restarters() 375 { 376 continue_startd(); 377 continue_delegates(); 378 } 379 380 /* 381 * Copy an array of strings into buf, separated by spaces. Returns 0 on 382 * success. 383 */ 384 static int 385 gather_args(char **args, char *buf, size_t buf_sz) 386 { 387 if (strlcpy(buf, *args, buf_sz) >= buf_sz) 388 return (-1); 389 390 for (++args; *args != NULL; ++args) { 391 if (strlcat(buf, " ", buf_sz) >= buf_sz) 392 return (-1); 393 if (strlcat(buf, *args, buf_sz) >= buf_sz) 394 return (-1); 395 } 396 397 return (0); 398 } 399 400 /* 401 * Halt every zone on the system. We are committed to doing a shutdown 402 * even if something goes wrong here. If something goes wrong, we just 403 * continue with the shutdown. Return non-zero if we need to wait for zones to 404 * halt later on. 405 */ 406 static int 407 halt_zones() 408 { 409 pid_t pid; 410 zoneid_t *zones; 411 size_t nz = 0, old_nz; 412 int i; 413 char zname[ZONENAME_MAX]; 414 415 /* 416 * Get a list of zones. If the number of zones changes in between the 417 * two zone_list calls, try again. 418 */ 419 420 for (;;) { 421 (void) zone_list(NULL, &nz); 422 if (nz == 1) 423 return (0); 424 old_nz = nz; 425 zones = calloc(sizeof (zoneid_t), nz); 426 if (zones == NULL) { 427 (void) fprintf(stderr, 428 gettext("%s: Could not halt zones" 429 " (out of memory).\n"), cmdname); 430 return (0); 431 } 432 433 (void) zone_list(zones, &nz); 434 if (old_nz == nz) 435 break; 436 free(zones); 437 } 438 439 if (nz == 2) { 440 (void) fprintf(stderr, gettext("%s: Halting 1 zone.\n"), 441 cmdname); 442 } else { 443 (void) fprintf(stderr, gettext("%s: Halting %i zones.\n"), 444 cmdname, nz - 1); 445 } 446 447 for (i = 0; i < nz; i++) { 448 if (zones[i] == GLOBAL_ZONEID) 449 continue; 450 if (getzonenamebyid(zones[i], zname, sizeof (zname)) < 0) { 451 /* 452 * getzonenamebyid should only fail if we raced with 453 * another process trying to shut down the zone. 454 * We assume this happened and ignore the error. 455 */ 456 if (errno != EINVAL) { 457 (void) fprintf(stderr, 458 gettext("%s: Unexpected error while " 459 "looking up zone %ul: %s.\n"), 460 cmdname, zones[i], strerror(errno)); 461 } 462 463 continue; 464 } 465 pid = fork(); 466 if (pid < 0) { 467 (void) fprintf(stderr, 468 gettext("%s: Zone \"%s\" could not be" 469 " halted (could not fork(): %s).\n"), 470 cmdname, zname, strerror(errno)); 471 continue; 472 } 473 if (pid == 0) { 474 (void) execl(ZONEADM_PROG, ZONEADM_PROG, 475 "-z", zname, "halt", NULL); 476 (void) fprintf(stderr, 477 gettext("%s: Zone \"%s\" could not be halted" 478 " (cannot exec(" ZONEADM_PROG "): %s).\n"), 479 cmdname, zname, strerror(errno)); 480 exit(0); 481 } 482 } 483 484 return (1); 485 } 486 487 /* 488 * This function tries to wait for all non-global zones to go away. 489 * It will timeout if no progress is made for 5 seconds, or a total of 490 * 30 seconds elapses. 491 */ 492 493 static void 494 check_zones_haltedness() 495 { 496 int t = 0, t_prog = 0; 497 size_t nz = 0, last_nz; 498 499 do { 500 last_nz = nz; 501 (void) zone_list(NULL, &nz); 502 if (nz == 1) 503 return; 504 505 (void) sleep(1); 506 507 if (last_nz > nz) 508 t_prog = 0; 509 510 t++; 511 t_prog++; 512 513 if (t == 10) { 514 if (nz == 2) { 515 (void) fprintf(stderr, 516 gettext("%s: Still waiting for 1 zone to " 517 "halt. Will wait up to 20 seconds.\n"), 518 cmdname); 519 } else { 520 (void) fprintf(stderr, 521 gettext("%s: Still waiting for %i zones " 522 "to halt. Will wait up to 20 seconds.\n"), 523 cmdname, nz - 1); 524 } 525 } 526 527 } while ((t < 30) && (t_prog < 5)); 528 } 529 530 531 /* 532 * Validate that this is a root disk or dataset 533 * Returns 0 if it is a root disk or dataset; 534 * returns 1 if it is a disk argument or dataset, but not valid or not root; 535 * returns -1 if it is not a valid argument or a disk argument. 536 */ 537 static int 538 validate_disk(char *arg, char *mountpoint) 539 { 540 static char root_dev_path[] = "/dev/dsk"; 541 char kernpath[MAXPATHLEN]; 542 struct stat buf; 543 struct stat64 statbuf; 544 int rc = 0; 545 546 if (strlen(arg) > MAXPATHLEN) { 547 (void) fprintf(stderr, 548 gettext("%s: argument is too long\n"), cmdname); 549 return (-1); 550 } 551 552 bcopy(FASTBOOT_MOUNTPOINT, mountpoint, sizeof (FASTBOOT_MOUNTPOINT)); 553 554 /* 555 * Do a force umount just in case some other filesystem has 556 * been mounted there. 557 */ 558 (void) umount2(mountpoint, MS_FORCE); 559 560 /* Create the directory if it doesn't already exist */ 561 if (lstat(mountpoint, &buf) != 0) { 562 if (mkdirp(mountpoint, 0755) != 0) { 563 (void) fprintf(stderr, 564 gettext("failed to create mountpoint %s\n"), 565 mountpoint); 566 return (-1); 567 } 568 } 569 570 if (strncmp(arg, root_dev_path, strlen(root_dev_path)) == 0) { 571 /* ufs root disk argument */ 572 rc = validate_ufs_disk(arg, mountpoint); 573 } else { 574 /* zfs root pool argument */ 575 rc = validate_zfs_pool(arg, mountpoint); 576 } 577 578 if (rc != 0) 579 return (rc); 580 581 (void) snprintf(kernpath, MAXPATHLEN, "%s/platform/i86pc/kernel/unix", 582 mountpoint); 583 584 if (stat64(kernpath, &statbuf) != 0) { 585 (void) fprintf(stderr, 586 gettext("%s: %s is not a root disk or dataset\n"), 587 cmdname, arg); 588 return (1); 589 } 590 591 return (0); 592 } 593 594 595 static int 596 validate_ufs_disk(char *arg, char *mountpoint) 597 { 598 char mntopts[MNT_LINE_MAX] = { '\0' }; 599 600 /* perform the mount */ 601 if (mount(arg, mountpoint, MS_DATA|MS_OPTIONSTR, 602 MNTTYPE_UFS, NULL, 0, mntopts, sizeof (mntopts)) != 0) { 603 perror(cmdname); 604 (void) fprintf(stderr, 605 gettext("%s: failed to mount %s\n"), cmdname, arg); 606 return (-1); 607 } 608 609 return (0); 610 } 611 612 static int 613 validate_zfs_pool(char *arg, char *mountpoint) 614 { 615 zfs_handle_t *zhp = NULL; 616 char mntopts[MNT_LINE_MAX] = { '\0' }; 617 int rc = 0; 618 619 if ((g_zfs = libzfs_init()) == NULL) { 620 (void) fprintf(stderr, gettext("internal error: failed to " 621 "initialize ZFS library\n")); 622 return (-1); 623 } 624 625 /* Try to open the dataset */ 626 if ((zhp = zfs_open(g_zfs, arg, 627 ZFS_TYPE_FILESYSTEM | ZFS_TYPE_DATASET)) == NULL) 628 return (-1); 629 630 /* perform the mount */ 631 if (mount(zfs_get_name(zhp), mountpoint, MS_DATA|MS_OPTIONSTR, 632 MNTTYPE_ZFS, NULL, 0, mntopts, sizeof (mntopts)) != 0) { 633 perror(cmdname); 634 (void) fprintf(stderr, 635 gettext("%s: failed to mount %s\n"), cmdname, arg); 636 rc = -1; 637 } 638 639 validate_zfs_err_out: 640 if (zhp != NULL) 641 zfs_close(zhp); 642 643 libzfs_fini(g_zfs); 644 return (rc); 645 } 646 647 /* 648 * Return 0 if not zfs, or is zfs and have successfully constructed the 649 * boot argument; returns non-zero otherwise. 650 * At successful completion fpth contains pointer where mount point ends. 651 * NOTE: arg is supposed to be the resolved path 652 */ 653 static int 654 get_zfs_bootfs_arg(const char *arg, const char ** fpth, int *is_zfs, 655 char *bootfs_arg) 656 { 657 zfs_handle_t *zhp = NULL; 658 zpool_handle_t *zpoolp = NULL; 659 FILE *mtabp = NULL; 660 struct mnttab mnt; 661 char *poolname = NULL; 662 char physpath[MAXNAMELEN]; 663 char mntsp[ZPOOL_MAXNAMELEN]; 664 char bootfs[ZPOOL_MAXNAMELEN]; 665 int rc = 0; 666 size_t mntlen = 0; 667 size_t msz; 668 669 *fpth = arg; 670 *is_zfs = 0; 671 672 bzero(physpath, sizeof (physpath)); 673 bzero(bootfs, sizeof (bootfs)); 674 675 if ((mtabp = fopen(MNTTAB, "r")) == NULL) { 676 return (-1); 677 } 678 679 while (getmntent(mtabp, &mnt) == 0) { 680 if (strstr(arg, mnt.mnt_mountp) == arg && 681 (msz = strlen(mnt.mnt_mountp)) > mntlen) { 682 mntlen = msz; 683 *is_zfs = strcmp(MNTTYPE_ZFS, mnt.mnt_fstype) == 0; 684 (void) strlcpy(mntsp, mnt.mnt_special, sizeof (mntsp)); 685 } 686 } 687 688 (void) fclose(mtabp); 689 690 if (mntlen > 1) 691 *fpth += mntlen; 692 693 if (!*is_zfs) 694 return (0); 695 696 if ((g_zfs = libzfs_init()) == NULL) 697 return (-1); 698 699 /* Try to open the dataset */ 700 if ((zhp = zfs_open(g_zfs, mntsp, 701 ZFS_TYPE_FILESYSTEM | ZFS_TYPE_DATASET)) == NULL) { 702 (void) fprintf(stderr, gettext("cannot open %s\n"), mntsp); 703 rc = -1; 704 goto validate_zfs_err_out; 705 } 706 707 (void) strlcpy(bootfs, mntsp, sizeof (bootfs)); 708 709 if ((poolname = strtok(mntsp, "/")) == NULL) { 710 rc = -1; 711 goto validate_zfs_err_out; 712 } 713 714 if ((zpoolp = zpool_open(g_zfs, poolname)) == NULL) { 715 (void) fprintf(stderr, gettext("cannot open %s\n"), poolname); 716 rc = -1; 717 goto validate_zfs_err_out; 718 } 719 720 if (zpool_get_physpath(zpoolp, physpath) != 0) { 721 (void) fprintf(stderr, gettext("cannot find phys_path\n")); 722 rc = -1; 723 goto validate_zfs_err_out; 724 } 725 726 if (zpool_set_prop(zpoolp, "bootfs", bootfs) != 0) { 727 (void) fprintf(stderr, gettext("cannot set bootfs to %s\n"), 728 bootfs); 729 rc = -1; 730 goto validate_zfs_err_out; 731 } 732 733 (void) snprintf(bootfs_arg, BOOTARGS_MAX, 734 "-B zfs-bootfs=%s,bootpath=\"%s\"", bootfs, physpath); 735 736 validate_zfs_err_out: 737 if (zhp != NULL) 738 zfs_close(zhp); 739 740 if (zpoolp != NULL) 741 zpool_close(zpoolp); 742 743 libzfs_fini(g_zfs); 744 return (rc); 745 } 746 747 /* 748 * Validate that the file exists, and is an ELF file. 749 * Returns 0 on success, -1 on failure. 750 */ 751 static int 752 validate_unix(char *arg, int *mplen, int *is_zfs, char *bootfs_arg, 753 int *failsafe) 754 { 755 const char *location; 756 int class, format; 757 unsigned char ident[EI_NIDENT]; 758 char physpath[MAXPATHLEN]; 759 int elffd = -1; 760 size_t sz; 761 762 if ((sz = resolvepath(arg, physpath, sizeof (physpath) - 1)) == 763 (size_t)-1) { 764 (void) fprintf(stderr, 765 gettext("cannot resolve path for %s: %s\n"), 766 arg, strerror(errno)); 767 return (-1); 768 } 769 (void) strlcpy(arg, physpath, sz + 1); 770 771 if (strlen(arg) > MAXPATHLEN) { 772 (void) fprintf(stderr, 773 gettext("%s: new kernel name is too long\n"), cmdname); 774 return (-1); 775 } 776 777 if (strncmp(basename(arg), "unix", 4) != 0) { 778 (void) fprintf(stderr, 779 gettext("%s: %s: kernel name must be unix\n"), 780 cmdname, arg); 781 return (-1); 782 } 783 784 if (get_zfs_bootfs_arg(arg, &location, is_zfs, bootfs_arg) != 0) 785 goto err_out; 786 787 *mplen = location - arg; 788 789 if ((strstr(location, "/boot/platform")) == location) 790 *failsafe = 1; 791 else if ((strstr(location, "/platform")) == location) 792 *failsafe = 0; 793 else { 794 (void) fprintf(stderr, 795 gettext("%s: %s: no /boot/platform or /platform in" 796 " file name\n"), cmdname, arg); 797 goto err_out; 798 } 799 800 if ((elffd = open64(arg, O_RDONLY)) < 0 || 801 (pread64(elffd, ident, EI_NIDENT, 0) != EI_NIDENT)) { 802 (void) fprintf(stderr, "%s: %s: %s\n", 803 cmdname, arg, strerror(errno)); 804 goto err_out; 805 } 806 807 class = ident[EI_CLASS]; 808 809 if ((class != ELFCLASS32 && class != ELFCLASS64) || 810 ident[EI_MAG0] != ELFMAG0 || ident[EI_MAG1] != ELFMAG1 || 811 ident[EI_MAG2] != ELFMAG2 || ident[EI_MAG3] != ELFMAG3) { 812 (void) fprintf(stderr, 813 gettext("%s: %s: not a valid ELF file\n"), 814 cmdname, arg); 815 goto err_out; 816 } 817 818 format = ident[EI_DATA]; 819 820 if (format != CUR_ELFDATA) { 821 (void) fprintf(stderr, gettext("%s: %s: invalid data format\n"), 822 cmdname, arg); 823 goto err_out; 824 } 825 826 return (0); 827 828 err_out: 829 if (elffd >= 0) { 830 (void) close(elffd); 831 elffd = -1; 832 } 833 return (-1); 834 } 835 836 #ifndef __i386 837 /* ARGSUSED */ 838 #endif /* __i386 */ 839 static int 840 is_fastboot_default(uid_t uid) 841 { 842 #if defined(__i386) 843 int ret; 844 struct stat st; 845 static const char fastboot_default[] = "/etc/fastreboot"; 846 847 ret = (lstat(fastboot_default, &st) == 0 && 848 S_ISREG(st.st_mode) && 849 (st.st_mode & S_IRUSR) != 0 && 850 uid == st.st_uid); 851 852 return (ret); 853 #else 854 return (0); 855 #endif /* __i386 */ 856 } 857 858 static int 859 halt_exec(const char *path, ...) 860 { 861 pid_t pid; 862 int i; 863 int st; 864 const char *arg; 865 va_list vp; 866 const char *argv[256]; 867 868 if ((pid = fork()) == -1) { 869 return (errno); 870 } else if (pid == 0) { 871 (void) fclose(stdout); 872 (void) fclose(stderr); 873 874 argv[0] = path; 875 i = 1; 876 877 va_start(vp, path); 878 879 do { 880 arg = va_arg(vp, const char *); 881 argv[i] = arg; 882 } while (arg != NULL && 883 ++i != sizeof (argv) / sizeof (argv[0])); 884 885 va_end(vp); 886 887 (void) execve(path, (char * const *)argv, NULL); 888 (void) fprintf(stderr, gettext("cannot execute %s: %s\n"), 889 path, strerror(errno)); 890 exit(-1); 891 } else { 892 if (waitpid(pid, &st, 0) == pid && 893 !WIFSIGNALED(st) && WIFEXITED(st)) 894 st = WEXITSTATUS(st); 895 else 896 st = -1; 897 } 898 return (st); 899 } 900 901 /* 902 * Invokes lumount for bename. 903 * At successfull completion returns zero and copies contents of bename 904 * into mountpoint[] 905 */ 906 static int 907 fastboot_bename(const char *bename, char *mountpoint, size_t mpsz) 908 { 909 int rc; 910 911 (void) halt_exec(LUUMOUNT_PROG, "-n", bename, NULL); 912 913 if ((rc = halt_exec(LUMOUNT_PROG, "-n", bename, FASTBOOT_MOUNTPOINT, 914 NULL)) != 0) 915 (void) fprintf(stderr, gettext("%s: cannot mount BE %s\n"), 916 cmdname, bename); 917 else 918 (void) strlcpy(mountpoint, FASTBOOT_MOUNTPOINT, mpsz); 919 920 return (rc); 921 } 922 923 /* 924 * Returns 0 on successful parsing of the arguments; 925 * retuens non-zero on failure. 926 */ 927 static int 928 parse_fastboot_args(char *bootargs_buf, int *is_dryrun, const char *bename, 929 int *failsafe) 930 { 931 char mountpoint[MAXPATHLEN]; 932 char bootargs_saved[BOOTARGS_MAX]; 933 char bootargs_scratch[BOOTARGS_MAX]; 934 char bootfs_arg[BOOTARGS_MAX]; 935 char unixfile[BOOTARGS_MAX]; 936 char *head, *newarg; 937 int buflen; /* length of the bootargs_buf */ 938 int mplen; /* length of the mount point */ 939 int rootlen = 0; /* length of the root argument */ 940 int unixlen = 0; /* length of the unix argument */ 941 int off = 0; /* offset into the new boot argument */ 942 int is_zfs = 0; 943 int rc = 0; 944 945 bzero(mountpoint, sizeof (mountpoint)); 946 947 /* 948 * If argc is not 0, buflen is length of the argument being passed in; 949 * else it is 0 as bootargs_buf has been initialized to all 0's. 950 */ 951 buflen = strlen(bootargs_buf); 952 953 /* Save a copy of the original argument */ 954 bcopy(bootargs_buf, bootargs_saved, buflen); 955 bzero(&bootargs_saved[buflen], sizeof (bootargs_saved) - buflen); 956 957 /* Save another copy to be used by strtok */ 958 bcopy(bootargs_buf, bootargs_scratch, buflen); 959 bzero(&bootargs_scratch[buflen], sizeof (bootargs_scratch) - buflen); 960 head = &bootargs_scratch[0]; 961 962 /* Zero out the boot argument buffer as we will reconstruct it */ 963 bzero(bootargs_buf, BOOTARGS_MAX); 964 bzero(bootfs_arg, BOOTARGS_MAX); 965 bzero(unixfile, sizeof (unixfile)); 966 967 /* Get the first argument */ 968 newarg = strtok(bootargs_scratch, " "); 969 970 /* 971 * If this is a dry run request, verify that the drivers can handle 972 * fast reboot. 973 */ 974 if (newarg && strncasecmp(newarg, "dryrun", strlen("dryrun")) == 0) { 975 *is_dryrun = 1; 976 (void) system("/usr/sbin/devfsadm"); 977 } 978 979 /* 980 * Always perform a dry run to identify all the drivers that 981 * need to implement devo_reset(). 982 */ 983 if (uadmin(A_SHUTDOWN, AD_FASTREBOOT_DRYRUN, 984 (uintptr_t)bootargs_saved) != 0) { 985 (void) fprintf(stderr, gettext("%s: not all drivers " 986 "have implemented quiesce(9E)\n"), cmdname); 987 } else if (*is_dryrun) { 988 (void) fprintf(stderr, gettext("%s: all drivers have " 989 "implemented quiesce(9E)\n"), cmdname); 990 } 991 992 /* 993 * Return if it is a true dry run. 994 */ 995 if (*is_dryrun) 996 return (rc); 997 998 if (bename && (rc = fastboot_bename(bename, mountpoint, 999 sizeof (mountpoint))) != 0) 1000 return (rc); 1001 1002 /* 1003 * If BE is not specified, look for disk argument to construct 1004 * mountpoint; if BE has been specified, mountpoint has already been 1005 * constructed. 1006 */ 1007 if (newarg && newarg[0] != '-' && !bename) { 1008 int tmprc; 1009 1010 if ((tmprc = validate_disk(newarg, mountpoint)) == 0) { 1011 /* 1012 * The first argument is a valid root argument. 1013 * Get the next argument. 1014 */ 1015 newarg = strtok(NULL, " "); 1016 rootlen = (newarg) ? (newarg - head) : buflen; 1017 (void) strlcpy(fastboot_mounted, mountpoint, 1018 sizeof (fastboot_mounted)); 1019 1020 } else if (tmprc == -1) { 1021 /* 1022 * Not a disk argument. Use / as default root. 1023 */ 1024 bcopy("/", mountpoint, 1); 1025 bzero(&mountpoint[1], sizeof (mountpoint) - 1); 1026 } else { 1027 /* 1028 * Disk argument, but not valid or not root. 1029 * Return failure. 1030 */ 1031 return (EINVAL); 1032 } 1033 } 1034 1035 /* 1036 * Make mountpoint the first part of unixfile. 1037 * If there is not disk argument, and BE has not been specified, 1038 * mountpoint could be empty. 1039 */ 1040 mplen = strlen(mountpoint); 1041 bcopy(mountpoint, unixfile, mplen); 1042 1043 /* 1044 * Look for unix argument 1045 */ 1046 if (newarg && newarg[0] != '-') { 1047 bcopy(newarg, &unixfile[mplen], strlen(newarg)); 1048 newarg = strtok(NULL, " "); 1049 rootlen = (newarg) ? (newarg - head) : buflen; 1050 } else if (mplen != 0) { 1051 /* 1052 * No unix argument, but mountpoint is not empty, use 1053 * /platform/i86pc/$ISADIR/kernel/unix as default. 1054 */ 1055 char isa[20]; 1056 1057 if (sysinfo(SI_ARCHITECTURE_64, isa, sizeof (isa)) != -1) 1058 (void) snprintf(&unixfile[mplen], 1059 sizeof (unixfile) - mplen, 1060 "/platform/i86pc/kernel/%s/unix", isa); 1061 else if (sysinfo(SI_ARCHITECTURE_32, isa, sizeof (isa)) != -1) { 1062 (void) snprintf(&unixfile[mplen], 1063 sizeof (unixfile) - mplen, 1064 "/platform/i86pc/kernel/unix"); 1065 } else { 1066 (void) fprintf(stderr, 1067 gettext("%s: unknown architecture"), cmdname); 1068 return (EINVAL); 1069 } 1070 } 1071 1072 /* 1073 * We now have the complete unix argument. Verify that it exists and 1074 * is an ELF file. Split the argument up into mountpoint and unix 1075 * portions again. This is necessary to handle cases where mountpoint 1076 * is specified on the command line as part of the unix argument, 1077 * such as this: 1078 * # reboot -f /.alt/platform/i86pc/kernel/amd64/unix 1079 */ 1080 unixlen = strlen(unixfile); 1081 if (unixlen > 0) { 1082 if (validate_unix(unixfile, &mplen, &is_zfs, 1083 bootfs_arg, failsafe) != 0) { 1084 /* Not a valid unix file */ 1085 return (EINVAL); 1086 } else { 1087 int space = 0; 1088 /* 1089 * Construct boot argument. 1090 */ 1091 unixlen = strlen(unixfile); 1092 1093 /* 1094 * mdep cannot start with space because bootadm 1095 * creates bogus menu entries if it does. 1096 */ 1097 if (mplen > 0) { 1098 bcopy(unixfile, bootargs_buf, mplen); 1099 (void) strcat(bootargs_buf, " "); 1100 space = 1; 1101 } 1102 bcopy(&unixfile[mplen], &bootargs_buf[mplen + space], 1103 unixlen - mplen); 1104 (void) strcat(bootargs_buf, " "); 1105 off += unixlen + space + 1; 1106 } 1107 } else { 1108 /* Check to see if root is zfs */ 1109 const char *dp; 1110 (void) get_zfs_bootfs_arg("/", &dp, &is_zfs, bootfs_arg); 1111 } 1112 1113 if (is_zfs && (buflen != 0 || bename != NULL)) { 1114 /* LINTED E_SEC_SPRINTF_UNBOUNDED_COPY */ 1115 off += sprintf(bootargs_buf + off, "%s ", bootfs_arg); 1116 } 1117 1118 /* 1119 * Copy the rest of the arguments 1120 */ 1121 bcopy(&bootargs_saved[rootlen], &bootargs_buf[off], buflen - rootlen); 1122 1123 return (rc); 1124 } 1125 1126 int 1127 main(int argc, char *argv[]) 1128 { 1129 char *ttyn = ttyname(STDERR_FILENO); 1130 1131 uid_t euid; 1132 int qflag = 0, needlog = 1, nosync = 0; 1133 int fast_reboot = 0; 1134 uintptr_t mdep = NULL; 1135 int cmd, fcn, c, aval, r; 1136 const char *usage; 1137 zoneid_t zoneid = getzoneid(); 1138 int need_check_zones = 0; 1139 char bootargs_buf[BOOTARGS_MAX]; 1140 int failsafe = 0; 1141 char *bename = NULL; 1142 1143 const char * const resetting = "/etc/svc/volatile/resetting"; 1144 1145 (void) setlocale(LC_ALL, ""); 1146 (void) textdomain(TEXT_DOMAIN); 1147 1148 cmdname = basename(argv[0]); 1149 1150 if (strcmp(cmdname, "halt") == 0) { 1151 (void) audit_halt_setup(argc, argv); 1152 usage = gettext("usage: %s [ -dlnqy ]\n"); 1153 cmd = A_SHUTDOWN; 1154 fcn = AD_HALT; 1155 } else if (strcmp(cmdname, "poweroff") == 0) { 1156 (void) audit_halt_setup(argc, argv); 1157 usage = gettext("usage: %s [ -dlnqy ]\n"); 1158 cmd = A_SHUTDOWN; 1159 fcn = AD_POWEROFF; 1160 } else if (strcmp(cmdname, "reboot") == 0) { 1161 (void) audit_reboot_setup(); 1162 #if defined(__i386) 1163 usage = gettext("usage: %s [ -dlnqfe: ] [ boot args ]\n"); 1164 #else 1165 usage = gettext("usage: %s [ -dlnq ] [ boot args ]\n"); 1166 #endif 1167 cmd = A_SHUTDOWN; 1168 fcn = AD_BOOT; 1169 } else { 1170 (void) fprintf(stderr, 1171 gettext("%s: not installed properly\n"), cmdname); 1172 return (1); 1173 } 1174 1175 while ((c = getopt(argc, argv, "dlnqyfe:")) != EOF) { 1176 switch (c) { 1177 case 'd': 1178 if (zoneid == GLOBAL_ZONEID) 1179 cmd = A_DUMP; 1180 else { 1181 (void) fprintf(stderr, 1182 gettext("%s: -d only valid from global" 1183 " zone\n"), cmdname); 1184 return (1); 1185 } 1186 break; 1187 case 'l': 1188 needlog = 0; 1189 break; 1190 case 'n': 1191 nosync = 1; 1192 break; 1193 case 'q': 1194 qflag = 1; 1195 break; 1196 case 'y': 1197 ttyn = NULL; 1198 break; 1199 #if defined(__i386) 1200 case 'f': 1201 fast_reboot = 1; 1202 break; 1203 case 'e': 1204 bename = optarg; 1205 break; 1206 #endif 1207 default: 1208 /* 1209 * TRANSLATION_NOTE 1210 * Don't translate the words "halt" or "reboot" 1211 */ 1212 (void) fprintf(stderr, usage, cmdname); 1213 return (1); 1214 } 1215 } 1216 1217 argc -= optind; 1218 argv += optind; 1219 1220 if (argc != 0) { 1221 if (fcn != AD_BOOT) { 1222 (void) fprintf(stderr, usage, cmdname); 1223 return (1); 1224 } 1225 1226 /* Gather the arguments into bootargs_buf. */ 1227 if (gather_args(argv, bootargs_buf, sizeof (bootargs_buf)) != 1228 0) { 1229 (void) fprintf(stderr, 1230 gettext("%s: Boot arguments too long.\n"), cmdname); 1231 return (1); 1232 } 1233 1234 mdep = (uintptr_t)bootargs_buf; 1235 } else { 1236 /* 1237 * Initialize it to 0 in case of fastboot, the buffer 1238 * will be used. 1239 */ 1240 bzero(bootargs_buf, sizeof (bootargs_buf)); 1241 } 1242 1243 if ((euid = geteuid()) != 0) { 1244 (void) fprintf(stderr, 1245 gettext("%s: permission denied\n"), cmdname); 1246 goto fail; 1247 } 1248 1249 /* 1250 * Check whether fast reboot is the default operating mode 1251 */ 1252 if (!fast_reboot) 1253 fast_reboot = is_fastboot_default(euid); 1254 1255 if (bename && !fast_reboot) { 1256 (void) fprintf(stderr, gettext("%s: -e only valid with -f\n"), 1257 cmdname); 1258 return (EINVAL); 1259 } 1260 1261 1262 /* 1263 * If fast reboot, do some sanity check on the argument 1264 */ 1265 if (fast_reboot) { 1266 int rc; 1267 int is_dryrun = 0; 1268 1269 if (zoneid != GLOBAL_ZONEID) { 1270 (void) fprintf(stderr, 1271 gettext("%s: fast reboot only valid from global" 1272 " zone\n"), cmdname); 1273 return (EINVAL); 1274 } 1275 1276 rc = parse_fastboot_args(bootargs_buf, &is_dryrun, 1277 bename, &failsafe); 1278 1279 /* 1280 * If dry run, or if arguments are invalid, return. 1281 */ 1282 if (is_dryrun) 1283 return (rc); 1284 else if (rc != 0) 1285 goto fail; 1286 1287 /* 1288 * For all the other errors, we continue on in case user 1289 * user want to force fast reboot. 1290 */ 1291 if (strlen(bootargs_buf) != 0) 1292 mdep = (uintptr_t)bootargs_buf; 1293 } 1294 1295 #if 0 /* For debugging */ 1296 if (mdep != NULL) 1297 (void) fprintf(stderr, "mdep = %s\n", (char *)mdep); 1298 #endif 1299 1300 if (fcn != AD_BOOT && ttyn != NULL && 1301 strncmp(ttyn, "/dev/term/", strlen("/dev/term/")) == 0) { 1302 /* 1303 * TRANSLATION_NOTE 1304 * Don't translate ``halt -y'' 1305 */ 1306 (void) fprintf(stderr, 1307 gettext("%s: dangerous on a dialup;"), cmdname); 1308 (void) fprintf(stderr, 1309 gettext("use ``%s -y'' if you are really sure\n"), cmdname); 1310 goto fail; 1311 } 1312 1313 if (needlog) { 1314 char *user = getlogin(); 1315 struct passwd *pw; 1316 char *tty; 1317 1318 openlog(cmdname, 0, LOG_AUTH); 1319 if (user == NULL && (pw = getpwuid(getuid())) != NULL) 1320 user = pw->pw_name; 1321 if (user == NULL) 1322 user = "root"; 1323 1324 tty = ttyname(1); 1325 1326 if (tty == NULL) 1327 syslog(LOG_CRIT, "initiated by %s", user); 1328 else 1329 syslog(LOG_CRIT, "initiated by %s on %s", user, tty); 1330 } 1331 1332 /* 1333 * We must assume success and log it before auditd is terminated. 1334 */ 1335 if (fcn == AD_BOOT) 1336 aval = audit_reboot_success(); 1337 else 1338 aval = audit_halt_success(); 1339 1340 if (aval == -1) { 1341 (void) fprintf(stderr, 1342 gettext("%s: can't turn off auditd\n"), cmdname); 1343 if (needlog) 1344 (void) sleep(5); /* Give syslogd time to record this */ 1345 } 1346 1347 (void) signal(SIGHUP, SIG_IGN); /* for remote connections */ 1348 1349 /* 1350 * We start to fork a bunch of zoneadms to halt any active zones. 1351 * This will proceed with halt in parallel until we call 1352 * check_zone_haltedness later on. 1353 */ 1354 if (zoneid == GLOBAL_ZONEID && cmd != A_DUMP) { 1355 need_check_zones = halt_zones(); 1356 } 1357 1358 1359 /* sync boot archive in the global zone */ 1360 if (zoneid == GLOBAL_ZONEID && !nosync) { 1361 if (fast_reboot) 1362 (void) system("/sbin/bootadm -a update_all fastboot"); 1363 else 1364 (void) system("/sbin/bootadm -a update_all"); 1365 } 1366 1367 /* 1368 * If we're not forcing a crash dump, mark the system as quiescing for 1369 * smf(5)'s benefit, and idle the init process. 1370 */ 1371 if (cmd != A_DUMP) { 1372 if (direct_init(PCDSTOP) == -1) { 1373 /* 1374 * TRANSLATION_NOTE 1375 * Don't translate the word "init" 1376 */ 1377 (void) fprintf(stderr, 1378 gettext("%s: can't idle init\n"), cmdname); 1379 goto fail; 1380 } 1381 1382 if (creat(resetting, 0755) == -1) 1383 (void) fprintf(stderr, 1384 gettext("%s: could not create %s.\n"), 1385 cmdname, resetting); 1386 1387 /* 1388 * Stop all restarters so they do not try to restart services 1389 * that are terminated. 1390 */ 1391 stop_restarters(); 1392 1393 /* 1394 * Wait a little while for zones to shutdown. 1395 */ 1396 if (need_check_zones) { 1397 check_zones_haltedness(); 1398 1399 (void) fprintf(stderr, 1400 gettext("%s: Completing system halt.\n"), 1401 cmdname); 1402 } 1403 } 1404 1405 /* 1406 * Make sure we don't get stopped by a jobcontrol shell 1407 * once we start killing everybody. 1408 */ 1409 (void) signal(SIGTSTP, SIG_IGN); 1410 (void) signal(SIGTTIN, SIG_IGN); 1411 (void) signal(SIGTTOU, SIG_IGN); 1412 (void) signal(SIGTERM, SIG_IGN); 1413 1414 /* 1415 * If we're not forcing a crash dump, give everyone 5 seconds to 1416 * handle a SIGTERM and clean up properly. 1417 */ 1418 if (cmd != A_DUMP) { 1419 (void) kill(-1, SIGTERM); 1420 (void) sleep(5); 1421 } 1422 1423 if (!qflag && !nosync) { 1424 struct utmpx wtmpx; 1425 1426 bzero(&wtmpx, sizeof (struct utmpx)); 1427 (void) strcpy(wtmpx.ut_line, "~"); 1428 (void) time(&wtmpx.ut_tv.tv_sec); 1429 1430 if (cmd == A_DUMP) 1431 (void) strcpy(wtmpx.ut_name, "crash dump"); 1432 else 1433 (void) strcpy(wtmpx.ut_name, "shutdown"); 1434 1435 (void) updwtmpx(WTMPX_FILE, &wtmpx); 1436 sync(); 1437 } 1438 1439 if (cmd == A_DUMP && nosync != 0) 1440 (void) uadmin(A_DUMP, AD_NOSYNC, NULL); 1441 1442 if (fast_reboot) { 1443 if (failsafe) 1444 (void) fprintf(stderr, "Fast reboot - failsafe.\n"); 1445 else 1446 (void) fprintf(stderr, "Fast reboot.\n"); 1447 1448 fcn = AD_FASTREBOOT; 1449 } 1450 1451 if (uadmin(cmd, fcn, mdep) == -1) 1452 (void) fprintf(stderr, "%s: uadmin failed: %s\n", 1453 cmdname, strerror(errno)); 1454 else 1455 (void) fprintf(stderr, "%s: uadmin unexpectedly returned 0\n", 1456 cmdname); 1457 1458 do { 1459 r = remove(resetting); 1460 } while (r != 0 && errno == EINTR); 1461 1462 if (r != 0 && errno != ENOENT) 1463 (void) fprintf(stderr, gettext("%s: could not remove %s.\n"), 1464 cmdname, resetting); 1465 1466 if (direct_init(PCRUN) == -1) { 1467 /* 1468 * TRANSLATION_NOTE 1469 * Don't translate the word "init" 1470 */ 1471 (void) fprintf(stderr, 1472 gettext("%s: can't resume init\n"), cmdname); 1473 } 1474 1475 continue_restarters(); 1476 1477 if (get_initpid() != -1) 1478 /* tell init to restate current level */ 1479 (void) kill(get_initpid(), SIGHUP); 1480 1481 fail: 1482 if (fcn == AD_BOOT) 1483 (void) audit_reboot_fail(); 1484 else 1485 (void) audit_halt_fail(); 1486 1487 if (fast_reboot) { 1488 if (bename) { 1489 (void) halt_exec(LUUMOUNT_PROG, "-n", bename, NULL); 1490 1491 } else if (strlen(fastboot_mounted) != 0) { 1492 (void) umount(fastboot_mounted); 1493 } 1494 } 1495 1496 return (1); 1497 } 1498