Replace experimental emergency shell with actual rescue mode

Most major init systems have a way to start a rescue shell.  This is
usally started when the string `rescue` is read from the kernel's
command line.

The traditional Finit way of handling this has been to skip certain
phases of the standard boot, skip /etc/finit.conf et al, and go for a
/lib/finit/rescue.conf instead.  This pratice has been imroved over
the last few commits with a sulogin.  However, there was no way to
resume boot, like most other init systems offer.

This patch implements a very simple rescue mode, utilizing the new
sulogin, replacing the old (and experimental) emergency shell.  If
Ctrl-D is pressed at the maintenance login prompt the boot is now
resumed.  The same goes for exit/Ctrl-D from the maintenace shell.

The preferred sulogin is the bundled /libexec/finit/sulogin, but
if that isn't installed, the first one in $PATH is used.  If no
sulogin at all is found, Finit proceeds as before this patch, to
skip certains steps and go for a /lib/finit/rescue.conf.  Hence,
al steps can be controlled by an administrator.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This commit is contained in:
Joachim Wiberg
2021-04-25 21:32:35 +02:00
parent fe334135ce
commit 4e5d06b580
2 changed files with 16 additions and 55 deletions
-9
View File
@@ -48,11 +48,6 @@ PKG_CHECK_MODULES([uev], [libuev >= 2.2.0])
PKG_CHECK_MODULES([lite], [libite >= 2.2.0])
# Check for configured Finit features
AC_ARG_ENABLE(emergency_shell,
AS_HELP_STRING([--enable-emergency-shell], [Experimental emergency fallback at boot.
Use only for debugging very early boot problems with Finit]),,[
enable_emergency_shell=no])
AC_ARG_ENABLE(auto_reload,
AS_HELP_STRING([--enable-auto-reload], [Automatic reload on any .conf change]),,[
enable_auto_reload=no])
@@ -127,9 +122,6 @@ AC_ARG_WITH(watchdog,
### Enable features ###########################################################################
# Create config.h from selected features and fallback defaults
AS_IF([test "x$enable_emergency_shell" = "xyes"], [
AC_DEFINE(EMERGENCY_SHELL, 1, [Fork off init and let PID 1 wait and start /bin/sh if init crashes.])])
AS_IF([test "x$enable_auto_reload" = "xyes"], [
AC_DEFINE(AUTO_RELOAD, 1, [Finit automatically does `initctl reload` on any .conf change])])
@@ -253,7 +245,6 @@ Optional features:
Built-in watchdogd....: $with_watchdog $watchdog
Built-in logrotate....: $enable_logrotate
Scripting tool logit..: $enable_logit
Emergency shell.......: $enable_emergency_shell
Redirect output.......: $enable_redirect
Default hostname......: $hostname
Default runlevel......: $runlevel
+16 -46
View File
@@ -235,48 +235,6 @@ static void fs_init(void)
}
}
/*
* If everything goes south we can use this to give the operator an
* emergency shell to debug the problem -- Finit should not crash!
*
* Note: Only use this for debugging a new Finit setup, don't use
* this in production since it gives a root shell to anyone
* if Finit crashes.
*
* This emergency shell steps in to prevent "Aieee, PID 1 crashed"
* messages from the kernel, which usually results in a reboot, so
* that the operator instead can debug the problem.
*/
static void emergency_shell(void)
{
#ifdef EMERGENCY_SHELL
pid_t pid;
pid = fork();
if (pid) {
while (1) {
pid_t id;
/* Reap 'em (prevents Zombies) */
id = waitpid(-1, NULL, WNOHANG);
if (id == pid)
break;
}
fprintf(stderr, "\n=> Embarrassingly, Finit has crashed. Check /dev/kmsg for details.\n");
fprintf(stderr, "=> To debug, add 'debug' to the kernel command line.\n\n");
/*
* Become session leader and set controlling TTY
* to enable Ctrl-C and job control in shell.
*/
setsid();
ioctl(STDIN_FILENO, TIOCSCTTY, 1);
execl(_PATH_BSHELL, _PATH_BSHELL, NULL);
}
#endif /* EMERGENCY_SHELL */
}
/*
* Handle bootstrap transition to configured runlevel, start TTYs
@@ -505,13 +463,24 @@ int main(int argc, char *argv[])
if (chdir("/"))
_pe("Failed cd /");
/* Allow progress, if enabled */
enable_progress(1);
/*
* In case of emergency.
*/
emergency_shell();
if (rescue) {
char *sulogin[] = {
_PATH_SULOGIN,
"sulogin",
};
size_t i;
for (i = 0; i < NELEMS(sulogin); i++) {
if (systemf(sulogin[i]))
continue;
rescue = 0;
break;
}
}
/*
* Load plugins early, the first hook is in banner(), so we
@@ -522,6 +491,7 @@ int main(int argc, char *argv[])
/*
* Hello world.
*/
enable_progress(1); /* Allow progress, if enabled */
banner();
/*