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