mirror of
https://github.com/systemd/systemd.git
synced 2026-06-30 19:57:29 +00:00
tpm2-setup: make NV index space exhaustion issues more discoverable
Let's log about this explicitly, and include a message catalog entry for it.
This commit is contained in:
@@ -1002,3 +1002,16 @@ device nodes appear early in boot, while regular users may appear only later.
|
||||
For devices managed by systemd-udevd, it is instead recommended to use the
|
||||
"uaccess"/"xaccess" mechanisms to grant limited and temporary access to device
|
||||
nodes, see sd-login(8).
|
||||
|
||||
-- ab984ea008964fb88d6e389fb513fb94
|
||||
Subject: TPM NV index space exhausted, unable to initialize NvPCR
|
||||
Defined-By: systemd
|
||||
Support: %SUPPORT_URL%
|
||||
|
||||
The Trusted Platform Module's (TPM) NV index space has been exhausted, and an
|
||||
additional NvPCR, i.e. additional Platform Configuration Register (PCR) stored in
|
||||
non-volatile indexes (NV Indexes), could not be initialized.
|
||||
|
||||
This typically means the persistent NV index memory available on the TPM is
|
||||
taken up by other resources, or is extremely limited. A TPM reset might help
|
||||
recovering space (but will invalidate all TPM bound keys and resources).
|
||||
|
||||
@@ -6031,6 +6031,9 @@ int tpm2_define_nvpcr_nv_index(
|
||||
/* auth= */ NULL,
|
||||
&public_info,
|
||||
&new_handle->esys_handle);
|
||||
if (rc == TPM2_RC_NV_SPACE)
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(ENOSPC),
|
||||
"NV index space on TPM exhausted, cannot allocate NvPCR.");
|
||||
if (rc == TPM2_RC_NV_DEFINED) {
|
||||
log_debug("NV index 0x%" PRIu32 " already registered.", nv_index);
|
||||
|
||||
|
||||
@@ -306,6 +306,9 @@ _SD_BEGIN_DECLARATIONS;
|
||||
#define SD_MESSAGE_SYSTEM_ACCOUNT_REQUIRED SD_ID128_MAKE(34,05,20,5d,36,8e,49,fe,b5,ab,39,25,fe,e1,38,74)
|
||||
#define SD_MESSAGE_SYSTEM_ACCOUNT_REQUIRED_STR SD_ID128_MAKE_STR(34,05,20,5d,36,8e,49,fe,b5,ab,39,25,fe,e1,38,74)
|
||||
|
||||
#define SD_MESSAGE_TPM_INVINDEX_EXHAUSTED SD_ID128_MAKE(ab,98,4e,a0,08,96,4f,b8,8d,6e,38,9f,b5,13,fb,94)
|
||||
#define SD_MESSAGE_TPM_INVINDEX_EXHAUSTED_STR SD_ID128_MAKE_STR(ab,98,4e,a0,08,96,4f,b8,8d,6e,38,9f,b5,13,fb,94)
|
||||
|
||||
_SD_END_DECLARATIONS;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -385,7 +385,7 @@ static int setup_srk(void) {
|
||||
typedef struct SetupNvPCRContext {
|
||||
Tpm2Context *tpm2_context;
|
||||
struct iovec anchor_secret;
|
||||
size_t n_already, n_anchored;
|
||||
size_t n_already, n_anchored, n_failed;
|
||||
Set *done;
|
||||
} SetupNvPCRContext;
|
||||
|
||||
@@ -404,16 +404,11 @@ static int setup_nvpcr_one(
|
||||
|
||||
assert(c);
|
||||
assert(name);
|
||||
assert(c->tpm2_context);
|
||||
|
||||
if (set_contains(c->done, name))
|
||||
return 0;
|
||||
|
||||
if (!c->tpm2_context) {
|
||||
r = tpm2_context_new_or_warn(arg_tpm2_device, &c->tpm2_context);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
r = tpm2_nvpcr_initialize(c->tpm2_context, /* session= */ NULL, name, &c->anchor_secret);
|
||||
if (r == -EUNATCH) {
|
||||
assert(!iovec_is_set(&c->anchor_secret));
|
||||
@@ -427,8 +422,16 @@ static int setup_nvpcr_one(
|
||||
|
||||
r = tpm2_nvpcr_initialize(c->tpm2_context, /* session= */ NULL, name, &c->anchor_secret);
|
||||
}
|
||||
if (r < 0)
|
||||
if (r == -ENOSPC) {
|
||||
c->n_failed++;
|
||||
return log_struct_errno(LOG_ERR, r,
|
||||
LOG_MESSAGE("The TPM's NV index space is exhausted, unable to allocate NvPCR '%s': %m", name),
|
||||
LOG_MESSAGE_ID(SD_MESSAGE_TPM_INVINDEX_EXHAUSTED_STR));
|
||||
}
|
||||
if (r < 0) {
|
||||
c->n_failed++;
|
||||
return log_error_errno(r, "Failed to extend NvPCR index with anchor secret: %m");
|
||||
}
|
||||
|
||||
if (r > 0)
|
||||
c->n_anchored++;
|
||||
@@ -455,10 +458,17 @@ static int setup_nvpcr(void) {
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to find .nvpcr files: %m");
|
||||
|
||||
int ret = 0;
|
||||
STRV_FOREACH(i, l) {
|
||||
r = setup_nvpcr_one(&c, *i);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (!c.tpm2_context) {
|
||||
/* Inability to contact the TPM shall be fatal for us */
|
||||
r = tpm2_context_new_or_warn(arg_tpm2_device, &c.tpm2_context);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
/* But if we fail to initialize some NvPCR, we go on */
|
||||
RET_GATHER(ret, setup_nvpcr_one(&c, *i));
|
||||
}
|
||||
|
||||
if (c.n_already > 0 && c.n_anchored == 0 && !arg_early) {
|
||||
@@ -466,11 +476,12 @@ static int setup_nvpcr(void) {
|
||||
* have happened in the initrd, and thus the anchor ID was not committed to /var/ or the ESP
|
||||
* yet. Hence, let's explicitly do so now, to catch up. */
|
||||
|
||||
r = tpm2_nvpcr_acquire_anchor_secret(/* ret= */ NULL, /* sync_secondary= */ true);
|
||||
if (r < 0)
|
||||
return r;
|
||||
RET_GATHER(ret, tpm2_nvpcr_acquire_anchor_secret(/* ret= */ NULL, /* sync_secondary= */ true));
|
||||
}
|
||||
|
||||
if (c.n_failed > 0)
|
||||
log_warning("%zu NvPCRs failed to initialize, proceeding anyway.", c.n_failed);
|
||||
|
||||
if (c.n_anchored > 0) {
|
||||
if (c.n_already == 0)
|
||||
log_info("%zu NvPCRs initialized.", c.n_anchored);
|
||||
@@ -478,10 +489,10 @@ static int setup_nvpcr(void) {
|
||||
log_info("%zu NvPCRs initialized. (%zu NvPCRs were already initialized.)", c.n_anchored, c.n_already);
|
||||
} else if (c.n_already > 0)
|
||||
log_info("%zu NvPCRs already initialized.", c.n_already);
|
||||
else
|
||||
else if (c.n_failed == 0)
|
||||
log_debug("No NvPCRs defined, nothing initialized.");
|
||||
|
||||
return r;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int run(int argc, char *argv[]) {
|
||||
|
||||
Reference in New Issue
Block a user