From 5104405bf632fa00ecd15631e80a3a963943bf85 Mon Sep 17 00:00:00 2001 From: Ross Lagerwall Date: Fri, 15 Mar 2019 10:29:09 +0800 Subject: [PATCH] ACPI: APEI: Fix possible out-of-bounds access to BERT region mainline inclusion from mainline-5.0 commit 1c0d9b1c31d1 category: bugfix bugzilla: 11629 CVE: NA ------------------------------------------------- Check that the length recorded in the generic error status block is within the region before checking the contents of the region itself. Otherwise it may result in an out-of-bounds access if the system firmware has generated a status block with an invalid length (larger than the mapped region). Also move the block_status check so that it only happens after the block has been verified to be within the mapped region. Signed-off-by: Ross Lagerwall Acked-by: Borislav Petkov Tested-by: Tyler Baicar Signed-off-by: Rafael J. Wysocki Signed-off-by: Xiongfeng Wang Reviewed-by: Yao Hongbo Signed-off-by: Yang Yingliang --- drivers/acpi/apei/bert.c | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/drivers/acpi/apei/bert.c b/drivers/acpi/apei/bert.c index 12771fcf0417..0d948d0a41af 100644 --- a/drivers/acpi/apei/bert.c +++ b/drivers/acpi/apei/bert.c @@ -42,15 +42,7 @@ static void __init bert_print_all(struct acpi_bert_region *region, int remain = region_len; u32 estatus_len; - if (!estatus->block_status) - return; - - while (remain > sizeof(struct acpi_bert_region)) { - if (cper_estatus_check(estatus)) { - pr_err(FW_BUG "Invalid error record.\n"); - return; - } - + while (remain >= sizeof(struct acpi_bert_region)) { estatus_len = cper_estatus_len(estatus); if (remain < estatus_len) { pr_err(FW_BUG "Truncated status block (length: %u).\n", @@ -58,6 +50,15 @@ static void __init bert_print_all(struct acpi_bert_region *region, return; } + /* No more error records. */ + if (!estatus->block_status) + return; + + if (cper_estatus_check(estatus)) { + pr_err(FW_BUG "Invalid error record.\n"); + return; + } + pr_info_once("Error records from previous boot:\n"); cper_estatus_print(KERN_INFO HW_ERR, estatus); @@ -70,10 +71,6 @@ static void __init bert_print_all(struct acpi_bert_region *region, estatus->block_status = 0; estatus = (void *)estatus + estatus_len; - /* No more error records. */ - if (!estatus->block_status) - return; - remain -= estatus_len; } } -- GitLab