Skip to content

Commit 45b14a4

Browse files
rosslagerwallrafaeljw
authored andcommitted
efi: cper: Fix possible out-of-bounds access
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 <ross.lagerwall@citrix.com> Acked-by: Borislav Petkov <bp@suse.de> Tested-by: Tyler Baicar <baicar.tyler@gmail.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
1 parent 1c0d9b1 commit 45b14a4

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
@@ -546,19 +546,24 @@ EXPORT_SYMBOL_GPL(cper_estatus_check_header);
546546
int cper_estatus_check(const struct acpi_hest_generic_status *estatus)
547547
{
548548
struct acpi_hest_generic_data *gdata;
549-
unsigned int data_len, gedata_len;
549+
unsigned int data_len, record_size;
550550
int rc;
551551

552552
rc = cper_estatus_check_header(estatus);
553553
if (rc)
554554
return rc;
555+
555556
data_len = estatus->data_length;
556557

557558
apei_estatus_for_each_section(estatus, gdata) {
558-
gedata_len = acpi_hest_get_error_length(gdata);
559-
if (gedata_len > data_len - acpi_hest_get_size(gdata))
559+
if (sizeof(struct acpi_hest_generic_data) > data_len)
560+
return -EINVAL;
561+
562+
record_size = acpi_hest_get_record_size(gdata);
563+
if (record_size > data_len)
560564
return -EINVAL;
561-
data_len -= acpi_hest_get_record_size(gdata);
565+
566+
data_len -= record_size;
562567
}
563568
if (data_len)
564569
return -EINVAL;

0 commit comments

Comments
 (0)