On Wed, 25 Sep 2019 at 19:27, Jerry Snitselaar jsnitsel@redhat.com wrote:
If __calc_tpm2_event_size fails to parse an event it will return 0, resulting tpm2_calc_event_log_size returning -1. Currently there is no check of this return value, and efi_tpm_final_log_size can end up being set to this negative value resulting in a panic like the the one given below.
Also __calc_tpm2_event_size returns a size of 0 when it fails to parse an event, so update function documentation to reflect this.
...
The root cause of the issue that caused the failure of event parsing in this case is resolved by Peter Jone's patchset dealing with large event logs where crossing over a page boundary causes the page with the event count to be unmapped.
Fixes: c46f3405692de ("tpm: Reserve the TPM final events table") Cc: linux-efi@vger.kernel.org Cc: linux-integrity@vger.kernel.org Cc: stable@vger.kernel.org Cc: Matthew Garrett mjg59@google.com Cc: Ard Biesheuvel ard.biesheuvel@linaro.org Cc: Jarkko Sakkinen jarkko.sakkinen@linux.intel.com Signed-off-by: Jerry Snitselaar jsnitsel@redhat.com
Thanks Jerry, I have queued this in the efi/urgent branch.
v3: rebase on top of Peter Jone's patchset v2: added FW_BUG to pr_err, and renamed label to out_calc. Updated doc comment for __calc_tpm2_event_size.
drivers/firmware/efi/tpm.c | 9 ++++++++- include/linux/tpm_eventlog.h | 2 +- 2 files changed, 9 insertions(+), 2 deletions(-)
diff --git a/drivers/firmware/efi/tpm.c b/drivers/firmware/efi/tpm.c index b9ae5c6f9b9c..703469c1ab8e 100644 --- a/drivers/firmware/efi/tpm.c +++ b/drivers/firmware/efi/tpm.c @@ -85,11 +85,18 @@ int __init efi_tpm_eventlog_init(void) final_tbl->nr_events, log_tbl->log); }
if (tbl_size < 0) {
pr_err(FW_BUG "Failed to parse event in TPM Final Events Log\n");
goto out_calc;
}
memblock_reserve((unsigned long)final_tbl, tbl_size + sizeof(*final_tbl));
early_memunmap(final_tbl, sizeof(*final_tbl)); efi_tpm_final_log_size = tbl_size;
+out_calc:
early_memunmap(final_tbl, sizeof(*final_tbl));
out: early_memunmap(log_tbl, sizeof(*log_tbl)); return ret; diff --git a/include/linux/tpm_eventlog.h b/include/linux/tpm_eventlog.h index 12584b69a3f3..2dfdd63ac034 100644 --- a/include/linux/tpm_eventlog.h +++ b/include/linux/tpm_eventlog.h @@ -152,7 +152,7 @@ struct tcg_algorithm_info {
- total. Once we've done this we know the offset of the data length field,
- and can calculate the total size of the event.
- Return: size of the event on success, <0 on failure
*/
- Return: size of the event on success, 0 on failure
static inline int __calc_tpm2_event_size(struct tcg_pcr_event2_head *event,
2.23.0