* [PATCH] tpm: eventlog: check the payload size before reading tag events
@ 2026-11-03 8:41 Guanglei Zhu
2026-11-03 13:00 ` Jarkko Sakkinen
0 siblings, 1 reply; 5+ messages in thread
From: Guanglei Zhu @ 2026-11-03 8:41 UTC (permalink / raw)
To: peterhuewe, jarkko; +Cc: jgg, linux-integrity, linux-kernel, liuc63, stable
The EVENT_TAG branch of get_event_name() casts the event payload to
struct tcpa_pc_event and reads from it:
pc_event = (struct tcpa_pc_event *)event_entry;
switch (do_endian_conversion(pc_event->event_id)) {
...
for (i = 0; i < 20; i++)
d_len += sprintf(&data[2*i], "%02x",
pc_event->event_data[i]);
The log iterators only verify that the event header plus the declared
event_size stays within the log buffer; they do not require the
payload of an EVENT_TAG entry to be large enough for the fields the
branch reads. A truncated entry makes the branch read up to 20 bytes
of event_data[] past the end of the entry, and, for the last entry in
the log, past the end of the buffer itself.
Skip entries whose payload cannot even hold the event id, and skip
the 20-byte digest dump when the payload cannot hold the full
tcpa_pc_event header plus the digest, so the branch never reads
beyond the entry it is formatting.
Fixes: 55a82ab3181b ("[PATCH] tpm: add bios measurement log")
Cc: stable@vger.kernel.org
Signed-off-by: Guanglei Zhu <zhugl3@xiaopeng.com>
---
drivers/char/tpm/eventlog/tpm1.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/drivers/char/tpm/eventlog/tpm1.c b/drivers/char/tpm/eventlog/tpm1.c
index 0397e3361020..f93a358a706e 100644
--- a/drivers/char/tpm/eventlog/tpm1.c
+++ b/drivers/char/tpm/eventlog/tpm1.c
@@ -178,6 +178,10 @@ static int get_event_name(char *dest, struct tcpa_event *event,
}
break;
case EVENT_TAG:
+ if (do_endian_conversion(event->event_size) <
+ sizeof(pc_event->event_id))
+ break;
+
pc_event = (struct tcpa_pc_event *)event_entry;
/* ToDo Row data -> Base64 */
@@ -203,6 +207,9 @@ static int get_event_name(char *dest, struct tcpa_event *event,
name = tcpa_pc_event_id_strings[do_endian_conversion
(pc_event->event_id)];
n_len = strlen(name);
+ if (do_endian_conversion(event->event_size) <
+ sizeof(struct tcpa_pc_event) + 20)
+ break;
for (i = 0; i < 20; i++)
d_len += sprintf(&data[2*i], "%02x",
pc_event->event_data[i]);
--
2.50.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH] tpm: eventlog: check the payload size before reading tag events
2026-11-03 8:41 [PATCH] tpm: eventlog: check the payload size before reading tag events Guanglei Zhu
@ 2026-11-03 13:00 ` Jarkko Sakkinen
2026-11-04 2:58 ` Guanglei Zhu
0 siblings, 1 reply; 5+ messages in thread
From: Jarkko Sakkinen @ 2026-11-03 13:00 UTC (permalink / raw)
To: Guanglei Zhu
Cc: peterhuewe, jgg, linux-integrity, linux-kernel, liuc63, stable
On Tue, Nov 03, 2026 at 04:41:55PM +0800, Guanglei Zhu wrote:
> The EVENT_TAG branch of get_event_name() casts the event payload to
> struct tcpa_pc_event and reads from it:
>
> pc_event = (struct tcpa_pc_event *)event_entry;
>
> switch (do_endian_conversion(pc_event->event_id)) {
> ...
> for (i = 0; i < 20; i++)
> d_len += sprintf(&data[2*i], "%02x",
> pc_event->event_data[i]);
>
> The log iterators only verify that the event header plus the declared
> event_size stays within the log buffer; they do not require the
> payload of an EVENT_TAG entry to be large enough for the fields the
> branch reads. A truncated entry makes the branch read up to 20 bytes
> of event_data[] past the end of the entry, and, for the last entry in
> the log, past the end of the buffer itself.
What does the spec say about this?
>
> Skip entries whose payload cannot even hold the event id, and skip
> the 20-byte digest dump when the payload cannot hold the full
> tcpa_pc_event header plus the digest, so the branch never reads
> beyond the entry it is formatting.
>
> Fixes: 55a82ab3181b ("[PATCH] tpm: add bios measurement log")
> Cc: stable@vger.kernel.org
> Signed-off-by: Guanglei Zhu <zhugl3@xiaopeng.com>
> ---
> drivers/char/tpm/eventlog/tpm1.c | 7 +++++++
> 1 file changed, 7 insertions(+)
>
> diff --git a/drivers/char/tpm/eventlog/tpm1.c b/drivers/char/tpm/eventlog/tpm1.c
> index 0397e3361020..f93a358a706e 100644
> --- a/drivers/char/tpm/eventlog/tpm1.c
> +++ b/drivers/char/tpm/eventlog/tpm1.c
> @@ -178,6 +178,10 @@ static int get_event_name(char *dest, struct tcpa_event *event,
> }
> break;
> case EVENT_TAG:
> + if (do_endian_conversion(event->event_size) <
> + sizeof(pc_event->event_id))
> + break;
> +
> pc_event = (struct tcpa_pc_event *)event_entry;
>
> /* ToDo Row data -> Base64 */
> @@ -203,6 +207,9 @@ static int get_event_name(char *dest, struct tcpa_event *event,
> name = tcpa_pc_event_id_strings[do_endian_conversion
> (pc_event->event_id)];
> n_len = strlen(name);
> + if (do_endian_conversion(event->event_size) <
> + sizeof(struct tcpa_pc_event) + 20)
> + break;
> for (i = 0; i < 20; i++)
> d_len += sprintf(&data[2*i], "%02x",
> pc_event->event_data[i]);
> --
> 2.50.1
>
Br, Jarkko
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] tpm: eventlog: check the payload size before reading tag events
2026-11-03 13:00 ` Jarkko Sakkinen
@ 2026-11-04 2:58 ` Guanglei Zhu
2026-11-04 11:02 ` Jarkko Sakkinen
0 siblings, 1 reply; 5+ messages in thread
From: Guanglei Zhu @ 2026-11-04 2:58 UTC (permalink / raw)
To: jarkko; +Cc: peterhuewe, jgg, linux-integrity, linux-kernel, liuc63
The legacy PC Client spec defines the EV_EVENT_TAG payload as a
TCPA_PC_EVENT: event_id, event_size and event-type-specific data.
A conformant entry carries the 8-byte header, and the hash-type
ids carry a full digest.
The catch is that the log is an ACPI table the firmware leaves in
memory: the TPM never measures the log itself, so the kernel cannot
tell a conformant log from a corrupted one. The iterators already
work on that assumption - they stop once the declared event_size
runs past the buffer end - and this check applies the same rule to
what the EVENT_TAG branch reads off the payload.
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] tpm: eventlog: check the payload size before reading tag events
2026-11-04 2:58 ` Guanglei Zhu
@ 2026-11-04 11:02 ` Jarkko Sakkinen
2026-11-04 11:26 ` [PATCH v2] " Guanglei Zhu
0 siblings, 1 reply; 5+ messages in thread
From: Jarkko Sakkinen @ 2026-11-04 11:02 UTC (permalink / raw)
To: Guanglei Zhu; +Cc: peterhuewe, jgg, linux-integrity, linux-kernel, liuc63
On Wed, Nov 04, 2026 at 10:58:09AM +0800, Guanglei Zhu wrote:
> The legacy PC Client spec defines the EV_EVENT_TAG payload as a
> TCPA_PC_EVENT: event_id, event_size and event-type-specific data.
> A conformant entry carries the 8-byte header, and the hash-type
> ids carry a full digest.
>
> The catch is that the log is an ACPI table the firmware leaves in
> memory: the TPM never measures the log itself, so the kernel cannot
> tell a conformant log from a corrupted one. The iterators already
> work on that assumption - they stop once the declared event_size
> runs past the buffer end - and this check applies the same rule to
> what the EVENT_TAG branch reads off the payload.
Yeah, this is exactly what I wanted to know. Could you refine the
patch and send a new version with this?
It's really good stuff to have in the commit log when looking back
at old changes.
Br, Jarkko
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH v2] tpm: eventlog: check the payload size before reading tag events
2026-11-04 11:02 ` Jarkko Sakkinen
@ 2026-11-04 11:26 ` Guanglei Zhu
0 siblings, 0 replies; 5+ messages in thread
From: Guanglei Zhu @ 2026-11-04 11:26 UTC (permalink / raw)
To: peterhuewe, jarkko; +Cc: jgg, linux-integrity, linux-kernel, liuc63, stable
The EVENT_TAG branch of get_event_name() casts the event payload to
struct tcpa_pc_event and reads from it:
pc_event = (struct tcpa_pc_event *)event_entry;
switch (do_endian_conversion(pc_event->event_id)) {
...
for (i = 0; i < 20; i++)
d_len += sprintf(&data[2*i], "%02x",
pc_event->event_data[i]);
The log iterators only verify that the event header plus the declared
event_size stays within the log buffer; they do not require the
payload of an EVENT_TAG entry to be large enough for the fields the
branch reads. A truncated entry makes the branch read up to 20 bytes
of event_data[] past the end of the entry, and, for the last entry in
the log, past the end of the buffer itself.
The legacy PC Client spec defines the EV_EVENT_TAG payload as a
TCPA_PC_EVENT - event_id, event_size and event-type-specific data -
so a conformant entry carries the 8-byte header and the hash-type
ids carry a full digest. The log itself, however, is an ACPI table
the firmware leaves in memory: the TPM never measures the log, so
the kernel cannot tell a conformant log from a corrupted one. The
iterators already work on that assumption - they stop once the
declared event_size runs past the buffer end - and the readers
should apply the same rule to what they take off the payload.
Skip entries whose payload cannot even hold the event id, and skip
the 20-byte digest dump when the payload cannot hold the full
tcpa_pc_event header plus the digest, so the branch never reads
beyond the entry it is formatting.
Fixes: 55a82ab3181b ("[PATCH] tpm: add bios measurement log")
Cc: stable@vger.kernel.org
Signed-off-by: Guanglei Zhu <zhugl3@xiaopeng.com>
---
v2: fold the spec rationale from the list discussion into the commit
log, per review - what the legacy PC Client spec defines for the
tag payload, why the kernel cannot trust the log to conform, and
how the iterators already handle it.
drivers/char/tpm/eventlog/tpm1.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/drivers/char/tpm/eventlog/tpm1.c b/drivers/char/tpm/eventlog/tpm1.c
index 0397e33..f93a358 100644
--- a/drivers/char/tpm/eventlog/tpm1.c
+++ b/drivers/char/tpm/eventlog/tpm1.c
@@ -178,6 +178,10 @@ static int get_event_name(char *dest, struct tcpa_event *event,
}
break;
case EVENT_TAG:
+ if (do_endian_conversion(event->event_size) <
+ sizeof(pc_event->event_id))
+ break;
+
pc_event = (struct tcpa_pc_event *)event_entry;
/* ToDo Row data -> Base64 */
@@ -203,6 +207,9 @@ static int get_event_name(char *dest, struct tcpa_event *event,
name = tcpa_pc_event_id_strings[do_endian_conversion
(pc_event->event_id)];
n_len = strlen(name);
+ if (do_endian_conversion(event->event_size) <
+ sizeof(struct tcpa_pc_event) + 20)
+ break;
for (i = 0; i < 20; i++)
d_len += sprintf(&data[2*i], "%02x",
pc_event->event_data[i]);
--
2.43.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-11-04 11:26 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-03 8:41 [PATCH] tpm: eventlog: check the payload size before reading tag events Guanglei Zhu
2026-11-03 13:00 ` Jarkko Sakkinen
2026-11-04 2:58 ` Guanglei Zhu
2026-11-04 11:02 ` Jarkko Sakkinen
2026-11-04 11:26 ` [PATCH v2] " Guanglei Zhu
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.