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