diff -Nru cryptsetup-2.3.3/debian/changelog cryptsetup-2.3.3/debian/changelog --- cryptsetup-2.3.3/debian/changelog 2020-09-09 09:29:17.000000000 -0300 +++ cryptsetup-2.3.3/debian/changelog 2020-09-16 17:35:59.000000000 -0300 @@ -1,3 +1,17 @@ +cryptsetup (2:2.3.3-1ubuntu6) groovy; urgency=medium + + * d/initramfs/cryptroot-script: Re-execute cryptroot local-block script. + (LP: #1879980) + Currently, if an encrypted rootfs is configured on top of a MD RAID1 + array and such array gets degraded (like a member is removed/failed), + cryptsetup scripts cannot mount the rootfs and the boot fails. We fix + that issue here by allowing cryptroot script to re-run on initramfs + local-block stage, given that mdadm is able to activate a degraded + array in that point. There is an initramfs-tools counter-part for this + fix, but alone the cryptsetup portion is harmless. + + -- Guilherme G. Piccoli Wed, 16 Sep 2020 17:35:59 -0300 + cryptsetup (2:2.3.3-1ubuntu5) groovy; urgency=medium * SECURITY UPDATE: Out-of-bounds write diff -Nru cryptsetup-2.3.3/debian/cryptsetup-initramfs.install cryptsetup-2.3.3/debian/cryptsetup-initramfs.install --- cryptsetup-2.3.3/debian/cryptsetup-initramfs.install 2020-06-04 00:14:44.000000000 -0300 +++ cryptsetup-2.3.3/debian/cryptsetup-initramfs.install 2020-09-16 17:35:54.000000000 -0300 @@ -5,5 +5,6 @@ debian/initramfs/scripts/local-block/cryptroot /usr/share/initramfs-tools/scripts/local-block/ debian/initramfs/scripts/local-bottom/cryptgnupg-sc /usr/share/initramfs-tools/scripts/local-bottom/ debian/initramfs/scripts/local-bottom/cryptopensc /usr/share/initramfs-tools/scripts/local-bottom/ +debian/initramfs/scripts/local-bottom/cryptroot /usr/share/initramfs-tools/scripts/local-bottom/ debian/initramfs/scripts/local-top/cryptopensc /usr/share/initramfs-tools/scripts/local-top/ debian/initramfs/scripts/local-top/cryptroot /usr/share/initramfs-tools/scripts/local-top/ diff -Nru cryptsetup-2.3.3/debian/functions cryptsetup-2.3.3/debian/functions --- cryptsetup-2.3.3/debian/functions 2020-06-18 05:12:10.000000000 -0300 +++ cryptsetup-2.3.3/debian/functions 2020-09-16 17:35:54.000000000 -0300 @@ -9,6 +9,8 @@ TABFILE="${TABFILE-/etc/crypttab}" fi export DM_DEFAULT_NAME_MANGLING_MODE=hex # for dmsetup(8) +export CRYPTR_LOCAL_BLOCK="/run/cryptroot.local-block" +export CRYPTR_CNT_FILE="/run/cryptroot.initrd.cnt" # Logging helpers. Send the argument list to plymouth(1), or fold it # and print it to the standard error. diff -Nru cryptsetup-2.3.3/debian/initramfs/scripts/local-block/cryptroot cryptsetup-2.3.3/debian/initramfs/scripts/local-block/cryptroot --- cryptsetup-2.3.3/debian/initramfs/scripts/local-block/cryptroot 2020-06-04 00:14:44.000000000 -0300 +++ cryptsetup-2.3.3/debian/initramfs/scripts/local-block/cryptroot 2020-09-16 17:35:54.000000000 -0300 @@ -15,6 +15,10 @@ ;; esac +[ -f /lib/cryptsetup/functions ] || return 0 +. /lib/cryptsetup/functions + if [ -x /scripts/local-top/cryptroot ]; then + touch ${CRYPTR_LOCAL_BLOCK} exec /scripts/local-top/cryptroot fi diff -Nru cryptsetup-2.3.3/debian/initramfs/scripts/local-bottom/cryptroot cryptsetup-2.3.3/debian/initramfs/scripts/local-bottom/cryptroot --- cryptsetup-2.3.3/debian/initramfs/scripts/local-bottom/cryptroot 1969-12-31 21:00:00.000000000 -0300 +++ cryptsetup-2.3.3/debian/initramfs/scripts/local-bottom/cryptroot 2020-09-16 17:35:54.000000000 -0300 @@ -0,0 +1,23 @@ +#!/bin/sh +set +x +PREREQ="" + +prereqs() +{ + echo "$PREREQ" +} + +case $1 in +prereqs) + prereqs + exit 0 + ;; +esac + +# If we reached this stage, we do have a rootfs mounted +# so let's clean-up cryptroot setup mess... +[ -f /lib/cryptsetup/functions ] || return 0 +. /lib/cryptsetup/functions + +rm -f ${CRYPTR_LOCAL_BLOCK} +rm -f ${CRYPTR_CNT_FILE} diff -Nru cryptsetup-2.3.3/debian/initramfs/scripts/local-top/cryptroot cryptsetup-2.3.3/debian/initramfs/scripts/local-top/cryptroot --- cryptsetup-2.3.3/debian/initramfs/scripts/local-top/cryptroot 2020-06-04 00:14:44.000000000 -0300 +++ cryptsetup-2.3.3/debian/initramfs/scripts/local-top/cryptroot 2020-09-16 17:35:54.000000000 -0300 @@ -31,8 +31,8 @@ # wait_for_source() -# Wait for encrypted $CRYPTTAB_SOURCE for up to 180s. Set -# $CRYPTTAB_SOURCE to its normalized device name when it shows up; +# Wait for encrypted $CRYPTTAB_SOURCE . Set $CRYPTTAB_SOURCE +# to its normalized device name when it shows up; # return 1 if timeout. wait_for_source() { wait_for_udev 10 @@ -42,17 +42,27 @@ return 0 fi - # The lines below has been taken from - # /usr/share/initramfs-tools/scripts/local's local_device_setup(), - # as suggested per https://launchpad.net/bugs/164044 - # If the source device hasn't shown up yet, give it a little while # to allow for asynchronous device discovery (e.g. USB). + # + # We also need to take into account RAID or other devices that may + # only be available on local-block stage. So, wait 5 seconds upfront, + # in local-top; if that fails, end execution relying on local-block + # invocations. Allow $ROOTDELAY/3 invocations with 1s sleep times (with + # a minimum of 30 invocations), and if after that we still fail, then it's + # really time to give-up. Variable $initrd_cnt tracks the re-invocations. + # + # Part of the lines below has been taken from initramfs-tools + # scripts/local's local_device_setup(), as suggested per + # https://launchpad.net/bugs/164044 . + + local slumber=1 + if [ ! -f "${CRYPTR_LOCAL_BLOCK}" ]; then # we are running on local-top + slumber=5 + fi cryptsetup_message "Waiting for encrypted source device $CRYPTTAB_SOURCE..." - # Default delay is 180s, cf. initramfs-tools(8) - local slumber="${ROOTDELAY:-180}" while [ $slumber -gt 0 ]; do sleep 1 @@ -75,7 +85,23 @@ # Set up a crypttab(5) mapping defined by $CRYPTTAB_NAME, # $CRYPTTAB_SOURCE, $CRYPTTAB_KEY, $CRYPTTAB_OPTIONS. setup_mapping() { - local dev + local dev initrd_cnt + + # We control here the number of re-invocations of this script from + # local-block - the heuristic is $ROOTDELAY/3, with a minimum of 30. + # This number is somewhat dictated by mdadm, we want to run more times + # than that script, to allow decrypting volumes on top of arrays. + + if [ -f "${CRYPTR_CNT_FILE}" ]; then + initrd_cnt=$(cat ${CRYPTR_CNT_FILE}) + else + initrd_cnt=${ROOTDELAY:-90} + initrd_cnt=$((initrd_cnt/3)) + if [ "${initrd_cnt}" -lt 30 ]; then + initrd_cnt=30 + fi + echo ${initrd_cnt} > "${CRYPTR_CNT_FILE}" + fi # The same target can be specified multiple times # e.g. root and resume lvs-on-lvm-on-crypto @@ -86,17 +112,23 @@ crypttab_parse_options --export --missing-path=fail || return 1 if ! wait_for_source; then - # we've given up - if [ -n "$panic" ]; then - panic "ALERT! encrypted source device $CRYPTTAB_SOURCE does not exist, can't unlock $CRYPTTAB_NAME." - else - # let the user fix matters if they can - echo " ALERT! encrypted source device $CRYPTTAB_SOURCE does not exist, can't unlock $CRYPTTAB_NAME." - echo " Check cryptopts=source= bootarg: cat /proc/cmdline" - echo " or missing modules, devices: cat /proc/modules; ls /dev" - panic "Dropping to a shell." - fi - return 1 # can't continue because environment is lost + if [ ${initrd_cnt} -le 0 ]; then + # we've given up + if [ -n "$panic" ]; then + panic "ALERT! encrypted source device $CRYPTTAB_SOURCE does not exist, can't unlock $CRYPTTAB_NAME." + else + # let the user fix matters if they can + echo " ALERT! encrypted source device $CRYPTTAB_SOURCE does not exist, can't unlock $CRYPTTAB_NAME." + echo " Check cryptopts=source= bootarg: cat /proc/cmdline" + echo " or missing modules, devices: cat /proc/modules; ls /dev" + panic "Dropping to a shell." + fi + return 1 # can't continue because environment is lost + else + initrd_cnt=$((initrd_cnt - 1)) + echo ${initrd_cnt} > "${CRYPTR_CNT_FILE}" + return 0 # allow some attempts on local-block stage + fi fi # our `cryptroot-unlock` script searches for cryptsetup processes @@ -169,6 +201,10 @@ done cryptsetup_message "ERROR: $CRYPTTAB_NAME: maximum number of tries exceeded" + + if [ -f "${CRYPTR_CNT_FILE}" ]; then + echo 0 > "${CRYPTR_CNT_FILE}" + fi exit 1 }