From: Vitaly Kuznetsov Date: Thu, 30 Apr 2026 14:44:39 +0000 (+0200) Subject: cryptsetup: avoid a segfault when a keyfile is passed along with a TPM device X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=bd9971cd25f452e164e6c5af798a73d16aadbbd9;p=thirdparty%2Fsystemd.git cryptsetup: avoid a segfault when a keyfile is passed along with a TPM device When a keyfile is passed with tpm2-device=, e.g., systemd-cryptsetup attach test_data /vol /my-pass tpm2-device=auto the logic in attach_luks_or_plain_or_bitlk_by_tpm2() tries to process it as a TPM blob first. This did not work properly because it passes n_blobs=1 to acquire_tpm2_key(), and the key_file is only read when n_blobs == 0. As a result, the code ends up calling tpm2_unseal(..., blobs=NULL, n_blobs=1, ...). Before commit 5c6aad9 ("cryptsetup-tokens: Print tpm2-primary-alg: only when it is known"), the segfault was not observed because tpm2_unseal() was bailing out early when primary_alg == 0. However, after that change, it attempts to process the blob (which is NULL) and crashes. Fix this logic by passing n_blobs=0 to acquire_tpm2_key() so that it actually reads the key_file. Additionally, assert 'blobs' in tpm2_unseal() as a safeguard. Fixes #41867 --- diff --git a/src/cryptsetup/cryptsetup.c b/src/cryptsetup/cryptsetup.c index 2130c54047c..bf313340bf6 100644 --- a/src/cryptsetup/cryptsetup.c +++ b/src/cryptsetup/cryptsetup.c @@ -2060,7 +2060,7 @@ static int attach_luks_or_plain_or_bitlk_by_tpm2( /* pcrlock_path= */ NULL, /* primary_alg= */ 0, key_file, arg_keyfile_size, arg_keyfile_offset, - key_data, /* n_blobs= */ 1, + key_data, /* n_blobs= */ iovec_is_set(key_data) ? 1 : 0, /* policy_hash= */ NULL, /* we don't know the policy hash */ /* n_policy_hash= */ 0, /* salt= */ NULL, diff --git a/src/shared/tpm2-util.c b/src/shared/tpm2-util.c index 9fe3e018693..091a4dba89a 100644 --- a/src/shared/tpm2-util.c +++ b/src/shared/tpm2-util.c @@ -5804,6 +5804,7 @@ int tpm2_unseal(Tpm2Context *c, int r; assert(n_blobs > 0); + assert(blobs); assert(iovec_is_valid(pubkey)); assert(ret_secret);