sulogin.c 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. /* vi: set sw=4 ts=4: */
  2. /*
  3. * Mini sulogin implementation for busybox
  4. *
  5. * Licensed under GPLv2 or later, see file LICENSE in this source tree.
  6. */
  7. //config:config SULOGIN
  8. //config: bool "sulogin (17 kb)"
  9. //config: default y
  10. //config: select FEATURE_SYSLOG
  11. //config: help
  12. //config: sulogin is invoked when the system goes into single user
  13. //config: mode (this is done through an entry in inittab).
  14. //applet:IF_SULOGIN(APPLET_NOEXEC(sulogin, sulogin, BB_DIR_SBIN, BB_SUID_DROP, sulogin))
  15. //kbuild:lib-$(CONFIG_SULOGIN) += sulogin.o
  16. //usage:#define sulogin_trivial_usage
  17. //usage: "[-t N] [TTY]"
  18. //usage:#define sulogin_full_usage "\n\n"
  19. //usage: "Single user login\n"
  20. //usage: "\n -t N Timeout"
  21. #include "libbb.h"
  22. #include <syslog.h>
  23. int sulogin_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
  24. int sulogin_main(int argc UNUSED_PARAM, char **argv)
  25. {
  26. int timeout = 0;
  27. struct passwd *pwd;
  28. const char *shell;
  29. /* Note: sulogin is not a suid app. It is meant to be run by init
  30. * for single user / emergency mode. init starts it as root.
  31. * Normal users (potentially malicious ones) can only run it under
  32. * their UID, therefore no paranoia here is warranted:
  33. * $LD_LIBRARY_PATH in env, TTY = /dev/sda
  34. * are no more dangerous here than in e.g. cp applet.
  35. */
  36. logmode = LOGMODE_BOTH;
  37. openlog(applet_name, 0, LOG_AUTH);
  38. getopt32(argv, "t:+", &timeout);
  39. argv += optind;
  40. if (argv[0]) {
  41. close(0);
  42. close(1);
  43. dup(xopen(argv[0], O_RDWR));
  44. close(2);
  45. dup(0);
  46. }
  47. pwd = getpwuid(0);
  48. if (!pwd) {
  49. bb_simple_error_msg_and_die("no password entry for root");
  50. }
  51. while (1) {
  52. int r;
  53. r = ask_and_check_password_extended(pwd, timeout,
  54. "Give root password for system maintenance\n"
  55. "(or type Control-D for normal startup):"
  56. );
  57. if (r < 0) {
  58. /* ^D, ^C, timeout, or read error */
  59. bb_simple_info_msg("normal startup");
  60. return 0;
  61. }
  62. if (r > 0) {
  63. break;
  64. }
  65. pause_after_failed_login();
  66. bb_simple_info_msg("Login incorrect");
  67. }
  68. bb_simple_info_msg("starting shell for system maintenance");
  69. IF_SELINUX(renew_current_security_context());
  70. shell = getenv("SUSHELL");
  71. if (!shell)
  72. shell = getenv("sushell");
  73. if (!shell)
  74. shell = pwd->pw_shell;
  75. /* Exec login shell with no additional parameters. Never returns. */
  76. exec_login_shell(shell);
  77. }