]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.8-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 13 Dec 2016 00:45:14 +0000 (16:45 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 13 Dec 2016 00:45:14 +0000 (16:45 -0800)
added patches:
acpi-nfit-fix-bus-vs-dimm-confusion-in-xlat_status.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

queue-4.8/acpi-nfit-fix-bus-vs-dimm-confusion-in-xlat_status.patch [new file with mode: 0644]
queue-4.8/acpi-nfit-fix-extended-status-translations-for-acpi-dsms.patch [new file with mode: 0644]
queue-4.8/acpi-nfit-libnvdimm-fix-harden-ars_status-output-length-handling.patch [new file with mode: 0644]
queue-4.8/acpi-nfit-validate-ars_status-output-buffer-size.patch [new file with mode: 0644]
queue-4.8/series

diff --git a/queue-4.8/acpi-nfit-fix-bus-vs-dimm-confusion-in-xlat_status.patch b/queue-4.8/acpi-nfit-fix-bus-vs-dimm-confusion-in-xlat_status.patch
new file mode 100644 (file)
index 0000000..46fdf56
--- /dev/null
@@ -0,0 +1,70 @@
+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:
diff --git a/queue-4.8/acpi-nfit-fix-extended-status-translations-for-acpi-dsms.patch b/queue-4.8/acpi-nfit-fix-extended-status-translations-for-acpi-dsms.patch
new file mode 100644 (file)
index 0000000..ecc93e2
--- /dev/null
@@ -0,0 +1,64 @@
+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;
+       }
diff --git a/queue-4.8/acpi-nfit-libnvdimm-fix-harden-ars_status-output-length-handling.patch b/queue-4.8/acpi-nfit-libnvdimm-fix-harden-ars_status-output-length-handling.patch
new file mode 100644 (file)
index 0000000..dc24b20
--- /dev/null
@@ -0,0 +1,127 @@
+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);
diff --git a/queue-4.8/acpi-nfit-validate-ars_status-output-buffer-size.patch b/queue-4.8/acpi-nfit-validate-ars_status-output-buffer-size.patch
new file mode 100644 (file)
index 0000000..4a6c12c
--- /dev/null
@@ -0,0 +1,76 @@
+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;
index 19d1189885b73372bde185874fbbacb280090858..f77a8ac2507a6c6b923a86a12cb110db894ceac3 100644 (file)
@@ -13,3 +13,7 @@ scsi-lpfc-fix-oops-bug-in-lpfc_sli_ringtxcmpl_put.patch
 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