Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1c0d9b1c authored by Ross Lagerwall's avatar Ross Lagerwall Committed by Rafael J. Wysocki
Browse files

ACPI: APEI: Fix possible out-of-bounds access to BERT region



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: default avatarRoss Lagerwall <ross.lagerwall@citrix.com>
Acked-by: default avatarBorislav Petkov <bp@suse.de>
Tested-by: default avatarTyler Baicar <baicar.tyler@gmail.com>
Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
parent a2ed1ee9
Loading
Loading
Loading
Loading
+10 −13
Original line number Diff line number Diff line
@@ -42,22 +42,23 @@ static void __init bert_print_all(struct acpi_bert_region *region,
	int remain = region_len;
	u32 estatus_len;

	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",
			       estatus_len);
			return;
		}

		/* No more error records. */
		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;
		}

		estatus_len = cper_estatus_len(estatus);
		if (remain < estatus_len) {
			pr_err(FW_BUG "Truncated status block (length: %u).\n",
			       estatus_len);
			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;
	}
}