Bug#451535: Bug#529343: debian-installer: physical volume for encryption: doesnt care if already encrypted and kills data
On Wed, Sep 07, 2011 at 03:59:16PM +0100, Colin Watson wrote:
> Here's a first pass at this. What do people think?
I meant to send my previous version to the first of the merged bug set,
#451535. I'll send further mails only there rather than to #529343 as
well.
> The one thing I don't think I've got right yet is writing out
> /etc/crypttab at the end of installation. This needs a bit more work to
> write out the correct files in the partman device directory without
> causing partman to reinitialise the encrypted volume.
Well. Yes. That turned out to be the second 90% of the work! After
trying a few alternatives, I ended up with a new 'crypto_keep' method
and then tried to let init.d/crypto do as much of the work as possible,
while still being careful to avoid reinitialising the contents of
encrypted volumes.
In the process, I also decided that it was better to always have the
Activate option present, without trying to detect existing volumes
first. That way, we can actively warn people that this method only
works with LUKS where we have a useful encrypted volume header and that
they should back up their data before attempting an installation, rather
than having them get confused into destroying their data as before.
I'm fairly happy with this now, and am inclined to commit it if there
are no objections. The one problem I've found is that the check for an
unencrypted /boot doesn't work properly when activating existing
LVM-on-crypto volumes, but I think that's actually a pre-existing bug so
I'm not going to let that block this change.
* Add an "Activate existing encrypted volumes" option to the
partman-crypto main menu. If selected, this searches for existing
volumes, and for each one prompts for its passphrase and attempts to
open it; it then returns directly to the partitioning menu (closes:
#451535, LP: #420080).
=== modified file 'check.d/crypto_check_mountpoints'
--- check.d/crypto_check_mountpoints 2008-03-14 19:25:59 +0000
+++ check.d/crypto_check_mountpoints 2011-09-08 19:20:22 +0000
@@ -43,7 +43,7 @@ for dev in $DEVICES/*; do
[ -f $realdevdir/method ] || continue
method=$(cat $realdevdir/method)
type=$(cat $realdevdir/crypto_type)
- [ $method = crypto ] || continue
+ [ $method = crypto ] || [ $method = crypto_keep ] || continue
# Check 1 - Is cryptoroot possible?
if [ "$mnt" = / ]; then
=== modified file 'choose_partition/crypto/do_option'
--- choose_partition/crypto/do_option 2009-11-10 14:20:25 +0000
+++ choose_partition/crypto/do_option 2011-09-09 11:30:35 +0000
@@ -12,6 +12,118 @@
. /lib/partman/lib/crypto-base.sh
+get_passphrase () {
+ db_set partman-crypto/activate/passphrase-existing ""
+ db_fset partman-crypto/activate/passphrase-existing seen false
+ db_subst partman-crypto/activate/passphrase-existing DEVICE "$1"
+ db_input critical partman-crypto/activate/passphrase-existing
+
+ db_go || return 1
+
+ db_get partman-crypto/activate/passphrase-existing || RET=''
+ echo -n "$RET"
+}
+
+do_cryptsetup () {
+ local dev num id size path
+ local dump cipher keysize ivalgorithm keytype keyhash
+ local cryptdev pass
+
+ dev=$1
+ num=$2
+ id=$3
+ size=$4
+ path=$5
+
+ dump="$(cryptsetup luksDump "$path")"
+ cipher="$(echo "$dump" | sed -n '/^Cipher name:/s/.*[[:space:]]//p')"
+ if [ "$cipher" ]; then
+ crypto_load_udebs "cdebconf-$DEBIAN_FRONTEND-entropy" \
+ partman-crypto-dm
+ crypto_check_required_tools dm-crypt
+ crypto_load_modules dm-crypt "$cipher"
+ fi
+ keysize="$(echo "$dump" | sed -n '/^MK bits:/s/.*[[:space:]]//p')"
+ ivalgorithm="$(echo "$dump" | sed -n '/^Cipher mode:/s/.*[[:space:]]//p')"
+ keytype=passphrase
+ keyhash="$(echo "$dump" | sed -n '/^Hash spec:/s/.*[[:space:]]//p')"
+
+ cryptdev="${path##*/}_crypt"
+ if ! cryptsetup status "$cryptdev" >/dev/null 2>&1; then
+ while :; do
+ pass="$(get_passphrase "$path")" || return 1
+ if [ -z "$pass" ]; then
+ return 1
+ fi
+ echo -n "$pass" | log-output -t partman-crypto \
+ cryptsetup -d - luksOpen "$path" "$cryptdev" \
+ && break
+ done
+
+ cryptdev="/dev/mapper/$cryptdev"
+ echo dm-crypt > $id/crypto_type
+ echo "$keysize" > $id/keysize
+ echo "$ivalgorithm" > $id/ivalgorithm
+ echo "$keytype" > $id/keytype
+ echo "$keyhash" > $id/keyhash
+ echo cipher > $id/cipher
+ echo crypto_keep > $id/method
+ echo "$cryptdev" > $id/crypt_active
+
+ db_subst partman-crypto/text/in_use DEV "${cryptdev##*/}"
+ db_metaget partman-crypto/text/in_use description
+ partman_lock_unit "$(mapdevfs "$path")" "$RET"
+ fi
+}
+
+do_activate () {
+ local found_luks dev partitions num id size type fs path name part
+
+ found_luks=0
+ for dev in $DEVICES/*; do
+ [ -d "$dev" ] || continue
+ cd "$dev"
+
+ partitions=
+ open_dialog PARTITIONS
+ while { read_line num id size type fs path name; [ "$id" ]; }; do
+ [ "$fs" != free ] || continue
+ partitions="$partitions $id,$path"
+ done
+ close_dialog
+
+ for part in $partitions; do
+ id="${part%%,*}"
+ path="${part#*,}"
+
+ if cryptsetup isLuks "$path" 2>/dev/null; then
+ found_luks=1
+ do_cryptsetup "$dev" "$num" "$id" "$size" \
+ "$path" || continue
+ fi
+ done
+ done
+
+ if [ "$found_luks" = 0 ]; then
+ db_input critical partman-crypto/activate/no_luks
+ db_go || true
+ return
+ fi
+
+ # Encrypted devices as configured by d-i usually contain LVM PVs
+ export LVM_SUPPRESS_FD_WARNINGS=1
+ log-output -t partman-crypto pvscan
+ log-output -t partman-crypto vgscan
+ log-output -t partman-crypto vgchange -a y
+
+ # Tell partman to detect filesystems again.
+ rm -f /var/lib/partman/filesystems_detected
+
+ stop_parted_server
+ restart_partman
+ exit 0
+}
+
do_create () {
local parts line pv output vg pathmap
parts=""
@@ -93,6 +231,7 @@ while :; do
db_go || exit 10
db_get partman-crypto/mainmenu
case $RET in
+ activate) do_activate ;; # exits if any volumes were activated
create) do_create ;;
finish) break ;;
*)
=== modified file 'debian/control'
--- debian/control 2011-05-03 16:05:09 +0000
+++ debian/control 2011-09-09 12:06:37 +0000
@@ -12,7 +12,7 @@ Vcs-Bzr: http://bazaar.launchpad.net/~ub
Package: partman-crypto
XC-Package-Type: udeb
Architecture: any
-Depends: partman-base (>= 134), cdebconf-udeb (>= 0.133), di-utils (>= 1.68), ${shlibs:Depends}, ${misc:Depends}
+Depends: partman-base (>= 134), partman-lvm (>= 62), cdebconf-udeb (>= 0.133), di-utils (>= 1.68), ${shlibs:Depends}, ${misc:Depends}
Description: Add to partman support for block device encryption
Package: partman-crypto-dm
=== modified file 'debian/partman-crypto.templates'
--- debian/partman-crypto.templates 2009-12-05 22:29:36 +0000
+++ debian/partman-crypto.templates 2011-09-08 11:16:40 +0000
@@ -430,12 +430,12 @@ _Description: Proceed to install crypto
Template: partman-crypto/mainmenu
Type: select
-Choices-C: create, finish
+Choices-C: activate, create, finish
# Note to translators : Please keep your translations of the choices
# below a 65 columns limit (which means 65 characters
# in single-byte languages)
# :sl3:
-__Choices: Create encrypted volumes, Finish
+__Choices: Activate existing encrypted volumes, Create encrypted volumes, Finish
# :sl3:
_Description: Encryption configuration actions
This menu allows you to configure encrypted volumes.
@@ -454,3 +454,20 @@ Type: error
# :sl3:
_Description: No devices selected
No devices were selected for encryption.
+
+Template: partman-crypto/activate/no_luks
+Type: error
+# :sl3:
+_Description: No LUKS devices found
+ This partitioning program can only activate existing encrypted volumes that
+ use the LUKS format (dm-crypt with a passphrase). No such volumes were
+ found. If you have encrypted volumes using other formats, you may need to
+ back up your data before continuing with installation.
+
+Template: partman-crypto/activate/passphrase-existing
+Type: password
+# :sl3:
+_Description: Passphrase for ${DEVICE}:
+ Please enter the passphrase for the encrypted volume ${DEVICE}.
+ .
+ If you don't enter anything, the volume will not be activated.
=== modified file 'finish.d/crypto_aptinstall'
--- finish.d/crypto_aptinstall 2008-03-20 21:06:33 +0000
+++ finish.d/crypto_aptinstall 2011-09-07 22:17:00 +0000
@@ -39,7 +39,7 @@ for dev in $DEVICES/*; do
[ -f $id/crypto_type ] || continue
method=$(cat $id/method)
- [ $method = crypto ] || continue
+ [ $method = crypto ] || [ $method = crypto_keep ] || continue
type=$(cat $id/crypto_type)
case $type in
=== modified file 'init.d/crypto'
--- init.d/crypto 2010-05-27 09:44:55 +0000
+++ init.d/crypto 2011-09-09 12:36:17 +0000
@@ -4,6 +4,17 @@
# setup in choose_partition/crypto/do_option.
. /lib/partman/lib/base.sh
+. /lib/partman/lib/lvm-base.sh
+
+# Avoid warnings from lvm2 tools about open file descriptors
+export LVM_SUPPRESS_FD_WARNINGS=1
+
+if [ -x /sbin/vgdisplay ]; then
+ vgroups=$(/sbin/vgdisplay 2>/dev/null | grep '^[ ]*VG Name' | \
+ sed -e 's/.*[[:space:]]\(.*\)$/\1/' | sort)
+else
+ vgroups=''
+fi
dev_to_devdir () {
echo $DEVICES/$(echo $1 | tr / =)
@@ -72,7 +83,7 @@ create_partition () {
}
create_cryptdisk () {
- local dev id num size path cryptdev cipher
+ local dev id num size path cryptdev cipher file vg vgs
dev=$1
id=$2
num=$3
@@ -81,6 +92,7 @@ create_cryptdisk () {
cipher=$(cat $id/cipher)
keytype=$(cat $id/keytype)
+ method=$(cat $id/method)
templ="partman-crypto/text/cryptdev_description"
db_subst $templ CIPHER $cipher
@@ -128,17 +140,47 @@ create_cryptdisk () {
case $filesystem in
linux-swap)
echo swap > $cryptpart/method
- >$cryptpart/format
+ if [ "$method" = crypto ]; then
+ >$cryptpart/format
+ else
+ rm -f $cryptpart/format
+ fi
;;
$default_fs)
- echo format > $cryptpart/method
- >$cryptpart/format
- >$cryptpart/use_filesystem
- echo $filesystem > $cryptpart/filesystem
+ if [ "$method" = crypto ]; then
+ echo format > $cryptpart/method
+ >$cryptpart/format
+ >$cryptpart/use_filesystem
+ echo $filesystem > $cryptpart/filesystem
+ else
+ echo keep > $cryptpart/method
+ rm -f $cryptpart/format
+ fi
;;
esac
+ # To avoid ordering problems between init.d/crypto and init.d/lvm,
+ # we need to duplicate a bit of the latter here, in case an existing
+ # crypto device contains an LVM PV.
+ if [ "$method" = crypto_keep ]; then
+ if pvdisplay "$cryptdev" >/dev/null 2>&1; then
+ for file in acting_filesystem filesystem format \
+ formatable use_filesystem; do
+ rm -f $cryptpart/$file
+ done
+ echo lvm > $cryptpart/method
+ if [ ! -e $cryptpart/locked ]; then
+ vg="$(pv_get_vg "$cryptdev")"
+ for vgs in $vgroups; do
+ if [ "$vg" = "$vgs" ]; then
+ vg_lock_pvs "$vg" "$cryptdev"
+ fi
+ done
+ fi
+ fi
+ fi
+
update_partition $cryptdir $cryptid
echo $path:$num:$dev/$id > $cryptdir/crypt_realdev
@@ -174,7 +216,7 @@ for dev in /var/lib/partman/devices/*; d
[ -f $id/crypt_active ] || continue
method=$(cat $id/method)
- [ $method = crypto ] || continue
+ [ $method = crypto ] || [ $method = crypto_keep ] || continue
if ! create_cryptdisk $dev $id $num $size $path; then
db_fset partman-crypto/init_failed seen false
=== modified file 'lib/crypto-base.sh'
--- lib/crypto-base.sh 2011-08-26 12:20:00 +0000
+++ lib/crypto-base.sh 2011-09-07 22:27:14 +0000
@@ -82,7 +82,7 @@ crypto_prepare () {
if [ "$method" = swap ]; then
disable_swap "$dev" "$id"
fi
- if [ "$method" != crypto ]; then
+ if [ "$method" != crypto ] && [ "$method" != crypto_keep ]; then
crypto_prepare_method "$id" dm-crypt || return 1
rm -f "$id/use_filesystem"
rm -f "$id/format"
@@ -820,7 +820,8 @@ crypto_check_setup() {
[ -f $id/crypto_type ] || continue
method=$(cat $id/method)
- if [ $method != crypto ]; then
+ if [ $method != crypto ] && \
+ [ $method != crypto_keep ]; then
continue
fi
type=$(cat $id/crypto_type)
=== modified file 'update.d/crypto_visuals'
--- update.d/crypto_visuals 2007-12-05 20:18:24 +0000
+++ update.d/crypto_visuals 2011-09-07 22:16:23 +0000
@@ -37,8 +37,9 @@ cryptdev_shortname ()
esac
}
-if [ $method = crypto ]; then
- db_metaget partman/method_short/$method description || RET=''
+case $method in
+ crypto|crypto_keep)
+ db_metaget partman/method_short/crypto description || RET=''
echo ${RET:-crypto} >$id/visual_filesystem
if [ -f $id/crypt_active ]; then
@@ -52,5 +53,6 @@ if [ $method = crypto ]; then
# open_dialog CHANGE_FILE_SYSTEM $id linux-swap
# close_dialog
-fi
+ ;;
+esac
--
Colin Watson [cjwatson@ubuntu.com]
Reply to: