From cd70ead500c4498914af578fd65fb446854cd9ca Mon Sep 17 00:00:00 2001 From: Suraj Sonawane Date: Sat, 16 Nov 2024 15:44:28 +0530 Subject: [PATCH v5] acpi: nfit: vmalloc-out-of-bounds Read in acpi_nfit_ctl Fix an issue detected by syzbot with KASAN: BUG: KASAN: vmalloc-out-of-bounds in cmd_to_func drivers/acpi/nfit/ core.c:416 [inline] BUG: KASAN: vmalloc-out-of-bounds in acpi_nfit_ctl+0x20e8/0x24a0 drivers/acpi/nfit/core.c:459 The issue occurs in cmd_to_func when the call_pkg->nd_reserved2 array is accessed without verifying that call_pkg points to a buffer that is appropriately sized as a struct nd_cmd_pkg. This can lead to out-of-bounds access and undefined behavior if the buffer does not have sufficient space. To address this, a check was added in acpi_nfit_ctl() to ensure that buf is not NULL and that buf_len is less than sizeof(*call_pkg) before accessing it. This ensures safe access to the members of call_pkg, including the nd_reserved2 array. Reported-by: syzbot+7534f060ebda6b8b51b3@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=7534f060ebda6b8b51b3 Tested-by: syzbot+7534f060ebda6b8b51b3@syzkaller.appspotmail.com Fixes: ebe9f6f19d80 ("acpi/nfit: Fix bus command validation") Signed-off-by: Suraj Sonawane --- V1: https://lore.kernel.org/lkml/20241111080429.9861-1-surajsonawane0215@gmail.com/ V2: Initialized `out_obj` to `NULL` in `acpi_nfit_ctl()` to prevent potential uninitialized variable usage if condition is true. V3: Changed the condition to if (!buf || buf_len < sizeof(*call_pkg)) and updated the Fixes tag to reference the correct commit. V4: Removed the explicit cast to maintain the original code style. V5: Re-Initialized `out_obj` to NULL. drivers/acpi/nfit/core.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/acpi/nfit/core.c b/drivers/acpi/nfit/core.c index 5429ec9ef..573ed264c 100644 --- a/drivers/acpi/nfit/core.c +++ b/drivers/acpi/nfit/core.c @@ -439,7 +439,7 @@ int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm, { struct acpi_nfit_desc *acpi_desc = to_acpi_desc(nd_desc); struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm); - union acpi_object in_obj, in_buf, *out_obj; + union acpi_object in_obj, in_buf, *out_obj = NULL; const struct nd_cmd_desc *desc = NULL; struct device *dev = acpi_desc->dev; struct nd_cmd_pkg *call_pkg = NULL; @@ -454,8 +454,15 @@ int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm, if (cmd_rc) *cmd_rc = -EINVAL; - if (cmd == ND_CMD_CALL) + if (cmd == ND_CMD_CALL) { + if (!buf || buf_len < sizeof(*call_pkg)) { + rc = -EINVAL; + goto out; + } + call_pkg = buf; + } + func = cmd_to_func(nfit_mem, cmd, call_pkg, &family); if (func < 0) return func; -- 2.34.1