DM-verity

From Alpine Linux
Revision as of 19:28, 9 December 2024 by Pursuable1652 (talk | contribs)
This material is work-in-progress ...

Do not follow instructions here until this notice is removed.
(Last edited by Pursuable1652 on 9 Dec 2024.)

Why DM-Verity?

Possibly you want to continue the RoT (Root of Trust) from the hardware -> secure boot -> to dm-verity rootfs, and you already use TPMs to ensure only the hardware can unlock the disk encryption, but now you want to ensure your root-image/root-parition has not been tampered with.

What's the different between me just setting the root partition as read-only (or using Fedora's Immutable Root Partition) vs this?

DM-Verity disallows tampering with the read-only partition, and with this consideration, you may use ERO-FS or SquashFS to generate Read-Only Root-Paritition Images. If you set your EXT4 file system to writable, and DM-Verity were to use it, it would be seen as "corurpted" and not boot anymore, because even just ONE tiny data change to the root image/partition would render it "corrupted". This is the same technology used in Android and Chrome OS Devices.

What is ERO-FS?

[Google thought about implementing ERO-FS with DM-Verity] [1]. But even if Google didn't use it for some reason, ERO-FS is still an excellent and fast compressed read-only filesystem.

Here is an excerpt about mkfs.erofs on [Arch Linux Wiki] [2]:

mkfs.erofs(1) offers an attractive alternative to ext4 or squashfs on the root partition. EROFS, like squashfs, does not allow writes by design and has better performance in many cases than comparable filesystems on flash and solid-state media. It uses lz4 compression by default and was designed for Android phones by Huawei, which make extensive use of dm-verity.

Installing

Warning: This wiki will be using Alpine Linux Edge Version. (Alpine Linux Non-Edge Versions may not contain these packages in the this wiki page) (Use Alpine Linux Edge Testing as well)


First, some considerations, you may use a strictly READ-ONLY file system, such as SquashFS or EROFS, this wiki will be using EROFS (if you use a custom kernel, make sure it supports a file system such as ERO-FS, the default linux-lts does). [ERO-FS Github] [3] contains some information about how to compress and make your own read-only root image.

$ apk install dracut erofs-utils

$ mkdir image && cd image

$ wget https://dl-cdn.alpinelinux.org/alpine/v3.21/releases/x86_64/alpine-minirootfs-3.21.0-x86_64.tar.gz

$ tar -xvf alpine-minirootfs-3.21.0-x86_64.tar.gz && rm alpine-minirootfs-3.21.0-x86_64.tar.gz

Command below will generate an ERO-FS Image compressed with lz4 as ./erofs.img (erofs.img would be the root-partition file to use for dracut)

$ cd .. && mkfs.erofs -zlz4hc erofs.img ./image


Working with Dracut

If you want to use dm-verity on Alpine Linux, you need to use Dracut (Thus also generating a secure boot EFIStub with it as well). Reason is because dracut is one of the only initramfs generators to let you import your own modules and files into its initramfs.

Also remember, mount your ROOT_PARTITION as read only, since any changes will cause dm-verity to detect it as "corrupt"

Warning: The following guide was done with FULL disk encryption, so this might not work perfectly on Non encrypted disk setup, also done on UEFI using gummiboot (now called systemd-boot) EFIStub and generating a UKI (Unified Kernel Image)


Install basic stuff:

apk add dracut dracut-core cryptsetup gummiboot gummiboot-efistub

Create a new partition for your DM-verity:

Todo: add command for new verity partition with fdisk (should require 8-10% the size of Root partition)


Edit "/usr/lib/dracut/modules.d/90crypt/cryptroot-ask.sh" and add these lines right BEFORE "exit 0" (add your $ROOT_PARTITION directory and $VERITY_PARTITION directory):

Contents of /usr/lib/dracut/modules.d/90crypt/cryptroot-ask.sh

... ### DM-Verity mount /dev/mapper/[ROOT_PARTITION] /var/tmp cryptsetup open --key-file /var/tmp/[Keyfile_dir] /dev/[Verity_partition] [verity dm name] umount /var/tmp veritysetup open /dev/[ROOT_PARTITION] /dev/[VERITY_PARTITION] $(cat /usr/lib/dracut/roothash.txt) ### ...

To setup dm-verity (borrowed from Arch Linux Wiki):

veritysetup format /dev/[ROOT_PARTITION] /dev/[VERITY_PARTITION]

/etc/dracut.conf (put whatever your boot parameters are in "kernel_cmdline"):

Contents of /etc/dracut.conf

... kernel_cmdline="" add_dracutdrivers+=" busybox crypt crypt-gpg dm rootfs-block kernel-modules kernel-modules-extra " /etc/dracut.conf.d/secureboot.conf (do this if you have your own secureboot keys, or want to use secureboot): uefi_secureboot_cert="/[secureboot-keys-directory]/db.crt" uefi_secureboot_key="/[secureboot-keys-directory]/db.key" /etc/dracut.conf.d/files.conf (this is what will import veritysetup binary file into dracut initramfs): install_items+=" /sbin/veritysetup " ...

Finally, generate UKI using dracut (replace 6.X.X-X-lts with your kernel version) (also replace /boot/efi/EFI/Linux/alpine-linux.efi with your mount efi partition):

export DRACUT_KMODDIR_OVERRIDE=1

dracut --include /usr/lib/dracut/roothash.txt /usr/lib/dracut/roothash.txt --host-only --kernel-image /boot/vmlinuz-lts --kmoddir /lib/modules/6.X.X-X-lts --kver 6.X.X-X-lts --uefi --uefi-stub /usr/lib/gummiboot/linuxx64.efi.stub --force --compress lz4 /boot/efi/EFI/Linux/alpine-linux.efi /boot/efi/EFI/Linux/alpine-linux.efi efibootmgr

efibootmgr --create --disk /dev/[efi_partition] --part 1 --label alpine-linux --loader EFI/Linux/alpine-linux.efi

Unfortunately, using the default alpine linux kernel didn't work so download another distributions root system (like debians or devuan), and replace 6.X.X-X-lts, and vmlinuz-lts with anothers distributions kernel modules and kernel image (Or consider compiling your own linux-hardened kernel).

If you want to test if DM-verity fully works, change the $ROOT_PARTITION's files and it should say it is "corrupt", and not continue the boot process.

External Links

Android-13 Possibility of using ERO-FS:

DM-Verity (Arch Wiki):

ERO-FS Github

My old post on how it worked (This is my reddit account and didn't make a wiki page for this don't sue me)