Received: from mail.cmpwn.com (mail.cmpwn.com [45.56.77.53]) by nld3-dev1.alpinelinux.org (Postfix) with ESMTPS id AAAC7782CB5 for <~alpine/devel@lists.alpinelinux.org>; Sat, 18 Jan 2020 15:32:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=cmpwn.com; s=cmpwn; t=1579361577; bh=4OnnAxxu4840sXUD03IKGrAwaTFZBcqQ64ofdN5FH1w=; h=From:To:Cc:Subject:Date; b=bO974LUOZA63yyXF+ZG/VtnD0bGfUwjAMr+RudJ8sLphWiH8M4Irj2c6Aog2y2DdL EbhNQewcAnRLOSaKsj4cumb7eaA1/Deoj2jig9JEBm4cG+14i9YJ9lNkkE/gvD8BmD lQrGBK3JgXZH9el/lecHLqQuiX7Czkt2YuZXRTZ8= From: Drew DeVault To: ~alpine/devel@lists.alpinelinux.org, ncopa@alpinelinux.org Cc: Drew DeVault Subject: [RFC PATCH v4] Support encrypted root in setup-disk Date: Sat, 18 Jan 2020 10:32:55 -0500 Message-Id: <20200118153255.34070-1-sir@cmpwn.com> X-Mailer: git-send-email 2.25.0 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit --- This is untested, but I wanted to check with Nathaniel to see if this patch is closer to what he was thinking about on IRC yesterday. setup-disk.in | 103 +++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 80 insertions(+), 23 deletions(-) diff --git a/setup-disk.in b/setup-disk.in index 5eb8638..6e022d9 100644 --- a/setup-disk.in +++ b/setup-disk.in @@ -79,6 +79,26 @@ enumerate_fstab() { done } +# given an fstab on stdin, determine if any of the mountpoints are encrypted +crypt_required() { + while read devname mountpoint fstype mntops freq passno; do + if [ -z "$devname" ] || [ "${devname###}" != "$devname" ]; then + continue + fi + uuid="${devname##UUID=}" + if [ "$uuid" != "$devname" ]; then + devname="$(blkid --uuid "$uuid")" + fi + mapname="${devname##/dev/mapper/}" + if [ "$mapname" != "$devname" ]; then + if cryptsetup status "$mapname" >&1 >/dev/null; then + return 0 + fi + fi + done + return 1 +} + is_vmware() { grep -q VMware /proc/scsi/scsi 2>/dev/null \ || grep -q VMware /proc/ide/hd*/model 2>/dev/null @@ -343,7 +363,7 @@ setup_syslinux() { install_mounted_root() { local mnt="$1" shift 1 - local disks="${@}" mnt_boot= boot_fs= root_fs= + local disks="${@}" mnt_boot= boot_fs= root_fs= use_crypt= local initfs_features="ata base ide scsi usb virtio" local pvs= dev= rootdev= bootdev= extlinux_raidopt= root= modules= local kernel_opts="quiet" @@ -402,7 +422,6 @@ install_mounted_root() { esac done - if [ -n "$VERBOSE" ]; then echo "Root device: $rootdev" echo "Root filesystem: $root_fs" @@ -425,6 +444,28 @@ install_mounted_root() { # we should not try start modloop on sys install rm -f "$mnt"/etc/runlevels/*/modloop + # generate the fstab + if [ -f "$mnt"/etc/fstab ]; then + mv "$mnt"/etc/fstab "$mnt"/etc/fstab.old + fi + enumerate_fstab "$mnt" >> "$mnt"/etc/fstab + if [ -n "$SWAP_DEVICES" ]; then + local swap_dev + for swap_dev in $SWAP_DEVICES; do + echo -e "$(uuid_or_device ${swap_dev})\tswap\tswap\tdefaults\t0 0" \ + >> "$mnt"/etc/fstab + done + fi + cat >>"$mnt"/etc/fstab <<-__EOF__ + /dev/cdrom /media/cdrom iso9660 noauto,ro 0 0 + /dev/usbdisk /media/usb vfat noauto 0 0 + __EOF__ + + if crypt_required <"$mnt"/etc/fstab; then + use_crypt=1 + initfs_features="${initfs_features% cryptsetup} cryptsetup" + fi + # generate mkinitfs.conf mkdir -p "$mnt"/etc/mkinitfs/features.d echo "features=\"$initfs_features\"" > "$mnt"/etc/mkinitfs/mkinitfs.conf @@ -442,24 +483,14 @@ install_mounted_root() { if [ -n "$(get_bootopt nomodeset)" ]; then kernel_opts="nomodeset $kernel_opts" fi + if [ "$use_crypt" ] && cryptsetup status "$rootdev" 2>&1 >/dev/null; then + # Boot to encrypted root + root=$(cryptsetup status "$rootdev" | awk '/device:/ { print $2 }') + kernel_opts="cryptroot=$root cryptdm=root" + root=/dev/mapper/root + fi modules="sd-mod,usb-storage,${root_fs}${raidmod}" - # generate the fstab - if [ -f "$mnt"/etc/fstab ]; then - mv "$mnt"/etc/fstab "$mnt"/etc/fstab.old - fi - enumerate_fstab "$mnt" >> "$mnt"/etc/fstab - if [ -n "$SWAP_DEVICES" ]; then - local swap_dev - for swap_dev in $SWAP_DEVICES; do - echo -e "$(uuid_or_device ${swap_dev})\tswap\tswap\tdefaults\t0 0" \ - >> "$mnt"/etc/fstab - done - fi - cat >>"$mnt"/etc/fstab <<-__EOF__ - /dev/cdrom /media/cdrom iso9660 noauto,ro 0 0 - /dev/usbdisk /media/usb vfat noauto 0 0 - __EOF__ # remove the installed db in case its there so we force re-install rm -f "$mnt"/var/lib/apk/installed "$mnt"/lib/apk/db/installed echo "Installing system on $rootdev:" @@ -503,6 +534,10 @@ unmount_partitions() { # unmount the partitions umount $(awk '{print $2}' /proc/mounts | egrep "^$mnt(/|\$)" | sort -r) + + if [ "$USE_CRYPT" ]; then + cryptsetup close /dev/mapper/root + fi } # figure out decent default swap size in mega bytes @@ -994,6 +1029,18 @@ native_disk_install_lvm() { setup_root $root_dev $BOOT_DEV } +setup_crypt() { + mkdir -p /run/cryptsetup + echo "Preparing root partition for encryption." >&2 + echo "You will be prompted for your password at boot." >&2 + echo "If you forget your password, your data will be lost." >&2 + cryptsetup luksFormat --type luks2 "$1" >&2 + echo "Enter password again to unlock disk for installation." >&2 + cryptsetup open "$1" root >&2 + cryptroot="$1" + echo "/dev/mapper/root" +} + native_disk_install() { local prep_part_type=$(partition_id prep) local root_part_type=$(partition_id linux) @@ -1065,6 +1112,10 @@ native_disk_install() { root_dev=$(find_nth_non_boot_parts $index "$root_part_type" $@) fi + if [ "$USE_CRYPT" ]; then + root_dev=$(setup_crypt $root_dev) + fi + [ $SWAP_SIZE -gt 0 ] && setup_swap_dev $swap_dev setup_root $root_dev $BOOT_DEV $@ } @@ -1143,7 +1194,7 @@ ask_disk() { usage() { cat <<-__EOF__ - usage: setup-disk [-hLqrv] [-k kernelflavor] [-m MODE] [-o apkovl] [-s SWAPSIZE] + usage: setup-disk [-hLqrve] [-k kernelflavor] [-m MODE] [-o apkovl] [-s SWAPSIZE] [MOUNTPOINT | DISKDEV...] Install alpine on harddisk. @@ -1157,6 +1208,7 @@ usage() { options: -h Show this help + -e Encrypt disk -m Use disk for MODE without asking, where MODE is either 'data' or 'sys' -o Restore system from given apkovl file -k Use kernelflavor instead of $KERNEL_FLAVOR @@ -1193,11 +1245,13 @@ case $kver in *) KERNEL_FLAVOR=vanilla;; esac +USE_CRYPT= DISK_MODE= USE_LVM= # Parse args -while getopts "hk:Lm:o:qrs:v" opt; do +while getopts "hek:Lm:o:qrs:v" opt; do case $opt in + e) USE_CRYPT=1;; m) DISK_MODE="$OPTARG";; k) KERNEL_FLAVOR="$OPTARG";; L) USE_LVM="_lvm";; @@ -1275,17 +1329,20 @@ if [ -n "$diskdevs" ] && [ -z "$DISK_MODE" ]; then echo "The following $disk_is_or_disks_are selected${USE_LVM:+ (with LVM)}:" show_disk_info $diskdevs _lvm=${USE_LVM:-", 'lvm'"} - echon "How would you like to use $it_them? ('sys', 'data'${_lvm#_lvm} or '?' for help) [?] " + echon "How would you like to use $it_them? ('sys', 'cryptsys', 'data'${_lvm#_lvm} or '?' for help) [?] " default_read answer '?' case "$answer" in '?') diskmode_help;; - sys|data) break;; + cryptsys) + answer=sys + USE_CRYPT=1 + ;; + sys|data) ;; lvm) USE_LVM="_lvm" ;; nolvm) USE_LVM="";; lvmsys|lvmdata) answer=${answer#lvm} USE_LVM="_lvm" - break ;; esac done -- 2.25.0