diff -Nru cryptsetup-1.6.6/debian/changelog cryptsetup-1.6.6/debian/changelog --- cryptsetup-1.6.6/debian/changelog 2015-08-21 03:59:11.000000000 -0400 +++ cryptsetup-1.6.6/debian/changelog 2015-12-16 19:17:59.000000000 -0500 @@ -1,3 +1,23 @@ +cryptsetup (2:1.6.6-5ubuntu2+bug1481536.3~15.10.1) wily; urgency=medium + + [ Steve Langasek ] + * debian/initramfs/cryptroot-script: don't call vgchange, which udev rules + already handle for us. Instead we should be calling udevadm settle at + the right points to ensure devices are visible before we try to use + them. Thanks to Richard Hansen for the analysis. LP: #1481536. + + [ Richard Hansen ] + * debian/initramfs/cryptroot-script: + - don't assume devices will exist after running 'udevadm settle' + (wait until they appear, with a timeout) + - wait for the LVM logical volume device to appear before trying + to determine its filesystem type + - remove an unnecessary call to udev_settle() + - miscellaneous cleanups + LP: #1481536 + + -- Richard Hansen Wed, 16 Dec 2015 15:49:33 -0500 + cryptsetup (2:1.6.6-5ubuntu2) wily; urgency=medium * Fix stupid typo in Recommends "busybox | busybox-static" inversion. diff -Nru cryptsetup-1.6.6/debian/initramfs/cryptroot-script cryptsetup-1.6.6/debian/initramfs/cryptroot-script --- cryptsetup-1.6.6/debian/initramfs/cryptroot-script 2015-03-28 16:38:34.000000000 -0400 +++ cryptsetup-1.6.6/debian/initramfs/cryptroot-script 2015-12-16 19:15:13.000000000 -0500 @@ -155,18 +155,44 @@ return 0 } -activate_vg() +# arg #1: device to wait for +# arg #2 (optional): description of what we're waiting for, defaults to $1 +wait_for() { - # Sanity checks - if [ ! -x /sbin/lvm ]; then - message "cryptsetup: lvm is not available" - return 1 - fi + if [ ! -e "$1" ]; then + log_begin_msg "Waiting for ${2-$1}..." + + # Default delay is 180s + slumber=${ROOTDELAY:-180} + + slumber=$(( ${slumber} * 10 )) + while [ ! -e "$1" ]; do + # Each call to udev_settle can block for up to 30 + # seconds, so the worst case scenario here is a boot + # delay of $ROOTDELAY*10*30 seconds = 15 hours. + # However, this could only ever happen if udev + # constantly had new events being queued *and* none of + # these events resulted in the root device becoming + # available. Still, a more correct solution would + # measure against wall time and call udevadm settle + # in a loop until the $ROOTDELAY timeout has been + # reached. + udev_settle + + /bin/sleep 0.1 + slumber=$(( ${slumber} - 1 )) + [ ${slumber} -gt 0 ] || break + done - # Detect and activate available volume groups - /sbin/lvm vgscan - /sbin/lvm vgchange -a y --sysinit - return $? + if [ ${slumber} -gt 0 ]; then + log_end_msg 0 + else + log_end_msg 1 || true + fi + fi + # make sure the return value is true if the device exists, + # false otherwise + [ -e "$1" ] } setup_mapping() @@ -199,49 +225,9 @@ modprobe -q dm_crypt # Make sure the cryptsource device is available - if [ ! -e $cryptsource ]; then - activate_vg - fi - - # If the encrypted source device hasn't shown up yet, give it a - # little while to deal with removable devices - - # the following lines below have been taken from - # /usr/share/initramfs-tools/scripts/local, as suggested per - # https://launchpad.net/bugs/164044 - if [ ! -e "$cryptsource" ]; then - log_begin_msg "Waiting for encrypted source device..." - - # Default delay is 180s - if [ -z "${ROOTDELAY}" ]; then - slumber=180 - else - slumber=${ROOTDELAY} - fi - - slumber=$(( ${slumber} * 10 )) - while [ ! -e "$cryptsource" ]; do - # retry for LVM devices every 10 seconds - if [ ${slumber} -eq $(( ${slumber}/100*100 )) ]; then - activate_vg - fi - - /bin/sleep 0.1 - slumber=$(( ${slumber} - 1 )) - [ ${slumber} -gt 0 ] || break - done - - if [ ${slumber} -gt 0 ]; then - log_end_msg 0 - else - log_end_msg 1 || true - fi - fi - udev_settle - - # We've given up, but we'll let the user fix matters if they can - if [ ! -e "${cryptsource}" ]; then - + if ! wait_for "$cryptsource" "encrypted source device"; then + # We've given up, but we'll let the user fix matters + # if they can echo " ALERT! ${cryptsource} does not exist." echo " Check cryptopts=source= bootarg: cat /proc/cmdline" echo " or missing modules, devices: cat /proc/modules; ls /dev" @@ -271,93 +257,82 @@ cryptremove="/sbin/cryptsetup remove $crypttarget" NEWROOT="/dev/mapper/$crypttarget" + if [ -z "$cryptkeyscript" ]; then + if [ ${cryptsource#/dev/disk/by-uuid/} != $cryptsource ]; then + # UUIDs are not very helpful + diskname="$crypttarget" + else + diskname="$cryptsource ($crypttarget)" + fi + + if [ -x /bin/plymouth ] && plymouth --ping; then + cryptkeyscript="plymouth ask-for-password --prompt" + # Plymouth will add a : if it is a non-graphical prompt + cryptkey="Please unlock disk $diskname" + else + cryptkeyscript="/lib/cryptsetup/askpass" + cryptkey="Please unlock disk $diskname: " + fi + fi + # Try to get a satisfactory password $crypttries times count=0 - while [ $crypttries -le 0 ] || [ $count -lt $crypttries ]; do + export CRYPTTAB_TRIED="$count" + while [ ! -e "$NEWROOT" ]; do export CRYPTTAB_TRIED="$count" + if [ $crypttries -gt 0 ] && [ $count -ge $crypttries ]; then + message "cryptsetup: maximum number of tries exceeded for $crypttarget" + return 1 + fi count=$(( $count + 1 )) - if [ -z "$cryptkeyscript" ]; then - if [ ${cryptsource#/dev/disk/by-uuid/} != $cryptsource ]; then - # UUIDs are not very helpful - diskname="$crypttarget" - else - diskname="$cryptsource ($crypttarget)" - fi - - if [ -x /bin/plymouth ] && plymouth --ping; then - cryptkeyscript="plymouth ask-for-password --prompt" - # Plymouth will add a : if it is a non-graphical prompt - cryptkey="Please unlock disk $diskname" - else - cryptkeyscript="/lib/cryptsetup/askpass" - cryptkey="Please unlock disk $diskname: " - fi - fi + crypttarget="$crypttarget" cryptsource="$cryptsource" \ + $cryptkeyscript "$cryptkey" | $cryptopen && break + message "cryptsetup: cryptsetup failed, bad password or options?" + done + if ! wait_for "$NEWROOT" "unlocked device"; then + message "cryptsetup: unknown error setting up device mapping" + return 1 + fi - if [ ! -e "$NEWROOT" ]; then - if ! crypttarget="$crypttarget" cryptsource="$cryptsource" \ - $cryptkeyscript "$cryptkey" | $cryptopen; then - message "cryptsetup: cryptsetup failed, bad password or options?" - continue - fi - fi + FSTYPE="$(/sbin/blkid -s TYPE -o value "$NEWROOT")" - if [ ! -e "$NEWROOT" ]; then - message "cryptsetup: unknown error setting up device mapping" + # See if we need to setup lvm on the crypto device + if [ "$FSTYPE" = "LVM_member" ] || [ "$FSTYPE" = "LVM2_member" ]; then + if [ -z "$cryptlvm" ]; then + message "cryptsetup: lvm fs found but no lvm configured" return 1 fi - #FSTYPE='' - #eval $(fstype < "$NEWROOT") - FSTYPE="$(/sbin/blkid -s TYPE -o value "$NEWROOT")" - - # See if we need to setup lvm on the crypto device - #if [ "$FSTYPE" = "lvm" ] || [ "$FSTYPE" = "lvm2" ]; then - if [ "$FSTYPE" = "LVM_member" ] || [ "$FSTYPE" = "LVM2_member" ]; then - if [ -z "$cryptlvm" ]; then - message "cryptsetup: lvm fs found but no lvm configured" - return 1 - elif ! activate_vg; then - # disable error message, LP: #151532 - #message "cryptsetup: failed to setup lvm device" - return 1 - fi - - # Apparently ROOT is already set in /conf/param.conf for - # flashed kernels at least. See bugreport #759720. - if [ -f /conf/param.conf ] && grep -q "^ROOT=" /conf/param.conf; then - NEWROOT=$(sed -n 's/^ROOT=//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 + # Apparently ROOT is already set in /conf/param.conf for + # flashed kernels at least. See bugreport #759720. + if [ -f /conf/param.conf ] && grep -q "^ROOT=" /conf/param.conf; then + NEWROOT=$(sed -n 's/^ROOT=//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 - #eval $(fstype < "$NEWROOT") - FSTYPE="$(/sbin/blkid -s TYPE -o value "$NEWROOT")" fi - #if [ -z "$FSTYPE" ] || [ "$FSTYPE" = "unknown" ]; then - if [ -z "$FSTYPE" ]; then - message "cryptsetup: unknown fstype, bad password or options?" - udev_settle + if ! wait_for "$NEWROOT" "LVM logical volume"; then + message "cryptsetup: unknown error setting up LVM logical volume" $cryptremove - continue + return 1 fi - message "cryptsetup: $crypttarget set up successfully" - break - done + FSTYPE="$(/sbin/blkid -s TYPE -o value "$NEWROOT")" + fi - if [ $crypttries -gt 0 ] && [ $count -gt $crypttries ]; then - message "cryptsetup: maximum number of tries exceeded for $crypttarget" + if [ -z "$FSTYPE" ]; then + message "cryptsetup: unknown fstype, bad password or options?" + $cryptremove return 1 fi - udev_settle + message "cryptsetup: $crypttarget set up successfully" return 0 }