acpi/nfit: improve bounds checking for 'func'
authorDan Carpenter <dan.carpenter@oracle.com>
Tue, 25 Feb 2020 16:20:06 +0000 (19:20 +0300)
committerDan Williams <dan.j.williams@intel.com>
Sat, 29 Feb 2020 02:21:52 +0000 (18:21 -0800)
The 'func' variable can come from the user in the __nd_ioctl().  If it's
too high then the (1 << func) shift in acpi_nfit_clear_to_send() is
undefined.  In acpi_nfit_ctl() we pass 'func' to test_bit(func, &dsm_mask)
which could result in an out of bounds access.

To fix these issues, I introduced the NVDIMM_CMD_MAX (31) define and
updated nfit_dsm_revid() to use that define as well instead of magic
numbers.

Fixes: 11189c1089da ("acpi/nfit: Fix command-supported detection")
Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
Reviewed-by: Dan Williams <dan.j.williams@intel.com>
Link: https://lore.kernel.org/r/20200225161927.hvftuq7kjn547fyj@kili.mountain
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
drivers/acpi/nfit/core.c
drivers/acpi/nfit/nfit.h

index a3320f9..d0090f7 100644 (file)
@@ -360,7 +360,7 @@ static union acpi_object *acpi_label_info(acpi_handle handle)
 
 static u8 nfit_dsm_revid(unsigned family, unsigned func)
 {
-       static const u8 revid_table[NVDIMM_FAMILY_MAX+1][32] = {
+       static const u8 revid_table[NVDIMM_FAMILY_MAX+1][NVDIMM_CMD_MAX+1] = {
                [NVDIMM_FAMILY_INTEL] = {
                        [NVDIMM_INTEL_GET_MODES] = 2,
                        [NVDIMM_INTEL_GET_FWINFO] = 2,
@@ -386,7 +386,7 @@ static u8 nfit_dsm_revid(unsigned family, unsigned func)
 
        if (family > NVDIMM_FAMILY_MAX)
                return 0;
-       if (func > 31)
+       if (func > NVDIMM_CMD_MAX)
                return 0;
        id = revid_table[family][func];
        if (id == 0)
@@ -492,7 +492,8 @@ int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm,
         * Check for a valid command.  For ND_CMD_CALL, we also have to
         * make sure that the DSM function is supported.
         */
-       if (cmd == ND_CMD_CALL && !test_bit(func, &dsm_mask))
+       if (cmd == ND_CMD_CALL &&
+           (func > NVDIMM_CMD_MAX || !test_bit(func, &dsm_mask)))
                return -ENOTTY;
        else if (!test_bit(cmd, &cmd_mask))
                return -ENOTTY;
@@ -3492,7 +3493,8 @@ static int acpi_nfit_clear_to_send(struct nvdimm_bus_descriptor *nd_desc,
        if (nvdimm && cmd == ND_CMD_CALL &&
                        call_pkg->nd_family == NVDIMM_FAMILY_INTEL) {
                func = call_pkg->nd_command;
-               if ((1 << func) & NVDIMM_INTEL_SECURITY_CMDMASK)
+               if (func > NVDIMM_CMD_MAX ||
+                   (1 << func) & NVDIMM_INTEL_SECURITY_CMDMASK)
                        return -EOPNOTSUPP;
        }
 
index 2424194..b317f40 100644 (file)
@@ -34,6 +34,7 @@
                | ACPI_NFIT_MEM_NOT_ARMED | ACPI_NFIT_MEM_MAP_FAILED)
 
 #define NVDIMM_FAMILY_MAX NVDIMM_FAMILY_HYPERV
+#define NVDIMM_CMD_MAX 31
 
 #define NVDIMM_STANDARD_CMDMASK \
 (1 << ND_CMD_SMART | 1 << ND_CMD_SMART_THRESHOLD | 1 << ND_CMD_DIMM_FLAGS \