SDB:Static Initrd and Unified Kernel Image

Jump to: navigation, search
This article gives a description how to setup a system using a static initrd and/or an Unified Kernel Image.
Icon-checked.png
This procedure was tested on Tumbleweed


Introduction and Motivation

An unsigned initrd

The initramfs (or initrd) is a compressed archive generated by dracut (mkosi-initrd, ...). It contains the minimal set of services needed in order to mount the root file system and in this case the initramfs can only be used by the system it was generated on. Therefore, as built locally in the machine, it cannot be signed by the vendor. The bootchain isn't entirely secure and an attacker could change or corrupt the cpio archive, containing the initramfs.

Use static initrd and Unified Kernel Image

To improve security of the boot chain, one idea would be to build a static initramfs on the vendor side and let him sign it. We used OpenBuildService (OBS) to build this project and provide it through the package manager in the distribution. In order to provide more robust and secure images, the next step starting from the static initrd, is to use the Unified Kernel Image (UKI). It provides an all-in-one EFI binary containing Kernel, Modules, initramfs, kernel-cmdline-parameters, etc..It centralizes all builds, where the Kernel and the initrd are build from the OBS, and everything is signed one-time. The distribution becomes more robust and more secure

Important links


Install a static initrd and an Unified Kernel Image from Factory

Install the unsigned static initrd

sudo zypper install static-initrd-<flavor>-unsigned
  • A static initrd will be installed into /usr/share/initrd/static-initrd-<flavor>-<kernel_version>.unsigned
  • A flavor is a "dedicated" initrd, for specific use-cases, e.g.:
    • "generic" → Contains all modules to be the most generic initrd as possible, should works for the most cases.
    • "base" → Contains the minimum set of modules, could not work for all use-cases and needs to be extended via add-ons
    • "network" → An example of a dedicated initrd, which contains the basics and all "network" modules
  • All flavors are built unsigned. Unsigned ones are made to be used with the UKI project (see next sections). It is also useful to test the static initrd without caring about signatures.
localhost:~ # zypper se -t package static-initrd-*
Loading repository data...
Reading installed packages...
 
S  | Name                           | Summary                        | Type
---+--------------------------------+--------------------------------+--------
   | static-initrd-base-unsigned    | Unsigned static base initrd    | package
   | static-initrd-generic-unsigned | Unsigned static generic initrd | package
   | static-initrd-network-unsigned | Unsigned static network initrd | package

Add bootloader entry

  • Requires the uki-tool package
sudo zypper install uki-tool
  • Call the command to add the bootloader entry (/!\ Put the same kernel version used to build the static initrd, found in the initrd filename)
# For grub2
uki-tool grub2 --add --initrd /usr/share/initrd/static-initrd-generic-<kernelver>.unsigned --kerver <kernelver>
# For sdboot
uki-tool sdboot --add --initrd /usr/share/initrd/static-initrd-generic-<kernelver>.unsigned --kerver <kernelver>
# To see entries at boot with sdboot, edit the /boot/efi/loader/loader.conf with "timeout 5"

Install the Unified Kernel Image (uki-<kernel_flavor>)

# UKI based on the "default" kernel flavor
sudo zypper install uki-default

The package will:

  • install the UKI into /usr/lib/modules/${uname}/uki-<kernel_flavor>-<uki_version>.efi
  • Install the certificate to enroll into /usr/share/unified/certs/uki-<kernel_flavor>-<uki_version>-<cert_id>.crt
  • According to your bootloader add a new menu entry

Remove installed static initrd and UKI

Remove the unsigned static initrd

sudo zypper remove static-initrd-<flavor>-unsigned
# for grub2
uki-tool grub2 --remove --initrd /boot/static-initrd-<flavor>-<kernelver>.unsigned
# for sdboot
uki-tool sdboot --remove --initrd /boot/efi/<machine-id>/<kernelver>/static-initrd

Remove the UKI

sudo zypper remove uki-default

Experimentation

Icon-warning.png
Warning: This section describes the work in progress experimentation, it is not ready for production

UKI extension

Extensions are placed into an extra UKI directory:

  • Global extra in /usr/lib/modules/uki.extra.d
  • UKI specific extra in /usr/lib/modules/$(uname -r)/${uki_name}.efi.extra.d/ (/usr/lib/modules/6.9.1-1.foo/bar_123.efi.extra.d/)

Build locally using the uki-tool

ukit extension\
    --packages "strace"\
    --type raw\
    --arch x86_64\
    --uki /usr/lib/modules/$(uname -r)/${efi_file}\
    --name strace

This example creates a formatted extension, containing strace, including its dependencies, named "strace"

localhost:~ # ukit extension -n "debug" -p "strace" -u /usr/lib/modules/6.9.7-1-default/uki-0.1.0.efi
[INFO] Check the uki /usr/lib/modules/6.9.7-1-default/uki-0.1.0.efi and extract the initrd...
[INFO] Create the extension 'debug-ext.raw' with 'strace' in format squashfs at type raw for the uki /usr/lib/modules/6.9.7-1-default/uki-0.1.0.efi
[INFO] Get all dependencies to install...
[INFO] Create an image of sized 18M...
[============================================================================================================================================================================================================================================================================================================\] 200/200 100%
[INFO] extension image created at ./debug-ext.raw
localhost:~ # cp ./debug-ext.raw /boot/efi/EFI/opensuse/uki-0.1.0.efi
uki-0.1.0.efi          uki-0.1.0.efi.extra.d/
localhost:~ # cp ./debug-ext.raw /boot/efi/EFI/opensuse/uki-0.1.0.efi.extra.d/

Install through packages

Will come soon ...

Work with snapshots

Problem: Snapshots are loaded with the `rootflags` option from the cmdline. However, the cmdline is embedded into the signed UKI file and cannot be modified without invalidating the signature.

Add-ons

To work with snapshots for UKI, we need to use the UKI's "add-ons" feature. Add-ons are companions files as for extensions and they aim to dynamically add cmdline options. For snapshots, we would need the add-ons that adds one rootflag option to specify the correct snapshots.

Problem: The way add-ons are used by UKI doesn't allow loading just one from a list. Therefore we can't choose, during the bootloader, on which snapshot to boot...

EFI specific add-ons

To answer this problem, goal is to create a new kind of add-on, where the add-on will need to be chosen in the menu entry of the bootloader to be loaded with the UKI. For example with grub2, you would need to have the keyword "add-on" from the grub.cfg following the path to the binary to load.

In investigation ...

Snapper plugin

To automatically deal with snapshots for sd-boot or grub2, a snapper plugin can be developed.

In investigation ...

UKI profiles

In investigation ...


See also

Related articles