{"api_version":"1","generated_at":"2026-09-16T16:40:16+00:00","cve":"CVE-2026-89971","urls":{"html":"https://cve.report/CVE-2026-89971","api":"https://cve.report/api/cve/CVE-2026-89971.json","docs":"https://cve.report/api","cve_org":"https://www.cve.org/CVERecord?id=CVE-2026-89971","nvd":"https://nvd.nist.gov/vuln/detail/CVE-2026-89971"},"summary":{"title":"nvme: skip the zoned limits update if the zone info query failed","description":"In the Linux kernel, the following vulnerability has been resolved:\n\nnvme: skip the zoned limits update if the zone info query failed\n\nnvme_query_zone_info() returns either a negative errno or a positive\nNVMe status code, but nvme_update_ns_info_block() only tests for the\nnegative case:\n\n\tret = nvme_query_zone_info(ns, lbaf, &zi);\n\tif (ret < 0)\n\t\tgoto out;\n\nIf the device fails the Identify Namespace (I/O Command Set specific)\ncommand, or the Identify Controller command issued by\nnvme_set_max_append(), the positive status falls through and setup\ncontinues with the zero-initialized zone info.  nvme_update_zone_info()\nthen marks the queue zoned with chunk_sectors and ns->head->zsze set to\nzero.\n\nblk_validate_zoned_limits() does not check chunk_sectors, so the limits\ncommit succeeds.  blk_revalidate_disk_zones() does reject the zero zone\nsize, but by then the limits are live and nothing rolls them back, so\nI/O keeps being submitted to a zoned queue with a zero zone size and\ndisk_zone_no() shifts by ilog2(0):\n\n  nvme0n1: Invalid non power of two zone size (0)\n  UBSAN: shift-out-of-bounds in include/linux/blkdev.h:747:16\n  shift exponent -1 is negative\n   disk_zone_no include/linux/blkdev.h:747 [inline]\n   bio_straddles_zones include/linux/blkdev.h:1058 [inline]\n   blk_zone_wplug_handle_write block/blk-zoned.c:1423 [inline]\n   blk_zone_plug_bio.cold+0x25/0x1c8 block/blk-zoned.c:1605\n   blk_mq_submit_bio+0x18fb/0x2870 block/blk-mq.c:3196\n   submit_bh_wbc+0x575/0x740 fs/buffer.c:2824\n   __block_write_full_folio+0x728/0xdd0 fs/buffer.c:1933\n\nAny device, firmware or NVMe-oF target that fails this one command\nreaches this.\n\nSkip the zoned limits update in that case, and log which of the two\nthings happened: during a revalidation the queue keeps the zone\ngeometry it was last validated with, and on a first scan the namespace\nis registered without zoned limits, so that it is still available as a\nhandle for admin commands.  Neither of the paths in\nnvme_query_zone_info() that return a positive status logs anything, so\nthe failure would otherwise be silent.\n\nzi.zone_size is an exact indicator: every path that returns a positive\nstatus returns before it is assigned, and after that the only failure\nleft is -ENODEV, which the caller already handles.\n\nFound by FuzzNvme.","state":"PUBLISHED","assigner":"Linux","published_at":"2026-09-16 11:17:07","updated_at":"2026-09-16 15:18:21"},"problem_types":[],"metrics":[{"version":"3.1","source":"416baaa9-dc9f-4396-8d5f-8c081fb06d67","type":"Secondary","score":"7.5","severity":"HIGH","vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H","data":{"version":"3.1","vectorString":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H","baseScore":7.5,"baseSeverity":"HIGH","attackVector":"NETWORK","attackComplexity":"LOW","privilegesRequired":"NONE","userInteraction":"NONE","scope":"UNCHANGED","confidentialityImpact":"NONE","integrityImpact":"NONE","availabilityImpact":"HIGH"}},{"version":"3.1","source":"CNA","type":"DECLARED","score":"7.5","severity":"HIGH","vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H","data":{"baseScore":7.5,"baseSeverity":"HIGH","vectorString":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H","version":"3.1"}}],"references":[{"url":"https://git.kernel.org/stable/c/bb6dafa79040357cf5043836e1db108c2af8b1e1","name":"https://git.kernel.org/stable/c/bb6dafa79040357cf5043836e1db108c2af8b1e1","refsource":"416baaa9-dc9f-4396-8d5f-8c081fb06d67","tags":[],"title":"","mime":"","httpstatus":"","archivestatus":"0"},{"url":"https://git.kernel.org/stable/c/7fad53ae2052a2b4fc7ca567d6555bdb1176ba35","name":"https://git.kernel.org/stable/c/7fad53ae2052a2b4fc7ca567d6555bdb1176ba35","refsource":"416baaa9-dc9f-4396-8d5f-8c081fb06d67","tags":[],"title":"","mime":"","httpstatus":"","archivestatus":"0"},{"url":"https://git.kernel.org/stable/c/3838e80fcfb32e62baffb63c6dc0a60153665a4d","name":"https://git.kernel.org/stable/c/3838e80fcfb32e62baffb63c6dc0a60153665a4d","refsource":"416baaa9-dc9f-4396-8d5f-8c081fb06d67","tags":[],"title":"","mime":"","httpstatus":"","archivestatus":"0"},{"url":"https://www.cve.org/CVERecord?id=CVE-2026-89971","name":"CVE Program record","refsource":"CVE.ORG","tags":["canonical"]},{"url":"https://nvd.nist.gov/vuln/detail/CVE-2026-89971","name":"NVD vulnerability detail","refsource":"NVD","tags":["canonical","analysis"]}],"affected":[{"source":"CNA","vendor":"Linux","product":"Linux","version":"affected c85c9ab926a592e2f59f7d9a6ca7d6562843d8fa 7fad53ae2052a2b4fc7ca567d6555bdb1176ba35 git","platforms":[]},{"source":"CNA","vendor":"Linux","product":"Linux","version":"affected c85c9ab926a592e2f59f7d9a6ca7d6562843d8fa bb6dafa79040357cf5043836e1db108c2af8b1e1 git","platforms":[]},{"source":"CNA","vendor":"Linux","product":"Linux","version":"affected c85c9ab926a592e2f59f7d9a6ca7d6562843d8fa 3838e80fcfb32e62baffb63c6dc0a60153665a4d git","platforms":[]},{"source":"CNA","vendor":"Linux","product":"Linux","version":"affected 6.9","platforms":[]},{"source":"CNA","vendor":"Linux","product":"Linux","version":"unaffected 6.9 semver","platforms":[]},{"source":"CNA","vendor":"Linux","product":"Linux","version":"unaffected 6.18.52 6.18.* semver","platforms":[]},{"source":"CNA","vendor":"Linux","product":"Linux","version":"unaffected 7.2.5 7.2.* semver","platforms":[]},{"source":"CNA","vendor":"Linux","product":"Linux","version":"unaffected 7.3-rc2 * original_commit_for_fix","platforms":[]}],"timeline":[],"solutions":[],"workarounds":[],"exploits":[],"credits":[],"nvd_cpes":[],"vendor_comments":[],"enrichments":{"kev":null,"epss":null,"legacy_qids":[]},"source_records":{"cve_program":{"containers":{"cna":{"affected":[{"defaultStatus":"unaffected","product":"Linux","programFiles":["drivers/nvme/host/core.c"],"repo":"https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git","vendor":"Linux","versions":[{"lessThan":"7fad53ae2052a2b4fc7ca567d6555bdb1176ba35","status":"affected","version":"c85c9ab926a592e2f59f7d9a6ca7d6562843d8fa","versionType":"git"},{"lessThan":"bb6dafa79040357cf5043836e1db108c2af8b1e1","status":"affected","version":"c85c9ab926a592e2f59f7d9a6ca7d6562843d8fa","versionType":"git"},{"lessThan":"3838e80fcfb32e62baffb63c6dc0a60153665a4d","status":"affected","version":"c85c9ab926a592e2f59f7d9a6ca7d6562843d8fa","versionType":"git"}]},{"defaultStatus":"affected","product":"Linux","programFiles":["drivers/nvme/host/core.c"],"repo":"https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git","vendor":"Linux","versions":[{"status":"affected","version":"6.9"},{"lessThan":"6.9","status":"unaffected","version":"0","versionType":"semver"},{"lessThanOrEqual":"6.18.*","status":"unaffected","version":"6.18.52","versionType":"semver"},{"lessThanOrEqual":"7.2.*","status":"unaffected","version":"7.2.5","versionType":"semver"},{"lessThanOrEqual":"*","status":"unaffected","version":"7.3-rc2","versionType":"original_commit_for_fix"}]}],"cpeApplicability":[{"nodes":[{"cpeMatch":[{"criteria":"cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*","versionEndExcluding":"6.18.52","versionStartIncluding":"6.9","vulnerable":true},{"criteria":"cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*","versionEndExcluding":"7.2.5","versionStartIncluding":"6.9","vulnerable":true},{"criteria":"cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*","versionEndExcluding":"7.3-rc2","versionStartIncluding":"6.9","vulnerable":true}],"negate":false,"operator":"OR"}]}],"descriptions":[{"lang":"en","value":"In the Linux kernel, the following vulnerability has been resolved:\n\nnvme: skip the zoned limits update if the zone info query failed\n\nnvme_query_zone_info() returns either a negative errno or a positive\nNVMe status code, but nvme_update_ns_info_block() only tests for the\nnegative case:\n\n\tret = nvme_query_zone_info(ns, lbaf, &zi);\n\tif (ret < 0)\n\t\tgoto out;\n\nIf the device fails the Identify Namespace (I/O Command Set specific)\ncommand, or the Identify Controller command issued by\nnvme_set_max_append(), the positive status falls through and setup\ncontinues with the zero-initialized zone info.  nvme_update_zone_info()\nthen marks the queue zoned with chunk_sectors and ns->head->zsze set to\nzero.\n\nblk_validate_zoned_limits() does not check chunk_sectors, so the limits\ncommit succeeds.  blk_revalidate_disk_zones() does reject the zero zone\nsize, but by then the limits are live and nothing rolls them back, so\nI/O keeps being submitted to a zoned queue with a zero zone size and\ndisk_zone_no() shifts by ilog2(0):\n\n  nvme0n1: Invalid non power of two zone size (0)\n  UBSAN: shift-out-of-bounds in include/linux/blkdev.h:747:16\n  shift exponent -1 is negative\n   disk_zone_no include/linux/blkdev.h:747 [inline]\n   bio_straddles_zones include/linux/blkdev.h:1058 [inline]\n   blk_zone_wplug_handle_write block/blk-zoned.c:1423 [inline]\n   blk_zone_plug_bio.cold+0x25/0x1c8 block/blk-zoned.c:1605\n   blk_mq_submit_bio+0x18fb/0x2870 block/blk-mq.c:3196\n   submit_bh_wbc+0x575/0x740 fs/buffer.c:2824\n   __block_write_full_folio+0x728/0xdd0 fs/buffer.c:1933\n\nAny device, firmware or NVMe-oF target that fails this one command\nreaches this.\n\nSkip the zoned limits update in that case, and log which of the two\nthings happened: during a revalidation the queue keeps the zone\ngeometry it was last validated with, and on a first scan the namespace\nis registered without zoned limits, so that it is still available as a\nhandle for admin commands.  Neither of the paths in\nnvme_query_zone_info() that return a positive status logs anything, so\nthe failure would otherwise be silent.\n\nzi.zone_size is an exact indicator: every path that returns a positive\nstatus returns before it is assigned, and after that the only failure\nleft is -ENODEV, which the caller already handles.\n\nFound by FuzzNvme."}],"metrics":[{"cvssV3_1":{"baseScore":7.5,"baseSeverity":"HIGH","vectorString":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H","version":"3.1"},"scenarios":[{"lang":"en","value":"AV:N - The NVMe host core parses Identify responses during namespace scan for PCIe and NVMe-oF (nvme-tcp/rdma/fc). A malicious or compromised NVMe-oF target over routable TCP (typically 4420) can fail the ZNS Identify command and trigger the bug from the network.\nAC:L - A malicious controller only needs to report CSI=ZNS then return a positive NVMe status on Identify CSI-NS or Identify CSI-CTRL; nvme_update_ns_info_block() treats that as success and installs zero zone geometry with no race or victim-specific layout.\nPR:N - The attacker is the connected NVMe-oF peer and needs no host account or capability. NVMe/TCP TLS and DH-HMAC-CHAP are optional and off by default, matching prior NVMe-oF host CNA scoring as PR:N.\nUI:N - Namespace scan and AEN Notice Namespace Changed rescans run in nvme_wq once a controller exists, including nvmf-autoconnect. Partition probe and filesystem writeback then submit I/O that hits disk_zone_no with no extra victim action at exploit time.\nS:U - The invalid zoned limits and UBSAN shift occur in the host kernel block layer. This is not a VM escape, IOMMU bypass, or other cross-authority boundary.\nC:N - The flaw leaves zi zero-initialized and later does sector >> ilog2(0) in disk_zone_no. That is an undefined shift, not an out-of-bounds read, use-after-free, or other kernel memory disclosure primitive.\nI:N - nvme_update_zone_info() only programs this queue's chunk_sectors and zsze to zero from uncleared zi. There is no out-of-bounds write, use-after-free, or attacker-controlled write/control-flow hijack primitive.\nA:H - FuzzNvme reproduced UBSAN shift-out-of-bounds in disk_zone_no on live I/O after zoned limits committed with zone size 0. CONFIG_UBSAN_TRAP and panic_on_warn panic the host, which kernel CNA guidance scores as high availability."}]}],"providerMetadata":{"dateUpdated":"2026-09-16T14:40:51.265Z","orgId":"416baaa9-dc9f-4396-8d5f-8c081fb06d67","shortName":"Linux"},"references":[{"url":"https://git.kernel.org/stable/c/7fad53ae2052a2b4fc7ca567d6555bdb1176ba35"},{"url":"https://git.kernel.org/stable/c/bb6dafa79040357cf5043836e1db108c2af8b1e1"},{"url":"https://git.kernel.org/stable/c/3838e80fcfb32e62baffb63c6dc0a60153665a4d"}],"title":"nvme: skip the zoned limits update if the zone info query failed","x_generator":{"engine":"bippy-1.2.0"}}},"cveMetadata":{"assignerOrgId":"416baaa9-dc9f-4396-8d5f-8c081fb06d67","assignerShortName":"Linux","cveId":"CVE-2026-89971","datePublished":"2026-09-16T10:32:50.995Z","dateReserved":"2026-09-11T19:38:34.778Z","dateUpdated":"2026-09-16T14:40:51.265Z","state":"PUBLISHED"},"dataType":"CVE_RECORD","dataVersion":"5.2"},"nvd":{"publishedDate":"2026-09-16 11:17:07","lastModifiedDate":"2026-09-16 15:18:21","problem_types":[],"metrics":{"cvssMetricV31":[{"source":"416baaa9-dc9f-4396-8d5f-8c081fb06d67","type":"Secondary","cvssData":{"version":"3.1","vectorString":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H","baseScore":7.5,"baseSeverity":"HIGH","attackVector":"NETWORK","attackComplexity":"LOW","privilegesRequired":"NONE","userInteraction":"NONE","scope":"UNCHANGED","confidentialityImpact":"NONE","integrityImpact":"NONE","availabilityImpact":"HIGH"},"exploitabilityScore":3.9,"impactScore":3.6}]},"configurations":[]},"legacy_mitre":{"record":{"CveYear":"2026","CveId":"89971","Ordinal":"1","Title":"nvme: skip the zoned limits update if the zone info query failed","CVE":"CVE-2026-89971","Year":"2026"},"notes":[{"CveYear":"2026","CveId":"89971","Ordinal":"1","NoteData":"In the Linux kernel, the following vulnerability has been resolved:\n\nnvme: skip the zoned limits update if the zone info query failed\n\nnvme_query_zone_info() returns either a negative errno or a positive\nNVMe status code, but nvme_update_ns_info_block() only tests for the\nnegative case:\n\n\tret = nvme_query_zone_info(ns, lbaf, &zi);\n\tif (ret < 0)\n\t\tgoto out;\n\nIf the device fails the Identify Namespace (I/O Command Set specific)\ncommand, or the Identify Controller command issued by\nnvme_set_max_append(), the positive status falls through and setup\ncontinues with the zero-initialized zone info.  nvme_update_zone_info()\nthen marks the queue zoned with chunk_sectors and ns->head->zsze set to\nzero.\n\nblk_validate_zoned_limits() does not check chunk_sectors, so the limits\ncommit succeeds.  blk_revalidate_disk_zones() does reject the zero zone\nsize, but by then the limits are live and nothing rolls them back, so\nI/O keeps being submitted to a zoned queue with a zero zone size and\ndisk_zone_no() shifts by ilog2(0):\n\n  nvme0n1: Invalid non power of two zone size (0)\n  UBSAN: shift-out-of-bounds in include/linux/blkdev.h:747:16\n  shift exponent -1 is negative\n   disk_zone_no include/linux/blkdev.h:747 [inline]\n   bio_straddles_zones include/linux/blkdev.h:1058 [inline]\n   blk_zone_wplug_handle_write block/blk-zoned.c:1423 [inline]\n   blk_zone_plug_bio.cold+0x25/0x1c8 block/blk-zoned.c:1605\n   blk_mq_submit_bio+0x18fb/0x2870 block/blk-mq.c:3196\n   submit_bh_wbc+0x575/0x740 fs/buffer.c:2824\n   __block_write_full_folio+0x728/0xdd0 fs/buffer.c:1933\n\nAny device, firmware or NVMe-oF target that fails this one command\nreaches this.\n\nSkip the zoned limits update in that case, and log which of the two\nthings happened: during a revalidation the queue keeps the zone\ngeometry it was last validated with, and on a first scan the namespace\nis registered without zoned limits, so that it is still available as a\nhandle for admin commands.  Neither of the paths in\nnvme_query_zone_info() that return a positive status logs anything, so\nthe failure would otherwise be silent.\n\nzi.zone_size is an exact indicator: every path that returns a positive\nstatus returns before it is assigned, and after that the only failure\nleft is -ENODEV, which the caller already handles.\n\nFound by FuzzNvme.","Type":"Description","Title":"nvme: skip the zoned limits update if the zone info query failed"}]}}}