From 0b6954b8d538f0e7eb6b7aa852fb0e3a4a9ed352 Mon Sep 17 00:00:00 2001 From: Kapil Porwal Date: Fri, 20 Jan 2023 01:00:42 +0530 Subject: [PATCH] elogtool: Fix potential buffer overrun BUG=b:239110778 TEST=Make sure that the output of elogtool is unaffected by this change. Signed-off-by: Kapil Porwal Change-Id: Ia1a6341abd834dd9ad5f12c9f2eefb0489364a08 Reviewed-on: https://review.coreboot.org/c/coreboot/+/72099 Reviewed-by: Subrata Banik Tested-by: build bot (Jenkins) --- util/cbfstool/elogtool.c | 6 +++++- util/cbfstool/eventlog.c | 35 +++++++++++++++++++++++++++++++++-- 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/util/cbfstool/elogtool.c b/util/cbfstool/elogtool.c index 1e9b6605f9..846575765e 100644 --- a/util/cbfstool/elogtool.c +++ b/util/cbfstool/elogtool.c @@ -196,7 +196,11 @@ static int cmd_list(const struct buffer *buf) event = buffer_get(buf) + sizeof(struct elog_header); while ((const void *)(event) < buffer_end(buf)) { - if (event->type == ELOG_TYPE_EOL || event->length == 0) + if (((const void *)event + sizeof(*event)) >= buffer_end(buf) + || event->length <= sizeof(*event) + || event->length > ELOG_MAX_EVENT_SIZE + || ((const void *)event + event->length) >= buffer_end(buf) + || event->type == ELOG_TYPE_EOL) break; eventlog_print_event(event, count); diff --git a/util/cbfstool/eventlog.c b/util/cbfstool/eventlog.c index 9faf39b10d..0ab8930548 100644 --- a/util/cbfstool/eventlog.c +++ b/util/cbfstool/eventlog.c @@ -460,6 +460,32 @@ static int eventlog_print_data(const struct event_header *event) {0, NULL}, }; + size_t elog_type_to_min_size[] = { + [ELOG_TYPE_LOG_CLEAR] = sizeof(uint16_t), + [ELOG_TYPE_BOOT] = sizeof(uint32_t), + [ELOG_TYPE_LAST_POST_CODE] = sizeof(uint16_t), + [ELOG_TYPE_POST_EXTRA] = sizeof(uint32_t), + [ELOG_TYPE_OS_EVENT] = sizeof(uint32_t), + [ELOG_TYPE_ACPI_ENTER] = sizeof(uint8_t), + [ELOG_TYPE_ACPI_WAKE] = sizeof(uint8_t), + [ELOG_TYPE_ACPI_DEEP_WAKE] = sizeof(uint8_t), + [ELOG_TYPE_WAKE_SOURCE] = sizeof(struct elog_event_data_wake), + [ELOG_TYPE_EC_EVENT] = sizeof(uint8_t), + [ELOG_TYPE_EC_DEVICE_EVENT] = sizeof(uint8_t), + [ELOG_DEPRECATED_TYPE_CROS_RECOVERY_MODE] = sizeof(uint8_t), + [ELOG_TYPE_MANAGEMENT_ENGINE] = sizeof(uint8_t), + [ELOG_TYPE_MEM_CACHE_UPDATE] = sizeof(struct elog_event_mem_cache_update), + [ELOG_TYPE_EXTENDED_EVENT] = sizeof(struct elog_event_extended_event), + [ELOG_TYPE_CROS_DIAGNOSTICS] = sizeof(uint8_t), + [ELOG_TYPE_FW_VBOOT_INFO] = sizeof(uint16_t), + [0xff] = 0, + }; + + if (event->length <= sizeof(*event) + elog_type_to_min_size[event->type]) { + eventlog_printf("INVALID DATA (length = %u)", event->length - sizeof(*event)); + return 0; + } + switch (event->type) { case ELOG_TYPE_LOG_CLEAR: { const uint16_t *bytes = event_get_data(event); @@ -587,10 +613,15 @@ static int eventlog_print_data(const struct event_header *event) eventlog_printf("boot_mode=%s", vb2_boot_mode_string(info->boot_mode)); if (info->boot_mode == VB2_BOOT_MODE_BROKEN_SCREEN || - info->boot_mode == VB2_BOOT_MODE_MANUAL_RECOVERY) - eventlog_printf("recovery_reason=%#x/%#x (%s)", + info->boot_mode == VB2_BOOT_MODE_MANUAL_RECOVERY) { + if (event->length <= sizeof(*event) + sizeof(*info)) + eventlog_printf("INVALID DATA (length = %u)", + event->length - sizeof(*event)); + else + eventlog_printf("recovery_reason=%#x/%#x (%s)", info->recovery_reason, info->recovery_subcode, vb2_get_recovery_reason_string(info->recovery_reason)); + } eventlog_printf("fw_tried=%s", vb2_slot_string(info->slot)); eventlog_printf("fw_try_count=%d", info->tries);