From: Matthew Monaco <matthew.monaco@0x01b.net> Cryptmount provides a lot of the work that is duplicate in the mkinitcpio encrypt hook and initscripts. Use it to map all volumes from crypttab that don't have "noauto" and which aren't already mounted. Also, use it to unmap volumes in crypttab that aren't already mounted and aren't / or /usr. --- PKGBUILD | 2 +- functions | 94 ----------------------------------------------------------- rc.shutdown | 53 +++++++++++++++++++++++---------- rc.sysinit | 37 ++++++++++++++++++----- 4 files changed, 68 insertions(+), 118 deletions(-) diff --git a/PKGBUILD b/PKGBUILD index 3130e5e..36c85b0 100644 --- a/PKGBUILD +++ b/PKGBUILD @@ -10,7 +10,7 @@ conflicts=('initscripts') provides=('initscripts=9999') backup=(etc/inittab etc/rc.conf etc/rc.local etc/rc.local.shutdown) makedepends=('asciidoc') -depends=('glibc' 'bash' 'grep' 'coreutils' 'udev>=182' 'iproute2' +depends=('glibc' 'bash' 'grep' 'coreutils' 'cryptmount' 'udev>=182' 'iproute2' 'ncurses' 'kbd' 'findutils' 'sysvinit') optdepends=('net-tools: legacy networking support' 'bridge-utils: Network bridging support' diff --git a/functions b/functions index 7516345..fd20349 100644 --- a/functions +++ b/functions @@ -377,100 +377,6 @@ activate_vgs() { (( $? == 0 )) && stat_done || stat_fail } -do_unlock() { - # $1 = requested name - # $2 = source device - # $3 = password - # $4 = options - stat_append "${1}.." - local open=create a=$1 b=$2 failed=0 - # Ordering of options is different if you are using LUKS vs. not. - # Use ugly swizzling to deal with it. - # isLuks only gives an exit code but no output to stdout or stderr. - if cryptsetup isLuks "$2" 2>/dev/null; then - open=luksOpen - a=$2 - b=$1 - fi - case $3 in - SWAP) - local _overwriteokay=0 - if [[ -b $2 && -r $2 ]]; then - # This is DANGEROUS! If there is any known file system, - # partition table, RAID or LVM volume on the device - # we don't overwrite it. - # - # 'blkid' returns 2 if no valid signature has been found. - # Only in this case we should allow overwriting the device. - # - # This sanity check _should_ be sufficient, but it might not. - # This may cause dataloss if it is not used carefully. - blkid -p "$2" &>/dev/null - (( $? == 2 )) && _overwriteokay=1 - fi - if (( _overwriteokay == 0 )); then - false - elif cryptsetup -d /dev/urandom $4 $open "$a" "$b" >/dev/null; then - stat_append "creating swapspace.." - mkswap -f -L $1 /dev/mapper/$1 >/dev/null - fi;; - ASK) - printf "\nOpening '$1' volume:\n" - cryptsetup $4 $open "$a" "$b" < /dev/console;; - /dev*) - local ckdev=${3%%:*} - local cka=${3#*:} - local ckb=${cka#*:} - local cka=${cka%:*} - local ckfile=/dev/ckfile - local ckdir=/dev/ckdir - case ${cka} in - *[!0-9]*) - # Use a file on the device - # cka is not numeric: cka=filesystem, ckb=path - mkdir ${ckdir} - mount -r -t ${cka} ${ckdev} ${ckdir} - dd if=${ckdir}/${ckb} of=${ckfile} >/dev/null 2>&1 - umount ${ckdir} - rmdir ${ckdir};; - *) - # Read raw data from the block device - # cka is numeric: cka=offset, ckb=length - dd if=${ckdev} of=${ckfile} bs=1 skip=${cka} count=${ckb} >/dev/null 2>&1;; - esac - cryptsetup -d ${ckfile} $4 $open "$a" "$b" >/dev/null - dd if=/dev/urandom of=${ckfile} bs=1 count=$(stat -c %s ${ckfile}) conv=notrunc >/dev/null 2>&1 - rm ${ckfile};; - /*) - cryptsetup -d "$3" $4 $open "$a" "$b" >/dev/null;; - *) - printf "${C_FAIL}crypttab contains a literal encryption key. This will stop working in the future.${C_OTHER}\n" - echo "$3" | cryptsetup $4 $open "$a" "$b" >/dev/null;; - esac - if (( $? )); then - failed=1 - stat_append "failed " - else - stat_append "ok " - fi - return $failed -} - -read_crypttab() { - # $1 = function to call with the split out line from the crypttab - local line nspo failed=0 - while read line; do - [[ $line && $line != '#'* ]] || continue - eval nspo=("${line%#*}") - if $1 "${nspo[0]}" "${nspo[1]}" "${nspo[2]}" "${nspo[*]:3}"; then - crypto_unlocked=1 - else - failed=1 - fi - done < /etc/crypttab - return $failed -} - set_timezone() { local tz=$1 zonefile=/usr/share/zoneinfo/$1 diff --git a/rc.shutdown b/rc.shutdown index ec30d56..292de7e 100755 --- a/rc.shutdown +++ b/rc.shutdown @@ -64,23 +64,44 @@ status "Unmounting Non-API Filesystems" umount_all run_hook shutdown_postumount -# Kill non-root encrypted partition mappings -if [[ -f /etc/crypttab ]] && type -p cryptsetup >/dev/null; then +deactivate_cryptos() { + local vol vols mntpnt fail=0 i=0 + + [[ -f "/etc/crypttab" ]] || return + type -p cryptmount >/dev/null || return + mapfile -t vols < <(cryptmount -Lq "$@") + + for ((i = 0; i < ${#vols[@]}; i++)); do + if [[ ! -e "/dev/mapper/${vols[$i]}" ]]; then + unset vols[$i] + elif mntpnt="$(findmnt -S "/dev/mapper/${vols[$i]}" -noTARGET)" && \ + [[ "$mntpnt" = "/" || "$mntpnt" = "/usr" ]]; then + unset vols[$i] + fi + done + + (( ${#vols[@]} )) || return + stat_busy "Deactivating encrypted volumes:" - # Maybe someone has LVM on an encrypted block device - # executing an extra vgchange is errorless - [[ $USELVM = [Yy][Ee][Ss] ]] && vgchange --sysinit -a n &>/dev/null - do_lock() { - stat_append "${1}.." - if cryptsetup remove "$1" &>/dev/null; then - stat_append "ok " - else - stat_append "failed " - fi - } - read_crypttab do_lock - stat_done -fi + + # Maybe someone has LVM on an encrypted block device + # executing an extra vgchange is errorless + [[ $USELVM = [Yy][Ee][Ss] ]] && vgchange --sysinit -a n &>/dev/null + + for vol in ${vols[@]}; do + if cryptmount -Uq "$vol"; then + stat_append "$C_DONE $vol$C_MAIN" + else + stat_append "$C_FAIL $vol$C_MAIN" + fail=1 + fi + done + + (( fail )) && stat_fail || stat_done +} + +# Kill any mapped volumes in crypttab (exclude / and /usr) +deactivate_cryptos [[ $USELVM = [Yy][Ee][Ss] && -x $(type -P lvm) && -d /sys/block ]] && status "Deactivating LVM2 groups" vgchange --sysinit -a n &>/dev/null diff --git a/rc.sysinit b/rc.sysinit index f91190c..c2de464 100755 --- a/rc.sysinit +++ b/rc.sysinit @@ -123,14 +123,37 @@ udevd_modprobe sysinit # Activate LVM2 groups if any activate_vgs -# Set up non-root encrypted partition mappings -if [[ -f /etc/crypttab ]] && type -p cryptsetup >/dev/null; then +activate_cryptos() { + local vol vols fail=0 unlocked=0 i=0 + + [[ -f "/etc/crypttab" ]] || return + type -p cryptmount >/dev/null || return + mapfile -t vols < <(cryptmount -Lq "$@") + + for ((i = 0; i < ${#vols[@]}; i++)); do + [[ ! -e "/dev/mapper/${vols[$i]}" ]] || unset vols[$i] + done + + (( ${#vols[@]} )) || return + stat_busy "Unlocking encrypted volumes:" - crypto_unlocked=0 - read_crypttab do_unlock && stat_done || stat_fail - # Maybe someone has LVM on an encrypted block device - (( crypto_unlocked )) && activate_vgs -fi + + for vol in ${vols[@]}; do + if cryptmount -Mq "$vol"; then + stat_append "$C_DONE $vol$C_MAIN" + unlocked=1 + else + stat_append "$C_FAIL $vol$C_MAIN" + fail=1 + fi + done + + (( fail )) && stat_fail || stat_done + (( unlocked )) && activate_vgs +} + +# Map any unmapped encrypted volumes in crypttab +activate_cryptos # Check filesystems run_hook sysinit_prefsck -- 1.7.10.2