[PATCH v3] nvme: core: reject invalid LBA data size from Identify Namespace
Chao S
coshi036 at gmail.com
Tue Jun 23 13:37:46 PDT 2026
Hi John, Keith,
Thanks for catching the sparse warning, and sorry for the delayed response.
> BTW, I have thought that check_shl_overflow would catch
> id->lbaf[lbaf].ds < SECTOR_SHIFT (so that we don't need the extra check).
Confirmed -- check_shl_overflow() returns true for the negative shift
that ds < SECTOR_SHIFT produces (_to_shift collapses to 0 and the
_to_shift != _s test fires). I checked ds=0 and ds=8: both are still
rejected with the explicit lower-bound test removed, so it is redundant.
For the C=1 warning, the minimal fix is to drop that redundant check and
feed nsze through a plain u64 local -- as Keith found, laundering the
le64_to_cpu() result through a non-__le64 type makes the warning go away:
u64 nsze;
...
nsze = le64_to_cpu(id->nsze);
if (check_shl_overflow(nsze, id->lbaf[lbaf].ds - SECTOR_SHIFT,
&capacity)) {
dev_warn_once(...);
ret = -ENODEV;
goto out;
}
This keeps check_shl_overflow() in one tested helper and avoids a
wrapper. John's nvme_valid_ds() works too; if we prefer that, I'd name it
for its actual sense (it returns true on overflow, i.e. invalid), e.g.
nvme_ds_overflows().
One note: I'd lean toward keeping check_shl_overflow() rather than
open-coding the bound. It folds the lower-bound (negative shift) and the
overflow case into one tested helper, so we don't have to re-derive the
boundary by hand -- e.g. the lower bound is on ds itself, not on the
post-subtract (ds - SECTOR_SHIFT) shift, which I found easy to get
subtly wrong.
Keith, since v3 is already in your tree: do you want an incremental fixup
on top, or a v4 to replace the applied commit? I have both ready.
Thanks,
Chao
On Wed, Jun 3, 2026 at 6:08 AM John Garry <john.g.garry at oracle.com> wrote:
>
> On 02/06/2026 17:18, John Garry wrote:
> >
> >> I say we can ignore the sparse warning, or we
> >> can rewrite this to avoid the check_shl_overflow entirely.
> >
>
> FWIW, adding a separate function keeps sparse happy for me:
>
> diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
> index ea837b94d3e5..3ec98038668e 100644
> --- a/drivers/nvme/host/core.c
> +++ b/drivers/nvme/host/core.c
> @@ -2364,6 +2364,11 @@ static int nvme_query_fdp_info(struct nvme_ns
> *ns, struct nvme_ns_info *info)
> return ret;
> }
>
> +static bool nvme_valid_ds(u64 nsze, signed int shift, u64 *capacity)
> +{
> + return check_shl_overflow(nsze, shift, capacity);
> +}
> +
> static int nvme_update_ns_info_block(struct nvme_ns *ns,
> struct nvme_ns_info *info)
> {
> @@ -2407,10 +2412,8 @@ static int nvme_update_ns_info_block(struct
> nvme_ns *ns,
> goto out;
> }
>
> - if (id->lbaf[lbaf].ds < SECTOR_SHIFT ||
> - check_shl_overflow(le64_to_cpu(id->nsze),
> - id->lbaf[lbaf].ds - SECTOR_SHIFT,
> - &capacity)) {
> + if (nvme_valid_ds(le64_to_cpu(id->nsze),
> + id->lbaf[lbaf].ds - SECTOR_SHIFT, &capacity)) {
> dev_warn_once(ns->ctrl->device,
> "invalid LBA data size %u, skipping namespace\n",
> id->lbaf[lbaf].ds);
>
More information about the Linux-nvme
mailing list