diff options
-rwxr-xr-x | modules.d/slx-dmsetup/hooks/dmsetup-slx-device | 106 |
1 files changed, 72 insertions, 34 deletions
diff --git a/modules.d/slx-dmsetup/hooks/dmsetup-slx-device b/modules.d/slx-dmsetup/hooks/dmsetup-slx-device index 1475aea0..ac965175 100755 --- a/modules.d/slx-dmsetup/hooks/dmsetup-slx-device +++ b/modules.d/slx-dmsetup/hooks/dmsetup-slx-device @@ -156,21 +156,37 @@ dmsetup_create_noudevsync() { return $ret } -# encrypt_device <dev_path> <encrypted_name> [<size>] +# encrypt_device <dev_path> <encrypted_name> [<start> <size>] encrypt_device() { # TODO: Send key back to us, demand ransom modprobe dm-crypt || echo "$0: dm-crypt loading failed, maybe builtin?" [ -b "$1" ] || return 1 [ -n "$2" ] || return 1 - [ -z "$3" ] && local size="$( blockdev --getsz "$1" )" + [ -z "$3" ] && + local dev_size="$( blockdev --getsz "$1" )" + if [ -z "$dev_size" ]; then + echo "$0: Cannot encrypt non-existent device $1" + return 1 + fi + local size="$4" + local start="$3" + # Sanitize + [ "$start" -ge 0 ] 2> /dev/null || start=0 + [ "$size" -gt 0 ] 2> /dev/null || size="$dev_size" + # Put in bounds + (( start > dev_size )) && start="$dev_size" + (( start + size > dev_size )) && size="$(( dev_size - start ))" local key key="$( < /dev/urandom xxd -c32 -p -l32 )" [ -z "$key" ] && key="$( < /dev/urandom tr -c -d 'a-f0-9' | dd count=1 bs=32 )" [ -z "$key" ] && key="$( < /dev/urandom head -c32 | xxd -c32 -p )" [ -z "$key" ] && key="$( < /dev/urandom xxd -c32 -p | head -n 1 )" - [ -z "$key" ] && echo "$0: ERROR: Could not generate encryption key" + if [ -z "$key" ]; then + echo "$0: ERROR: Could not generate encryption key" + return 1 + fi if ! dmsetup_create_noudevsync "$2" \ - "0 ${3:-${size}} crypt aes-xts-plain64 $key 0 $1 0 1 allow_discards"; then + "0 ${size} crypt aes-xts-plain64 $key 0 $1 ${start} 1 allow_discards"; then echo "$0: Failed to encrypt $1." return 1 fi @@ -639,6 +655,7 @@ fi declare -g writable_device_used_sz=0 # first, reserve the space for the rootfs cow snapshot (of either type)... +# (this is the first line of our custom partition table) read -r name crypt min max ignore <<< "${thin_snapshot:-${snapshot}}" declare -g scratch_device="/dev/mapper/scratch" @@ -653,30 +670,39 @@ else echo "$0: Using this client maximum scratch space ($writable_device_sz sectors)." scratch_device_sz="$writable_device_sz" fi -# Round down to 4k border, so next slice won't be misaligned if we're on a 4k sector disk -scratch_device_sz="$(( (scratch_device_sz / 8) * 8 ))" - -# Create a linear target for the scratch device. This might seem superfluous, -# but it works around problems when using NVMe as pool data device directly. -if ! dmsetup_create_noudevsync "${scratch_device##*/}" \ - "0 $scratch_device_sz linear $writable_device $writable_device_used_sz"; then - echo "$0: Failed to create scratch space for the CoW layer." - # this should never fail, but if it does, we would likely not be able to use - # $writable_device for any dmsetup stuff, so just fallback to ramdisk - # until we have a better idea on what to do :) - ramdisk_fallback -fi -save_partition_info "${scratch_device##*/}" "*" "1" "$scratch_device_sz" -# encrypt the scratch device, if configured -if [ -z "$id44_crypted" ]; then - if [ "$crypt" -ne 0 ] \ - && encrypt_device "$scratch_device" "${scratch_device##*/}-crypt" "$scratch_device_sz"; then - scratch_device="/dev/mapper/${scratch_device##*/}-crypt" +if (( scratch_device_sz == writable_device_sz )); then + # Only one, use directly, maybe crypt + if [ -z "$id44_crypted" ] && [ "$crypt" -ne 0 ]; then + if ! encrypt_device "$writable_device" "${scratch_device##*/}" 0 "$scratch_device_sz"; then + echo "$0: Continuing with unencrypted scratch" + scratch_device="$writable_device" + fi else + # Noop + scratch_device="$writable_device" + fi +else + # Smaller slice requested, device mapper to the rescure + # Round down to 4k border, so next slice won't be misaligned if we're on a 4k sector disk + scratch_device_sz="$(( (scratch_device_sz / 8) * 8 ))" + + # encrypt the scratch device, if configured + if [ -z "$id44_crypted" ] && (( crypt != 0 )) \ + && ! encrypt_device "$writable_device" "${scratch_device##*/}" 0 "$scratch_device_sz"; then echo "$0: Continuing with unencrypted scratch" + crypt=0 # So we do the linear thing below + fi + if (( crypt == 0 )) && ! dmsetup_create_noudevsync "${scratch_device##*/}" \ + "0 $scratch_device_sz linear $writable_device $writable_device_used_sz"; then + echo "$0: Failed to create scratch space for the CoW layer." + # this should never fail, but if it does, we would likely not be able to use + # $writable_device for any dmsetup stuff, so just fallback to ramdisk + # until we have a better idea on what to do :) + ramdisk_fallback fi fi +save_partition_info "${scratch_device##*/}" "*" "1" "$scratch_device_sz" writable_device_used_sz="$scratch_device_sz" @@ -696,16 +722,18 @@ for line in "${linear[@]}"; do # as above, round down to align on 4k sector devices to_allocate="$(( (to_allocate / 8) * 8 ))" - if ! dmsetup_create_noudevsync "$name" "0 $to_allocate linear $writable_device $writable_device_used_sz"; then + if (( crypt != 0 )) \ + && ! encrypt_device "$writable_device" "${name}" "$writable_device_used_sz" "$to_allocate"; then + echo "$0: Failed to encrypt '$name', continuing without encryption." + crypt=0 + fi + if (( crypt == 0 )) && ! dmsetup_create_noudevsync \ + "$name" "0 $to_allocate linear $writable_device $writable_device_used_sz"; then echo "$0: Failed to create linear device: $line" continue fi # TODO sane? save_partition_info "$name" "*" "1" "$to_allocate" - if [ "$crypt" -ne 0 ] && \ - ! encrypt_device "/dev/mapper/$name" "${name}-crypt" "$to_allocate"; then - echo "$0: Failed to encrypt '$name'." - fi writable_device_used_sz=$(( to_allocate + writable_device_used_sz )) done @@ -735,14 +763,17 @@ if [ -n "$thin_snapshot" ] || [ -n "$thin_volume" ]; then [ -n "$id44_crypted" ] && crypt=0 # thin-volume can be created with max size, # since they are overprovisioned anyway. - if ! create_volume "$name" "$(( volume_id++ ))" "$max"; then + suffix= + (( crypt != 0 )) && suffix="-k" + if ! create_volume "$name$suffix" "$(( volume_id++ ))" "$max"; then echo "Failed to create thin volume '$name'." fi - save_partition_info "$name" "*" "1" "${scratch_device_sz}-${max}" - if [ "$crypt" -ne 0 ] && ! encrypt_device \ - "/dev/mapper/$name" "$name-crypt" "$max"; then - echo "Failed to encrypt thin volume '$name'." + if (( crypt != 0 )) && ! encrypt_device \ + "/dev/mapper/$name$suffix" "$name" 0 "$max"; then + echo "Failed to encrypt thin volume '$name', continuing without encryption." + name="$name$suffix" fi + save_partition_info "$name" "*" "1" "${scratch_device_sz}-${max}" done if [ -n "$thin_snapshot" ]; then @@ -769,10 +800,17 @@ if [ -n "$thin_snapshot" ] || [ -n "$thin_volume" ]; then if (( root_ntfs_extra > 0 )); then thin_snapshot_sz="$(( thin_snapshot_sz + root_ntfs_extra ))" fi - if ! create_volume "$name" 1 "$thin_snapshot_sz" "$read_only_device"; then + suffix= + (( crypt != 0 )) && suffix="-k" + if ! create_volume "$name$suffix" 1 "$thin_snapshot_sz" "$read_only_device"; then echo "Failed to create external snapshot for '$read_only_device'." ramdisk_fallback fi + if (( crypt != 0 )) && ! encrypt_device \ + "/dev/mapper/$name$suffix" "$name" 0 "$thin_snapshot_sz"; then + echo "Failed to encrypt thin volume '$name', continuing without encryption." + name="$name$suffix" + fi finish_setup "$name" "1" "$thin_snapshot_sz" fi echo "$0: Thin volumes defined, but no snapshot. Using tmpfs." |