kexec is broken with lanzaboote #143

Open
opened 2023-04-08 02:26:36 +00:00 by jpdisco · 10 comments
jpdisco commented 2023-04-08 02:26:36 +00:00 (Migrated from github.com)

I am trying to reboot via kexec my computer using systemdctl kexec. This used to work just fine with normal nixos, but I am trying out lanzaboote (very cool btw :)) and it is not working at all anymore.

I now get this error.

Running /nix/store/pjp3v7ni274d1hh7cn4m5yhslgggzbrl-kexec-tools-2.0.25/bin/kexec --load "/boot/EFI/Linux/nixos-generation-294.efi" --append "init=/nix/store/h4mjlcgl479ll843nv43slmaqzr62wd8-nixos-system-poopbox-23.05.20230406.0e19daa/init loglevel=4"(null)
Cannot determine the file type of /boot/EFI/Linux/nixos-generation-294.efi
(kexec) failed with exit status 255.

Is there something I can do to fix this, or is kexec just something that is broken right now?

I am trying to reboot via kexec my computer using `systemdctl kexec`. This used to work just fine with normal nixos, but I am trying out lanzaboote (very cool btw :)) and it is not working at all anymore. I now get this error. ``` Running /nix/store/pjp3v7ni274d1hh7cn4m5yhslgggzbrl-kexec-tools-2.0.25/bin/kexec --load "/boot/EFI/Linux/nixos-generation-294.efi" --append "init=/nix/store/h4mjlcgl479ll843nv43slmaqzr62wd8-nixos-system-poopbox-23.05.20230406.0e19daa/init loglevel=4"(null) Cannot determine the file type of /boot/EFI/Linux/nixos-generation-294.efi (kexec) failed with exit status 255. ``` Is there something I can do to fix this, or is kexec just something that is broken right now?
blitz commented 2023-04-09 08:45:50 +00:00 (Migrated from github.com)

Can you show the command line that used to work for you before?

Cannot determine the file type of /boot/EFI/Linux/nixos-generation-294.efi

I'm pretty sure kexec doesn't support UEFI binaries. You need to specify the kernel directly for --load. It's one of the bzImage files in EFI/nixos.

Can you show the command line that used to work for you before? > Cannot determine the file type of /boot/EFI/Linux/nixos-generation-294.efi I'm pretty sure kexec doesn't support UEFI binaries. You need to specify the kernel directly for `--load`. It's one of the `bzImage` files in `EFI/nixos`.
jpdisco commented 2023-04-09 20:31:26 +00:00 (Migrated from github.com)

It looks like you are right about the UEFI binaries, when I disable lanzaboote, it runs load with one of those bzImage files and it works well.

Running /nix/store/pjp3v7ni274d1hh7cn4m5yhslgggzbrl-kexec-tools-2.0.25/bin/kexec --load "/boot/EFI/nixos/zk1jnsj87zc6rl0klly6534sj5q5vzj8-linux-6.9.2-bzImage.efi" --append "init=/nix/store/h4mjlcgl479ll843nv43slmaqzr62wd8-nixos-system-poopbox-23.05.20230406.0e19daa/init loglevel=4(null)

So it seems like when lanzaboote is enabled it tries to load a UEFI binary for some reason.

It looks like you are right about the UEFI binaries, when I disable lanzaboote, it runs load with one of those bzImage files and it works well. ``` Running /nix/store/pjp3v7ni274d1hh7cn4m5yhslgggzbrl-kexec-tools-2.0.25/bin/kexec --load "/boot/EFI/nixos/zk1jnsj87zc6rl0klly6534sj5q5vzj8-linux-6.9.2-bzImage.efi" --append "init=/nix/store/h4mjlcgl479ll843nv43slmaqzr62wd8-nixos-system-poopbox-23.05.20230406.0e19daa/init loglevel=4(null) ``` So it seems like when lanzaboote is enabled it tries to load a UEFI binary for some reason.
Myaats commented 2023-04-09 21:18:43 +00:00 (Migrated from github.com)

Looked into it and it seems like kexec has yet to add support for Unified Kernel Images1. As lanzaboote only emits UKI's onto your ESP that one won't work, as a workaround try to use the kernel and init path provided by /nix/var/nix/profiles/system/boot.json or the other systems/generations.

Looked into it and it seems like kexec has yet to add support for Unified Kernel Images[^1]. As lanzaboote only emits UKI's onto your ESP that one won't work, as a workaround try to use the kernel and init path provided by `/nix/var/nix/profiles/system/boot.json` or the other systems/generations. [^1]: https://www.spinics.net/lists/kexec/msg30939.html
MatthewCash commented 2023-04-09 21:25:22 +00:00 (Migrated from github.com)

I ran into this same problem a few weeks ago. If no kernel is manually loaded for kexec, systemd will try to load the one in the default boot loader entry. Run bootctl status | grep linux:, and it will show which kernel systemd will try to kexec into.

The solution seems to be to enable/run the prepare-kexec.service service, which will run a NixOS provided script to correctly setup kexec.

I ran into this same problem a few weeks ago. If no kernel is manually loaded for kexec, systemd will try to load the one in the default boot loader entry. Run `bootctl status | grep linux:`, and it will show which kernel systemd will *try* to kexec into. The solution seems to be to enable/run the `prepare-kexec.service` service, which will run a NixOS provided script to correctly setup kexec.
lilyinstarlight commented 2023-04-09 21:37:29 +00:00 (Migrated from github.com)

It looks like systemd can either parse the systemd-boot conf to determine the linux kernel to kexec or it just looks in $esp/EFI/Linux, which is where it is getting the lanzaboote image from

I did look into the systemd source code though and noticed there is a functionality to allow other bootloaders to specify this sort of information:

https://github.com/systemd/systemd/blob/v253/src/shared/bootspec.c#L1154-L1159

/* This function is similar to boot_entries_load_config(), however we automatically search for the
 * ESP and the XBOOTLDR partition unless it is explicitly specified. Also, if the user did not pass
 * an ESP or XBOOTLDR path directly, let's see if /run/boot-loader-entries/ exists. If so, let's
 * read data from there, as if it was an ESP (i.e. loading both entries and loader.conf data from
 * it). This allows other boot loaders to pass boot loader entry information to our tools if they
 * want to. */

So we could just synthesize a /run/boot-loader-entries with fake systemd-boot config for the correct kernels/initrds and then systemctl kexec would also work as expected

It looks like systemd can either parse the systemd-boot conf to determine the linux kernel to kexec or it just looks in `$esp/EFI/Linux`, which is where it is getting the lanzaboote image from I did look into the systemd source code though and noticed there is a functionality to allow other bootloaders to specify this sort of information: https://github.com/systemd/systemd/blob/v253/src/shared/bootspec.c#L1154-L1159 > ```c > /* This function is similar to boot_entries_load_config(), however we automatically search for the > * ESP and the XBOOTLDR partition unless it is explicitly specified. Also, if the user did not pass > * an ESP or XBOOTLDR path directly, let's see if /run/boot-loader-entries/ exists. If so, let's > * read data from there, as if it was an ESP (i.e. loading both entries and loader.conf data from > * it). This allows other boot loaders to pass boot loader entry information to our tools if they > * want to. */ > ``` So we could just synthesize a `/run/boot-loader-entries` with fake systemd-boot config for the correct kernels/initrds and then `systemctl kexec` would also work as expected
alois31 commented 2023-04-10 17:09:16 +00:00 (Migrated from github.com)

The solution seems to be to enable/run the prepare-kexec.service service, which will run a NixOS provided script to correctly setup kexec.

This service is already enabled, but for some reason it doesn't get run automatically.

> The solution seems to be to enable/run the `prepare-kexec.service` service, which will run a NixOS provided script to correctly setup kexec. This service is already enabled, but for some reason it doesn't get run automatically.
MatthewCash commented 2023-04-10 17:12:12 +00:00 (Migrated from github.com)

The solution seems to be to enable/run the prepare-kexec.service service, which will run a NixOS provided script to correctly setup kexec.

This service is already enabled, but for some reason it doesn't get run automatically.

I meant enable as in run on startup, like the systemctl enable command, so on NixOS you would set

systemd.services."prepare-kexec".wantedBy = [ "multi-user.target" ];
> > The solution seems to be to enable/run the `prepare-kexec.service` service, which will run a NixOS provided script to correctly setup kexec. > > This service is already enabled, but for some reason it doesn't get run automatically. I meant enable as in run on startup, like the `systemctl enable` command, so on NixOS you would set ``` systemd.services."prepare-kexec".wantedBy = [ "multi-user.target" ]; ```
jpdisco commented 2023-04-11 22:11:00 +00:00 (Migrated from github.com)

systemd.services."prepare-kexec".wantedBy = [ "multi-user.target" ];

I added to my configuration and the problems are fixed!

systemd.services."prepare-kexec".wantedBy = [ "multi-user.target" ]; I added to my configuration and the problems are fixed!
RaitoBezarius commented 2023-04-12 12:11:28 +00:00 (Migrated from github.com)

This seems like something that should be sent to NixOS upstream by pinging the @NixOS/systemd team.

This seems like something that should be sent to NixOS upstream by pinging the @NixOS/systemd team.
RaitoBezarius commented 2023-05-18 19:52:45 +00:00 (Migrated from github.com)

If someone can retest kexec on master, let me know. I will try to write test for it before.

If someone can retest kexec on master, let me know. I will try to write test for it before.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: raito/lanzaboote#143
No description provided.