--- /dev/null
+From d6eb270c57fef35798525004ddf2ac5dcdadd43b Mon Sep 17 00:00:00 2001
+From: Dan Williams <dan.j.williams@intel.com>
+Date: Tue, 6 Dec 2016 15:06:55 -0800
+Subject: acpi, nfit: fix bus vs dimm confusion in xlat_status
+
+From: Dan Williams <dan.j.williams@intel.com>
+
+commit d6eb270c57fef35798525004ddf2ac5dcdadd43b upstream.
+
+Given dimms and bus commands share the same command number space we need
+to be careful that we are translating status in the correct context.
+Otherwise we can, for example, fail an ND_CMD_GET_CONFIG_SIZE command
+because max_xfer is zero. It fails because that condition erroneously
+correlates with the 'cleared == 0' failure of ND_CMD_CLEAR_ERROR.
+
+Fixes: aef253382266 ("libnvdimm, nfit: centralize command status translation")
+Signed-off-by: Dan Williams <dan.j.williams@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/acpi/nfit/core.c | 17 ++++++++++++++---
+ 1 file changed, 14 insertions(+), 3 deletions(-)
+
+--- a/drivers/acpi/nfit/core.c
++++ b/drivers/acpi/nfit/core.c
+@@ -94,7 +94,7 @@ static struct acpi_device *to_acpi_dev(s
+ return to_acpi_device(acpi_desc->dev);
+ }
+
+-static int xlat_status(void *buf, unsigned int cmd, u32 status)
++static int xlat_bus_status(void *buf, unsigned int cmd, u32 status)
+ {
+ struct nd_cmd_clear_error *clear_err;
+ struct nd_cmd_ars_status *ars_status;
+@@ -175,6 +175,16 @@ static int xlat_status(void *buf, unsign
+ return 0;
+ }
+
++static int xlat_status(struct nvdimm *nvdimm, void *buf, unsigned int cmd,
++ u32 status)
++{
++ if (!nvdimm)
++ return xlat_bus_status(buf, cmd, status);
++ if (status)
++ return -EIO;
++ return 0;
++}
++
+ static int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc,
+ struct nvdimm *nvdimm, unsigned int cmd, void *buf,
+ unsigned int buf_len, int *cmd_rc)
+@@ -335,7 +345,8 @@ static int acpi_nfit_ctl(struct nvdimm_b
+ */
+ rc = buf_len - offset - in_buf.buffer.length;
+ if (cmd_rc)
+- *cmd_rc = xlat_status(buf, cmd, fw_status);
++ *cmd_rc = xlat_status(nvdimm, buf, cmd,
++ fw_status);
+ } else {
+ dev_err(dev, "%s:%s underrun cmd: %s buf_len: %d out_len: %d\n",
+ __func__, dimm_name, cmd_name, buf_len,
+@@ -345,7 +356,7 @@ static int acpi_nfit_ctl(struct nvdimm_b
+ } else {
+ rc = 0;
+ if (cmd_rc)
+- *cmd_rc = xlat_status(buf, cmd, fw_status);
++ *cmd_rc = xlat_status(nvdimm, buf, cmd, fw_status);
+ }
+
+ out:
--- /dev/null
+From 9a901f5495e26e691c7d0ea7b6057a2f3e6330ed Mon Sep 17 00:00:00 2001
+From: Vishal Verma <vishal.l.verma@intel.com>
+Date: Mon, 5 Dec 2016 17:00:37 -0700
+Subject: acpi, nfit: fix extended status translations for ACPI DSMs
+
+From: Vishal Verma <vishal.l.verma@intel.com>
+
+commit 9a901f5495e26e691c7d0ea7b6057a2f3e6330ed upstream.
+
+ACPI DSMs can have an 'extended' status which can be non-zero to convey
+additional information about the command. In the xlat_status routine,
+where we translate the command statuses, we were returning an error for
+a non-zero extended status, even if the primary status indicated success.
+
+Return from each command's 'case' once we have verified both its status
+and extend status are good.
+
+Fixes: 11294d63ac91 ("nfit: fail DSMs that return non-zero status by default")
+Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
+Signed-off-by: Dan Williams <dan.j.williams@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/acpi/nfit/core.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+--- a/drivers/acpi/nfit/core.c
++++ b/drivers/acpi/nfit/core.c
+@@ -113,7 +113,7 @@ static int xlat_status(void *buf, unsign
+ flags = ND_ARS_PERSISTENT | ND_ARS_VOLATILE;
+ if ((status >> 16 & flags) == 0)
+ return -ENOTTY;
+- break;
++ return 0;
+ case ND_CMD_ARS_START:
+ /* ARS is in progress */
+ if ((status & 0xffff) == NFIT_ARS_START_BUSY)
+@@ -122,7 +122,7 @@ static int xlat_status(void *buf, unsign
+ /* Command failed */
+ if (status & 0xffff)
+ return -EIO;
+- break;
++ return 0;
+ case ND_CMD_ARS_STATUS:
+ ars_status = buf;
+ /* Command failed */
+@@ -154,7 +154,7 @@ static int xlat_status(void *buf, unsign
+ /* Unknown status */
+ if (status >> 16)
+ return -EIO;
+- break;
++ return 0;
+ case ND_CMD_CLEAR_ERROR:
+ clear_err = buf;
+ if (status & 0xffff)
+@@ -163,7 +163,7 @@ static int xlat_status(void *buf, unsign
+ return -EIO;
+ if (clear_err->length > clear_err->cleared)
+ return clear_err->cleared;
+- break;
++ return 0;
+ default:
+ break;
+ }
--- /dev/null
+From efda1b5d87cbc3d8816f94a3815b413f1868e10d Mon Sep 17 00:00:00 2001
+From: Dan Williams <dan.j.williams@intel.com>
+Date: Tue, 6 Dec 2016 09:10:12 -0800
+Subject: acpi, nfit, libnvdimm: fix / harden ars_status output length handling
+
+From: Dan Williams <dan.j.williams@intel.com>
+
+commit efda1b5d87cbc3d8816f94a3815b413f1868e10d upstream.
+
+Given ambiguities in the ACPI 6.1 definition of the "Output (Size)"
+field of the ARS (Address Range Scrub) Status command, a firmware
+implementation may in practice return 0, 4, or 8 to indicate that there
+is no output payload to process.
+
+The specification states "Size of Output Buffer in bytes, including this
+field.". However, 'Output Buffer' is also the name of the entire
+payload, and earlier in the specification it states "Max Query ARS
+Status Output Buffer Size: Maximum size of buffer (including the Status
+and Extended Status fields)".
+
+Without this fix if the BIOS happens to return 0 it causes memory
+corruption as evidenced by this result from the acpi_nfit_ctl() unit
+test.
+
+ ars_status00000000: 00020000 00000000 ........
+ BUG: stack guard page was hit at ffffc90001750000 (stack is ffffc9000174c000..ffffc9000174ffff)
+ kernel stack overflow (page fault): 0000 [#1] SMP DEBUG_PAGEALLOC
+ task: ffff8803332d2ec0 task.stack: ffffc9000174c000
+ RIP: 0010:[<ffffffff814cfe72>] [<ffffffff814cfe72>] __memcpy+0x12/0x20
+ RSP: 0018:ffffc9000174f9a8 EFLAGS: 00010246
+ RAX: ffffc9000174fab8 RBX: 0000000000000000 RCX: 000000001fffff56
+ RDX: 0000000000000000 RSI: ffff8803231f5a08 RDI: ffffc90001750000
+ RBP: ffffc9000174fa88 R08: ffffc9000174fab0 R09: ffff8803231f54b8
+ R10: 0000000000000008 R11: 0000000000000001 R12: 0000000000000000
+ R13: 0000000000000000 R14: 0000000000000003 R15: ffff8803231f54a0
+ FS: 00007f3a611af640(0000) GS:ffff88033ed00000(0000) knlGS:0000000000000000
+ CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+ CR2: ffffc90001750000 CR3: 0000000325b20000 CR4: 00000000000406e0
+ Stack:
+ ffffffffa00bc60d 0000000000000008 ffffc90000000001 ffffc9000174faac
+ 0000000000000292 ffffffffa00c24e4 ffffffffa00c2914 0000000000000000
+ 0000000000000000 ffffffff00000003 ffff880331ae8ad0 0000000800000246
+ Call Trace:
+ [<ffffffffa00bc60d>] ? acpi_nfit_ctl+0x49d/0x750 [nfit]
+ [<ffffffffa01f4fe0>] nfit_test_probe+0x670/0xb1b [nfit_test]
+
+Fixes: 747ffe11b440 ("libnvdimm, tools/testing/nvdimm: fix 'ars_status' output buffer sizing")
+Signed-off-by: Dan Williams <dan.j.williams@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/acpi/nfit/core.c | 3 ++-
+ drivers/nvdimm/bus.c | 25 ++++++++++++++++++++-----
+ include/linux/libnvdimm.h | 2 +-
+ 3 files changed, 23 insertions(+), 7 deletions(-)
+
+--- a/drivers/acpi/nfit/core.c
++++ b/drivers/acpi/nfit/core.c
+@@ -298,7 +298,8 @@ static int acpi_nfit_ctl(struct nvdimm_b
+
+ for (i = 0, offset = 0; i < desc->out_num; i++) {
+ u32 out_size = nd_cmd_out_size(nvdimm, cmd, desc, i, buf,
+- (u32 *) out_obj->buffer.pointer);
++ (u32 *) out_obj->buffer.pointer,
++ out_obj->buffer.length - offset);
+
+ if (offset + out_size > out_obj->buffer.length) {
+ dev_dbg(dev, "%s:%s output object underflow cmd: %s field: %d\n",
+--- a/drivers/nvdimm/bus.c
++++ b/drivers/nvdimm/bus.c
+@@ -715,7 +715,7 @@ EXPORT_SYMBOL_GPL(nd_cmd_in_size);
+
+ u32 nd_cmd_out_size(struct nvdimm *nvdimm, int cmd,
+ const struct nd_cmd_desc *desc, int idx, const u32 *in_field,
+- const u32 *out_field)
++ const u32 *out_field, unsigned long remainder)
+ {
+ if (idx >= desc->out_num)
+ return UINT_MAX;
+@@ -727,9 +727,24 @@ u32 nd_cmd_out_size(struct nvdimm *nvdim
+ return in_field[1];
+ else if (nvdimm && cmd == ND_CMD_VENDOR && idx == 2)
+ return out_field[1];
+- else if (!nvdimm && cmd == ND_CMD_ARS_STATUS && idx == 2)
+- return out_field[1] - 8;
+- else if (cmd == ND_CMD_CALL) {
++ else if (!nvdimm && cmd == ND_CMD_ARS_STATUS && idx == 2) {
++ /*
++ * Per table 9-276 ARS Data in ACPI 6.1, out_field[1] is
++ * "Size of Output Buffer in bytes, including this
++ * field."
++ */
++ if (out_field[1] < 4)
++ return 0;
++ /*
++ * ACPI 6.1 is ambiguous if 'status' is included in the
++ * output size. If we encounter an output size that
++ * overshoots the remainder by 4 bytes, assume it was
++ * including 'status'.
++ */
++ if (out_field[1] - 8 == remainder)
++ return remainder;
++ return out_field[1] - 4;
++ } else if (cmd == ND_CMD_CALL) {
+ struct nd_cmd_pkg *pkg = (struct nd_cmd_pkg *) in_field;
+
+ return pkg->nd_size_out;
+@@ -876,7 +891,7 @@ static int __nd_ioctl(struct nvdimm_bus
+ /* process an output envelope */
+ for (i = 0; i < desc->out_num; i++) {
+ u32 out_size = nd_cmd_out_size(nvdimm, cmd, desc, i,
+- (u32 *) in_env, (u32 *) out_env);
++ (u32 *) in_env, (u32 *) out_env, 0);
+ u32 copy;
+
+ if (out_size == UINT_MAX) {
+--- a/include/linux/libnvdimm.h
++++ b/include/linux/libnvdimm.h
+@@ -153,7 +153,7 @@ u32 nd_cmd_in_size(struct nvdimm *nvdimm
+ const struct nd_cmd_desc *desc, int idx, void *buf);
+ u32 nd_cmd_out_size(struct nvdimm *nvdimm, int cmd,
+ const struct nd_cmd_desc *desc, int idx, const u32 *in_field,
+- const u32 *out_field);
++ const u32 *out_field, unsigned long remainder);
+ int nvdimm_bus_check_dimm_count(struct nvdimm_bus *nvdimm_bus, int dimm_count);
+ struct nd_region *nvdimm_pmem_region_create(struct nvdimm_bus *nvdimm_bus,
+ struct nd_region_desc *ndr_desc);
--- /dev/null
+From 82aa37cf09867c5e2c0326649d570e5b25c1189a Mon Sep 17 00:00:00 2001
+From: Dan Williams <dan.j.williams@intel.com>
+Date: Tue, 6 Dec 2016 12:45:24 -0800
+Subject: acpi, nfit: validate ars_status output buffer size
+
+From: Dan Williams <dan.j.williams@intel.com>
+
+commit 82aa37cf09867c5e2c0326649d570e5b25c1189a upstream.
+
+If an ARS Status command returns truncated output, do not process
+partial records or otherwise consume non-status fields.
+
+Fixes: 0caeef63e6d2 ("libnvdimm: Add a poison list and export badblocks")
+Signed-off-by: Dan Williams <dan.j.williams@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/acpi/nfit/core.c | 21 +++++++++++++++++----
+ 1 file changed, 17 insertions(+), 4 deletions(-)
+
+--- a/drivers/acpi/nfit/core.c
++++ b/drivers/acpi/nfit/core.c
+@@ -146,7 +146,8 @@ static int xlat_status(void *buf, unsign
+ * then just continue with the returned results.
+ */
+ 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 0;
+ }
+@@ -1858,19 +1859,32 @@ static int ars_get_status(struct acpi_nf
+ 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 nvdimm_bus *nvdimm_bus = acpi_desc->nvdimm_bus;
+ int rc;
+ 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++) {
++ /* 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,
+ ars_status->records[i].err_address,
+ ars_status->records[i].length);
+ if (rc)
+ return rc;
+ }
++ if (i < ars_status->num_records)
++ dev_warn(acpi_desc->dev, "detected truncated ars results\n");
+
+ return 0;
+ }
+@@ -2123,8 +2137,7 @@ static int acpi_nfit_query_poison(struct
+ if (rc < 0 && rc != -ENOSPC)
+ return rc;
+
+- if (ars_status_process_records(acpi_desc->nvdimm_bus,
+- acpi_desc->ars_status))
++ if (ars_status_process_records(acpi_desc, acpi_desc->ars_status))
+ return -ENOMEM;
+
+ return 0;
sched-autogroup-fix-64-bit-kernel-nice-level-adjustment.patch
vhost-vsock-fix-orphan-connection-reset.patch
perf-x86-fix-full-width-counter-counter-overflow.patch
+acpi-nfit-fix-extended-status-translations-for-acpi-dsms.patch
+acpi-nfit-libnvdimm-fix-harden-ars_status-output-length-handling.patch
+acpi-nfit-validate-ars_status-output-buffer-size.patch
+acpi-nfit-fix-bus-vs-dimm-confusion-in-xlat_status.patch