[PATCH] init: Add handshake to poweroff/reboot for signal handler setup
Denys Vlasenko
vda.linux at googlemail.com
Thu Feb 15 19:42:34 UTC 2018
On Wed, Feb 14, 2018 at 6:53 PM, Deb McLemore <debmc at linux.vnet.ibm.com> wrote:
> The only reproduction we were able to perform injected via a BMC soft poweroff being triggered.
>
> This then called into kernel/reboot.c (orderly_poweroff where the schedule_work was performed) utilizing the
>
> usermodehelper during the run_cmd /sbin/poweroff.
How about this?
+#if ENABLE_FEATURE_WAIT_FOR_INIT
+/* In Linux, "poweroff" may be spawned even before init.
+ * For example, with ACPI:
+ * linux/drivers/acpi/bus.c:
+ * static void sb_notify_work(struct work_struct *dummy)
+ * orderly_poweroff(true);
+ * linux/kernel/reboot.c:
+ * poweroff_cmd[] = "/sbin/poweroff";
+ * static int __orderly_poweroff(bool force)
+ * ret = run_cmd(poweroff_cmd);
+ * static int run_cmd(const char *cmd)
+ * ret = call_usermodehelper(argv[0], argv, envp, UMH_WAIT_EXEC);
+ *
+ * We want to make sure init exists and listens to signals.
+ */
+static int init_was_not_there(void)
+{
+ enum { initial = 5 }; /* 5 seconds should be plenty for timeout */
+ int cnt = initial - 1;
+
+ /* Just existence of PID 1 does not mean it installed
+ * the handlers already.
+ */
+#if 0
+ while (kill(1, 0) != 0 && --cnt >= 0)
+ sleep(1);
+#endif
+ /* ... so let's wait for some evidence a usual startup event,
+ * mounting of /proc, happened.
+ */
+ while (access("/proc/meminfo", F_OK) != 0 && --cnt >= 0)
+ sleep(1);
+
+ /* Does it look like init wasn't there? */
+ return (cnt != initial - 1);
+}
+#else
+# define init_was_not_there() 0
+#endif
int halt_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int halt_main(int argc UNUSED_PARAM, char **argv)
@@ -171,6 +220,8 @@ int halt_main(int argc UNUSED_PARAM, char **argv)
if (!ENABLE_FEATURE_CALL_TELINIT) {
/* bbox init assumed */
rc = kill(1, signals[which]);
+ if (init_was_not_there())
+ rc = kill(1, signals[which]);
} else {
Even if the logic of waiting for "/proc/meminfo" fails
on a weird system which does _not_ mount /proc,
this will not make "poweroff" slow. It will poweroff at once,
then will try to send poweroff signal again a few seconds later
(in all likelihood, way too late in the afterlife).
More information about the busybox
mailing list