1 /* $OpenBSD: init.c,v 1.72 2022/09/10 00:49:47 cheloha Exp $ */ 2 /* $NetBSD: init.c,v 1.22 1996/05/15 23:29:33 jtc Exp $ */ 3 4 /*- 5 * Copyright (c) 1991, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * This code is derived from software contributed to Berkeley by 9 * Donn Seeley at Berkeley Software Design, Inc. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. Neither the name of the University nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36 #include <sys/types.h> 37 #include <sys/reboot.h> 38 #include <sys/sysctl.h> 39 #include <sys/time.h> 40 #include <sys/tree.h> 41 #include <sys/wait.h> 42 #include <machine/cpu.h> 43 44 #include <err.h> 45 #include <errno.h> 46 #include <fcntl.h> 47 #include <limits.h> 48 #include <login_cap.h> 49 #include <signal.h> 50 #include <stdarg.h> 51 #include <stdio.h> 52 #include <stdlib.h> 53 #include <string.h> 54 #include <syslog.h> 55 #include <time.h> 56 #include <ttyent.h> 57 #include <unistd.h> 58 #include <util.h> 59 60 #ifdef SECURE 61 #include <pwd.h> 62 #include <readpassphrase.h> 63 #endif 64 65 #include "pathnames.h" 66 67 /* 68 * Sleep times; used to prevent thrashing. 69 */ 70 #define GETTY_SPACING 5 /* N secs minimum getty spacing */ 71 #define GETTY_SLEEP 30 /* sleep N secs after spacing problem */ 72 #define WINDOW_WAIT 3 /* wait N secs after starting window */ 73 #define STALL_TIMEOUT 30 /* wait N secs after warning */ 74 #define DEATH_WATCH 10 /* wait N secs for procs to die */ 75 76 /* 77 * User-based resource limits. 78 */ 79 #define RESOURCE_RC "daemon" 80 #define RESOURCE_WINDOW "default" 81 #define RESOURCE_GETTY "default" 82 83 #ifndef DEFAULT_STATE 84 #define DEFAULT_STATE runcom 85 #endif 86 87 void handle(sig_t, ...); 88 void delset(sigset_t *, ...); 89 90 void stall(char *, ...); 91 void warning(char *, ...); 92 void emergency(char *, ...); 93 void disaster(int); 94 95 typedef enum { 96 invalid_state, 97 single_user, 98 runcom, 99 read_ttys, 100 multi_user, 101 clean_ttys, 102 catatonia, 103 death, 104 do_reboot, 105 hard_death, 106 nice_death 107 } state_t; 108 typedef state_t (*state_func_t)(void); 109 110 state_t f_single_user(void); 111 state_t f_runcom(void); 112 state_t f_read_ttys(void); 113 state_t f_multi_user(void); 114 state_t f_clean_ttys(void); 115 state_t f_catatonia(void); 116 state_t f_death(void); 117 state_t f_do_reboot(void); 118 state_t f_hard_death(void); 119 state_t f_nice_death(void); 120 121 state_func_t state_funcs[] = { 122 NULL, 123 f_single_user, 124 f_runcom, 125 f_read_ttys, 126 f_multi_user, 127 f_clean_ttys, 128 f_catatonia, 129 f_death, 130 f_do_reboot, 131 f_hard_death, 132 f_nice_death 133 }; 134 135 enum { AUTOBOOT, FASTBOOT } runcom_mode = AUTOBOOT; 136 137 void transition(state_t); 138 volatile sig_atomic_t requested_transition = DEFAULT_STATE; 139 140 void setctty(char *); 141 142 typedef struct init_session { 143 int se_index; /* index of entry in ttys file */ 144 pid_t se_process; /* controlling process */ 145 struct timespec se_started; /* used to avoid thrashing */ 146 int se_flags; /* status of session */ 147 #define SE_SHUTDOWN 0x1 /* session won't be restarted */ 148 #define SE_PRESENT 0x2 /* session is in /etc/ttys */ 149 #define SE_DEVEXISTS 0x4 /* open does not result in ENODEV */ 150 char *se_device; /* filename of port */ 151 char *se_getty; /* what to run on that port */ 152 char **se_getty_argv; /* pre-parsed argument array */ 153 char *se_window; /* window system (started only once) */ 154 char **se_window_argv; /* pre-parsed argument array */ 155 struct init_session *se_prev; 156 struct init_session *se_next; 157 RB_ENTRY(init_session) se_entry; 158 } session_t; 159 160 static int cmp_sessions(session_t *, session_t *); 161 RB_HEAD(session_tree, init_session) session_tree = RB_INITIALIZER(session_tree); 162 RB_PROTOTYPE(session_tree, init_session, se_entry, cmp_sessions); 163 RB_GENERATE(session_tree, init_session, se_entry, cmp_sessions); 164 165 void free_session(session_t *); 166 session_t *new_session(session_t *, int, struct ttyent *); 167 session_t *sessions; 168 169 char **construct_argv(char *); 170 void start_window_system(session_t *); 171 void collect_child(pid_t); 172 pid_t start_getty(session_t *); 173 void transition_handler(int); 174 void alrm_handler(int); 175 void setsecuritylevel(int); 176 void setprocresources(char *); 177 int getsecuritylevel(void); 178 int setupargv(session_t *, struct ttyent *); 179 180 volatile sig_atomic_t clang; 181 182 void clear_session_logs(session_t *); 183 184 void add_session(session_t *); 185 void del_session(session_t *); 186 session_t *find_session(pid_t); 187 188 /* 189 * The mother of all processes. 190 */ 191 int 192 main(int argc, char *argv[]) 193 { 194 int c, fd; 195 struct sigaction sa; 196 sigset_t mask; 197 198 /* Dispose of random users. */ 199 if (getuid() != 0) 200 errc(1, EPERM, NULL); 201 202 /* System V users like to reexec init. */ 203 if (getpid() != 1) 204 errx(1, "already running"); 205 206 /* 207 * Paranoia. 208 */ 209 if ((fd = open(_PATH_DEVNULL, O_RDWR)) != -1) { 210 (void)dup2(fd, STDIN_FILENO); 211 (void)dup2(fd, STDOUT_FILENO); 212 (void)dup2(fd, STDERR_FILENO); 213 if (fd > 2) 214 (void)close(fd); 215 } 216 217 /* 218 * Note that this does NOT open a file... 219 * Does 'init' deserve its own facility number? 220 */ 221 openlog("init", LOG_CONS|LOG_ODELAY, LOG_AUTH); 222 223 /* 224 * Create an initial session. 225 */ 226 if (setsid() == -1) 227 warning("initial setsid() failed: %m"); 228 229 /* 230 * Establish an initial user so that programs running 231 * single user do not freak out and die (like passwd). 232 */ 233 if (setlogin("root") == -1) 234 warning("setlogin() failed: %m"); 235 236 /* 237 * This code assumes that we always get arguments through flags, 238 * never through bits set in some random machine register. 239 */ 240 while ((c = getopt(argc, argv, "sf")) != -1) 241 switch (c) { 242 case 's': 243 requested_transition = single_user; 244 break; 245 case 'f': 246 runcom_mode = FASTBOOT; 247 break; 248 default: 249 warning("unrecognized flag '-%c'", c); 250 break; 251 } 252 253 if (optind != argc) 254 warning("ignoring excess arguments"); 255 256 /* 257 * We catch or block signals rather than ignore them, 258 * so that they get reset on exec. 259 */ 260 handle(disaster, SIGABRT, SIGFPE, SIGILL, SIGSEGV, 261 SIGBUS, SIGSYS, SIGXCPU, SIGXFSZ, 0); 262 handle(transition_handler, SIGHUP, SIGINT, SIGTERM, SIGTSTP, 263 SIGUSR1, SIGUSR2, 0); 264 handle(alrm_handler, SIGALRM, 0); 265 sigfillset(&mask); 266 delset(&mask, SIGABRT, SIGFPE, SIGILL, SIGSEGV, SIGBUS, SIGSYS, 267 SIGXCPU, SIGXFSZ, SIGHUP, SIGINT, SIGTERM, SIGUSR1, SIGUSR2, 268 SIGTSTP, SIGALRM, 0); 269 sigprocmask(SIG_SETMASK, &mask, NULL); 270 memset(&sa, 0, sizeof sa); 271 sigemptyset(&sa.sa_mask); 272 sa.sa_flags = 0; 273 sa.sa_handler = SIG_IGN; 274 (void) sigaction(SIGTTIN, &sa, NULL); 275 (void) sigaction(SIGTTOU, &sa, NULL); 276 277 /* 278 * Start the state machine. 279 */ 280 transition(requested_transition); 281 282 /* 283 * Should never reach here. 284 */ 285 exit(1); 286 } 287 288 /* 289 * Associate a function with a signal handler. 290 */ 291 void 292 handle(sig_t handler, ...) 293 { 294 int sig; 295 struct sigaction sa; 296 sigset_t mask_everything; 297 va_list ap; 298 299 va_start(ap, handler); 300 301 memset(&sa, 0, sizeof sa); 302 sa.sa_handler = handler; 303 sigfillset(&mask_everything); 304 305 while ((sig = va_arg(ap, int))) { 306 sa.sa_mask = mask_everything; 307 /* XXX SA_RESTART? */ 308 sa.sa_flags = sig == SIGCHLD ? SA_NOCLDSTOP : 0; 309 sigaction(sig, &sa, NULL); 310 } 311 va_end(ap); 312 } 313 314 /* 315 * Delete a set of signals from a mask. 316 */ 317 void 318 delset(sigset_t *maskp, ...) 319 { 320 int sig; 321 va_list ap; 322 323 va_start(ap, maskp); 324 while ((sig = va_arg(ap, int))) 325 sigdelset(maskp, sig); 326 va_end(ap); 327 } 328 329 /* 330 * Log a message and sleep for a while (to give someone an opportunity 331 * to read it and to save log or hardcopy output if the problem is chronic). 332 * NB: should send a message to the session logger to avoid blocking. 333 */ 334 void 335 stall(char *message, ...) 336 { 337 va_list ap; 338 339 va_start(ap, message); 340 vsyslog(LOG_ALERT, message, ap); 341 va_end(ap); 342 closelog(); 343 sleep(STALL_TIMEOUT); 344 } 345 346 /* 347 * Like stall(), but doesn't sleep. 348 * If cpp had variadic macros, the two functions could be #defines for another. 349 * NB: should send a message to the session logger to avoid blocking. 350 */ 351 void 352 warning(char *message, ...) 353 { 354 va_list ap; 355 356 va_start(ap, message); 357 vsyslog(LOG_ALERT, message, ap); 358 va_end(ap); 359 closelog(); 360 } 361 362 /* 363 * Log an emergency message. 364 * NB: should send a message to the session logger to avoid blocking. 365 */ 366 void 367 emergency(char *message, ...) 368 { 369 struct syslog_data sdata = SYSLOG_DATA_INIT; 370 va_list ap; 371 372 va_start(ap, message); 373 vsyslog_r(LOG_EMERG, &sdata, message, ap); 374 va_end(ap); 375 } 376 377 /* 378 * Catch an unexpected signal. 379 */ 380 void 381 disaster(int sig) 382 { 383 emergency("fatal signal: %s", strsignal(sig)); 384 385 sleep(STALL_TIMEOUT); 386 _exit(sig); /* reboot */ 387 } 388 389 /* 390 * Get the security level of the kernel. 391 */ 392 int 393 getsecuritylevel(void) 394 { 395 #ifdef KERN_SECURELVL 396 int name[2], curlevel; 397 size_t len; 398 399 name[0] = CTL_KERN; 400 name[1] = KERN_SECURELVL; 401 len = sizeof curlevel; 402 if (sysctl(name, 2, &curlevel, &len, NULL, 0) == -1) { 403 emergency("cannot get kernel security level: %s", 404 strerror(errno)); 405 return (-1); 406 } 407 return (curlevel); 408 #else 409 return (-1); 410 #endif 411 } 412 413 /* 414 * Set the security level of the kernel. 415 */ 416 void 417 setsecuritylevel(int newlevel) 418 { 419 #ifdef KERN_SECURELVL 420 int name[2], curlevel; 421 422 curlevel = getsecuritylevel(); 423 if (newlevel == curlevel) 424 return; 425 name[0] = CTL_KERN; 426 name[1] = KERN_SECURELVL; 427 if (sysctl(name, 2, NULL, NULL, &newlevel, sizeof newlevel) == -1) { 428 emergency( 429 "cannot change kernel security level from %d to %d: %s", 430 curlevel, newlevel, strerror(errno)); 431 return; 432 } 433 #ifdef SECURE 434 warning("kernel security level changed from %d to %d", 435 curlevel, newlevel); 436 #endif 437 #endif 438 } 439 440 /* 441 * Change states in the finite state machine. 442 * The initial state is passed as an argument. 443 */ 444 void 445 transition(state_t s) 446 { 447 for (;;) 448 s = (*state_funcs[s])(); 449 } 450 451 /* 452 * Close out the accounting files for a login session. 453 * NB: should send a message to the session logger to avoid blocking. 454 */ 455 void 456 clear_session_logs(session_t *sp) 457 { 458 char *line = sp->se_device + sizeof(_PATH_DEV) - 1; 459 460 if (logout(line)) 461 logwtmp(line, "", ""); 462 } 463 464 /* 465 * Start a session and allocate a controlling terminal. 466 * Only called by children of init after forking. 467 */ 468 void 469 setctty(char *name) 470 { 471 int fd; 472 473 (void) revoke(name); 474 sleep(2); /* leave DTR low */ 475 if ((fd = open(name, O_RDWR)) == -1) { 476 stall("can't open %s: %m", name); 477 _exit(1); 478 } 479 if (login_tty(fd) == -1) { 480 stall("can't get %s for controlling terminal: %m", name); 481 _exit(1); 482 } 483 } 484 485 /* 486 * Bring the system up single user. 487 */ 488 state_t 489 f_single_user(void) 490 { 491 pid_t pid, wpid; 492 int status; 493 sigset_t mask; 494 char shell[PATH_MAX]; /* Allocate space here */ 495 char name[PATH_MAX]; /* Name (argv[0]) of shell */ 496 char *argv[2]; 497 #ifdef SECURE 498 struct ttyent *typ; 499 struct passwd *pp; 500 static const char banner[] = 501 "Enter root password, or ^D to go multi-user\n"; 502 char *clear; 503 char pbuf[1024]; 504 #endif 505 506 /* Init shell and name */ 507 strlcpy(shell, _PATH_BSHELL, sizeof shell); 508 strlcpy(name, "-sh", sizeof name); 509 510 /* 511 * If the kernel is in secure mode, downgrade it to insecure mode. 512 */ 513 if (getsecuritylevel() > 0) 514 setsecuritylevel(0); 515 516 if ((pid = fork()) == 0) { 517 /* 518 * Start the single user session. 519 */ 520 setctty(_PATH_CONSOLE); 521 522 #ifdef SECURE 523 /* 524 * Check the root password. 525 * We don't care if the console is 'on' by default; 526 * it's the only tty that can be 'off' and 'secure'. 527 */ 528 typ = getttynam("console"); 529 pp = getpwnam_shadow("root"); 530 if (typ && (typ->ty_status & TTY_SECURE) == 0 && pp && 531 *pp->pw_passwd) { 532 write(STDERR_FILENO, banner, sizeof banner - 1); 533 for (;;) { 534 int ok = 0; 535 clear = readpassphrase("Password:", pbuf, 536 sizeof(pbuf), RPP_ECHO_OFF); 537 if (clear == NULL || *clear == '\0') 538 _exit(0); 539 if (crypt_checkpass(clear, pp->pw_passwd) == 0) 540 ok = 1; 541 explicit_bzero(pbuf, sizeof(pbuf)); 542 if (ok) 543 break; 544 warning("single-user login failed\n"); 545 } 546 } 547 endttyent(); 548 endpwent(); 549 #endif /* SECURE */ 550 551 #ifdef DEBUGSHELL 552 { 553 char altshell[128], *cp = altshell; 554 int num; 555 556 #define SHREQUEST \ 557 "Enter pathname of shell or RETURN for sh: " 558 559 (void)write(STDERR_FILENO, 560 SHREQUEST, sizeof(SHREQUEST) - 1); 561 while ((num = read(STDIN_FILENO, cp, 1)) != -1 && 562 num != 0 && *cp != '\n' && cp < &altshell[127]) 563 cp++; 564 *cp = '\0'; 565 566 /* Copy in alternate shell */ 567 if (altshell[0] != '\0'){ 568 char *p; 569 570 /* Binary to exec */ 571 strlcpy(shell, altshell, sizeof shell); 572 573 /* argv[0] */ 574 p = strrchr(altshell, '/'); 575 if(p == NULL) p = altshell; 576 else p++; 577 578 name[0] = '-'; 579 strlcpy(&name[1], p, sizeof name -1); 580 } 581 } 582 #endif /* DEBUGSHELL */ 583 584 /* 585 * Unblock signals. 586 * We catch all the interesting ones, 587 * and those are reset to SIG_DFL on exec. 588 */ 589 sigemptyset(&mask); 590 sigprocmask(SIG_SETMASK, &mask, NULL); 591 592 /* 593 * Fire off a shell. 594 * If the default one doesn't work, try the Bourne shell. 595 */ 596 argv[0] = name; 597 argv[1] = NULL; 598 setenv("PATH", _PATH_STDPATH, 1); 599 execv(shell, argv); 600 emergency("can't exec %s for single user: %m", shell); 601 602 argv[0] = "-sh"; 603 argv[1] = NULL; 604 execv(_PATH_BSHELL, argv); 605 emergency("can't exec %s for single user: %m", _PATH_BSHELL); 606 sleep(STALL_TIMEOUT); 607 _exit(1); 608 } 609 610 if (pid == -1) { 611 /* 612 * We are seriously hosed. Do our best. 613 */ 614 emergency("can't fork single-user shell, trying again"); 615 while (waitpid(-1, NULL, WNOHANG) > 0) 616 continue; 617 return single_user; 618 } 619 620 requested_transition = 0; 621 do { 622 if ((wpid = waitpid(-1, &status, WUNTRACED)) != -1) 623 collect_child(wpid); 624 if (wpid == -1) { 625 if (errno == EINTR) 626 continue; 627 warning("wait for single-user shell failed: %m; restarting"); 628 return single_user; 629 } 630 if (wpid == pid && WIFSTOPPED(status)) { 631 warning("init: shell stopped, restarting\n"); 632 kill(pid, SIGCONT); 633 wpid = -1; 634 } 635 } while (wpid != pid && !requested_transition); 636 637 if (requested_transition) 638 return requested_transition; 639 640 if (!WIFEXITED(status)) { 641 if (WTERMSIG(status) == SIGKILL) { 642 /* 643 * reboot(8) killed shell? 644 */ 645 warning("single user shell terminated."); 646 sleep(STALL_TIMEOUT); 647 _exit(0); 648 } else { 649 warning("single user shell terminated, restarting"); 650 return single_user; 651 } 652 } 653 654 runcom_mode = FASTBOOT; 655 return runcom; 656 } 657 658 /* 659 * Run the system startup script. 660 */ 661 state_t 662 f_runcom(void) 663 { 664 pid_t pid, wpid; 665 int status; 666 char *argv[4]; 667 struct sigaction sa; 668 669 if ((pid = fork()) == 0) { 670 memset(&sa, 0, sizeof sa); 671 sigemptyset(&sa.sa_mask); 672 sa.sa_flags = 0; 673 sa.sa_handler = SIG_IGN; 674 (void) sigaction(SIGTSTP, &sa, NULL); 675 (void) sigaction(SIGHUP, &sa, NULL); 676 677 setctty(_PATH_CONSOLE); 678 679 argv[0] = "sh"; 680 argv[1] = _PATH_RUNCOM; 681 argv[2] = runcom_mode == AUTOBOOT ? "autoboot" : NULL; 682 argv[3] = NULL; 683 684 sigprocmask(SIG_SETMASK, &sa.sa_mask, NULL); 685 686 setprocresources(RESOURCE_RC); 687 688 execv(_PATH_BSHELL, argv); 689 stall("can't exec %s for %s: %m", _PATH_BSHELL, _PATH_RUNCOM); 690 _exit(1); /* force single user mode */ 691 } 692 693 if (pid == -1) { 694 emergency("can't fork for %s on %s: %m", 695 _PATH_BSHELL, _PATH_RUNCOM); 696 while (waitpid(-1, NULL, WNOHANG) > 0) 697 continue; 698 sleep(STALL_TIMEOUT); 699 return single_user; 700 } 701 702 /* 703 * Copied from single_user(). This is a bit paranoid. 704 */ 705 do { 706 if ((wpid = waitpid(-1, &status, WUNTRACED)) != -1) 707 collect_child(wpid); 708 if (wpid == -1) { 709 if (errno == EINTR) 710 continue; 711 warning("wait for %s on %s failed: %m; going to single user mode", 712 _PATH_BSHELL, _PATH_RUNCOM); 713 return single_user; 714 } 715 if (wpid == pid && WIFSTOPPED(status)) { 716 warning("init: %s on %s stopped, restarting\n", 717 _PATH_BSHELL, _PATH_RUNCOM); 718 kill(pid, SIGCONT); 719 wpid = -1; 720 } 721 } while (wpid != pid); 722 723 if (WIFSIGNALED(status) && WTERMSIG(status) == SIGTERM && 724 requested_transition == catatonia) { 725 /* /etc/rc executed /sbin/reboot; wait for the end quietly */ 726 sigset_t s; 727 728 sigfillset(&s); 729 for (;;) 730 sigsuspend(&s); 731 } 732 733 if (!WIFEXITED(status)) { 734 warning("%s on %s terminated abnormally, going to single user mode", 735 _PATH_BSHELL, _PATH_RUNCOM); 736 return single_user; 737 } 738 739 if (WEXITSTATUS(status)) 740 return single_user; 741 742 runcom_mode = AUTOBOOT; /* the default */ 743 /* NB: should send a message to the session logger to avoid blocking. */ 744 logwtmp("~", "reboot", ""); 745 return read_ttys; 746 } 747 748 /* 749 * Compare session keys. 750 */ 751 static int 752 cmp_sessions(session_t *sp1, session_t *sp2) 753 { 754 if (sp1->se_process < sp2->se_process) 755 return (-1); 756 if (sp1->se_process > sp2->se_process) 757 return (1); 758 return (0); 759 } 760 761 /* 762 * Add a new login session. 763 */ 764 void 765 add_session(session_t *sp) 766 { 767 if (RB_INSERT(session_tree, &session_tree, sp) != NULL) 768 emergency("insert %d: %s", sp->se_process, strerror(errno)); 769 } 770 771 /* 772 * Delete an old login session. 773 */ 774 void 775 del_session(session_t *sp) 776 { 777 RB_REMOVE(session_tree, &session_tree, sp); 778 } 779 780 /* 781 * Look up a login session by pid. 782 */ 783 session_t * 784 find_session(pid_t pid) 785 { 786 struct init_session s; 787 788 s.se_process = pid; 789 return (RB_FIND(session_tree, &session_tree, &s)); 790 } 791 792 /* 793 * Construct an argument vector from a command line. 794 */ 795 char ** 796 construct_argv(char *command) 797 { 798 int argc = 0; 799 char **argv = calloc((strlen(command) + 1) / 2 + 1, sizeof (char *)); 800 static const char separators[] = " \t"; 801 802 if (argv == NULL) 803 return (0); 804 805 if ((argv[argc++] = strtok(command, separators)) == 0) { 806 free(argv); 807 return (0); 808 } 809 while ((argv[argc++] = strtok(NULL, separators))) 810 continue; 811 return (argv); 812 } 813 814 /* 815 * Deallocate a session descriptor. 816 */ 817 void 818 free_session(session_t *sp) 819 { 820 free(sp->se_device); 821 if (sp->se_getty) { 822 free(sp->se_getty); 823 free(sp->se_getty_argv); 824 } 825 if (sp->se_window) { 826 free(sp->se_window); 827 free(sp->se_window_argv); 828 } 829 free(sp); 830 } 831 832 /* 833 * Allocate a new session descriptor. 834 */ 835 session_t * 836 new_session(session_t *sprev, int session_index, struct ttyent *typ) 837 { 838 session_t *sp; 839 840 if ((typ->ty_status & TTY_ON) == 0 || 841 typ->ty_name == 0 || 842 typ->ty_getty == 0) 843 return (0); 844 845 sp = calloc(1, sizeof (session_t)); 846 if (sp == NULL) 847 err(1, "calloc"); 848 849 sp->se_flags = SE_PRESENT; 850 sp->se_index = session_index; 851 852 if (asprintf(&sp->se_device, "%s%s", _PATH_DEV, typ->ty_name) == -1) 853 err(1, "asprintf"); 854 855 if (setupargv(sp, typ) == 0) { 856 free_session(sp); 857 return (0); 858 } 859 860 sp->se_next = NULL; 861 if (sprev == NULL) { 862 sessions = sp; 863 sp->se_prev = NULL; 864 } else { 865 sprev->se_next = sp; 866 sp->se_prev = sprev; 867 } 868 869 return (sp); 870 } 871 872 /* 873 * Calculate getty and if useful window argv vectors. 874 */ 875 int 876 setupargv(session_t *sp, struct ttyent *typ) 877 { 878 if (sp->se_getty) { 879 free(sp->se_getty); 880 free(sp->se_getty_argv); 881 } 882 if (asprintf(&sp->se_getty, "%s %s", typ->ty_getty, typ->ty_name) == -1) 883 err(1, "asprintf"); 884 sp->se_getty_argv = construct_argv(sp->se_getty); 885 if (sp->se_getty_argv == 0) { 886 warning("can't parse getty for port %s", sp->se_device); 887 free(sp->se_getty); 888 sp->se_getty = NULL; 889 return (0); 890 } 891 if (typ->ty_window) { 892 free(sp->se_window); 893 sp->se_window = strdup(typ->ty_window); 894 if (sp->se_window == NULL) { 895 warning("can't allocate window"); 896 return (0); 897 } 898 sp->se_window_argv = construct_argv(sp->se_window); 899 if (sp->se_window_argv == NULL) { 900 warning("can't parse window for port %s", 901 sp->se_device); 902 free(sp->se_window); 903 sp->se_window = NULL; 904 return (0); 905 } 906 } 907 return (1); 908 } 909 910 /* 911 * Walk the list of ttys and create sessions for each active line. 912 */ 913 state_t 914 f_read_ttys(void) 915 { 916 int session_index = 0; 917 session_t *sp, *snext; 918 struct ttyent *typ; 919 920 /* 921 * Destroy any previous session state. 922 * There shouldn't be any, but just in case... 923 */ 924 for (sp = sessions; sp; sp = snext) { 925 if (sp->se_process) 926 clear_session_logs(sp); 927 snext = sp->se_next; 928 free_session(sp); 929 } 930 sessions = NULL; 931 932 /* 933 * Allocate a session entry for each active port. 934 * Note that sp starts at 0. 935 */ 936 while ((typ = getttyent())) 937 if ((snext = new_session(sp, ++session_index, typ))) 938 sp = snext; 939 940 endttyent(); 941 942 return multi_user; 943 } 944 945 /* 946 * Start a window system running. 947 */ 948 void 949 start_window_system(session_t *sp) 950 { 951 pid_t pid; 952 sigset_t mask; 953 954 if ((pid = fork()) == -1) { 955 emergency("can't fork for window system on port %s: %m", 956 sp->se_device); 957 /* hope that getty fails and we can try again */ 958 return; 959 } 960 961 if (pid) 962 return; 963 964 sigemptyset(&mask); 965 sigprocmask(SIG_SETMASK, &mask, NULL); 966 967 if (setsid() == -1) 968 emergency("setsid failed (window) %m"); 969 970 setprocresources(RESOURCE_WINDOW); 971 972 execv(sp->se_window_argv[0], sp->se_window_argv); 973 stall("can't exec window system '%s' for port %s: %m", 974 sp->se_window_argv[0], sp->se_device); 975 _exit(1); 976 } 977 978 /* 979 * Start a login session running. 980 * For first open, man-handle tty directly to determine if it 981 * really exists. It is not efficient to spawn gettys on devices 982 * that do not exist. 983 */ 984 pid_t 985 start_getty(session_t *sp) 986 { 987 pid_t pid; 988 sigset_t mask; 989 struct timespec current_time, elapsed; 990 int p[2], new = 1; 991 992 if (sp->se_flags & SE_DEVEXISTS) 993 new = 0; 994 995 if (new) { 996 if (pipe(p) == -1) 997 return (-1); 998 } 999 1000 /* 1001 * fork(), not vfork() -- we can't afford to block. 1002 */ 1003 if ((pid = fork()) == -1) { 1004 emergency("can't fork for getty on port %s: %m", sp->se_device); 1005 return (-1); 1006 } 1007 1008 if (pid) { 1009 if (new) { 1010 char c; 1011 1012 close(p[1]); 1013 if (read(p[0], &c, 1) != 1) { 1014 close(p[0]); 1015 return (-1); 1016 } 1017 close(p[0]); 1018 if (c == '1') 1019 sp->se_flags |= SE_DEVEXISTS; 1020 else 1021 sp->se_flags |= SE_SHUTDOWN; 1022 } 1023 return (pid); 1024 } 1025 if (new) { 1026 int fd; 1027 1028 close(p[0]); 1029 fd = open(sp->se_device, O_RDONLY | O_NONBLOCK); 1030 if (fd == -1 && (errno == ENXIO || errno == ENOENT || 1031 errno == EISDIR)) { 1032 (void)write(p[1], "0", 1); 1033 close(p[1]); 1034 _exit(1); 1035 } 1036 (void)write(p[1], "1", 1); 1037 close(p[1]); 1038 close(fd); 1039 sleep(1); 1040 } 1041 1042 if (timespecisset(&sp->se_started)) { 1043 clock_gettime(CLOCK_MONOTONIC, ¤t_time); 1044 timespecsub(¤t_time, &sp->se_started, &elapsed); 1045 if (elapsed.tv_sec < GETTY_SPACING) { 1046 warning( 1047 "getty repeating too quickly on port %s, sleeping", 1048 sp->se_device); 1049 sleep(GETTY_SLEEP); 1050 } 1051 } 1052 1053 if (sp->se_window) { 1054 start_window_system(sp); 1055 sleep(WINDOW_WAIT); 1056 } 1057 1058 sigemptyset(&mask); 1059 sigprocmask(SIG_SETMASK, &mask, NULL); 1060 1061 setprocresources(RESOURCE_GETTY); 1062 1063 execv(sp->se_getty_argv[0], sp->se_getty_argv); 1064 stall("can't exec getty '%s' for port %s: %m", 1065 sp->se_getty_argv[0], sp->se_device); 1066 _exit(1); 1067 } 1068 1069 /* 1070 * Collect exit status for a child. 1071 * If an exiting login, start a new login running. 1072 */ 1073 void 1074 collect_child(pid_t pid) 1075 { 1076 session_t *sp, *sprev, *snext; 1077 1078 if (sessions == NULL) 1079 return; 1080 1081 if ((sp = find_session(pid)) == NULL) 1082 return; 1083 1084 clear_session_logs(sp); 1085 login_fbtab(sp->se_device + sizeof(_PATH_DEV) - 1, 0, 0); 1086 del_session(sp); 1087 sp->se_process = 0; 1088 1089 if (sp->se_flags & SE_SHUTDOWN) { 1090 if ((sprev = sp->se_prev)) 1091 sprev->se_next = sp->se_next; 1092 else 1093 sessions = sp->se_next; 1094 if ((snext = sp->se_next)) 1095 snext->se_prev = sp->se_prev; 1096 free_session(sp); 1097 return; 1098 } 1099 1100 if ((pid = start_getty(sp)) == -1) { 1101 /* serious trouble */ 1102 requested_transition = clean_ttys; 1103 return; 1104 } 1105 1106 sp->se_process = pid; 1107 clock_gettime(CLOCK_MONOTONIC, &sp->se_started); 1108 add_session(sp); 1109 } 1110 1111 /* 1112 * Catch a signal and request a state transition. 1113 */ 1114 void 1115 transition_handler(int sig) 1116 { 1117 1118 switch (sig) { 1119 case SIGHUP: 1120 requested_transition = clean_ttys; 1121 break; 1122 case SIGINT: 1123 requested_transition = do_reboot; 1124 break; 1125 case SIGTERM: 1126 requested_transition = death; 1127 break; 1128 case SIGUSR1: 1129 requested_transition = nice_death; 1130 break; 1131 case SIGUSR2: 1132 requested_transition = hard_death; 1133 break; 1134 case SIGTSTP: 1135 requested_transition = catatonia; 1136 break; 1137 default: 1138 requested_transition = 0; 1139 break; 1140 } 1141 } 1142 1143 /* 1144 * Take the system multiuser. 1145 */ 1146 state_t 1147 f_multi_user(void) 1148 { 1149 pid_t pid; 1150 session_t *sp; 1151 1152 /* 1153 * If the administrator has not set the security level to -1 1154 * to indicate that the kernel should not run multiuser in secure 1155 * mode, and the run script has not set a higher level of security 1156 * than level 1, then put the kernel into secure mode. 1157 */ 1158 if (requested_transition != catatonia) { 1159 if (getsecuritylevel() == 0) 1160 setsecuritylevel(1); 1161 } 1162 1163 requested_transition = 0; 1164 1165 for (sp = sessions; sp; sp = sp->se_next) { 1166 if (sp->se_process) 1167 continue; 1168 if ((pid = start_getty(sp)) == -1) { 1169 /* serious trouble */ 1170 requested_transition = clean_ttys; 1171 break; 1172 } 1173 sp->se_process = pid; 1174 clock_gettime(CLOCK_MONOTONIC, &sp->se_started); 1175 add_session(sp); 1176 } 1177 1178 while (!requested_transition) 1179 if ((pid = waitpid(-1, NULL, 0)) != -1) 1180 collect_child(pid); 1181 1182 return requested_transition; 1183 } 1184 1185 /* 1186 * This is an n-squared algorithm. We hope it isn't run often... 1187 */ 1188 state_t 1189 f_clean_ttys(void) 1190 { 1191 session_t *sp, *sprev; 1192 struct ttyent *typ; 1193 int session_index = 0; 1194 int devlen; 1195 1196 for (sp = sessions; sp; sp = sp->se_next) 1197 sp->se_flags &= ~SE_PRESENT; 1198 1199 devlen = sizeof(_PATH_DEV) - 1; 1200 while ((typ = getttyent())) { 1201 ++session_index; 1202 1203 for (sprev = NULL, sp = sessions; sp; sprev = sp, sp = sp->se_next) 1204 if (strcmp(typ->ty_name, sp->se_device + devlen) == 0) 1205 break; 1206 1207 if (sp) { 1208 sp->se_flags |= SE_PRESENT; 1209 if (sp->se_index != session_index) { 1210 warning("port %s changed utmp index from %d to %d", 1211 sp->se_device, sp->se_index, 1212 session_index); 1213 sp->se_index = session_index; 1214 } 1215 if ((typ->ty_status & TTY_ON) == 0 || 1216 typ->ty_getty == 0) { 1217 sp->se_flags |= SE_SHUTDOWN; 1218 kill(sp->se_process, SIGHUP); 1219 continue; 1220 } 1221 sp->se_flags &= ~SE_SHUTDOWN; 1222 if (setupargv(sp, typ) == 0) { 1223 warning("can't parse getty for port %s", 1224 sp->se_device); 1225 sp->se_flags |= SE_SHUTDOWN; 1226 kill(sp->se_process, SIGHUP); 1227 } 1228 continue; 1229 } 1230 1231 new_session(sprev, session_index, typ); 1232 } 1233 1234 endttyent(); 1235 1236 for (sp = sessions; sp; sp = sp->se_next) 1237 if ((sp->se_flags & SE_PRESENT) == 0) { 1238 sp->se_flags |= SE_SHUTDOWN; 1239 kill(sp->se_process, SIGHUP); 1240 } 1241 1242 return multi_user; 1243 } 1244 1245 /* 1246 * Block further logins. 1247 */ 1248 state_t 1249 f_catatonia(void) 1250 { 1251 session_t *sp; 1252 1253 for (sp = sessions; sp; sp = sp->se_next) 1254 sp->se_flags |= SE_SHUTDOWN; 1255 1256 return multi_user; 1257 } 1258 1259 /* 1260 * Note SIGALRM. 1261 */ 1262 void 1263 alrm_handler(int sig) 1264 { 1265 clang = 1; 1266 } 1267 1268 int death_howto = RB_HALT; 1269 1270 /* 1271 * Reboot the system. 1272 */ 1273 state_t 1274 f_do_reboot(void) 1275 { 1276 death_howto = RB_AUTOBOOT; 1277 return nice_death; 1278 } 1279 1280 /* 1281 * Bring the system down nicely, then we must powerdown because something 1282 * is very wrong. 1283 */ 1284 state_t 1285 f_hard_death(void) 1286 { 1287 death_howto |= RB_POWERDOWN; 1288 return nice_death; 1289 } 1290 1291 /* 1292 * Bring the system down to single user nicely, after run the shutdown script. 1293 */ 1294 state_t 1295 f_nice_death(void) 1296 { 1297 session_t *sp; 1298 int i; 1299 pid_t pid; 1300 static const int death_sigs[3] = { SIGHUP, SIGTERM, SIGKILL }; 1301 int status; 1302 1303 #ifdef CPU_LIDACTION 1304 int mib[] = {CTL_MACHDEP, CPU_LIDACTION}; 1305 int lidaction = 0; 1306 1307 if ((death_howto & RB_POWERDOWN) && 1308 (sysctl(mib, 2, NULL, NULL, &lidaction, 1309 sizeof(lidaction)) == -1) && (errno != EOPNOTSUPP)) 1310 warning("cannot disable lid action"); 1311 #endif 1312 1313 for (sp = sessions; sp; sp = sp->se_next) { 1314 sp->se_flags &= ~SE_PRESENT; 1315 sp->se_flags |= SE_SHUTDOWN; 1316 kill(sp->se_process, SIGHUP); 1317 } 1318 1319 /* terminate the accounting process */ 1320 acct(NULL); 1321 1322 /* NB: should send a message to the session logger to avoid blocking. */ 1323 logwtmp("~", "shutdown", ""); 1324 1325 if (access(_PATH_RUNCOM, R_OK) != -1) { 1326 struct sigaction sa; 1327 1328 switch ((pid = fork())) { 1329 case -1: 1330 break; 1331 case 0: 1332 1333 memset(&sa, 0, sizeof sa); 1334 sigemptyset(&sa.sa_mask); 1335 sa.sa_flags = 0; 1336 sa.sa_handler = SIG_IGN; 1337 (void) sigaction(SIGTSTP, &sa, NULL); 1338 (void) sigaction(SIGHUP, &sa, NULL); 1339 1340 setctty(_PATH_CONSOLE); 1341 1342 sigprocmask(SIG_SETMASK, &sa.sa_mask, NULL); 1343 1344 execl(_PATH_BSHELL, "sh", _PATH_RUNCOM, "shutdown", 1345 (char *)NULL); 1346 stall("can't exec %s for %s %s: %m", _PATH_BSHELL, 1347 _PATH_RUNCOM, "shutdown"); 1348 _exit(1); 1349 default: 1350 waitpid(pid, &status, 0); 1351 if (WIFEXITED(status) && WEXITSTATUS(status) == 2) 1352 death_howto |= RB_POWERDOWN; 1353 } 1354 } 1355 1356 for (i = 0; i < 3; ++i) { 1357 if (kill(-1, death_sigs[i]) == -1 && errno == ESRCH) 1358 goto die; 1359 1360 clang = 0; 1361 alarm(DEATH_WATCH); 1362 do { 1363 if ((pid = waitpid(-1, NULL, 0)) != -1) 1364 collect_child(pid); 1365 } while (clang == 0 && errno != ECHILD); 1366 1367 if (errno == ECHILD) 1368 goto die; 1369 } 1370 1371 warning("some processes would not die; ps axl advised"); 1372 1373 die: 1374 reboot(death_howto); 1375 1376 /* ... and if that fails.. oh well */ 1377 return single_user; 1378 } 1379 1380 /* 1381 * Bring the system down to single user. 1382 */ 1383 state_t 1384 f_death(void) 1385 { 1386 session_t *sp; 1387 int i; 1388 pid_t pid; 1389 static const int death_sigs[3] = { SIGHUP, SIGTERM, SIGKILL }; 1390 1391 /* terminate the accounting process */ 1392 acct(NULL); 1393 1394 for (sp = sessions; sp; sp = sp->se_next) 1395 sp->se_flags |= SE_SHUTDOWN; 1396 1397 /* NB: should send a message to the session logger to avoid blocking. */ 1398 logwtmp("~", "shutdown", ""); 1399 1400 for (i = 0; i < 3; ++i) { 1401 if (kill(-1, death_sigs[i]) == -1 && errno == ESRCH) 1402 return single_user; 1403 1404 clang = 0; 1405 alarm(DEATH_WATCH); 1406 do { 1407 if ((pid = waitpid(-1, NULL, 0)) != -1) 1408 collect_child(pid); 1409 } while (clang == 0 && errno != ECHILD); 1410 1411 if (errno == ECHILD) 1412 return single_user; 1413 } 1414 1415 warning("some processes would not die; ps axl advised"); 1416 1417 return single_user; 1418 } 1419 1420 void 1421 setprocresources(char *class) 1422 { 1423 login_cap_t *lc; 1424 1425 if ((lc = login_getclass(class)) != NULL) { 1426 setusercontext(lc, NULL, 0, 1427 LOGIN_SETPRIORITY|LOGIN_SETRESOURCES|LOGIN_SETUMASK); 1428 login_close(lc); 1429 } 1430 } 1431