Add support for a rescue (recovery) mode from kernel cmdline

This patch adds a rescue (revovery) mode to Finit.  Simply add `rescue`
to the kernel cmdline at boot and the following steps at bootstrap will
be skipped:

- Load of services/run/task/etc in /etc/finit.conf + /etc/finit.d/*.conf
- fsck of filesystems in /etc/fstab
- Remount of / to read-write
- Mount of all filesystems in /etc/fstab
- swapon
- A few plugin hooks:
  - HOOK_ROOTFS_UP
  - HOOK_MOUNT_ERROR
  - HOOK_BASEFS_UP
- `runparts DIR`
- /etc/rc.local

Instead of loading /etc/finit.conf and /etc/finit.d/*.conf Finit loads
the file /lib/finit/rescue.conf, which can be overridden by the operator
if needed.  If this file is removed (or lost), Finit falls back to start
a simple root shell, without any login.

Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
This commit is contained in:
Joachim Nilsson
2017-12-30 21:20:06 +01:00
parent bc149d95fc
commit ab723d2f31
7 changed files with 58 additions and 23 deletions
+3
View File
@@ -217,6 +217,9 @@ AC_EXPAND_DIR(plugin_path, "$libdir/finit/plugins")
AC_SUBST(plugin_path)
AC_DEFINE_UNQUOTED(PLUGIN_PATH, "$plugin_path", [Finit plugin path])
AC_EXPAND_DIR(rescue_conf, "$libdir/finit/rescue.conf")
AC_DEFINE_UNQUOTED(RESCUE_CONF, "$rescue_conf", [Finit rescue mode .conf])
# Generate all files
AC_OUTPUT
-3
View File
@@ -21,9 +21,6 @@ can also be used.
General
-------
* Add support for `rescue` on the kernel command line, start rescue mode
if enabled with `configure` script. Could mean skip `/etc/finit.conf`
et al and jump straight to a single getty login on console.
* Add support for timed shutdown in Finit, including cancelled shutdown.
* SysV init and systemd use SIGUSR1 to restart their FIFO/D-Bus. Add
API restart to SIGHUP callback for the same functionality in Finit.
+2
View File
@@ -58,6 +58,7 @@ REBOOT_LNKS = shutdown halt poweroff suspend
# Hook in install to add finit and reboot symlink(s)
install-exec-hook:
@$(INSTALL_DATA) $(srcdir)/rescue.conf $(DESTDIR)$(pkglibdir)
@for file in $(INIT_LNKS); do \
lnk=$(DESTDIR)$(sbindir)/$$file; \
if [ -e $$lnk ]; then \
@@ -80,6 +81,7 @@ install-exec-hook:
fi
uninstall-hook:
@$(RM) $(DESTDIR)$(pkglibdir)/rescue.conf
@for file in $(INIT_LNKS); do \
lnk=`readlink $(DESTDIR)$(sbindir)/$$file`; \
if [ "$$lnk" != "finit" ]; then \
+20
View File
@@ -78,6 +78,9 @@ void conf_parse_cmdline(void)
/* Catches finit_debug (deprecated), --debug, and debug */
if (strstr(tok, "debug"))
dbg = 1;
if (strstr(tok, "rescue") || strstr(tok, "recover"))
rescue = 1;
}
fclose(fp);
@@ -551,6 +554,19 @@ int conf_reload(void)
svc_mark_dynamic();
tty_mark();
if (rescue) {
int rc;
char line[80] = "tty [12345] @console noclear nologin";
/* If rescue.conf is missing, fall back to a root shell */
rc = parse_conf(RESCUE_CONF);
if (rc)
tty_register(line, global_rlimit, NULL);
print(rc, "Entering rescue mode");
goto done;
}
/* First, read /etc/finit.conf */
parse_conf(FINIT_CONF);
@@ -795,6 +811,10 @@ int conf_monitor(uev_ctx_t *ctx)
{
int rc = 0;
/* Skip second run, when called from finit.c in rescue mode */
if (ctx && rescue)
return 0;
/*
* If only one watcher fails, that's OK. A user may have only
* one of /etc/finit.conf or /etc/finit.d in use, and may also
+29 -20
View File
@@ -53,6 +53,7 @@ int wdogpid = 0; /* No watchdog by default */
int runlevel = 0; /* Bootstrap 'S' */
int cfglevel = RUNLEVEL; /* Fallback if no configured runlevel */
int prevlevel = -1;
int rescue = 0; /* rescue mode from kernel cmdline */
char *sdown = NULL;
char *network = NULL;
char *hostname = NULL;
@@ -262,18 +263,20 @@ static void finalize(void)
/*
* Network stuff
*/
_d("Setting up networking ...");
networking();
umask(022);
if (!rescue) {
_d("Setting up networking ...");
networking();
/* Hooks that rely on loopback, or basic networking being up. */
_d("Calling all network up hooks ...");
plugin_run_hooks(HOOK_NETWORK_UP);
/* Hooks that rely on loopback, or basic networking being up. */
_d("Calling all network up hooks ...");
plugin_run_hooks(HOOK_NETWORK_UP);
}
umask(022);
/*
* Run startup scripts in the runparts directory, if any.
*/
if (runparts && fisdir(runparts)) {
if (runparts && fisdir(runparts) && !rescue) {
_d("Running startup scripts in %s ...", runparts);
run_parts(runparts, NULL);
if (conf_any_change())
@@ -296,7 +299,7 @@ static void finalize(void)
service_step_all(SVC_TYPE_ANY);
/* Convenient SysV compat for when you just don't care ... */
if (!access(FINIT_RC_LOCAL, X_OK)) {
if (!access(FINIT_RC_LOCAL, X_OK) && !rescue) {
run_interactive(FINIT_RC_LOCAL, "Calling %s", FINIT_RC_LOCAL);
if (conf_any_change())
service_reload_dynamic();
@@ -385,7 +388,7 @@ int main(int argc, char* argv[])
/*
* Check file filesystems in /etc/fstab
*/
for (int pass = 1; pass < 10; pass++) {
for (int pass = 1; pass < 10 && !rescue; pass++) {
if (fsck(pass))
break;
}
@@ -479,12 +482,14 @@ int main(int argc, char* argv[])
/*
* Mount filesystems
*/
if (!rescue) {
#ifdef REMOUNT_ROOTFS
run("mount -n -o remount,rw /");
run("mount -n -o remount,rw /");
#endif
#ifdef SYSROOT
mount(SYSROOT, "/", NULL, MS_MOVE, NULL);
mount(SYSROOT, "/", NULL, MS_MOVE, NULL);
#endif
}
/* Debian has this little script to copy generated rules while the system was read-only */
if (fexist("/lib/udev/udev-finish"))
@@ -493,15 +498,17 @@ int main(int argc, char* argv[])
/* Bootstrap conditions, needed for hooks */
cond_init();
_d("Root FS up, calling hooks ...");
plugin_run_hooks(HOOK_ROOTFS_UP);
if (!rescue) {
_d("Root FS up, calling hooks ...");
plugin_run_hooks(HOOK_ROOTFS_UP);
umask(0);
if (run_interactive("mount -na", "Mounting filesystems"))
plugin_run_hooks(HOOK_MOUNT_ERROR);
umask(0);
if (run_interactive("mount -na", "Mounting filesystems"))
plugin_run_hooks(HOOK_MOUNT_ERROR);
run("swapon -ea");
umask(0022);
run("swapon -ea");
umask(0022);
}
/* Base FS up, enable standard SysV init signals */
sig_setup(&loop);
@@ -512,8 +519,10 @@ int main(int argc, char* argv[])
*/
conf_monitor(&loop);
_d("Base FS up, calling hooks ...");
plugin_run_hooks(HOOK_BASEFS_UP);
if (!rescue) {
_d("Base FS up, calling hooks ...");
plugin_run_hooks(HOOK_BASEFS_UP);
}
/*
* Initalize state machine and start all bootstrap tasks
+1
View File
@@ -96,6 +96,7 @@ extern int wdogpid;
extern int runlevel;
extern int cfglevel;
extern int prevlevel;
extern int rescue;
extern char *rcsd;
extern char *sdown;
extern char *network;
+3
View File
@@ -0,0 +1,3 @@
runlevel 1
hostname rescue
tty [12345] @console noclear nologin