-
Notifications
You must be signed in to change notification settings - Fork 204
Trying to use UKIs: Error because of composefs= parameter mismatch #1984
-
Hi there!
I've been playing around with UKIs and wanted to see whether I could get Secure Boot to work in combination with an Arch Linux base image. For this, I mainly replicated the instructions from the docs, which seem to be very similar to the steps in the Dockerfile at the root of the bootc repository. As such, this is what I came up with:
FROM ghcr.io/bootcrew/arch-bootc:latest AS rootfs RUN --mount=type=secret,id=secureboot_key \ --mount=type=secret,id=secureboot_cert <<EORUN set -euxo pipefail # Make sure locales and man pages are not ignored and install basic packages sed -i 's/NoExtract /# NoExtract /g' /etc/pacman.conf # For testing: Just install the SB-related utilities here so we can use this image # both as the "base" and as the "tools" image. pacman -Sy pacman -S --noconfirm glibc glibc-locales efitools efibootmgr mokutil sbsigntools systemd-ukify # Sign systemd-boot EFI binaries # bootctl will detect the .signed binaries and prefer them over the unsigned ones sbsign \ --key /run/secrets/secureboot_key \ --cert /run/secrets/secureboot_cert \ --output "/usr/lib/systemd/boot/efi/systemd-bootx64.efi.signed" \ "/usr/lib/systemd/boot/efi/systemd-bootx64.efi" sbverify \ --cert /run/secrets/secureboot_cert \ "/usr/lib/systemd/boot/efi/systemd-bootx64.efi.signed" # In case this ever actually installs and boots up, set a root password to be able to look around a bit... echo 'root:password' | chpasswd -c YESCRYPT EORUN FROM rootfs as sealed-uki RUN --mount=type=bind,from=rootfs,target=/target,ro \ --mount=type=secret,id=secureboot_key \ --mount=type=secret,id=secureboot_cert <<EORUN set -euxo pipefail # `bootc container compute-composefs-digest` creates a temporary composefs repo in /var/tmp, which doesnt exist inside the base image mkdir -p /var/tmp # Compute the composefs digest from the mounted rootfs digest=$(bootc container compute-composefs-digest /target) # Find the kernel version kver=$(basename $(find /usr/lib/modules -maxdepth 1 -mindepth 1 -type d -print0)) mkdir /out # From the docs. Fails with: # > error: Installing to disk: Setting up composefs boot: Setting up UKI boot: Writing 6.18.7-arch1-1.efi to ESP: The UKI has the wrong composefs= parameter (is 'sha512:0cc1...', should be sha512:fdca...) # Generate and sign the UKI with the digest embedded # ukify build \ # --linux "/target/usr/lib/modules/${kver}/vmlinuz" \ # --initrd "/target/usr/lib/modules/${kver}/initramfs.img" \ # --cmdline "composefs=${digest} rw" \ # --os-release "@/target/usr/lib/os-release" \ # --signtool sbsign \ # --secureboot-private-key /run/secrets/secureboot_key \ # --secureboot-certificate /run/secrets/secureboot_cert \ # --output "/out/${kver}.efi" # From the `seal-uki` script: bootc container ukify --rootfs "/target" \ --karg enforcing=0 \ -- \ --signtool sbsign \ --secureboot-private-key "/run/secrets/secureboot_key" \ --secureboot-certificate "/run/secrets/secureboot_cert" \ --measure \ --json pretty \ --output "/out/${kver}.efi" EORUN FROM rootfs COPY --from=sealed-uki /out/*.efi /boot/EFI/Linux/
This is the error I get when I try to install this image via bootc install to-disk:
error: Installing to disk: Setting up composefs boot: Setting up UKI boot: Writing 6.18.7-arch1-1.efi to ESP: The UKI has the wrong composefs= parameter (is 'sha512:bf864670d49635894050223df34d96ca5c8840f9acd6d6a8cf3090b31987bc9173b64d6be2d8fa49a2e684af4abcb7eaed6c15af2cd769d39109af826851010e', should be sha512:d533564f412fb87ae249d526ce8d968613b74561e7bdd13e34017e8967dc1b5af7116bc8973f46f496bc27d6d4008a4315b7ac9890f68b0b64ef3af547d27969)
I guess it makes sense: The about-to-be-installed image includes the UKI, while the rootfs - the image composefs digest was calculated of - does not. So different checksums are expected here.
I had a look at the source code and noticed that create_composefs_filesystem - where the "expected" composefs digest comes from, does not special-case files in /boot (which - again - makes sense), so naturally these files become a part of the digest.
So my question is: How is this meant to be used? I would have expected that either bootc takes care of not including the files in /boot in the checksum calculation or that I'm able to specify an UKI to be installed on top of the rootfs image, such that the situation where I'd need to include a signed digest into an image - and thus changing this exact digest - doesn't happen. What am I missing?
Beta Was this translation helpful? Give feedback.
All reactions
This seems like an issue with our xattr filters that we only apply on one path. Ref composefs/composefs-rs#211 (comment), composefs/composefs-rs#212
Replies: 3 comments 3 replies
-
When this is has happened to me in the past I diffed the computed filesystem trees - use --write-dumpfile-to.
Actually see
bootc/crates/xtask/src/xtask.rs
Line 519 in 4ec8a85
Beta Was this translation helpful? Give feedback.
All reactions
-
Can you check if you got bit by e.g. composefs/composefs-rs#211 (comment)
Beta Was this translation helpful? Give feedback.
All reactions
-
Hey, thanks for these suggestions!
I have a dumpfile now, so I know what bootc container compute-composefs-digest sees. Unfortunately, I can't spot anything unusual in there. It would be helpful to have another dumpfile of what bootc install sees and why it differs.
What I tried is to call the bootc binary from my host like this:
bootc container compute-composefs-digest-from-storage --write-dumpfile-to from-outside.dump 1a453cb05673
where 1a453cb05673 is the image id podman wrote to stdout after building rootfs. Is this a sensible approach?
Anyways, those are quite different from each other. It starts with different permissions for / (40555 vs. 40755) and goes on with a few files from /etc seemingly having an user.overlay.origin=- xattr set (??) when looking at the image "from the outside", but apparently not inside the build context.
It doesn't seem about SELinux labels (none of the files have them and the Arch Linux images don't include anything SELinux related, including any policy) and neither about the random-seed (which doesn't even exist in the image)
Beta Was this translation helpful? Give feedback.
All reactions
-
Had another look at this and it's definitely the xattrs. I ended up calling compute-composefs-digest-from-storage just like I'd called install to-disk (plus mounting /run/host-container-storage) and I guess this is the correct way.
$ diff -N from-outside.dump from-build.dumpfile
6c6
< /etc/.pwd.lock 0 100600 1 0 0 0 1771146228.0 - - - user.overlay.origin=-
---
> /etc/.pwd.lock 0 100600 1 0 0 0 1771146228.0 - - -
13c13
< /etc/audit 0 40755 4 0 0 0 1771151547.0 - - - user.overlay.origin=-
---
> /etc/audit 0 40755 4 0 0 0 1771151547.0 - - -
497c497
< /etc/default 0 40755 2 0 0 0 1761374527.0 - - - user.overlay.origin=-
---
> /etc/default 0 40755 2 0 0 0 1761374527.0 - - -
560,561c560,561
< /etc/pacman.d 0 40755 3 0 0 0 1771146222.0 - - - user.overlay.impure=y user.overlay.origin=-
< /etc/pacman.d/gnupg 0 40755 4 0 0 0 1771146228.0 - - - user.overlay.impure=y user.overlay.origin=-
---
> /etc/pacman.d 0 40755 3 0 0 0 1771146222.0 - - -
> /etc/pacman.d/gnupg 0 40755 4 0 0 0 1771146228.0 - - -
570c570
< /etc/pacman.d/gnupg/trustdb.gpg 12960 100644 1 0 0 0 1771146228.0 b1/52124436e928dff19059b64c2b04cef8e74d9ee9a7c77a64b5dc0a3edfa19143226a7ab47c6f152503839be601bf04873bfc75d8d9cf17a19de47c46d7623d - b152124436e928dff19059b64c2b04cef8e74d9ee9a7c77a64b5dc0a3edfa19143226a7ab47c6f152503839be601bf04873bfc75d8d9cf17a19de47c46d7623d user.overlay.origin=-
---
> /etc/pacman.d/gnupg/trustdb.gpg 12960 100644 1 0 0 0 1771146228.0 b1/52124436e928dff19059b64c2b04cef8e74d9ee9a7c77a64b5dc0a3edfa19143226a7ab47c6f152503839be601bf04873bfc75d8d9cf17a19de47c46d7623d - b152124436e928dff19059b64c2b04cef8e74d9ee9a7c77a64b5dc0a3edfa19143226a7ab47c6f152503839be601bf04873bfc75d8d9cf17a19de47c46d7623d
572c572
< /etc/pam.d 0 40755 2 0 0 0 1771151544.0 - - - user.overlay.origin=-
---
> /etc/pam.d 0 40755 2 0 0 0 1771151544.0 - - -
597c597
< /etc/profile.d 0 40755 2 0 0 0 1771152232.0 - - - user.overlay.origin=-
---
> /etc/profile.d 0 40755 2 0 0 0 1771152232.0 - - -
2746,2747c2746,2747
< /usr/include/dbus-1.0 0 40755 3 0 0 0 1759128552.0 - - - user.overlay.impure=y user.overlay.origin=-
< /usr/include/dbus-1.0/dbus 0 40755 2 0 0 0 1759128552.0 - - - user.overlay.origin=-
---
> /usr/include/dbus-1.0 0 40755 3 0 0 0 1759128552.0 - - -
> /usr/include/dbus-1.0/dbus 0 40755 2 0 0 0 1759128552.0 - - -
[ + quite a few more]
I did solve the permissions for root by introducing a chunkah step. While this is probably not universally good advice it's what I wanted to do anyway, so... I'm glad it works 🤷♂️
Now I'm afraid I'll have to take a close look at how the base image is built exactly and where those xattrs are coming from. As the bootcrew CI uses the buildah action this probably the main suspect here...
Beta Was this translation helpful? Give feedback.
All reactions
-
This seems like an issue with our xattr filters that we only apply on one path. Ref composefs/composefs-rs#211 (comment), composefs/composefs-rs#212
Beta Was this translation helpful? Give feedback.
All reactions
-
It took a while, but I think I understand now :-) Thanks for the pointers! Guess we'll have to wait for a fix then.
Btw, in case anyone stumbles over this and has the same issue: It works for me if I build the container starting from the Arch Linux image locally, i.e. include the Containerfile from bootcrew/arch-bootc as the first stage and build from that. I'm currently on podman 5.7.1/buildah 1.42.2 if it matters.
Beta Was this translation helpful? Give feedback.