Package: cryptsetup Version: 2:1.4.3-4 Severity: serious Tags: patch [Rationale for severity serious: renders system unbootable]
I recently upgraded a Thecus n2100 from squeeze to wheezy [better late than never!]. It's a headless system; the root filesystem is a logical volume on LVM over an encrypted physical volume. I use dropbear to ssh into the system at initramfs stage and unlock the encrypted PV, as described in /usr/share/doc/cryptsetup/README.remote.gz. After completing the upgrade and installing a new kernel version, I rebooted the system. Although it was possible to log in remotely to initramfs via ssh and successfully unlock encrypted root filesystem, the system did not proceed to mount the root FS and boot. Judging by the output of ps, a rescue shell is started after I unlock the encrypted volume. There is no terminal connected to the system, so I couldn't actually interact with the rescue shell, but grepping through the rescue shell's environment gives: "REASON=ALERT! /dev/ram0 does not exist. Dropping to a shell!" Before unlocking encrypted device, /conf/param.conf contains "ROOT=/dev/mapper/<name-of-root-lv>" line pointing to the correct root device; after unlocking it contains *two* ROOT lines, the original, correct line and a second, incorrect line (ROOT=/dev/ram0). I think this second line is causing the subsequent boot process to fail. It seems that the second line is put there by this part of /usr/share/initramfs-tools/scripts/local-top/cryptroot after unlocking the encrypted volume: ,----[ /usr/share/initramfs-tools/scripts/local-top/cryptroot ] | NEWROOT=${cmdline_root:-/dev/mapper/$cryptlvm} | if [ "$cryptrootdev" = "yes" ]; then | # required for lilo to find the root device | echo "ROOT=$NEWROOT" >>/conf/param.conf | fi | eval $(fstype < "$NEWROOT") `---- The first, correct ROOT line is put there by flash-kernel: The n2100 uses redboot as a bootloader; redboot loads a kernel image and an initramfs image from flash; in Debian, the flash-kernel package automates the process of writing the kernel and the initramfs image to flash; flash-kernel has explicit support for the n2100. Because redboot passes the kernel bogus root parameter [root=/dev/ram0], flash-kernel includes an initramfs-tools hook to write the correct root device to /conf/param.conf when building the initramfs image: ,----[ /usr/share/initramfs-tools/hooks/flash_kernel_set_root ] | # Should we override the root device or merely provide a default root | # device? | blsr="$(get_machine_field "$machine" "Bootloader-sets-root")" | | if [ "$blsr" = "no" ]; then | # The boot loader doesn't pass root= on the command line, so | # provide a default. | install -d $DESTDIR/conf/conf.d | echo "ROOT=\"$rootdev\"" > $DESTDIR/conf/conf.d/default_root | else | # The boot loader passes a bogus root= (e.g. root=/dev/ram), so | # override the command line parameter. | install -d $DESTDIR/conf | echo "ROOT=\"$rootdev\"" >> $DESTDIR/conf/param.conf | fi `---- The quoted section of local-top/cryptoroot causes a bogus second "ROOT=" entry (the bogus root=/dev/ram0 from the command line) to be written to /conf/param.conf. This prevents boot process from continuing correctly. This problem is present both in the version of cryptsetup in wheezy, and in the version in wheezy-backports (2:1.6.4-4~bpo70+1). I haven't tested it, but I'm guessing the version in jessie is also affected. I imagine that other system which use flash-kernel, with Bootloader-sets-root=yes, would also be affected if they use root on a LV over an encrypted device. I attach a patch which fixes the issue for me, it could probably do with further testing. The patch is against the version of cryptsetup in wheezy-backports.
--- debian/initramfs/cryptroot-script.orig +++ debian/initramfs/cryptroot-script @@ -297,10 +297,15 @@ return 1 fi - NEWROOT=${cmdline_root:-/dev/mapper/$cryptlvm} - if [ "$cryptrootdev" = "yes" ]; then - # required for lilo to find the root device - echo "ROOT=$NEWROOT" >>/conf/param.conf + if [ -f /conf/param.conf ] && grep -q '^ROOT=' /conf/param.conf + then + eval $(sed -n 's/^ROOT=/NEWROOT=/p' /conf/param.conf) + else + NEWROOT=${cmdline_root:-/dev/mapper/$cryptlvm} + if [ "$cryptrootdev" = "yes" ]; then + # required for lilo to find the root device + echo "ROOT=$NEWROOT" >>/conf/param.conf + fi fi eval $(fstype < "$NEWROOT") fi