Validate the NSID before indexing nvmev_vdev->ns[]#74
Open
jongukc wants to merge 1 commit into
Open
Conversation
The Identify Namespace / Identify Namespace Descriptor / Identify ZNS
Namespace handlers and the I/O dispatch path index nvmev_vdev->ns[] with
(cmd->nsid - 1) taken straight from the host command, with no bounds
check. nvmev_vdev->ns[] only holds nvmev_vdev->nr_ns elements, so an
Identify or I/O for NSID 0 (-> (size_t)-1) or for an NSID greater than
nr_ns indexes the array out of bounds.
This is reachable whenever the host issues Identify/I-O for an NSID the
device does not back -- e.g. during a controller rescan, or directly via
an admin/I-O passthrough command -- and leads to a KASAN slab-out-of-
bounds read of ns[].size and, for the I/O path, a call through a garbage
ns->proc_io_cmd function pointer (general protection fault).
BUG: KASAN: slab-out-of-bounds in nvmev_proc_admin_sq [nvmev]
Read of size 8 ... 8 bytes to the right of the 64-byte region (ns[1])
general protection fault in nvmev_proc_io_sq (ns[n].proc_io_cmd)
Validate the 1-based NSID against nr_ns before every ns[] access:
- Identify Namespace / Namespace Descriptor: an inactive/invalid NSID
returns a zero-filled structure, as the spec requires (the host
treats a zero NSZE as "namespace not present").
- Identify ZNS Namespace: also reorders the check ahead of the
NS_SSD_TYPE(nsid) lookup, which itself indexes a 2-element array.
- I/O dispatch: an I/O to an unbacked NSID is completed with
NVME_SC_INVALID_NS | NVME_SC_DNR instead of dereferencing ns[].
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Some command handlers use the NSID from the host command to index
nvmev_vdev->ns[]before checking whether the NSID is valid.nvmev_vdev->ns[]has onlynvmev_vdev->nr_nsentries.So an invalid NSID can access the array out of bounds.
This can happen in two cases:
00 - 1becomes(size_t)-1nr_nsAffected paths:
admin.c __nvmev_admin_identify_namespacens[nsid].sizeadmin.c __nvmev_admin_identify_namespace_descns[nsid].csiadmin.c __nvmev_admin_identify_zns_namespacens[nsid].ftlsandns[nsid].csiNS_SSD_TYPE(nsid), which indexes a 2-entry arrayio.c __nvmev_proc_ions = &ns[nsid]ns->proc_io_cmd(...)A valid NVMe controller should not index its internal namespace table with an invalid NSID.
For Identify, it should return a zero-filled structure for an inactive or invalid NSID.
For I/O, it should return
Invalid Namespace.Description
With KASAN enabled, the admin Identify path triggers a slab out-of-bounds read.
The I/O path is more dangerous. It can also call a garbage function pointer.
This happens because
ns->proc_io_cmdis read from an invalidstruct nvmev_ns.This was reproduced on unpatched Linux 7.1.0 by running Identify Namespace with NSID 2.
In this setup, only NSID 1 exists, so NSID 2 accesses
ns[1].This bug was found during fuzzing.
Linux 7.1.0 x86_64, CONFIG_KASAN=y, panic_on_warn=1,
kasan.fault=panic, running under QEMU/KVM.Reproduction
On the test machine, with NVMeVirt probed as
/dev/nvme0(block device/dev/nvme0n1).See nsid-oob-repro.sh:
Either command crashes the unpatched dispatcher kthread.
Fix
Validate the 1-based NSID against
nvmev_vdev->nr_nsbefore everyns[]access:NS_SSD_TYPE(nsid)lookup (itself a fixed 2-element array).NVME_SC_INVALID_NS | NVME_SC_DNRinstead of dereferencingns[].Validated on Linux 7.1.0.