Skip to content

Commit 7022c49

Browse files
rosslagerwallgregkh
authored andcommitted
efi: cper: Fix possible out-of-bounds access
[ Upstream commit 45b14a4 ] When checking a generic status block, we iterate over all the generic data blocks. The loop condition only checks that the start of the generic data block is valid (within estatus->data_length) but not the whole block. Because the size of data blocks (excluding error data) may vary depending on the revision and the revision is contained within the data block, ensure that enough of the current data block is valid before dereferencing any members otherwise an out-of-bounds access may occur if estatus->data_length is invalid. This relies on the fact that struct acpi_hest_generic_data_v300 is a superset of the earlier version. Also rework the other checks to avoid potential underflow. Signed-off-by: Ross Lagerwall <[email protected]> Acked-by: Borislav Petkov <[email protected]> Tested-by: Tyler Baicar <[email protected]> Signed-off-by: Rafael J. Wysocki <[email protected]> Signed-off-by: Sasha Levin <[email protected]>
1 parent 33640a0 commit 7022c49

File tree

1 file changed

+9
-4
lines changed

1 file changed

+9
-4
lines changed

drivers/firmware/efi/cper.c

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -641,19 +641,24 @@ EXPORT_SYMBOL_GPL(cper_estatus_check_header);
641641
int cper_estatus_check(const struct acpi_hest_generic_status *estatus)
642642
{
643643
struct acpi_hest_generic_data *gdata;
644-
unsigned int data_len, gedata_len;
644+
unsigned int data_len, record_size;
645645
int rc;
646646

647647
rc = cper_estatus_check_header(estatus);
648648
if (rc)
649649
return rc;
650+
650651
data_len = estatus->data_length;
651652

652653
apei_estatus_for_each_section(estatus, gdata) {
653-
gedata_len = acpi_hest_get_error_length(gdata);
654-
if (gedata_len > data_len - acpi_hest_get_size(gdata))
654+
if (sizeof(struct acpi_hest_generic_data) > data_len)
655+
return -EINVAL;
656+
657+
record_size = acpi_hest_get_record_size(gdata);
658+
if (record_size > data_len)
655659
return -EINVAL;
656-
data_len -= acpi_hest_get_record_size(gdata);
660+
661+
data_len -= record_size;
657662
}
658663
if (data_len)
659664
return -EINVAL;

0 commit comments

Comments
 (0)