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