[arch-projects] [RFC initscripts 24/29] Replace cryptsetup with cryptmount wrapper

Matthew Monaco dgbaley27 at 0x01b.net
Fri May 18 12:22:18 EDT 2012


From: Matthew Monaco <matthew.monaco at 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



More information about the arch-projects mailing list