diff options
author | Simon Rettberg | 2024-06-13 15:41:01 +0200 |
---|---|---|
committer | Simon Rettberg | 2024-06-13 15:41:01 +0200 |
commit | bed4315a7ca1c67b5528e2a5def6ded1dcf26054 (patch) | |
tree | 1b0e840560659342e149c57cd6c79ec0e52e240c | |
parent | De-duplicate tools copied vs. what busybox ships (diff) | |
download | systemd-init-bed4315a7ca1c67b5528e2a5def6ded1dcf26054.tar.gz systemd-init-bed4315a7ca1c67b5528e2a5def6ded1dcf26054.tar.xz systemd-init-bed4315a7ca1c67b5528e2a5def6ded1dcf26054.zip |
[slx-dmsetup] Avoid unnecessary dm targets, rename crypted ones
1)
Avoid creating linear targets that would be fully covered by an
encrypted target later. Also don't create a linear slice for the
thinpool if it's going to be the only thing we put in our writable
partition.
2)
Previously, when we created an encrypted device, it would look like
|
` devicename
` devicename-crypt
Which was a bit confusing/surprising, because the final name was not
what was specified in our custom partition table. Now, the result would
look like
|
` devicename-k
` devicename
So the final device you'd use has the expected name.
-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." |