Commit 82aa37cf authored by Dan Williams's avatar Dan Williams

acpi, nfit: validate ars_status output buffer size

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

Cc: <stable@vger.kernel.org>
Fixes: 0caeef63 ("libnvdimm: Add a poison list and export badblocks")
Signed-off-by: default avatarDan Williams <dan.j.williams@intel.com>
parent efda1b5d
...@@ -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;
} }
...@@ -2002,19 +2003,32 @@ static int ars_get_status(struct acpi_nfit_desc *acpi_desc) ...@@ -2002,19 +2003,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;
} }
...@@ -2267,8 +2281,7 @@ static int acpi_nfit_query_poison(struct acpi_nfit_desc *acpi_desc, ...@@ -2267,8 +2281,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