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