Message ID | 20241115164223.20854-1-surajsonawane0215@gmail.com (mailing list archive) |
---|---|
State | Superseded, archived |
Headers | show |
Series | [v4] acpi: nfit: vmalloc-out-of-bounds Read in acpi_nfit_ctl | expand |
On 11/15/24 9:42 AM, Suraj Sonawane wrote: > 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 <surajsonawane0215@gmail.com> Reviewed-by: Dave Jiang <dave.jiang@intel.com> > --- > 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. > > drivers/acpi/nfit/core.c | 9 ++++++++- > 1 file changed, 8 insertions(+), 1 deletion(-) > > diff --git a/drivers/acpi/nfit/core.c b/drivers/acpi/nfit/core.c > index 5429ec9ef..84d8eef2a 100644 > --- a/drivers/acpi/nfit/core.c > +++ b/drivers/acpi/nfit/core.c > @@ -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;
Suraj Sonawane wrote: > 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 <surajsonawane0215@gmail.com> > --- > 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. > > drivers/acpi/nfit/core.c | 9 ++++++++- > 1 file changed, 8 insertions(+), 1 deletion(-) > > diff --git a/drivers/acpi/nfit/core.c b/drivers/acpi/nfit/core.c > index 5429ec9ef..84d8eef2a 100644 > --- a/drivers/acpi/nfit/core.c > +++ b/drivers/acpi/nfit/core.c > @@ -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; This goto is wrong. This will result in ACPI_FREE() being called on an undefined out_obj. This should be: return -EINVAL; Ira > + } > + > call_pkg = buf; > + } > + > func = cmd_to_func(nfit_mem, cmd, call_pkg, &family); > if (func < 0) > return func; > -- > 2.34.1 >
On 16/11/24 01:00, Ira Weiny wrote: > Suraj Sonawane wrote: >> 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 <surajsonawane0215@gmail.com> >> --- >> 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. >> >> drivers/acpi/nfit/core.c | 9 ++++++++- >> 1 file changed, 8 insertions(+), 1 deletion(-) >> >> diff --git a/drivers/acpi/nfit/core.c b/drivers/acpi/nfit/core.c >> index 5429ec9ef..84d8eef2a 100644 >> --- a/drivers/acpi/nfit/core.c >> +++ b/drivers/acpi/nfit/core.c >> @@ -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; > > This goto is wrong. This will result in ACPI_FREE() being called on an > undefined out_obj. > > This should be: > return -EINVAL; > Thanks for catching that. You’re correct about the goto issue. I had initialized out_obj to NULL in previous versions but missed it in this patch. In v5, I’ve re-initialized out_obj to NULL, to avoid unintended access. Here’s the updated patch link: https://lore.kernel.org/lkml/20241116114027.19303-1-surajsonawane0215@gmail.com/ > Ira > >> + } >> + >> call_pkg = buf; >> + } >> + >> func = cmd_to_func(nfit_mem, cmd, call_pkg, &family); >> if (func < 0) >> return func; >> -- >> 2.34.1 >> Best Regards, Suraj Sonawane
diff --git a/drivers/acpi/nfit/core.c b/drivers/acpi/nfit/core.c index 5429ec9ef..84d8eef2a 100644 --- a/drivers/acpi/nfit/core.c +++ b/drivers/acpi/nfit/core.c @@ -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;