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