[PATCH] init: Add handshake to poweroff/reboot for signal handler setup

Deb McLemore debmc at linux.vnet.ibm.com
Thu Feb 15 21:52:35 UTC 2018


Any logic attempting to guess at the state of startup will give false

confidence that the signaling setup is completed.


On 02/15/2018 01:42 PM, Denys Vlasenko wrote:
> 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