Fix error paths for pcrextend_pcr_now and pkcs7_extract_signers (#43357)

- pcrextend: Fix use-after-free/double-free error in pcrextend_pcr_now

  With SignInitrdPCRs=disabled in mkosi the TPM/PCR services are broken
which triggers the error path in the varlink call which means that we
get parameters set in the response. The wrong ownership assumption when
looking at the reply with _cleanup_ set caused a memory corruption that
surfaced in systemd-sysext with an ABRT.
This is a common mistake done with the API, fix it by not setting
_cleanup_(sd_json_variant_unrefp).

- pkcs7: Correct error handling for pkcs7_extract_signers

  The lack of error handling for sym_i2d_X509_NAME/sym_i2d_ASN1_INTEGER
means that we get a NULL iovec that will cause an assertion failure
later. The use of regular free for OpenSSL is probably okay but since
the allocator can differ, one should use OPENSSL_free.
Add error handling and do an explicit copy instead of ownership transfer
between possibly different allocators.
This commit is contained in:
Yu Watanabe
2026-08-12 02:48:51 +09:00
committed by GitHub
2 changed files with 16 additions and 7 deletions
+4 -2
View File
@@ -58,7 +58,8 @@ int pcrextend_pcr_now(unsigned pcr, const char *word, const struct iovec *secret
if (iovec_is_set(secret))
sd_json_variant_sensitive(parameters);
_cleanup_(sd_json_variant_unrefp) sd_json_variant *reply = NULL;
/* Both the reply and the error id are borrowed from the connection, don't unref/free them. */
sd_json_variant *reply = NULL;
const char *error_id = NULL;
r = sd_varlink_call(vl, "io.systemd.PCRExtend.Extend", parameters, &reply, &error_id);
if (r < 0)
@@ -91,7 +92,8 @@ int pcrextend_nvpcr_now(const char *nvpcr, const char *word, const char *event)
if (r < 0)
return r;
_cleanup_(sd_json_variant_unrefp) sd_json_variant *reply = NULL;
/* Both the reply and the error id are borrowed from the connection, don't unref/free them. */
sd_json_variant *reply = NULL;
const char *error_id = NULL;
r = sd_varlink_callbo(
vl,
+12 -5
View File
@@ -2,6 +2,7 @@
#include "alloc-util.h"
#include "crypto-util.h"
#include "iovec-util.h"
#include "pkcs7-util.h"
#include "log.h"
@@ -72,13 +73,19 @@ int pkcs7_extract_signers(
return log_debug_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Failed to get signer information.");
_cleanup_(signer_done) Signer signer = {};
_cleanup_(OPENSSL_freep) void *issuer = NULL, *serial = NULL;
_cleanup_free_ unsigned char *p = NULL;
int len = sym_i2d_X509_NAME(si->issuer_and_serial->issuer, &p);
signer.issuer = IOVEC_MAKE(TAKE_PTR(p), len);
int len = sym_i2d_X509_NAME(si->issuer_and_serial->issuer, (unsigned char**) &issuer);
if (len < 0)
return log_openssl_errors(LOG_DEBUG, "Failed to convert issuer name to DER format");
if (!iovec_memdup(&IOVEC_MAKE(issuer, len), &signer.issuer))
return log_oom_debug();
len = sym_i2d_ASN1_INTEGER(si->issuer_and_serial->serial, &p);
signer.serial = IOVEC_MAKE(TAKE_PTR(p), len);
len = sym_i2d_ASN1_INTEGER(si->issuer_and_serial->serial, (unsigned char**) &serial);
if (len < 0)
return log_openssl_errors(LOG_DEBUG, "Failed to convert serial number to DER format");
if (!iovec_memdup(&IOVEC_MAKE(serial, len), &signer.serial))
return log_oom_debug();
signers[n_signers++] = TAKE_STRUCT(signer);
}