| From 01091c496f920e634ea84b689f480c39016752a8 Mon Sep 17 00:00:00 2001 |
| From: Dan Carpenter <dan.carpenter@oracle.com> |
| Date: Tue, 25 Feb 2020 19:20:06 +0300 |
| Subject: acpi/nfit: improve bounds checking for 'func' |
| |
| From: Dan Carpenter <dan.carpenter@oracle.com> |
| |
| commit 01091c496f920e634ea84b689f480c39016752a8 upstream. |
| |
| 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> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/acpi/nfit/core.c | 10 ++++++---- |
| drivers/acpi/nfit/nfit.h | 1 + |
| 2 files changed, 7 insertions(+), 4 deletions(-) |
| |
| --- a/drivers/acpi/nfit/core.c |
| +++ b/drivers/acpi/nfit/core.c |
| @@ -360,7 +360,7 @@ static union acpi_object *acpi_label_inf |
| |
| 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 |
| |
| 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_desc |
| * 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; |
| @@ -3499,7 +3500,8 @@ static int acpi_nfit_clear_to_send(struc |
| 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; |
| } |
| |
| --- a/drivers/acpi/nfit/nfit.h |
| +++ b/drivers/acpi/nfit/nfit.h |
| @@ -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 \ |