sbctl icon indicating copy to clipboard operation
sbctl copied to clipboard

Do not run sbctl pacman hook last

Open swsnr opened this issue 3 years ago • 16 comments
trafficstars

With the systemd 250 approach of placing a signed copy of the boot loader at /usr/lib/systemd/boot/efi/systemd-bootx64.efi.signed for bootctl update to install (see #111) it's rather inconvenient that zz-sbctl.hook runs last, because it leaves no way for a hook to update the bootloader after the signed copy was updated by sbctl.

I've removed my custom hook for now and let systemd-boot-update.service do its job after reboot, but I'd prefer to implement the systemd suggestion of having the package manager update the bootloader proactively. Unfortunately with the current name of the sbctl hook that's not really possible.

Would you mind to rename the hook to e.g. yy-sbctl.hook? Or zz-00-sbctl.hook? So that there's at least some means to have another hook after sbctl?

swsnr avatar Jan 03 '22 10:01 swsnr

Any reason why you don't want to use systemd-boot-update.service?

https://github.com/systemd/systemd/commit/71c8bf28378958a5ab2348e9ec586fbe78c71dfd

Foxboron avatar Jan 03 '22 10:01 Foxboron

I'd like to follow the recommendation noted in that commit message: Have the package manager call bootctl update and use the service only as a safety net.

swsnr avatar Jan 03 '22 10:01 swsnr

Which is appropriate in this scenario since pacman doesn't do anything.

The main issue is that there is no standard filename for the bootctl upgrade hook, which is why sbctl tries very hard to be last.

Foxboron avatar Jan 03 '22 10:01 Foxboron

I do not like to rely on systemd-boot-update.service. It only runs at boot but I don't always reboot right after pacman -U, even if it touches systemd. It's some kind of action at a distance which I just don't like because it tends to cause trouble when one doesn't expect anything to happen :shrug:

Given that there's no standard hook for bootctl on Arch Linux, why does sbctl need to try so hard to be last? If an administrator installs a custom hook to update systemd-boot isn't it their responsibility to make sure their hook runs at the appropriate time?

In any case the current hook name leaves no means for the administrator to run a later hook, i.e. do any work on the signed binaries. I don't think that's good design in and by itself.

Would yy-sbctl.hook be that bad? It still runs at the end, but at least allows a sysadmin to run something afterwards.

swsnr avatar Jan 03 '22 11:01 swsnr

I'm contemplating if renaming it to 50-sbctl-sign.hook would be Good Enough™️. I need to think a bit and see what other distros name the bootctl hook if they provide it.

Foxboron avatar Jan 03 '22 15:01 Foxboron

I think I'd appreciate that. The hook's specifically for Arch, and as long as Arch doesn't start to ship a bootctl update hook as part of systemd I think there's little harm in renaming it.

It's perhaps also worth noting that the hooks included in systemd all start with 30 :slightly_smiling_face:

swsnr avatar Jan 03 '22 18:01 swsnr

I'm contemplating if renaming it to 50-sbctl-sign.hook would be Good Enoughtm. I need to think a bit and see what other distros name the bootctl hook if they provide it.

Nitpick, but wouldn't that mean it gets run before mkinitcpio generates the new initramfs or unified images since that hook is currently named 90-mkinitcpio-install.hook?

ludvigng avatar Feb 17 '22 17:02 ludvigng

Nitpick, but wouldn't that mean it gets run before mkinitcpio generates the new initramfs or unified images since that hook is currently named 90-mkinitcpio-install.hook?

Good point!

Foxboron avatar Feb 17 '22 17:02 Foxboron

I use systemd-boot-pacman-hook from the AUR to install newer bootctl on updates.

So [for me] the sbctl needs to run after 90-mkinitcpio-install.hook, but before 95-systemd-boot.hook. 93 sounds like the right choice.

The above hook has 149 votes, so it's mildly popular -- it's probably wise to keep it in mind.

WhyNotHugo avatar Mar 24 '22 18:03 WhyNotHugo

The mkinitcpio hook runs at 90-, anything after that doesn't usually touch the ESP. The systemd-boot hook runs at 95-, so this hook anywhere from 90- to 95-. If some space for other hooks is allowed then 93- sound good because you can run two hooks between mkinitcpio and signing the ESP. The pacman order is 0-9, a-z, then A-Z. If you really want this to run last, use zz- so the user can run some hooks after it. Most hooks stay below 99-.

sharpenedblade avatar Mar 26 '22 18:03 sharpenedblade

Hi !

The workaround suggested in @lunaryorn 's blog, which is to sign the bootloader in /usr/lib/systemd/boot/efi/and not in /boot/efi/ seems like a good way to go with systemd > 250 and systemd-boot-update.service, wouldn't it be interesting to have that tip in the sbctl documentation ? As I understand it, the USAGE section of the man page, as-is, might break systems if the boot-loader is updated after next boot (and therefore not signed).

I only learned about the recommendation to use update-service as a backup from this thread, so I suppose a lot of people are going to be using it, and signing the bootloader in /usr/lib/systemd/boot/efi/ seems like a decent standard.

By the way, sbctl is an incredible tool, it makes the whole process really easy, thanks very much !

cvlc12 avatar Jul 02 '22 13:07 cvlc12

I agree completely with @Gertalitec. I've been using the same approach very successfully. First, sign ${FILE}, saving it to ${FILE}.signed:

# Sign systemd-boot binaries.
#
# The signed binaries are placed in /usr/lib/systemd/boot/efi/*.efi.signed.
# `bootctl` will then install these binaries instead of the regular unsigned
# ones.

[Trigger]
Type = Path
Operation = Install
Operation = Upgrade
Target = usr/lib/systemd/boot/efi/systemd-boot*.efi

[Action]
Description = Signing bootctl binaries...
When = PostTransaction
Exec = /bin/sh -c 'while read -r f; do sbctl sign "$f" --output "$f.signed"; done'
NeedsTargets

The only annoying thing is: I have to also sign the files manually a first time upon installation. I do this with a boostrapping script for the bootloader:

post_install() {
  # Create SecureBoot keys -- these need to be manually registered (with `sbctl
  # enroll-keys) before turning on SecureBoot.
  sbctl create-keys

  # Sign the existing systemd-boot binaries.
  # The included hook will sign them again after updates.
  for f in /usr/lib/systemd/boot/efi/systemd-boot*.efi; do
    sbctl sign "$f" --output "$f.signed"
  done

  # Install the already-signed binaries.
  # A hook provided by a dependency will update installed binaries after updates.
  bootctl install

  post_update
}

Do you think this can be included in contrib/?

WhyNotHugo avatar Jul 02 '22 14:07 WhyNotHugo

I'm not even sure the hook above is necessary, since with sbctl -s the bootloader in /usr/lib/ will automatically be signed by sbctl after updates anyway.

I think the only step needed is # sbctl sign -s -o /usr/lib/systemd/boot/efi/systemd-bootx64.efi.signed /usr/lib/systemd/boot/efi/systemd-bootx64.efi

I'm not even sure using -o is necessary but I'd have to check

cvlc12 avatar Jul 02 '22 14:07 cvlc12

I had issues having a package supply a /usr/share/secureboot/files.db (because it contains checksums, so it mutates when other packages are updated).

I guess I could run sbctl -s on the same bootstrap script.

The flow using the .signed files is still a very valid tho.

WhyNotHugo avatar Jul 02 '22 14:07 WhyNotHugo

@Gertalitec just wanted to say I tried # sbctl sign -s /usr/lib/systemd/boot/efi/systemd-bootx64.efi but it overwrites the original find so I'm not sure it's fine to omit the -o (BTW I restored the original file).

sambonbonne avatar Nov 09 '22 11:11 sambonbonne

I've been using

[Trigger]
Operation = Install
Operation = Upgrade
Type = Package
Target = systemd

[Action]
When = PostTransaction
Description = Updating systemd's efi files
Exec = /usr/bin/bootctl update

For a long time. Then I started using sbctl and it all worked out of the box.

I think people with similar setups might be impacted if sbctl's pacman hook doesn't run last.

juxuanu avatar Nov 22 '22 09:11 juxuanu