diff options
author | Dan Williams <dan.j.williams@intel.com> | 2020-11-23 17:43:53 -0800 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2020-12-30 11:54:05 +0100 |
commit | 36fdd770c037e8292e4184eb2a36054c16d08739 (patch) | |
tree | 0ac6c02bac357b91c2cd1c9b27b096dce2fe672a | |
parent | 3e437f7e7a7672b15d5959212ac256cc411b93a6 (diff) | |
download | kernel_replicant_linux-36fdd770c037e8292e4184eb2a36054c16d08739.tar.gz kernel_replicant_linux-36fdd770c037e8292e4184eb2a36054c16d08739.tar.bz2 kernel_replicant_linux-36fdd770c037e8292e4184eb2a36054c16d08739.zip |
ACPI: NFIT: Fix input validation of bus-family
commit 9a7e3d7f056831a6193d6d737fb7a26dfdceb04b upstream.
Dan reports that smatch thinks userspace can craft an out-of-bound bus
family number. However, nd_cmd_clear_to_send() blocks all non-zero
values of bus-family since only the kernel can initiate these commands.
However, in the speculation path, family is a user controlled array
index value so mask it for speculation safety. Also, since the
nd_cmd_clear_to_send() safety is non-obvious and possibly may change in
the future include input validation as if userspace could get past the
nd_cmd_clear_to_send() gatekeeper.
Link: http://lore.kernel.org/r/20201111113000.GA1237157@mwanda
Reported-by: Dan Carpenter <dan.carpenter@oracle.com>
Fixes: 6450ddbd5d8e ("ACPI: NFIT: Define runtime firmware activation commands")
Cc: <stable@vger.kernel.org>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | drivers/acpi/nfit/core.c | 6 |
1 files changed, 5 insertions, 1 deletions
diff --git a/drivers/acpi/nfit/core.c b/drivers/acpi/nfit/core.c index 442608220b5c..4c97b0f44fce 100644 --- a/drivers/acpi/nfit/core.c +++ b/drivers/acpi/nfit/core.c @@ -5,6 +5,7 @@ #include <linux/list_sort.h> #include <linux/libnvdimm.h> #include <linux/module.h> +#include <linux/nospec.h> #include <linux/mutex.h> #include <linux/ndctl.h> #include <linux/sysfs.h> @@ -478,8 +479,11 @@ int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm, cmd_mask = nd_desc->cmd_mask; if (cmd == ND_CMD_CALL && call_pkg->nd_family) { family = call_pkg->nd_family; - if (!test_bit(family, &nd_desc->bus_family_mask)) + if (family > NVDIMM_BUS_FAMILY_MAX || + !test_bit(family, &nd_desc->bus_family_mask)) return -EINVAL; + family = array_index_nospec(family, + NVDIMM_BUS_FAMILY_MAX + 1); dsm_mask = acpi_desc->family_dsm_mask[family]; guid = to_nfit_bus_uuid(family); } else { |