From ab561f8c6d409935bc7bc33de16b8b6ff22001e5 Mon Sep 17 00:00:00 2001 From: Wolf <wolf@wolfsden.cz> Date: Sun, 22 Sep 2019 21:31:49 +0200 Subject: [PATCH] Add support for unlocking multi-device root Add cryptroo[0-9]= family of options to allow unlocking multi-device root filesystems, which is needed for btrfs raid1. --- initramfs-init.in | 80 ++++++++++++++++++++++++++++++++++++++--- mkinitfs-bootparam.7.in | 28 +++++++++++++++ 2 files changed, 103 insertions(+), 5 deletions(-) diff --git a/initramfs-init.in b/initramfs-init.in index eaacb13..f149af0 100755 --- a/initramfs-init.in +++ b/initramfs-init.in @@ -330,11 +330,15 @@ mount -t tmpfs -o nodev,nosuid,noexec shm /dev/shm # acpi_osi="!Windows 2006" xen-pciback.hide=(01:00.0) set -- $(cat /proc/cmdline) -myopts="alpine_dev autodetect autoraid chart cryptroot cryptdm cryptheader cryptoffset - cryptdiscards cryptkey debug_init dma init init_args keep_apk_new modules ovl_dev - pkgs quiet root_size root usbdelay ip alpine_repo apkovl alpine_start splash - blacklist overlaytmpfs rootfstype rootflags nbd resume s390x_net dasd ssh_key - BOOTIF" +myopts="alpine_dev autodetect autoraid chart cryptroot cryptdm cryptheader + cryptoffset cryptdiscards cryptkey debug_init dma init init_args + keep_apk_new modules ovl_dev pkgs quiet root_size root usbdelay ip + alpine_repo apkovl alpine_start splash blacklist overlaytmpfs rootfstype + rootflags nbd resume s390x_net dasd ssh_key BOOTIF" +for i in `seq 0 9`; do + myopts="$myopts cryptroot$i cryptdm$i cryptheader$i cryptoffset$i + cryptdiscards$i cryptkey$i" +done for opt; do case "$opt" in @@ -461,6 +465,72 @@ if [ -n "$KOPT_cryptroot" ]; then fi fi +( +# Helper functions to avoid obscuring logic with so many evals +for var in cryptroot cryptdiscards cryptdm cryptoffset cryptheader cryptkey; do + eval "$var() { eval 'printf -- %s \"\$KOPT_$var'\$1'\"'; }" +done +for i in `seq 0 9`; do + [ -n "$(cryptroot $i)" ] || continue + any=true + + ebegin "Opening encrypted device $(cryptroot $i)" + + opts="-c $(cryptroot $i)" + + if [ "$(cryptdiscards $i)" = "yes" ]; then + opts="$opts -D" + fi + + if [ -n "$(cryptdm $i)" ]; then + name="$(cryptdm $i)" + else + name=$( + dd if=/dev/urandom bs=4096 count=1 2>/dev/null \ + | sha1sum | tr -d \ - + ) + cat >&2 <<-EOF +WARNING: cryptsetup does not work without having a device name set. You should + provide one using cryptdm$i=. Using temporary name: + $name. + EOF + fi + opts="$opts -m $name" + + if [ -n "$(cryptheader $i)" ]; then + opts="$opts -H $(cryptheader $i)" + fi + + if [ -n "$(cryptoffset $i)" ]; then + opts="$opts -o $(cryptoffset $i)" + fi + + if [ "$(cryptkey $i)" = "yes" ]; then + opts="$opts -k /crypto_keyfile.bin" + elif [ -n "$(cryptkey $i)" ]; then + opts="$opts -k $(cryptkey $i)" + fi + + nlplug-findfs $opts -p /sbin/mdev ${KOPT_debug_init:+-d} \ + ${KOPT_usbdelay:+-t $(( $KOPT_usbdelay * 1000 ))} \ + /dev/mapper/"$name" + eend $? +done + +# We need to continue only if there is at least one cryptrootX specified +[ "$any" = "true" ] || exit 0 + +# Since btrfs needs all devices to be present, scanning cannot be done by the +# nlplug-findfs above. So lets do both lvm and btrfs manually here. +if [ -x /sbin/lvm ]; then + /sbin/lvm vgchange -aya --noudevsync --sysinit -qq +fi +if [ -x /sbin/btrfs ]; then + /sbin/btrfs device scan >/dev/null || \ + echo "Failed to scan devices for btrfs filesystem." +fi +) + if [ -n "$KOPT_nbd" ]; then # TODO: Might fail because nlplug-findfs hasn't plugged eth0 yet configure_ip diff --git a/mkinitfs-bootparam.7.in b/mkinitfs-bootparam.7.in index 1589d0d..ddc0468 100644 --- a/mkinitfs-bootparam.7.in +++ b/mkinitfs-bootparam.7.in @@ -27,20 +27,39 @@ security implications. After the block device has been decrypted, make it available as /dev/mapper/\fINAME\fR. .TP +\fBcryptdm[0-9]=\fINAME\fR +After the block device has been decrypted, make it available as +/dev/mapper/\fINAME\fR. See "CRYPTO NOTES" for details. +.TP \fBcryptheader=\fIDEVICE\fR When the LUKS headers and encrypted data are on different devices, this option specifies the device with the LUKS headers. .TP +\fBcryptheader[0-9]=\fIDEVICE\fR +When the LUKS headers and encrypted data are on different devices, this option +specifies the device with the LUKS headers. See "CRYPTO NOTES" for details. +.TP \fBcryptkey=\fIKEYFILE\fR Attempt to decrypt an encypted partition using an keyfile. .TP +\fBcryptkey[0-9]=\fIKEYFILE\fR +Attempt to decrypt an encypted partition using an keyfile. See "CRYPTO NOTES" +for details. +.TP \fBcryptoffset=\fISECTORS\fR Indicate that the encrypted data begins the given number of sectors after the start of the block device. .TP +\fBcryptoffset[0-9]=\fISECTORS\fR +Indicate that the encrypted data begins the given number of sectors after the +start of the block device. See "CRYPTO NOTES" for details. +.TP \fBcryptroot=\fIDEVICE\fR Attempt to decrypt \fIDEVICE\fR. .TP +\fBcryptroot[0-9]=\fIDEVICE\fR +Attempt to decrypt \fIDEVICE\fR. See "CRYPTO NOTES" for details. +.TP \fBdasd\fR Enable DASD devices on S/390x architectures. .TP @@ -127,6 +146,15 @@ from a different system/OS. .TP \fI@datadir@/initramfs-init\fR Default script that will be run in the initramfs. +.SH CRYPTO NOTES +There are two ways to specify what encrypted device should be unlocked. +.PP +One is \fBcryptroot=\fR family of options. 99% of the time this is what you want +to use. It works just fine as long as you need to unlock just one device. +.PP +Other is \fBcryptroot[0-9]=\fR family of options. When you have your root on +for example btrfs raid1, you need to unlock multiple devices. Up to 10 devices +can be specified. .SH AUTHOR .PP Written by Natanael Copa <ncopa@alpinelinux.org>, Timo Teräs <timo.teras@iki.fi> and others. -- GitLab