]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blobdiff - releases/4.14.111/efi-cper-fix-possible-out-of-bounds-access.patch
Linux 4.14.111
[thirdparty/kernel/stable-queue.git] / releases / 4.14.111 / efi-cper-fix-possible-out-of-bounds-access.patch
diff --git a/releases/4.14.111/efi-cper-fix-possible-out-of-bounds-access.patch b/releases/4.14.111/efi-cper-fix-possible-out-of-bounds-access.patch
new file mode 100644 (file)
index 0000000..0a29e1d
--- /dev/null
@@ -0,0 +1,65 @@
+From 4762198f67971267219148d22af61719cd9110fe Mon Sep 17 00:00:00 2001
+From: Ross Lagerwall <ross.lagerwall@citrix.com>
+Date: Mon, 28 Jan 2019 10:04:24 +0000
+Subject: efi: cper: Fix possible out-of-bounds access
+
+[ Upstream commit 45b14a4ffcc1e0b5caa246638f942cbe7eaea7ad ]
+
+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>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/firmware/efi/cper.c | 13 +++++++++----
+ 1 file changed, 9 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/firmware/efi/cper.c b/drivers/firmware/efi/cper.c
+index d2fcafcea07e..ce23d5402bd6 100644
+--- a/drivers/firmware/efi/cper.c
++++ b/drivers/firmware/efi/cper.c
+@@ -641,19 +641,24 @@ EXPORT_SYMBOL_GPL(cper_estatus_check_header);
+ int cper_estatus_check(const struct acpi_hest_generic_status *estatus)
+ {
+       struct acpi_hest_generic_data *gdata;
+-      unsigned int data_len, gedata_len;
++      unsigned int data_len, record_size;
+       int rc;
+       rc = cper_estatus_check_header(estatus);
+       if (rc)
+               return rc;
++
+       data_len = estatus->data_length;
+       apei_estatus_for_each_section(estatus, gdata) {
+-              gedata_len = acpi_hest_get_error_length(gdata);
+-              if (gedata_len > data_len - acpi_hest_get_size(gdata))
++              if (sizeof(struct acpi_hest_generic_data) > data_len)
++                      return -EINVAL;
++
++              record_size = acpi_hest_get_record_size(gdata);
++              if (record_size > data_len)
+                       return -EINVAL;
+-              data_len -= acpi_hest_get_record_size(gdata);
++
++              data_len -= record_size;
+       }
+       if (data_len)
+               return -EINVAL;
+-- 
+2.19.1
+