Ryan Rueger

Home · About · Teaching · Keys
Mathematics · Computing · Cycling

Regenerating `initramfs` from another snapshot with `mkinitcpio`

 

I was hit by an unfortunate bug recently, in which a bundled ssl library overrode the system wide version rendering my system unbootable. I could not even get into early userspace because the initramfs generated with this library could not cryptsetup open my encrypted root partition.

This is usually a moment in whch those who have a (btrfs/zfs/lvm) system rollback solution in place can calmly rollback their system and go on with their day. (/boot along with the initramfs files should be kept under rollback control, otherwise snapshots using older kernels would not be bottable).

However, suppose we want to fix the issue directly: we need to know how to regenerate an initramfs from a system root that is not the current one (/).

Suppose our snapshots look like this

/btrfs/@root
/btrfs/snapshots/@good_snapshot-1
/btrfs/snapshots/@good_snapshot-2
/btrfs/snapshots/@good_snapshot-3

After the update, /btrfs/@root is broken (because /btrfs/@root/boot/initramfs-linux.img are broken) and suppose we are currently booted into /btrfs/snapshots/@good_snapshot-3. What it means for us to be “booted into” /btrfs/snapshots/@good_snapshot-3 is that the subvolume /btrfs/snapshots/@good_snapshot-3 is mounted to / just after the root partition is unlocked in the boot process.

Reading the manual of mkinitcpio we see that we need the options

-g, --generate filename
   Generate a CPIO image as filename. Default: no; this means nothing will
   be written to the filesystem unless this option is specified.

-r, --moduleroot root
  Specifies the root directory to find modules in, defaulting to /

-k, --kernel kernelversion
  Use kernelversion, instead of the current running kernel. This may be a
  path to a kernel image (only supported for x86-based architectures), a
  specific kernel version or the special keyword none. In the latter case,
  no kernel modules are added to the image.

The option -g will tell mkinitcpio where to save the initramfs, we want this to be generated in the root of the currently broken snapshot /btrfs/@root/boot/initramfs-linux.img. Moreover, we want mkinitcpio to read all module information from /btrfs/@root and not / (which is currently mounted to /btrfs/snasphots/@good_snapshot-3), so we pass this to the -r option. Finally, we want mkinitcpio to read the correct kernel version (image) from disk to create the initramfs, so we need to pass -k /btrfs/@root/boot/vmlinuz-linux to mkinitcpio. Now that the initramfs has been regenerated, we can re-install our bootloader entries and boot into /btrfs/@root as usual.

This is another example where Unified Kernel Images (UKI’s) can really save ones bacon: after regenerating the initramfs, we can sipmly re-create a bootable UKI and create a new EFI entry if necessary with efibootmgr to create a bootable system. We need not worry about bootloaders getting confused with archived snapshots and live systems.