From: Len Baker <len.baker@gmx.com>
To: "Gustavo A. R. Silva" <gustavoars@kernel.org>
Cc: Len Baker <len.baker@gmx.com>, Christoph Hellwig <hch@lst.de>,
Sagi Grimberg <sagi@grimberg.me>,
Chaitanya Kulkarni <kch@nvidia.com>,
Kees Cook <keescook@chromium.org>,
linux-hardening@vger.kernel.org, linux-nvme@lists.infradead.org,
linux-kernel@vger.kernel.org
Subject: Re: [PATCH] nvmet: prefer struct_size over open coded arithmetic
Date: Sat, 23 Oct 2021 13:28:38 +0200 [thread overview]
Message-ID: <20211023112838.GB4145@titan> (raw)
In-Reply-To: <20211017172357.GA1214270@embeddedor>
Hi Gustavo,
first of all, thanks for this review (and all others reviews as
well) ;)
More below.
On Sun, Oct 17, 2021 at 12:23:57PM -0500, Gustavo A. R. Silva wrote:
> On Sun, Oct 17, 2021 at 11:56:50AM +0200, Len Baker wrote:
> > As noted in the "Deprecated Interfaces, Language Features, Attributes,
> > and Conventions" documentation [1], size calculations (especially
> > multiplication) should not be performed in memory allocator (or similar)
> > function arguments due to the risk of them overflowing. This could lead
> > to values wrapping around and a smaller allocation being made than the
> > caller was expecting. Using those allocations could lead to linear
> > overflows of heap memory and other misbehaviors.
> >
> > In this case this is not actually dynamic size: all the operands
> > involved in the calculation are constant values. However it is better to
> > refactor this anyway, just to keep the open-coded math idiom out of
> > code.
> >
> > So, use the struct_size() helper to do the arithmetic instead of the
> > argument "size + count * size" in the kmalloc() function.
> >
> > This code was detected with the help of Coccinelle and audited and fixed
> > manually.
> >
> > [1] https://www.kernel.org/doc/html/latest/process/deprecated.html#open-coded-arithmetic-in-allocator-arguments
> >
> > Signed-off-by: Len Baker <len.baker@gmx.com>
> > ---
> > Hi,
> >
> > this patch is built against the linux-next tree (tag next-20211015).
>
> You don't need to include these lines in every patch. Just add [next]
> to the subject line, like this:
>
> [PATCH][next] nvmet: prefer struct_size over open coded arithmetic
>
> It should be clear enough for people that you are talking about
> linux-next. And in case someone asks, then you proceed to clarify. :)
Ok, understood. Thanks for the advise.
> > Regards,
> > Len
> >
> > drivers/nvme/target/admin-cmd.c | 4 ++--
> > 1 file changed, 2 insertions(+), 2 deletions(-)
> >
> > diff --git a/drivers/nvme/target/admin-cmd.c b/drivers/nvme/target/admin-cmd.c
> > index aa6d84d8848e..4aa71625c86a 100644
> > --- a/drivers/nvme/target/admin-cmd.c
> > +++ b/drivers/nvme/target/admin-cmd.c
> > @@ -278,8 +278,8 @@ static void nvmet_execute_get_log_page_ana(struct nvmet_req *req)
> > u16 status;
> >
> > status = NVME_SC_INTERNAL;
> > - desc = kmalloc(sizeof(struct nvme_ana_group_desc) +
> > - NVMET_MAX_NAMESPACES * sizeof(__le32), GFP_KERNEL);
> > + desc = kmalloc(struct_size(desc, nsids, NVMET_MAX_NAMESPACES),
> > + GFP_KERNEL);
>
> It might be worth exploring if the flexible array is actually needed,
> once the allocation is always determined by NVMET_MAX_NAMESPACES. Maybe
> it can be changed to the following and remove the dynamic allocation
> entirely?
>
> struct nvme_ana_group_desc {
> __le32 grpid;
> __le32 nnsids;
> __le64 chgcnt;
> __u8 state;
> __u8 rsvd17[15];
> __le32 nsids[NVMET_MAX_NAMESPACES];
> };
What's the size limit for dynamic allocation vs stack allocation? I think
that NVMET_MAX_NAMESPACES * sizeof(__le32) = 1024 * 4 = 4096 bytes is big
enough (but I don't know if it is the correct way to think).
However, due to the following comment in the NVMET_MAX_NAMESPACES macro
definition:
/*
* Nice round number that makes a list of nsids fit into a page.
* Should become tunable at some point in the future.
*/
#define NVMET_MAX_NAMESPACES 1024
I think that it is better to use the dynamic allocation since in the
future the struct size could be dynamic.
>
> If the above is possible then (at least) these lines should be audited:
>
> drivers/nvme/host/multipath.c-551- if (WARN_ON_ONCE(offset > ctrl->ana_log_size - sizeof(*desc)))
>
> drivers/nvme/host/multipath.c-566- offset += sizeof(*desc);
> drivers/nvme/host/multipath.c-567- if (WARN_ON_ONCE(offset > ctrl->ana_log_size - nsid_buf_size))
>
> If the flexible array remains, then this line could use
> flex_array_size():
>
> drivers/nvme/host/multipath.c-555- nsid_buf_size = nr_nsids * sizeof(__le32);
Ok. I didn't see it.
>
> struct_size() could be used here, as well:
>
> drivers/nvme/host/multipath.c-847- ana_log_size = sizeof(struct nvme_ana_rsp_hdr) +
> drivers/nvme/host/multipath.c:848: ctrl->nanagrpid * sizeof(struct nvme_ana_group_desc) +
> drivers/nvme/host/multipath.c-849- ctrl->max_namespaces * sizeof(__le32);
Sorry, but here it's not possible to use struct_size() due to
sizeof(struct nvme_ana_group_desc) + ctrl->max_namespaces * sizeof(__le32)
it's not one single element. The "sizeof(struct nvme_ana_group_desc)" is
multiplied by "ctrl->nanagrpid" and then added "ctrl->max_namespaces * sizeof(__le32)".
> drivers/nvme/target/admin-cmd.c:267: return sizeof(struct nvme_ana_group_desc) + count * sizeof(__le32);
Ok. I forgot it. Apologies.
Again, thanks for your time and advises,
Len
next prev parent reply other threads:[~2021-10-23 11:29 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-10-17 9:56 [PATCH] nvmet: prefer struct_size over open coded arithmetic Len Baker
2021-10-17 17:23 ` Gustavo A. R. Silva
2021-10-23 11:28 ` Len Baker [this message]
2021-10-23 20:14 ` Gustavo A. R. Silva
2021-10-20 17:24 ` Christoph Hellwig
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20211023112838.GB4145@titan \
--to=len.baker@gmx.com \
--cc=gustavoars@kernel.org \
--cc=hch@lst.de \
--cc=kch@nvidia.com \
--cc=keescook@chromium.org \
--cc=linux-hardening@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-nvme@lists.infradead.org \
--cc=sagi@grimberg.me \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.