Commit 53ed7c2e authored by Dan Williams's avatar Dan Williams Committed by Greg Kroah-Hartman

acpi, nfit: validate ars_status output buffer size

commit 82aa37cf upstream.

If an ARS Status command returns truncated output, do not process
partial records or otherwise consume non-status fields.

Fixes: 0caeef63 ("libnvdimm: Add a poison list and export badblocks")
Signed-off-by: default avatarDan Williams <dan.j.williams@intel.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent e04e2dac
...@@ -146,7 +146,8 @@ static int xlat_status(void *buf, unsigned int cmd, u32 status) ...@@ -146,7 +146,8 @@ static int xlat_status(void *buf, unsigned int cmd, u32 status)
* then just continue with the returned results. * then just continue with the returned results.
*/ */
if (status == NFIT_ARS_STATUS_INTR) { if (status == NFIT_ARS_STATUS_INTR) {
if (ars_status->flags & NFIT_ARS_F_OVERFLOW) if (ars_status->out_length >= 40 && (ars_status->flags
& NFIT_ARS_F_OVERFLOW))
return -ENOSPC; return -ENOSPC;
return 0; return 0;
} }
...@@ -1858,19 +1859,32 @@ static int ars_get_status(struct acpi_nfit_desc *acpi_desc) ...@@ -1858,19 +1859,32 @@ static int ars_get_status(struct acpi_nfit_desc *acpi_desc)
return cmd_rc; return cmd_rc;
} }
static int ars_status_process_records(struct nvdimm_bus *nvdimm_bus, static int ars_status_process_records(struct acpi_nfit_desc *acpi_desc,
struct nd_cmd_ars_status *ars_status) struct nd_cmd_ars_status *ars_status)
{ {
struct nvdimm_bus *nvdimm_bus = acpi_desc->nvdimm_bus;
int rc; int rc;
u32 i; u32 i;
/*
* First record starts at 44 byte offset from the start of the
* payload.
*/
if (ars_status->out_length < 44)
return 0;
for (i = 0; i < ars_status->num_records; i++) { for (i = 0; i < ars_status->num_records; i++) {
/* only process full records */
if (ars_status->out_length
< 44 + sizeof(struct nd_ars_record) * (i + 1))
break;
rc = nvdimm_bus_add_poison(nvdimm_bus, rc = nvdimm_bus_add_poison(nvdimm_bus,
ars_status->records[i].err_address, ars_status->records[i].err_address,
ars_status->records[i].length); ars_status->records[i].length);
if (rc) if (rc)
return rc; return rc;
} }
if (i < ars_status->num_records)
dev_warn(acpi_desc->dev, "detected truncated ars results\n");
return 0; return 0;
} }
...@@ -2123,8 +2137,7 @@ static int acpi_nfit_query_poison(struct acpi_nfit_desc *acpi_desc, ...@@ -2123,8 +2137,7 @@ static int acpi_nfit_query_poison(struct acpi_nfit_desc *acpi_desc,
if (rc < 0 && rc != -ENOSPC) if (rc < 0 && rc != -ENOSPC)
return rc; return rc;
if (ars_status_process_records(acpi_desc->nvdimm_bus, if (ars_status_process_records(acpi_desc, acpi_desc->ars_status))
acpi_desc->ars_status))
return -ENOMEM; return -ENOMEM;
return 0; return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment