From f2c2cbdf22e8bdcef58a9d6c9df90ec7d9fd9c3b Mon Sep 17 00:00:00 2001 From: Wolf 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 | 70 +++++++++++++++++++++++++++++++++++++++++ mkinitfs-bootparam.7.in | 28 +++++++++++++++++ 2 files changed, 98 insertions(+) diff --git a/initramfs-init.in b/initramfs-init.in index 2147e03..8c442dd 100755 --- a/initramfs-init.in +++ b/initramfs-init.in @@ -348,6 +348,10 @@ myopts="alpine_dev autodetect autoraid chart cryptroot cryptdm cryptheader crypt 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 zfcp" +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 @@ -487,6 +491,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 af095c2..dab6a4c 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 @@ -130,6 +149,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 , Timo Teräs and others.