Commit e6d654e9 authored by Gregory Price's avatar Gregory Price Committed by Ard Biesheuvel
Browse files

tpm: fix signed/unsigned bug when checking event logs



A prior bugfix that fixes a signed/unsigned error causes
another signed unsigned error.

A situation where log_tbl->size is invalid can cause the
size passed to memblock_reserve to become negative.

log_size from the main event log is an unsigned int, and
the code reduces to the following

u64 value = (int)unsigned_value;

This results in sign extension, and the value sent to
memblock_reserve becomes effectively negative.

Fixes: be59d57f ("efi/tpm: Fix sanity check of unsigned tbl_size being less than zero")
Signed-off-by: default avatarGregory Price <gourry@gourry.net>
Reviewed-by: default avatarIlias Apalodimas <ilias.apalodimas@linaro.org>
Signed-off-by: default avatarArd Biesheuvel <ardb@kernel.org>
parent c004703e
Loading
Loading
Loading
Loading
+9 −8
Original line number Diff line number Diff line
@@ -40,7 +40,8 @@ int __init efi_tpm_eventlog_init(void)
{
	struct linux_efi_tpm_eventlog *log_tbl;
	struct efi_tcg2_final_events_table *final_tbl;
	int tbl_size;
	unsigned int tbl_size;
	int final_tbl_size;
	int ret = 0;

	if (efi.tpm_log == EFI_INVALID_TABLE_ADDR) {
@@ -80,26 +81,26 @@ int __init efi_tpm_eventlog_init(void)
		goto out;
	}

	tbl_size = 0;
	final_tbl_size = 0;
	if (final_tbl->nr_events != 0) {
		void *events = (void *)efi.tpm_final_log
				+ sizeof(final_tbl->version)
				+ sizeof(final_tbl->nr_events);

		tbl_size = tpm2_calc_event_log_size(events,
		final_tbl_size = tpm2_calc_event_log_size(events,
							  final_tbl->nr_events,
							  log_tbl->log);
	}

	if (tbl_size < 0) {
	if (final_tbl_size < 0) {
		pr_err(FW_BUG "Failed to parse event in TPM Final Events Log\n");
		ret = -EINVAL;
		goto out_calc;
	}

	memblock_reserve(efi.tpm_final_log,
			 tbl_size + sizeof(*final_tbl));
	efi_tpm_final_log_size = tbl_size;
			 final_tbl_size + sizeof(*final_tbl));
	efi_tpm_final_log_size = final_tbl_size;

out_calc:
	early_memunmap(final_tbl, sizeof(*final_tbl));