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