diff mbox series

[isar-cip-core] initramfs-crypt-hook: Optimize disk encryption in combination with expansion of last partition

Message ID 20250120123425.79292-1-alexander.heinisch@siemens.com (mailing list archive)
State New
Headers show
Series [isar-cip-core] initramfs-crypt-hook: Optimize disk encryption in combination with expansion of last partition | expand

Commit Message

Heinisch, Alexander Jan. 20, 2025, 12:34 p.m. UTC
From: Alexander Heinisch <alexander.heinisch@siemens.com>

In the current implementation (since: 284175c3) disk expansion logic
is done before the actual disk encryption.

This results in reencrypting the full expanded size of the disk, instead
of only reencrypting the sections containing the actual data. This results
in a drastic increase of time (approx 20x on our systems ) needed for reencryption!

Since relevant disk contents are only available in the sections of the disk
available before the expansion, it is sufficient to reencrypt them only.

This patch changes order of encryption and disk expansion resulting in
faster encryption (since only the necessary parts are encrypted).
The resize operation does not reencrypt the added disk parts but just
extends the LUKS container (cryptsetup resize) to reflect the maximum
available disk space.

Signed-off-by: Alexander Heinisch <alexander.heinisch@siemens.com>
---
 .../files/local-top-complete                  | 37 +++++++++++++++++--
 1 file changed, 33 insertions(+), 4 deletions(-)

Comments

Heinisch, Alexander Jan. 20, 2025, 12:51 p.m. UTC | #1
On Mon, 2025-01-20 at 13:34 +0100, alexander.heinisch@siemens.com
wrote:
> From: Alexander Heinisch <alexander.heinisch@siemens.com>
> 
> In the current implementation (since: 284175c3) disk expansion logic
> is done before the actual disk encryption.
> 
> This results in reencrypting the full expanded size of the disk,
> instead
> of only reencrypting the sections containing the actual data. This
> results
> in a drastic increase of time (approx 20x on our systems ) needed for
> reencryption!
> 
> Since relevant disk contents are only available in the sections of
> the disk
> available before the expansion, it is sufficient to reencrypt them
> only.
> 
> This patch changes order of encryption and disk expansion resulting
> in
> faster encryption (since only the necessary parts are encrypted).
> The resize operation does not reencrypt the added disk parts but just
> extends the LUKS container (cryptsetup resize) to reflect the maximum
> available disk space.

The thing I am not sure about this patch is, if executing the disk
expansion here is really the way to go, or if we shall just reuse the
expand-on-first-boot from isar (incl. fixes proposed earlier - [1])?


[1]:https://github.com/ilbers/isar/commit/8b30a4f86cb3ea3369bff3884141872c3a7d9979

BR Alexander

> 
> Signed-off-by: Alexander Heinisch <alexander.heinisch@siemens.com>
> ---
>  .../files/local-top-complete                  | 37
> +++++++++++++++++--
>  1 file changed, 33 insertions(+), 4 deletions(-)
> 
> diff --git a/recipes-initramfs/initramfs-crypt-hook/files/local-top-
> complete b/recipes-initramfs/initramfs-crypt-hook/files/local-top-
> complete
> index 8adc4e5..c4135c3 100644
> --- a/recipes-initramfs/initramfs-crypt-hook/files/local-top-complete
> +++ b/recipes-initramfs/initramfs-crypt-hook/files/local-top-complete
> @@ -153,6 +153,35 @@ expand_partition() {
>         # Inform the kernel about the partitioning change
>         partx -u "${last_part}"
>  
> +       last_part_device_name=${last_part#\/dev/}
> +
> +       mount_point=$(mktemp -d -p "" "$(basename "$0").XXXXXXXXXX")
> +
> +       mapping_name=$(cat
> /sys/class/block/"$last_part_device_name"/holders/*/dm/name)
> +       cryptsetup resize "$mapping_name"
> +       mount /dev/mapper/"$mapping_name" "${mount_point}"
> +       fs_type=$(findmnt -fno FSTYPE "${mount_point}" )
> +       last_part=/dev/mapper/"$mapping_name"
> +
> +       case ${fs_type} in
> +       ext*)
> +
> +               # Do not fail resize2fs if no mtab entry is found,
> e.g.,
> +               # when using systemd mount units.
> +               export EXT2FS_NO_MTAB_OK=1
> +               resize2fs "${last_part}"
> +               ;;
> +       btrfs)
> +               btrfs filesystem resize max "${mount_point}"
> +               ;;
> +       *)
> +               log_warning_msg "Unrecognized filesystem type
> ${fs_type} - no resize performed"
> +               ;;
> +       esac
> +
> +       umount "${mount_point}"
> +       rmdir "${mount_point}"
> +
>         log_end_msg
>  }
>  
> @@ -215,10 +244,6 @@ for partition_set in $partition_sets; do
>                 echo "ROOT=$decrypted_part" >/conf/param.conf
>         fi
>  
> -       if [ "$partition_expand" = "expand" ]; then
> -               expand_partition $part_device
> -       fi
> -
>         if /usr/sbin/cryptsetup luksDump --batch-mode "$part_device"
> \
>                         | grep -q "luks2"; then
>                 open_tpm2_partition "$part_device"
> "$crypt_mount_name" "$tpm_device"
> @@ -259,6 +284,10 @@ for partition_set in $partition_sets; do
>         esac
>  
>         finalize_tpm2_encryption "$part_device"
> +
> +       if [ "$partition_expand" = "expand" ]; then
> +               expand_partition $part_device
> +       fi
>  done
>  
>  if [ -n "$watchdog_pid" ]; then
Jan Kiszka Jan. 20, 2025, 1:51 p.m. UTC | #2
On 20.01.25 13:51, Heinisch, Alexander (FT RPD CED SES-AT) wrote:
> On Mon, 2025-01-20 at 13:34 +0100, alexander.heinisch@siemens.com
> wrote:
>> From: Alexander Heinisch <alexander.heinisch@siemens.com>
>>
>> In the current implementation (since: 284175c3) disk expansion logic
>> is done before the actual disk encryption.
>>
>> This results in reencrypting the full expanded size of the disk,
>> instead
>> of only reencrypting the sections containing the actual data. This
>> results
>> in a drastic increase of time (approx 20x on our systems ) needed for
>> reencryption!
>>
>> Since relevant disk contents are only available in the sections of
>> the disk
>> available before the expansion, it is sufficient to reencrypt them
>> only.
>>
>> This patch changes order of encryption and disk expansion resulting
>> in
>> faster encryption (since only the necessary parts are encrypted).
>> The resize operation does not reencrypt the added disk parts but just
>> extends the LUKS container (cryptsetup resize) to reflect the maximum
>> available disk space.
> 
> The thing I am not sure about this patch is, if executing the disk
> expansion here is really the way to go, or if we shall just reuse the
> expand-on-first-boot from isar (incl. fixes proposed earlier - [1])?
> 

If you find a good way to factor out the common code an reuse that
inside the initramfs, I'm open for patches. However, as we discussed on
the isar list as well, using the systemd service later on will no longer
work once we properly hide the keys when initramfs ends.

Jan
Heinisch, Alexander Jan. 20, 2025, 2:09 p.m. UTC | #3
On Mon, 2025-01-20 at 14:51 +0100, Jan Kiszka wrote:
> On 20.01.25 13:51, Heinisch, Alexander (FT RPD CED SES-AT) wrote:
> > On Mon, 2025-01-20 at 13:34 +0100, alexander.heinisch@siemens.com
> > wrote:
> > > From: Alexander Heinisch <alexander.heinisch@siemens.com>
> > > 
> > > In the current implementation (since: 284175c3) disk expansion
> > > logic
> > > is done before the actual disk encryption.
> > > 
> > > This results in reencrypting the full expanded size of the disk,
> > > instead
> > > of only reencrypting the sections containing the actual data.
> > > This
> > > results
> > > in a drastic increase of time (approx 20x on our systems ) needed
> > > for
> > > reencryption!
> > > 
> > > Since relevant disk contents are only available in the sections
> > > of
> > > the disk
> > > available before the expansion, it is sufficient to reencrypt
> > > them
> > > only.
> > > 
> > > This patch changes order of encryption and disk expansion
> > > resulting
> > > in
> > > faster encryption (since only the necessary parts are encrypted).
> > > The resize operation does not reencrypt the added disk parts but
> > > just
> > > extends the LUKS container (cryptsetup resize) to reflect the
> > > maximum
> > > available disk space.
> > 
> > The thing I am not sure about this patch is, if executing the disk
> > expansion here is really the way to go, or if we shall just reuse
> > the
> > expand-on-first-boot from isar (incl. fixes proposed earlier -
> > [1])?
> > 
> 
> If you find a good way to factor out the common code an reuse that
> inside the initramfs, I'm open for patches. However, as we discussed
> on
> the isar list as well, using the systemd service later on will no
> longer
> work once we properly hide the keys when initramfs ends.
> 

True!

Refactoring that part out, probably introduces more boilerplate, than
the actual refactoring will save. Anyhow, once the new sealing is in
place the systemd service support for crypt has to be
reconsidered/dropped anyways.
Will keep it as proposed in the patch.

BR Alexander

> Jan
>
Jan Kiszka Jan. 20, 2025, 3:10 p.m. UTC | #4
On 20.01.25 15:09, Heinisch, Alexander (FT RPD CED SES-AT) wrote:
> On Mon, 2025-01-20 at 14:51 +0100, Jan Kiszka wrote:
>> On 20.01.25 13:51, Heinisch, Alexander (FT RPD CED SES-AT) wrote:
>>> On Mon, 2025-01-20 at 13:34 +0100, alexander.heinisch@siemens.com
>>> wrote:
>>>> From: Alexander Heinisch <alexander.heinisch@siemens.com>
>>>>
>>>> In the current implementation (since: 284175c3) disk expansion
>>>> logic
>>>> is done before the actual disk encryption.
>>>>
>>>> This results in reencrypting the full expanded size of the disk,
>>>> instead
>>>> of only reencrypting the sections containing the actual data.
>>>> This
>>>> results
>>>> in a drastic increase of time (approx 20x on our systems ) needed
>>>> for
>>>> reencryption!
>>>>
>>>> Since relevant disk contents are only available in the sections
>>>> of
>>>> the disk
>>>> available before the expansion, it is sufficient to reencrypt
>>>> them
>>>> only.
>>>>
>>>> This patch changes order of encryption and disk expansion
>>>> resulting
>>>> in
>>>> faster encryption (since only the necessary parts are encrypted).
>>>> The resize operation does not reencrypt the added disk parts but
>>>> just
>>>> extends the LUKS container (cryptsetup resize) to reflect the
>>>> maximum
>>>> available disk space.
>>>
>>> The thing I am not sure about this patch is, if executing the disk
>>> expansion here is really the way to go, or if we shall just reuse
>>> the
>>> expand-on-first-boot from isar (incl. fixes proposed earlier -
>>> [1])?
>>>
>>
>> If you find a good way to factor out the common code an reuse that
>> inside the initramfs, I'm open for patches. However, as we discussed
>> on
>> the isar list as well, using the systemd service later on will no
>> longer
>> work once we properly hide the keys when initramfs ends.
>>
> 
> True!
> 
> Refactoring that part out, probably introduces more boilerplate, than
> the actual refactoring will save. Anyhow, once the new sealing is in
> place the systemd service support for crypt has to be
> reconsidered/dropped anyways.

That was already done:

https://github.com/ilbers/isar/commit/004f9935102f81b18a54fc9c0940d23b84be411a

The isar service is for unencrypted partitions only, this one here is 
for fully integrated encrypted ones.

Jan
Heinisch, Alexander Jan. 20, 2025, 3:22 p.m. UTC | #5
On Mon, 2025-01-20 at 16:10 +0100, Jan Kiszka wrote:
> On 20.01.25 15:09, Heinisch, Alexander (FT RPD CED SES-AT) wrote:
> > On Mon, 2025-01-20 at 14:51 +0100, Jan Kiszka wrote:
> > > On 20.01.25 13:51, Heinisch, Alexander (FT RPD CED SES-AT) wrote:
> > > > On Mon, 2025-01-20 at 13:34 +0100,
> > > > alexander.heinisch@siemens.com
> > > > wrote:
> > > > > From: Alexander Heinisch <alexander.heinisch@siemens.com>
> > > > >
> > > > > In the current implementation (since: 284175c3) disk
> > > > > expansion
> > > > > logic
> > > > > is done before the actual disk encryption.
> > > > >
> > > > > This results in reencrypting the full expanded size of the
> > > > > disk,
> > > > > instead
> > > > > of only reencrypting the sections containing the actual data.
> > > > > This
> > > > > results
> > > > > in a drastic increase of time (approx 20x on our systems )
> > > > > needed
> > > > > for
> > > > > reencryption!
> > > > >
> > > > > Since relevant disk contents are only available in the
> > > > > sections
> > > > > of
> > > > > the disk
> > > > > available before the expansion, it is sufficient to reencrypt
> > > > > them
> > > > > only.
> > > > >
> > > > > This patch changes order of encryption and disk expansion
> > > > > resulting
> > > > > in
> > > > > faster encryption (since only the necessary parts are
> > > > > encrypted).
> > > > > The resize operation does not reencrypt the added disk parts
> > > > > but
> > > > > just
> > > > > extends the LUKS container (cryptsetup resize) to reflect the
> > > > > maximum
> > > > > available disk space.
> > > >
> > > > The thing I am not sure about this patch is, if executing the
> > > > disk
> > > > expansion here is really the way to go, or if we shall just
> > > > reuse
> > > > the
> > > > expand-on-first-boot from isar (incl. fixes proposed earlier -
> > > > [1])?
> > > >
> > >
> > > If you find a good way to factor out the common code an reuse
> > > that
> > > inside the initramfs, I'm open for patches. However, as we
> > > discussed
> > > on
> > > the isar list as well, using the systemd service later on will no
> > > longer
> > > work once we properly hide the keys when initramfs ends.
> > >
> >
> > True!
> >
> > Refactoring that part out, probably introduces more boilerplate,
> > than
> > the actual refactoring will save. Anyhow, once the new sealing is
> > in
> > place the systemd service support for crypt has to be
> > reconsidered/dropped anyways.
>
> That was already done:
>

Somehow managed to not notice the revert, until now. So, please just
ignore the comments :-)

> https://github.com/ilbers/isar/commit/004f9935102f81b18a54fc9c0940d23b84be411a
>
> The isar service is for unencrypted partitions only, this one here is
> for fully integrated encrypted ones.

:-)
>

> Jan
>
Jan Kiszka Jan. 20, 2025, 3:47 p.m. UTC | #6
On 20.01.25 13:34, alexander.heinisch@siemens.com wrote:
> From: Alexander Heinisch <alexander.heinisch@siemens.com>
> 
> In the current implementation (since: 284175c3) disk expansion logic
> is done before the actual disk encryption.
> 
> This results in reencrypting the full expanded size of the disk, instead
> of only reencrypting the sections containing the actual data. This results
> in a drastic increase of time (approx 20x on our systems ) needed for reencryption!
> 
> Since relevant disk contents are only available in the sections of the disk
> available before the expansion, it is sufficient to reencrypt them only.
> 
> This patch changes order of encryption and disk expansion resulting in
> faster encryption (since only the necessary parts are encrypted).
> The resize operation does not reencrypt the added disk parts but just
> extends the LUKS container (cryptsetup resize) to reflect the maximum
> available disk space.
> 
> Signed-off-by: Alexander Heinisch <alexander.heinisch@siemens.com>
> ---
>  .../files/local-top-complete                  | 37 +++++++++++++++++--
>  1 file changed, 33 insertions(+), 4 deletions(-)
> 
> diff --git a/recipes-initramfs/initramfs-crypt-hook/files/local-top-complete b/recipes-initramfs/initramfs-crypt-hook/files/local-top-complete
> index 8adc4e5..c4135c3 100644
> --- a/recipes-initramfs/initramfs-crypt-hook/files/local-top-complete
> +++ b/recipes-initramfs/initramfs-crypt-hook/files/local-top-complete
> @@ -153,6 +153,35 @@ expand_partition() {
>  	# Inform the kernel about the partitioning change
>  	partx -u "${last_part}"
>  
> +	last_part_device_name=${last_part#\/dev/}
> +
> +	mount_point=$(mktemp -d -p "" "$(basename "$0").XXXXXXXXXX")

New binary (except for clevis) - would have to be listed in
HOOK_COPY_EXECS to ensure its actually available.

But we are working here against a temporary rootfs in RAM, thus could
simply use a static name derived from the hook name as well.

> +
> +	mapping_name=$(cat /sys/class/block/"$last_part_device_name"/holders/*/dm/name)
> +	cryptsetup resize "$mapping_name"
> +	mount /dev/mapper/"$mapping_name" "${mount_point}"
> +	fs_type=$(findmnt -fno FSTYPE "${mount_point}" )

New binary findmnt. But why not using get_fstype like the rest?

> +	last_part=/dev/mapper/"$mapping_name"
> +
> +	case ${fs_type} in
> +	ext*)
> +
> +		# Do not fail resize2fs if no mtab entry is found, e.g.,
> +		# when using systemd mount units.
> +		export EXT2FS_NO_MTAB_OK=1
> +		resize2fs "${last_part}"
> +		;;
> +	btrfs)
> +		btrfs filesystem resize max "${mount_point}"
> +		;;
> +	*)
> +		log_warning_msg "Unrecognized filesystem type ${fs_type} - no resize performed"
> +		;;
> +	esac
> +
> +	umount "${mount_point}"
> +	rmdir "${mount_point}"

rmdir does not exist by default. You could use rm -r instead.

But we don't need that strictly spoken. The initrd rootfs will get
dropped anyway.

> +
>  	log_end_msg
>  }
>  
> @@ -215,10 +244,6 @@ for partition_set in $partition_sets; do
>  		echo "ROOT=$decrypted_part" >/conf/param.conf
>  	fi
>  
> -	if [ "$partition_expand" = "expand" ]; then
> -		expand_partition $part_device
> -	fi
> -
>  	if /usr/sbin/cryptsetup luksDump --batch-mode "$part_device" \
>  			| grep -q "luks2"; then
>  		open_tpm2_partition "$part_device" "$crypt_mount_name" "$tpm_device"
> @@ -259,6 +284,10 @@ for partition_set in $partition_sets; do
>  	esac
>  
>  	finalize_tpm2_encryption "$part_device"
> +
> +	if [ "$partition_expand" = "expand" ]; then
> +		expand_partition $part_device
> +	fi
>  done
>  
>  if [ -n "$watchdog_pid" ]; then

Hehe, I was waiting for something like that from you already. I was too
lazy adding these extra bits without having the pressure myself.

Jan
Clara Kowalsky Jan. 23, 2025, 8:26 a.m. UTC | #7
On 20.01.25 13:34, Heinisch, Alexander via lists.cip-project.org wrote:
> From: Alexander Heinisch <alexander.heinisch@siemens.com>
> 
> In the current implementation (since: 284175c3) disk expansion logic
> is done before the actual disk encryption.
> 
> This results in reencrypting the full expanded size of the disk, instead
> of only reencrypting the sections containing the actual data. This results
> in a drastic increase of time (approx 20x on our systems ) needed for reencryption!
> 
> Since relevant disk contents are only available in the sections of the disk
> available before the expansion, it is sufficient to reencrypt them only.
> 
> This patch changes order of encryption and disk expansion resulting in
> faster encryption (since only the necessary parts are encrypted).
> The resize operation does not reencrypt the added disk parts but just
> extends the LUKS container (cryptsetup resize) to reflect the maximum
> available disk space.
> 
> Signed-off-by: Alexander Heinisch <alexander.heinisch@siemens.com>
> ---
>   .../files/local-top-complete                  | 37 +++++++++++++++++--
>   1 file changed, 33 insertions(+), 4 deletions(-)
> 
> diff --git a/recipes-initramfs/initramfs-crypt-hook/files/local-top-complete b/recipes-initramfs/initramfs-crypt-hook/files/local-top-complete
> index 8adc4e5..c4135c3 100644
> --- a/recipes-initramfs/initramfs-crypt-hook/files/local-top-complete
> +++ b/recipes-initramfs/initramfs-crypt-hook/files/local-top-complete
> @@ -153,6 +153,35 @@ expand_partition() {
>   	# Inform the kernel about the partitioning change
>   	partx -u "${last_part}"
>   
> +	last_part_device_name=${last_part#\/dev/}
> +
> +	mount_point=$(mktemp -d -p "" "$(basename "$0").XXXXXXXXXX")
> +
> +	mapping_name=$(cat /sys/class/block/"$last_part_device_name"/holders/*/dm/name)
> +	cryptsetup resize "$mapping_name"

I tried out your patch and cryptsetup is here asking for a passphrase. 
As the passphrase is stored in tmp_key, I think we need to hand it over via:
cryptsetup resize --key-file="$tmp_key" "$mapping_name"

> +	mount /dev/mapper/"$mapping_name" "${mount_point}"
> +	fs_type=$(findmnt -fno FSTYPE "${mount_point}" )
> +	last_part=/dev/mapper/"$mapping_name"
> +
> +	case ${fs_type} in
> +	ext*)
> +
> +		# Do not fail resize2fs if no mtab entry is found, e.g.,
> +		# when using systemd mount units.
> +		export EXT2FS_NO_MTAB_OK=1
> +		resize2fs "${last_part}"
> +		;;
> +	btrfs)
> +		btrfs filesystem resize max "${mount_point}"
> +		;;
> +	*)
> +		log_warning_msg "Unrecognized filesystem type ${fs_type} - no resize performed"
> +		;;
> +	esac
> +
> +	umount "${mount_point}"
> +	rmdir "${mount_point}"
> +
>   	log_end_msg
>   }
>   
> @@ -215,10 +244,6 @@ for partition_set in $partition_sets; do
>   		echo "ROOT=$decrypted_part" >/conf/param.conf
>   	fi
>   
> -	if [ "$partition_expand" = "expand" ]; then
> -		expand_partition $part_device
> -	fi
> -
>   	if /usr/sbin/cryptsetup luksDump --batch-mode "$part_device" \
>   			| grep -q "luks2"; then
>   		open_tpm2_partition "$part_device" "$crypt_mount_name" "$tpm_device"
> @@ -259,6 +284,10 @@ for partition_set in $partition_sets; do
>   	esac
>   
>   	finalize_tpm2_encryption "$part_device"
> +
> +	if [ "$partition_expand" = "expand" ]; then
> +		expand_partition $part_device
> +	fi
>   done
>   
>   if [ -n "$watchdog_pid" ]; then
> 
> 
> 
> -=-=-=-=-=-=-=-=-=-=-=-
> Links: You receive all messages sent to this group.
> View/Reply Online (#17548): https://lists.cip-project.org/g/cip-dev/message/17548
> Mute This Topic: https://lists.cip-project.org/mt/110713429/8340681
> Group Owner: cip-dev+owner@lists.cip-project.org
> Unsubscribe: https://lists.cip-project.org/g/cip-dev/leave/13391150/8340681/947370571/xyzzy [clara.kowalsky@siemens.com]
> -=-=-=-=-=-=-=-=-=-=-=-
>
Jan Kiszka Jan. 25, 2025, 6:34 a.m. UTC | #8
On 23.01.25 09:26, Clara Kowalsky wrote:
> 
> 
> On 20.01.25 13:34, Heinisch, Alexander via lists.cip-project.org wrote:
>> From: Alexander Heinisch <alexander.heinisch@siemens.com>
>>
>> In the current implementation (since: 284175c3) disk expansion logic
>> is done before the actual disk encryption.
>>
>> This results in reencrypting the full expanded size of the disk, instead
>> of only reencrypting the sections containing the actual data. This
>> results
>> in a drastic increase of time (approx 20x on our systems ) needed for
>> reencryption!
>>
>> Since relevant disk contents are only available in the sections of the
>> disk
>> available before the expansion, it is sufficient to reencrypt them only.
>>
>> This patch changes order of encryption and disk expansion resulting in
>> faster encryption (since only the necessary parts are encrypted).
>> The resize operation does not reencrypt the added disk parts but just
>> extends the LUKS container (cryptsetup resize) to reflect the maximum
>> available disk space.
>>
>> Signed-off-by: Alexander Heinisch <alexander.heinisch@siemens.com>
>> ---
>>   .../files/local-top-complete                  | 37 +++++++++++++++++--
>>   1 file changed, 33 insertions(+), 4 deletions(-)
>>
>> diff --git a/recipes-initramfs/initramfs-crypt-hook/files/local-top-
>> complete b/recipes-initramfs/initramfs-crypt-hook/files/local-top-
>> complete
>> index 8adc4e5..c4135c3 100644
>> --- a/recipes-initramfs/initramfs-crypt-hook/files/local-top-complete
>> +++ b/recipes-initramfs/initramfs-crypt-hook/files/local-top-complete
>> @@ -153,6 +153,35 @@ expand_partition() {
>>       # Inform the kernel about the partitioning change
>>       partx -u "${last_part}"
>>   +    last_part_device_name=${last_part#\/dev/}
>> +
>> +    mount_point=$(mktemp -d -p "" "$(basename "$0").XXXXXXXXXX")
>> +
>> +    mapping_name=$(cat /sys/class/block/"$last_part_device_name"/
>> holders/*/dm/name)
>> +    cryptsetup resize "$mapping_name"
> 
> I tried out your patch and cryptsetup is here asking for a passphrase.
> As the passphrase is stored in tmp_key, I think we need to hand it over
> via:
> cryptsetup resize --key-file="$tmp_key" "$mapping_name"
> 

I assume that this applies to v2 as well. Good that I still didn't merge
it. Alex, please have a look and come up with some v3.

Jan
Heinisch, Alexander Jan. 27, 2025, 9:59 a.m. UTC | #9
>On 23.01.25 09:26, Clara Kowalsky wrote:
>> 
>> 
>> On 20.01.25 13:34, Heinisch, Alexander via lists.cip-project.org wrote:
>>> From: Alexander Heinisch <alexander.heinisch@siemens.com>
>>>
>>> In the current implementation (since: 284175c3) disk expansion logic 
>>> is done before the actual disk encryption.
>>>
>>> This results in reencrypting the full expanded size of the disk, 
>>> instead of only reencrypting the sections containing the actual data. 
>>> This results in a drastic increase of time (approx 20x on our systems 
>>> ) needed for reencryption!
>>>
>>> Since relevant disk contents are only available in the sections of 
>>> the disk available before the expansion, it is sufficient to 
>>> reencrypt them only.
>>>
>>> This patch changes order of encryption and disk expansion resulting 
>>> in faster encryption (since only the necessary parts are encrypted).
>>> The resize operation does not reencrypt the added disk parts but just 
>>> extends the LUKS container (cryptsetup resize) to reflect the maximum 
>>> available disk space.
>>>
>>> Signed-off-by: Alexander Heinisch <alexander.heinisch@siemens.com>
>>> ---
>>>   .../files/local-top-complete                  | 37 
>>> +++++++++++++++++--
>>>   1 file changed, 33 insertions(+), 4 deletions(-)
>>>
>>> diff --git a/recipes-initramfs/initramfs-crypt-hook/files/local-top-
>>> complete b/recipes-initramfs/initramfs-crypt-hook/files/local-top-
>>> complete
>>> index 8adc4e5..c4135c3 100644
>>> --- a/recipes-initramfs/initramfs-crypt-hook/files/local-top-complete
>>> +++ b/recipes-initramfs/initramfs-crypt-hook/files/local-top-complete
>>> @@ -153,6 +153,35 @@ expand_partition() {
>>>       # Inform the kernel about the partitioning change
>>>       partx -u "${last_part}"
>>>   +    last_part_device_name=${last_part#\/dev/}
>>> +
>>> +    mount_point=$(mktemp -d -p "" "$(basename "$0").XXXXXXXXXX")
>>> +
>>> +    mapping_name=$(cat /sys/class/block/"$last_part_device_name"/
>>> holders/*/dm/name)
>>> +    cryptsetup resize "$mapping_name"
>> 
>> I tried out your patch and cryptsetup is here asking for a passphrase.
>> As the passphrase is stored in tmp_key, I think we need to hand it 
>> over
>> via:
>> cryptsetup resize --key-file="$tmp_key" "$mapping_name"

Thank you for testing the patch!

Don't know why this happens in V1 -

After the initial cryptsetup + enroll_tpm2_token the info needed to decrypt
is stored in the luks header (metadata) + tpm (key). Thus, the $tmp_key file is not 
needed anymore, and probably it was a good advice to remove it at that stage, so
other initramfs hooks cannot access it.

@Clara: Since I missed some dependencies for V1 the initramfs in V1 errors. Did you patch that before?
What was your configuration?

>> 
>
>I assume that this applies to v2 as well. Good that I still didn't merge it. Alex, please have a look and come up with some v3.

For V2 - we tested the patch with isar-cip-core upstream applied on 32fcde2c
against bookworm using the following .config.yaml:

```
#
# Automatically generated by kas 4.5
#
_source_dir: /repo
build_system: isar
header:
  includes:
  - kas-cip.yml
  - kas/board/qemu-amd64.yml
  - kas/opt/6.1.yml
  - kas/opt/bookworm.yml
  - kas/opt/expand-on-first-boot.yml
  - kas/opt/ebg-secure-boot-snakeoil.yml
  - kas/opt/encrypt-data.yml
  - kas/opt/encrypt-all.yml
  version: 17
local_conf_header:
  __menu_config_vars: WDOG_TIMEOUT = "60"
menu_configuration:
  DEBIAN_BOOKWORM: true
  DEBIAN_BULLSEYE: false
  DEBIAN_BUSTER: false
  DEBIAN_TRIXIE: false
  EXPAND_ON_FIRST_BOOT: true
  IMAGE_COMPLETE_SWUPDATE: true
  IMAGE_DATA_ENCRYPTION: true
  IMAGE_DELTA_SWUPDATE: false
  IMAGE_FULL_ENCRYPTION: true
  IMAGE_RO_ROOTFS_EROFS: false
  IMAGE_RO_ROOTFS_SQUASHFS: true
  IMAGE_SECURE_BOOT: true
  IMAGE_SECURITY: false
  IMAGE_SWUPDATE: true
  IMAGE_TESTING: false
  KERNEL_4_19: false
  KERNEL_4_4: false
  KERNEL_5_10: false
  KERNEL_6_1: true
  KERNEL_RT: false
  TARGET_BBB: false
  TARGET_HIHOPE_RZG2M: false
  TARGET_IWG20D: false
  TARGET_QEMU_AMD64: true
  TARGET_QEMU_ARM: false
  TARGET_QEMU_ARM64: false
  TARGET_QEMU_RISCV64: false
  TARGET_X86_UEFI: false
  WDOG_TIMEOUT: 60
```

The initial disk size was expanded to 15GB:

```
qemu-img resize cip-core-image-cip-core-bookworm-qemu-amd64.wic 15G
```

and started using the upstream `./start-qemu`

The relevant outputs in the initramfs:

```
Device /dev/sda7 is not a valid LUKS device.
Begin: Encryption of /dev/sda7 ... var: 11/262144 files (0.0% non-contiguous), 34348/524288 blocks
resize2fs 1.47.0 (5-Feb-2023)
Resizing the filesystem on /dev/sda7 to 516096 (4k) blocks.
The filesystem on /dev/sda7 is now 516096 (4k) blocks long.

Warning: keyslot operation could fail as it requires more than available memory.Finished, time 00m17s, 2032 MiB written, speed 112.1 MiB/s
New TPM2 token enrolled as key slot 1.
done.
Wiped slot 0.
Begin: Expanding partition /dev/sda7 ... resize2fs 1.47.0 (5-Feb-2023)
Resizing the filesystem on /dev/mapper/encrypted_var to 3024128 (4k) blocks.
The filesystem on /dev/mapper/encrypted_var is now 3024128 (4k) blocks long.

done.
```

Further checks done on rootfs, after first boot:

```
root@demo:~# lsblk
NAME                                     MAJ:MIN RM   SIZE RO TYPE  MOUNTPOINTS
sda                                        8:0    0    15G  0 disk  
├─sda1                                     8:1    0  20.8M  0 part  
├─sda2                                     8:2    0    64M  0 part  
├─sda3                                     8:3    0    64M  0 part  
├─sda4                                     8:4    0     1G  0 part  
│ └─fedcba98-7654-3210-cafe-5e0710000001 252:0    0  1008M  0 crypt 
│   └─verityroot                         252:4    0 125.5M  1 crypt /
├─sda5                                     8:5    0     1G  0 part  
│ └─fedcba98-7654-3210-cafe-5e0710000002 252:1    0  1008M  0 crypt 
├─sda6                                     8:6    0   1.3G  0 part  
│ └─encrypted_home                       252:2    0   1.3G  0 crypt /home
└─sda7                                     8:7    0  11.6G  0 part  
  └─encrypted_var                        252:3    0  11.5G  0 crypt /var
root@demo:~# df -h
Filesystem                  Size  Used Avail Use% Mounted on
udev                        455M     0  455M   0% /dev
tmpfs                       500M  6.8M  494M   2% /run
/dev/dm-4                   126M  126M     0 100% /
/dev/mapper/encrypted_home  1.2G   40K  1.2G   1% /home
/dev/mapper/encrypted_var    12G  172K   11G   1% /var
overlay                      12G  172K   11G   1% /etc
tmpfs                       475M     0  475M   0% /dev/shm
tmpfs                       5.0M     0  5.0M   0% /run/lock
tmpfs                       475M     0  475M   0% /tmp
```

BR Alexander

>
>Jan
>
>--
>Siemens AG, Foundational Technologies
>Linux Expert Center
Clara Kowalsky Feb. 7, 2025, 7:38 a.m. UTC | #10
On 27.01.25 10:59, Heinisch, Alexander (FT RPD CED SES-AT) wrote:
>> On 23.01.25 09:26, Clara Kowalsky wrote:
>>>
>>>
>>> On 20.01.25 13:34, Heinisch, Alexander via lists.cip-project.org wrote:
>>>> From: Alexander Heinisch <alexander.heinisch@siemens.com>
>>>>
>>>> In the current implementation (since: 284175c3) disk expansion logic
>>>> is done before the actual disk encryption.
>>>>
>>>> This results in reencrypting the full expanded size of the disk,
>>>> instead of only reencrypting the sections containing the actual data.
>>>> This results in a drastic increase of time (approx 20x on our systems
>>>> ) needed for reencryption!
>>>>
>>>> Since relevant disk contents are only available in the sections of
>>>> the disk available before the expansion, it is sufficient to
>>>> reencrypt them only.
>>>>
>>>> This patch changes order of encryption and disk expansion resulting
>>>> in faster encryption (since only the necessary parts are encrypted).
>>>> The resize operation does not reencrypt the added disk parts but just
>>>> extends the LUKS container (cryptsetup resize) to reflect the maximum
>>>> available disk space.
>>>>
>>>> Signed-off-by: Alexander Heinisch <alexander.heinisch@siemens.com>
>>>> ---
>>>>    .../files/local-top-complete                  | 37
>>>> +++++++++++++++++--
>>>>    1 file changed, 33 insertions(+), 4 deletions(-)
>>>>
>>>> diff --git a/recipes-initramfs/initramfs-crypt-hook/files/local-top-
>>>> complete b/recipes-initramfs/initramfs-crypt-hook/files/local-top-
>>>> complete
>>>> index 8adc4e5..c4135c3 100644
>>>> --- a/recipes-initramfs/initramfs-crypt-hook/files/local-top-complete
>>>> +++ b/recipes-initramfs/initramfs-crypt-hook/files/local-top-complete
>>>> @@ -153,6 +153,35 @@ expand_partition() {
>>>>        # Inform the kernel about the partitioning change
>>>>        partx -u "${last_part}"
>>>>    +    last_part_device_name=${last_part#\/dev/}
>>>> +
>>>> +    mount_point=$(mktemp -d -p "" "$(basename "$0").XXXXXXXXXX")
>>>> +
>>>> +    mapping_name=$(cat /sys/class/block/"$last_part_device_name"/
>>>> holders/*/dm/name)
>>>> +    cryptsetup resize "$mapping_name"
>>>
>>> I tried out your patch and cryptsetup is here asking for a passphrase.
>>> As the passphrase is stored in tmp_key, I think we need to hand it
>>> over
>>> via:
>>> cryptsetup resize --key-file="$tmp_key" "$mapping_name"
> 
> Thank you for testing the patch!
> 
> Don't know why this happens in V1 -
> 
> After the initial cryptsetup + enroll_tpm2_token the info needed to decrypt
> is stored in the luks header (metadata) + tpm (key). Thus, the $tmp_key file is not
> needed anymore, and probably it was a good advice to remove it at that stage, so
> other initramfs hooks cannot access it.
> 
> @Clara: Since I missed some dependencies for V1 the initramfs in V1 errors. Did you patch that before?
> What was your configuration?
> 

Hi Alexander, sorry for the delay, just tested v2 and received the same 
error of cryptsetup asking for a passphrase for resizing the last 
partition. See my configuration below.

>>>
>>
>> I assume that this applies to v2 as well. Good that I still didn't merge it. Alex, please have a look and come up with some v3.
> 
> For V2 - we tested the patch with isar-cip-core upstream applied on 32fcde2c
> against bookworm using the following .config.yaml:
> 
> ```
> #
> # Automatically generated by kas 4.5
> #
> _source_dir: /repo
> build_system: isar
> header:
>    includes:
>    - kas-cip.yml
>    - kas/board/qemu-amd64.yml
>    - kas/opt/6.1.yml
>    - kas/opt/bookworm.yml
>    - kas/opt/expand-on-first-boot.yml
>    - kas/opt/ebg-secure-boot-snakeoil.yml
>    - kas/opt/encrypt-data.yml
>    - kas/opt/encrypt-all.yml
>    version: 17
> local_conf_header:
>    __menu_config_vars: WDOG_TIMEOUT = "60"
> menu_configuration:
>    DEBIAN_BOOKWORM: true
>    DEBIAN_BULLSEYE: false
>    DEBIAN_BUSTER: false
>    DEBIAN_TRIXIE: false
>    EXPAND_ON_FIRST_BOOT: true
>    IMAGE_COMPLETE_SWUPDATE: true
>    IMAGE_DATA_ENCRYPTION: true
>    IMAGE_DELTA_SWUPDATE: false
>    IMAGE_FULL_ENCRYPTION: true
>    IMAGE_RO_ROOTFS_EROFS: false
>    IMAGE_RO_ROOTFS_SQUASHFS: true
>    IMAGE_SECURE_BOOT: true
>    IMAGE_SECURITY: false
>    IMAGE_SWUPDATE: true
>    IMAGE_TESTING: false
>    KERNEL_4_19: false
>    KERNEL_4_4: false
>    KERNEL_5_10: false
>    KERNEL_6_1: true
>    KERNEL_RT: false
>    TARGET_BBB: false
>    TARGET_HIHOPE_RZG2M: false
>    TARGET_IWG20D: false
>    TARGET_QEMU_AMD64: true
>    TARGET_QEMU_ARM: false
>    TARGET_QEMU_ARM64: false
>    TARGET_QEMU_RISCV64: false
>    TARGET_X86_UEFI: false
>    WDOG_TIMEOUT: 60
> ```
> 
> The initial disk size was expanded to 15GB:
> 
> ```
> qemu-img resize cip-core-image-cip-core-bookworm-qemu-amd64.wic 15G
> ```
> 
> and started using the upstream `./start-qemu`
> 
> The relevant outputs in the initramfs:
> 
> ```
> Device /dev/sda7 is not a valid LUKS device.
> Begin: Encryption of /dev/sda7 ... var: 11/262144 files (0.0% non-contiguous), 34348/524288 blocks
> resize2fs 1.47.0 (5-Feb-2023)
> Resizing the filesystem on /dev/sda7 to 516096 (4k) blocks.
> The filesystem on /dev/sda7 is now 516096 (4k) blocks long.
> 
> Warning: keyslot operation could fail as it requires more than available memory.Finished, time 00m17s, 2032 MiB written, speed 112.1 MiB/s
> New TPM2 token enrolled as key slot 1.
> done.
> Wiped slot 0.
> Begin: Expanding partition /dev/sda7 ... resize2fs 1.47.0 (5-Feb-2023)
> Resizing the filesystem on /dev/mapper/encrypted_var to 3024128 (4k) blocks.
> The filesystem on /dev/mapper/encrypted_var is now 3024128 (4k) blocks long.
> 
> done.
> ```
> 
> Further checks done on rootfs, after first boot:
> 
> ```
> root@demo:~# lsblk
> NAME                                     MAJ:MIN RM   SIZE RO TYPE  MOUNTPOINTS
> sda                                        8:0    0    15G  0 disk
> ├─sda1                                     8:1    0  20.8M  0 part
> ├─sda2                                     8:2    0    64M  0 part
> ├─sda3                                     8:3    0    64M  0 part
> ├─sda4                                     8:4    0     1G  0 part
> │ └─fedcba98-7654-3210-cafe-5e0710000001 252:0    0  1008M  0 crypt
> │   └─verityroot                         252:4    0 125.5M  1 crypt /
> ├─sda5                                     8:5    0     1G  0 part
> │ └─fedcba98-7654-3210-cafe-5e0710000002 252:1    0  1008M  0 crypt
> ├─sda6                                     8:6    0   1.3G  0 part
> │ └─encrypted_home                       252:2    0   1.3G  0 crypt /home
> └─sda7                                     8:7    0  11.6G  0 part
>    └─encrypted_var                        252:3    0  11.5G  0 crypt /var
> root@demo:~# df -h
> Filesystem                  Size  Used Avail Use% Mounted on
> udev                        455M     0  455M   0% /dev
> tmpfs                       500M  6.8M  494M   2% /run
> /dev/dm-4                   126M  126M     0 100% /
> /dev/mapper/encrypted_home  1.2G   40K  1.2G   1% /home
> /dev/mapper/encrypted_var    12G  172K   11G   1% /var
> overlay                      12G  172K   11G   1% /etc
> tmpfs                       475M     0  475M   0% /dev/shm
> tmpfs                       5.0M     0  5.0M   0% /run/lock
> tmpfs                       475M     0  475M   0% /tmp
> ```
> 
> BR Alexander
> 
>>
>> Jan
>>
>> --
>> Siemens AG, Foundational Technologies
>> Linux Expert Center

I tested it with my current bullseye setup and with bookworm. I 
installed the image via the isar-image-installer to real hardware, 
didn't try it out in QEMU. On bullseye, after unsuccessful resizing of 
the last partition (cryptsetup asking for the passphrase), I can login 
and lsblk shows that the encryption worked for/home and /var, but not 
the resizing for /var.
On bookworm, I am stuck in an endless loop of initramfs trying to 
encrypt and resize.

This is the used config for bookworm:

#
# Automatically generated by kas 4.7
#
_source_dir: /repo
build_system: isar
header:
   includes:
   - kas-cip.yml
   - kas/board/qemu-amd64.yml
   - kas/opt/6.1.yml
   - kas/opt/bookworm.yml
   - kas/opt/expand-on-first-boot.yml
   - kas/opt/ebg-swu.yml
   - kas/opt/encrypt-data.yml
   - kas/opt/encrypt-all.yml
   version: 18
local_conf_header:
   __menu_config_vars: WDOG_TIMEOUT = "60"
menu_configuration:
   DEBIAN_BOOKWORM: true
   DEBIAN_BULLSEYE: false
   DEBIAN_BUSTER: false
   DEBIAN_TRIXIE: false
   EXPAND_ON_FIRST_BOOT: true
   IMAGE_COMPLETE_SWUPDATE: true
   IMAGE_DATA_ENCRYPTION: true
   IMAGE_DELTA_SWUPDATE: false
   IMAGE_FULL_ENCRYPTION: true
   IMAGE_RO_ROOTFS_EROFS: false
   IMAGE_RO_ROOTFS_SQUASHFS: true
   IMAGE_SECURE_BOOT: false
   IMAGE_SECURITY: false
   IMAGE_SWUPDATE: true
   IMAGE_TESTING: false
   KERNEL_4_19: false
   KERNEL_4_4: false
   KERNEL_5_10: false
   KERNEL_6_1: true
   KERNEL_RT: false
   TARGET_BBB: false
   TARGET_HIHOPE_RZG2M: false
   TARGET_IWG20D: false
   TARGET_QEMU_AMD64: true
   TARGET_QEMU_ARM: false
   TARGET_QEMU_ARM64: false
   TARGET_QEMU_RISCV64: false
   TARGET_X86_UEFI: false
   WDOG_TIMEOUT: 60

And yes, when this part was still in isar, I patched it following the 
doc/README.tpm2.encryption.md. My patch was this, feeding the LUKS 
password to cryptsetup resize:

---
  .../files/local-top-complete                  | 30 +++++++++++++------
  1 file changed, 21 insertions(+), 9 deletions(-)

diff --git 
a/recipes-initramfs/initramfs-crypt-hook/files/local-top-complete 
b/recipes-initramfs/initramfs-crypt-hook/files/local-top-complete
index c4135c3..dfda787 100644
--- a/recipes-initramfs/initramfs-crypt-hook/files/local-top-complete
+++ b/recipes-initramfs/initramfs-crypt-hook/files/local-top-complete
@@ -153,15 +153,27 @@ expand_partition() {
  	# Inform the kernel about the partitioning change
  	partx -u "${last_part}"

-	last_part_device_name=${last_part#\/dev/}
-
-	mount_point=$(mktemp -d -p "" "$(basename "$0").XXXXXXXXXX")
-
-	mapping_name=$(cat 
/sys/class/block/"$last_part_device_name"/holders/*/dm/name)
-	cryptsetup resize "$mapping_name"
-	mount /dev/mapper/"$mapping_name" "${mount_point}"
-	fs_type=$(findmnt -fno FSTYPE "${mount_point}" )
-	last_part=/dev/mapper/"$mapping_name"
+	fs_type=$(blkid --output value --match-tag TYPE "${last_part}" )
+	if [ "$fs_type" = "crypto_LUKS" ]; then
+		if [ ! -x /usr/sbin/cryptsetup ]; then
+			echo "'cryptsetup' is missing cannot resize last partition as it is 
from type 'crypto_LUKS'"
+			exit 1
+		fi
+		last_part_device_name=${last_part#\/dev/}
+
+		mapping_name=$(cat 
/sys/class/block/"$last_part_device_name"/holders/*/dm/name)
+		keyslot="$(cryptsetup luksDump "$last_part" | awk 
'/Tokens:/,/Digests:/' | awk '/Keyslot:/ {print $2}' | head -n 1)"
+		if [ -n "$keyslot" ]; then
+			clevis luks pass -d "$last_part" -s"$keyslot" | cryptsetup resize 
"$mapping_name"
+		else
+			cryptsetup resize "$mapping_name"
+		fi
+		echo "Resized the LUKS partition." >&2
+		exit 0
+	else
+		mount_point=$(mktemp -d -p "" "$(basename "$0").XXXXXXXXXX")
+		mount "${last_part}" "${mount_point}"
+	fi

  	case ${fs_type} in
  	ext*)
diff mbox series

Patch

diff --git a/recipes-initramfs/initramfs-crypt-hook/files/local-top-complete b/recipes-initramfs/initramfs-crypt-hook/files/local-top-complete
index 8adc4e5..c4135c3 100644
--- a/recipes-initramfs/initramfs-crypt-hook/files/local-top-complete
+++ b/recipes-initramfs/initramfs-crypt-hook/files/local-top-complete
@@ -153,6 +153,35 @@  expand_partition() {
 	# Inform the kernel about the partitioning change
 	partx -u "${last_part}"
 
+	last_part_device_name=${last_part#\/dev/}
+
+	mount_point=$(mktemp -d -p "" "$(basename "$0").XXXXXXXXXX")
+
+	mapping_name=$(cat /sys/class/block/"$last_part_device_name"/holders/*/dm/name)
+	cryptsetup resize "$mapping_name"
+	mount /dev/mapper/"$mapping_name" "${mount_point}"
+	fs_type=$(findmnt -fno FSTYPE "${mount_point}" )
+	last_part=/dev/mapper/"$mapping_name"
+
+	case ${fs_type} in
+	ext*)
+
+		# Do not fail resize2fs if no mtab entry is found, e.g.,
+		# when using systemd mount units.
+		export EXT2FS_NO_MTAB_OK=1
+		resize2fs "${last_part}"
+		;;
+	btrfs)
+		btrfs filesystem resize max "${mount_point}"
+		;;
+	*)
+		log_warning_msg "Unrecognized filesystem type ${fs_type} - no resize performed"
+		;;
+	esac
+
+	umount "${mount_point}"
+	rmdir "${mount_point}"
+
 	log_end_msg
 }
 
@@ -215,10 +244,6 @@  for partition_set in $partition_sets; do
 		echo "ROOT=$decrypted_part" >/conf/param.conf
 	fi
 
-	if [ "$partition_expand" = "expand" ]; then
-		expand_partition $part_device
-	fi
-
 	if /usr/sbin/cryptsetup luksDump --batch-mode "$part_device" \
 			| grep -q "luks2"; then
 		open_tpm2_partition "$part_device" "$crypt_mount_name" "$tpm_device"
@@ -259,6 +284,10 @@  for partition_set in $partition_sets; do
 	esac
 
 	finalize_tpm2_encryption "$part_device"
+
+	if [ "$partition_expand" = "expand" ]; then
+		expand_partition $part_device
+	fi
 done
 
 if [ -n "$watchdog_pid" ]; then