From 590b75fd6fd1683b89aa6faca505aeb202365be9 Mon Sep 17 00:00:00 2001 From: "M.Schmidt" Date: Tue, 3 Dec 2024 21:47:11 +0100 Subject: [PATCH] improve(lvm+cryptroot extensions): enable possibility for LVM on LUKS --- extensions/fs-cryptroot-support.sh | 15 +++++++++- extensions/lvm.sh | 38 ++++++++++++-------------- lib/functions/image/loop.sh | 2 +- lib/functions/image/partitioning.sh | 31 +++++++++++---------- lib/functions/image/rootfs-to-image.sh | 3 +- lib/functions/rootfs/trap-rootfs.sh | 9 ++++-- 6 files changed, 55 insertions(+), 43 deletions(-) diff --git a/extensions/fs-cryptroot-support.sh b/extensions/fs-cryptroot-support.sh index 6d42e88e0..05949d831 100644 --- a/extensions/fs-cryptroot-support.sh +++ b/extensions/fs-cryptroot-support.sh @@ -21,12 +21,13 @@ function extension_prepare_config__prepare_cryptroot() { fi } -function prepare_root_device__encrypt_root_device() { +function prepare_root_device__250_encrypt_root_device() { # We encrypt the rootdevice (currently a loop device) and return the new mapped rootdevice check_loop_device "$rootdevice" display_alert "Extension: ${EXTENSION}: Encrypting root partition with LUKS..." "cryptsetup luksFormat $rootdevice" "" echo -n $CRYPTROOT_PASSPHRASE | cryptsetup luksFormat $CRYPTROOT_PARAMETERS $rootdevice - echo -n $CRYPTROOT_PASSPHRASE | cryptsetup luksOpen $rootdevice $CRYPTROOT_MAPPER - + add_cleanup_handler cleanup_cryptroot display_alert "Extension: ${EXTENSION}: Root partition encryption complete." "" "ext" # TODO: pass /dev/mapper to Docker rootdevice=/dev/mapper/$CRYPTROOT_MAPPER # used by `mkfs` and `mount` commands @@ -65,6 +66,9 @@ function pre_install_kernel_debs__adjust_dropbear_configuration() { # /usr/share/initramfs-tools/hooks/dropbear will automatically add 'id_ecdsa.pub' to authorized_keys file # during mkinitramfs of update-initramfs #cat "${dropbear_dir}"/id_ecdsa.pub > "${SDCARD}"/etc/dropbear-initramfs/authorized_keys + + + # copy it a) later via hook to make use of a proper naming / structural equal -> "${DESTIMG}/${version}.img" CRYPTROOT_SSH_UNLOCK_KEY_NAME="${VENDOR}_${REVISION}_${BOARD^}_${RELEASE}_${BRANCH}_${DESKTOP_ENVIRONMENT}".key # copy dropbear ssh key to image output dir for convenience cp "${dropbear_dir}"/id_ecdsa "${DEST}/images/${CRYPTROOT_SSH_UNLOCK_KEY_NAME}" @@ -73,3 +77,12 @@ function pre_install_kernel_debs__adjust_dropbear_configuration() { fi fi } + +function post_umount_final_image__750_cryptroot_cleanup(){ + execute_and_remove_cleanup_handler cleanup_cryptroot +} + +function cleanup_cryptroot(){ + cryptsetup luksClose "${CRYPTROOT_MAPPER}" 2>&1 + display_alert "Cryptroot closed ${CRYPTROOT_MAPPER}" "${EXTENSION}" "info" +} \ No newline at end of file diff --git a/extensions/lvm.sh b/extensions/lvm.sh index 96200dda4..1d9ac4d1d 100644 --- a/extensions/lvm.sh +++ b/extensions/lvm.sh @@ -32,22 +32,17 @@ function extension_prepare_config__prepare_lvm() { } function post_create_partitions__setup_lvm() { - - LOOP=$(losetup -f) - [[ -z $LOOP ]] && exit_with_error "Unable to find free loop device" - check_loop_device "$LOOP" - losetup $LOOP ${SDCARD}.raw - partprobe $LOOP - - # the partition to setup LVM on is defined as rootpart - local lvmpart=${rootpart} - local lvmdev=${LOOP}p${lvmpart} - display_alert "LVM will be on Partition ${lvmpart}, thats ${lvmdev}" "${EXTENSION}" "info" - # Setup LVM on the partition, ROOTFS - parted -s ${SDCARD}.raw -- set ${lvmpart} lvm on + parted -s ${SDCARD}.raw -- set ${rootpart} lvm on display_alert "LVM Partition table created" "${EXTENSION}" "info" parted -s ${SDCARD}.raw -- print >> "${DEST}"/${LOG_SUBPATH}/lvm.log 2>&1 +} + +function prepare_root_device__create_volume_group() { + + # the partition to setup LVM on is defined as rootpart + local lvmdev=$rootdevice + display_alert "LVM will be on Partition ${rootpart}, thats ${lvmdev}" "${EXTENSION}" "info" # Caculate the required volume size declare -g -i rootfs_size @@ -57,20 +52,18 @@ function post_create_partitions__setup_lvm() { display_alert "Root volume size" "$volsize MiB" "info" # Create the PV VG and VOL - display_alert "LVM Creating VG" "${SDCARD}.raw" "info" + display_alert "LVM Creating VG" "${lvmdev}" "info" check_loop_device ${lvmdev} pvcreate ${lvmdev} vgcreate ${LVM_VG_NAME} ${lvmdev} + wait_for_disk_sync "wait for VG to sync" # Note that devices wont come up automatically inside docker lvcreate -Zn --name root --size ${volsize}M ${LVM_VG_NAME} vgmknodes lvs >> "${DEST}"/${LOG_SUBPATH}/lvm.log 2>&1 + # TODO [ms] check if disable-scan-enable is necessary vgchange -a n ${LVM_VG_NAME} - losetup -d ${LOOP} display_alert "LVM created volume group" "${EXTENSION}" "info" -} - -function prepare_root_device__create_volume_group() { display_alert "Using LVM root" "${EXTENSION}" "info" vgscan @@ -87,8 +80,11 @@ function format_partitions__format_lvm() { display_alert "LVM labeled partitions" "${EXTENSION}" "info" } -function post_umount_final_image__close_lvm() { - # Deactivat the Volume Group - vgchange -a n ${LVM_VG_NAME} +function post_umount_final_image__lvm_cleanup(){ + execute_and_remove_cleanup_handler cleanup_lvm +} + +function cleanup_lvm() { + vgchange -a n ${LVM_VG_NAME} >> "${DEST}"/${LOG_SUBPATH}/lvm.log 2>&1 || true display_alert "LVM deactivated volume group" "${EXTENSION}" "info" } \ No newline at end of file diff --git a/lib/functions/image/loop.sh b/lib/functions/image/loop.sh index 446919ef4..528aca911 100644 --- a/lib/functions/image/loop.sh +++ b/lib/functions/image/loop.sh @@ -19,7 +19,7 @@ function check_loop_device() { function check_loop_device_internal() { local device="${1}" - display_alert "Checking look device" "${device}" "debug" + display_alert "Checking loop device" "${device}" "debug" if [[ ! -b "${device}" ]]; then if [[ $CONTAINER_COMPAT == yes && -b "/tmp/${device}" ]]; then display_alert "Creating device node" "${device}" diff --git a/lib/functions/image/partitioning.sh b/lib/functions/image/partitioning.sh index f9c0e9f0d..66cc5fbb0 100644 --- a/lib/functions/image/partitioning.sh +++ b/lib/functions/image/partitioning.sh @@ -246,7 +246,6 @@ function prepare_partitions() { fi declare -g LOOP - call_extension_method "post_create_partitions" <<- 'POST_CREATE_PARTITIONS' *called after all partitions are created, but not yet formatted* POST_CREATE_PARTITIONS @@ -256,10 +255,15 @@ function prepare_partitions() { exec {FD}> /var/lock/armbian-debootstrap-losetup flock -x $FD - - #--partscan is using to force the kernel for scaning partition table in preventing of partprobe errors - LOOP=$(losetup --show --partscan --find "${SDCARD}".raw) || exit_with_error "Unable to find free loop device" - display_alert "Allocated loop device" "LOOP=${LOOP}" + #--partscan is using to force the kernel for scanning partition table in preventing of partprobe errors + if [[ -z $LOOP ]]; then + LOOP=$(losetup -f) + # LOOP=$(losetup --show --partscan --find "${SDCARD}".raw) || exit_with_error "Unable to find free loop device" + [[ -z $LOOP ]] && exit_with_error "Unable to find free loop device" + display_alert "Allocated loop device" "LOOP=${LOOP}" + check_loop_device "$LOOP" + losetup $LOOP ${SDCARD}.raw + fi # loop device was grabbed here, unlock flock -u $FD @@ -279,8 +283,8 @@ function prepare_partitions() { ## ROOT PARTITION ## if [[ -n $rootpart ]]; then - local physical_rootdevice="${LOOP}p${rootpart}" - local rootdevice="${LOOP}p${rootpart}" + local rootdevice=${LOOP}p${rootpart} + local physical_rootdevice=$rootdevice call_extension_method "prepare_root_device" <<- 'PREPARE_ROOT_DEVICE' *Specialized storage extensions typically transform the root device into a mapped device and should hook in here * @@ -306,23 +310,20 @@ function prepare_partitions() { root_part_uuid="$(blkid -s UUID -o value ${LOOP}p${rootpart})" declare -g -r ROOT_PART_UUID="${root_part_uuid}" - physical_root_part_uuid="$(blkid -s UUID -o value $physical_rootdevice)" - declare -g -r PHYSICAL_ROOT_PART_UUID="${physical_root_part_uuid}" - display_alert "Physical root device" "$physical_rootdevice (UUID=${PHYSICAL_ROOT_PART_UUID})" "debug" - display_alert "Mounting rootfs" "$rootdevice (UUID=${ROOT_PART_UUID})" run_host_command_logged mount ${fscreateopt} $rootdevice $MOUNT/ # create fstab (and crypttab) entry - local rootfs if [[ $CRYPTROOT_ENABLE == yes ]]; then # map the LUKS container partition via its UUID to be the 'cryptroot' device + physical_root_part_uuid="$(blkid -s UUID -o value $physical_rootdevice)" echo "$CRYPTROOT_MAPPER UUID=${physical_root_part_uuid} none luks" >> $SDCARD/etc/crypttab - rootfs=$rootdevice # used in fstab - else - rootfs="UUID=$(blkid -s UUID -o value $rootdevice)" + run_host_command_logged cat $SDCARD/etc/crypttab fi + rootfs="UUID=$(blkid -s UUID -o value $rootdevice)" echo "$rootfs / ${mkfs[$ROOTFS_TYPE]} defaults,noatime${mountopts[$ROOTFS_TYPE]} 0 1" >> $SDCARD/etc/fstab + run_host_command_logged cat $SDCARD/etc/fstab + else # update_initramfs will fail if /lib/modules/ doesn't exist mount --bind --make-private $SDCARD $MOUNT/ diff --git a/lib/functions/image/rootfs-to-image.sh b/lib/functions/image/rootfs-to-image.sh index 92dcc6625..ab460e9a9 100644 --- a/lib/functions/image/rootfs-to-image.sh +++ b/lib/functions/image/rootfs-to-image.sh @@ -117,9 +117,8 @@ function create_image_from_sdcard_rootfs() { fi wait_for_disk_sync "before umount MOUNT" - + umount_chroot_recursive "${MOUNT}" "MOUNT" - [[ $CRYPTROOT_ENABLE == yes ]] && cryptsetup luksClose "$CRYPTROOT_MAPPER" call_extension_method "post_umount_final_image" "config_post_umount_final_image" <<- 'POST_UMOUNT_FINAL_IMAGE' *allow config to hack into the image after the unmount* diff --git a/lib/functions/rootfs/trap-rootfs.sh b/lib/functions/rootfs/trap-rootfs.sh index ce8ba64ce..abc9e684d 100644 --- a/lib/functions/rootfs/trap-rootfs.sh +++ b/lib/functions/rootfs/trap-rootfs.sh @@ -56,15 +56,18 @@ function trap_handler_cleanup_rootfs_and_image() { debug_tmpfs_show_usage "before cleanup of rootfs" cd "${SRC}" || echo "Failed to cwd to ${SRC}" # Move pwd away, so unmounts work + # those will loop until they're unmounted. + display_alert "Cleanup sdcard begin" "trap_handler_cleanup_rootfs_and_image" "cleanup" umount_chroot_recursive "${SDCARD}" "SDCARD" || true + + display_alert "Cleanup mount begin" "trap_handler_cleanup_rootfs_and_image" "cleanup" umount_chroot_recursive "${MOUNT}" "MOUNT" || true + display_alert "Cleanup umount sdcard begin" "trap_handler_cleanup_rootfs_and_image" "cleanup" # unmount tmpfs mounted on SDCARD if it exists. #@TODO: move to new tmpfs-utils scheme mountpoint -q "${SDCARD}" && umount "${SDCARD}" - [[ $CRYPTROOT_ENABLE == yes ]] && cryptsetup luksClose "${CRYPTROOT_MAPPER}" - if [[ "${PRESERVE_SDCARD_MOUNT}" == "yes" ]]; then display_alert "Preserving SD card mount" "trap_handler_cleanup_rootfs_and_image" "warn" return 0 @@ -72,7 +75,7 @@ function trap_handler_cleanup_rootfs_and_image() { # shellcheck disable=SC2153 # global var. if [[ -b "${LOOP}" ]]; then - display_alert "Freeing loop" "trap_handler_cleanup_rootfs_and_image ${LOOP}" "wrn" + display_alert "Freeing loop" "trap_handler_cleanup_rootfs_and_image ${LOOP}" "warn" free_loop_device_insistent "${LOOP}" || true fi