{"id":"CVE-2026-64320","state":"PUBLISHED","title":"nvmet: fix pre-auth out-of-bounds heap read in Discovery Get Log Page","description":"In the Linux kernel, the following vulnerability has been resolved:\n\nnvmet: fix pre-auth out-of-bounds heap read in Discovery Get Log Page\n\nnvmet_execute_disc_get_log_page() validates only the dword alignment\nof the host-supplied Log Page Offset (lpo).  The 64-bit offset is then\nadded to a small kzalloc'd buffer that holds the discovery log page\nand the result is passed straight to nvmet_copy_to_sgl(), which\nmemcpy()s data_len bytes out to the host with no source-side bound\ncheck:\n\n    u64 offset      = nvmet_get_log_page_offset(req->cmd);  /* 64-bit host */\n    size_t data_len = nvmet_get_log_page_len(req->cmd);     /* 32-bit host */\n    ...\n    if (offset & 0x3) { ... }                               /* only check */\n    ...\n    alloc_len = sizeof(*hdr) + entry_size * discovery_log_entries(req);\n    buffer = kzalloc(alloc_len, GFP_KERNEL);\n    ...\n    status = nvmet_copy_to_sgl(req, 0, buffer + offset, data_len);\n\nThe Discovery controller is unauthenticated -- nvmet_host_allowed()\nreturns true unconditionally for the discovery subsystem -- so the call\nis reachable pre-authentication by any TCP/RDMA/FC peer that can reach\nthe nvmet target.  With a discovery log page of ~1 KiB, an attacker\nrequesting up to 4 KiB starting at offset == alloc_len reads the next\nslab page out and gets its content returned over the fabric (an\nempirical run on a default nvmet-tcp loopback target leaked 81\ncanonical kernel pointers in one Get Log Page response).  Pointing the\noffset at unmapped kernel memory faults the in-kernel memcpy and\ncrashes (or panics, on panic_on_oops=1) the target host instead.\n\nThe attacker-controlled source-side offset pattern\n\"nvmet_copy_to_sgl(req, 0, buffer + ATTACKER_OFFSET, ...)\" is unique\nto nvmet_execute_disc_get_log_page in the entire nvmet codebase: every\nother Get Log Page handler in admin-cmd.c either ignores lpo (and\nsilently starts every response at offset 0) or tracks a local\ndestination offset with a fixed source pointer.\n\nValidate the host-supplied offset against the log page size, cap the\ncopy length to what is actually available, and zero-fill any remainder\nof the host transfer buffer.  The zero-fill matches the existing\nshort-response pattern in nvmet_execute_get_log_changed_ns()\n(admin-cmd.c) and prevents leaking transport SGL contents when the\nhost asks for more bytes than the log page contains.","publishedAt":"2026-07-25T08:49:48.908Z","updatedAt":"2026-10-30T12:27:44.977Z","severity":{"score":9.1,"label":"Critical","version":"3.1","vector":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:H","source":"Linux"},"assigner":"Linux","products":["Linux Linux"],"affected":[{"vendor":"Linux","product":"Linux","defaultStatus":"unaffected","versions":[{"version":"a07b4970f464f13640e28e16dad6cfa33647cc99","status":"affected","lessThan":"ff815b5e8688dcf68529b7f0fde8de5847f63f1e","versionType":"git"},{"version":"a07b4970f464f13640e28e16dad6cfa33647cc99","status":"affected","lessThan":"8ae9bb92fc9a712a8d32da9c5fd657101f9b260b","versionType":"git"},{"version":"a07b4970f464f13640e28e16dad6cfa33647cc99","status":"affected","lessThan":"33b974eb626154ae9348f2bac7de84cb2a3d9dd4","versionType":"git"},{"version":"a07b4970f464f13640e28e16dad6cfa33647cc99","status":"affected","lessThan":"56c021a0869260d04c4b65d1471936aaf9177114","versionType":"git"},{"version":"a07b4970f464f13640e28e16dad6cfa33647cc99","status":"affected","lessThan":"a29b316b9bbfd269f323ab4ba9906a894025680f","versionType":"git"},{"version":"a07b4970f464f13640e28e16dad6cfa33647cc99","status":"affected","lessThan":"53cd102a7a56079b11b897835bd9b94c14e6322c","versionType":"git"}],"repo":"https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git","programFiles":["drivers/nvme/target/discovery.c"]},{"vendor":"Linux","product":"Linux","defaultStatus":"affected","versions":[{"version":"4.8","status":"affected"},{"version":"0","status":"unaffected","lessThan":"4.8","versionType":"semver"},{"version":"6.1.191","status":"unaffected","lessThanOrEqual":"6.1.*","versionType":"semver"},{"version":"6.6.160","status":"unaffected","lessThanOrEqual":"6.6.*","versionType":"semver"},{"version":"6.12.96","status":"unaffected","lessThanOrEqual":"6.12.*","versionType":"semver"},{"version":"6.18.39","status":"unaffected","lessThanOrEqual":"6.18.*","versionType":"semver"},{"version":"7.1.4","status":"unaffected","lessThanOrEqual":"7.1.*","versionType":"semver"},{"version":"7.2","status":"unaffected","lessThanOrEqual":"*","versionType":"original_commit_for_fix"}],"repo":"https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git","programFiles":["drivers/nvme/target/discovery.c"]}],"references":["https://git.kernel.org/stable/c/ff815b5e8688dcf68529b7f0fde8de5847f63f1e","https://git.kernel.org/stable/c/8ae9bb92fc9a712a8d32da9c5fd657101f9b260b","https://git.kernel.org/stable/c/33b974eb626154ae9348f2bac7de84cb2a3d9dd4","https://git.kernel.org/stable/c/56c021a0869260d04c4b65d1471936aaf9177114","https://git.kernel.org/stable/c/a29b316b9bbfd269f323ab4ba9906a894025680f","https://git.kernel.org/stable/c/53cd102a7a56079b11b897835bd9b94c14e6322c"],"weaknesses":["CWE-125"],"ingestedAt":"2026-10-30T12:46:06.359Z","source":{"repository":"CVEProject/cvelistV5","path":"cves/2026/64xxx/CVE-2026-64320.json","commit":"1f312381e38164a43607eebab851b151dd16861e","baselineCommit":"556c9d3a8cd17e218bb8e452ba7cd619a384ff47"},"raw":{"dataType":"CVE_RECORD","dataVersion":"5.2","cveMetadata":{"cveId":"CVE-2026-64320","state":"PUBLISHED","datePublished":"2026-07-25T08:49:48.908Z","dateUpdated":"2026-10-30T12:27:44.977Z","assignerShortName":"Linux","assignerOrgId":"416baaa9-dc9f-4396-8d5f-8c081fb06d67","dateReserved":"2026-07-19T15:36:31.780Z"},"containers":{"cna":{"title":"nvmet: fix pre-auth out-of-bounds heap read in Discovery Get Log Page","descriptions":[{"lang":"en","value":"In the Linux kernel, the following vulnerability has been resolved:\n\nnvmet: fix pre-auth out-of-bounds heap read in Discovery Get Log Page\n\nnvmet_execute_disc_get_log_page() validates only the dword alignment\nof the host-supplied Log Page Offset (lpo).  The 64-bit offset is then\nadded to a small kzalloc'd buffer that holds the discovery log page\nand the result is passed straight to nvmet_copy_to_sgl(), which\nmemcpy()s data_len bytes out to the host with no source-side bound\ncheck:\n\n    u64 offset      = nvmet_get_log_page_offset(req->cmd);  /* 64-bit host */\n    size_t data_len = nvmet_get_log_page_len(req->cmd);     /* 32-bit host */\n    ...\n    if (offset & 0x3) { ... }                               /* only check */\n    ...\n    alloc_len = sizeof(*hdr) + entry_size * discovery_log_entries(req);\n    buffer = kzalloc(alloc_len, GFP_KERNEL);\n    ...\n    status = nvmet_copy_to_sgl(req, 0, buffer + offset, data_len);\n\nThe Discovery controller is unauthenticated -- nvmet_host_allowed()\nreturns true unconditionally for the discovery subsystem -- so the call\nis reachable pre-authentication by any TCP/RDMA/FC peer that can reach\nthe nvmet target.  With a discovery log page of ~1 KiB, an attacker\nrequesting up to 4 KiB starting at offset == alloc_len reads the next\nslab page out and gets its content returned over the fabric (an\nempirical run on a default nvmet-tcp loopback target leaked 81\ncanonical kernel pointers in one Get Log Page response).  Pointing the\noffset at unmapped kernel memory faults the in-kernel memcpy and\ncrashes (or panics, on panic_on_oops=1) the target host instead.\n\nThe attacker-controlled source-side offset pattern\n\"nvmet_copy_to_sgl(req, 0, buffer + ATTACKER_OFFSET, ...)\" is unique\nto nvmet_execute_disc_get_log_page in the entire nvmet codebase: every\nother Get Log Page handler in admin-cmd.c either ignores lpo (and\nsilently starts every response at offset 0) or tracks a local\ndestination offset with a fixed source pointer.\n\nValidate the host-supplied offset against the log page size, cap the\ncopy length to what is actually available, and zero-fill any remainder\nof the host transfer buffer.  The zero-fill matches the existing\nshort-response pattern in nvmet_execute_get_log_changed_ns()\n(admin-cmd.c) and prevents leaking transport SGL contents when the\nhost asks for more bytes than the log page contains."}],"affected":[{"vendor":"Linux","product":"Linux","defaultStatus":"unaffected","versions":[{"version":"a07b4970f464f13640e28e16dad6cfa33647cc99","status":"affected","lessThan":"ff815b5e8688dcf68529b7f0fde8de5847f63f1e","versionType":"git"},{"version":"a07b4970f464f13640e28e16dad6cfa33647cc99","status":"affected","lessThan":"8ae9bb92fc9a712a8d32da9c5fd657101f9b260b","versionType":"git"},{"version":"a07b4970f464f13640e28e16dad6cfa33647cc99","status":"affected","lessThan":"33b974eb626154ae9348f2bac7de84cb2a3d9dd4","versionType":"git"},{"version":"a07b4970f464f13640e28e16dad6cfa33647cc99","status":"affected","lessThan":"56c021a0869260d04c4b65d1471936aaf9177114","versionType":"git"},{"version":"a07b4970f464f13640e28e16dad6cfa33647cc99","status":"affected","lessThan":"a29b316b9bbfd269f323ab4ba9906a894025680f","versionType":"git"},{"version":"a07b4970f464f13640e28e16dad6cfa33647cc99","status":"affected","lessThan":"53cd102a7a56079b11b897835bd9b94c14e6322c","versionType":"git"}],"repo":"https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git","programFiles":["drivers/nvme/target/discovery.c"]},{"vendor":"Linux","product":"Linux","defaultStatus":"affected","versions":[{"version":"4.8","status":"affected"},{"version":"0","status":"unaffected","lessThan":"4.8","versionType":"semver"},{"version":"6.1.191","status":"unaffected","lessThanOrEqual":"6.1.*","versionType":"semver"},{"version":"6.6.160","status":"unaffected","lessThanOrEqual":"6.6.*","versionType":"semver"},{"version":"6.12.96","status":"unaffected","lessThanOrEqual":"6.12.*","versionType":"semver"},{"version":"6.18.39","status":"unaffected","lessThanOrEqual":"6.18.*","versionType":"semver"},{"version":"7.1.4","status":"unaffected","lessThanOrEqual":"7.1.*","versionType":"semver"},{"version":"7.2","status":"unaffected","lessThanOrEqual":"*","versionType":"original_commit_for_fix"}],"repo":"https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git","programFiles":["drivers/nvme/target/discovery.c"]}],"references":[{"url":"https://git.kernel.org/stable/c/ff815b5e8688dcf68529b7f0fde8de5847f63f1e"},{"url":"https://git.kernel.org/stable/c/8ae9bb92fc9a712a8d32da9c5fd657101f9b260b"},{"url":"https://git.kernel.org/stable/c/33b974eb626154ae9348f2bac7de84cb2a3d9dd4"},{"url":"https://git.kernel.org/stable/c/56c021a0869260d04c4b65d1471936aaf9177114"},{"url":"https://git.kernel.org/stable/c/a29b316b9bbfd269f323ab4ba9906a894025680f"},{"url":"https://git.kernel.org/stable/c/53cd102a7a56079b11b897835bd9b94c14e6322c"}],"metrics":[{"cvssV3_1":{"version":"3.1","vectorString":"CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:H","baseScore":9.1,"baseSeverity":"CRITICAL"},"scenarios":[{"lang":"en","value":"AV:N - The vulnerable discovery command is remotely reachable through routable NVMe/TCP, as well as NVMe/RDMA and FC transports.\nAC:L - The attacker controls the protocol sequence, transfer length, and aligned 64-bit offset, with no race or condition outside their control.\nPR:N - The discovery subsystem accepts every Host NQN and explicitly skips DH-HMAC-CHAP authentication, making the command reachable pre-authentication.\nUI:N - No victim action is required after the NVMe-oF target port is available.\nS:U - The disclosure and crash affect the vulnerable target kernel within the same security authority.\nC:H - The unbounded offset permits repeated multi-kilobyte kernel heap disclosures; testing cited by the fix exposed 81 canonical kernel pointers in one response.\nI:N - The primitive reads target memory into transport response pages but provides no attacker-selected write to target memory.\nA:H - An offset resolving to unmapped or noncanonical memory faults the in-kernel memcpy, causing an oops or target-host panic."}]}],"providerMetadata":{"shortName":"Linux","orgId":"416baaa9-dc9f-4396-8d5f-8c081fb06d67","dateUpdated":"2026-10-30T12:27:44.977Z"},"cpeApplicability":[{"nodes":[{"operator":"OR","negate":false,"cpeMatch":[{"vulnerable":true,"criteria":"cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*","versionStartIncluding":"4.8","versionEndExcluding":"6.1.191"},{"vulnerable":true,"criteria":"cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*","versionStartIncluding":"4.8","versionEndExcluding":"6.6.160"},{"vulnerable":true,"criteria":"cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*","versionStartIncluding":"4.8","versionEndExcluding":"6.12.96"},{"vulnerable":true,"criteria":"cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*","versionStartIncluding":"4.8","versionEndExcluding":"6.18.39"},{"vulnerable":true,"criteria":"cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*","versionStartIncluding":"4.8","versionEndExcluding":"7.1.4"},{"vulnerable":true,"criteria":"cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*","versionStartIncluding":"4.8","versionEndExcluding":"7.2"}]}]}],"x_generator":{"engine":"bippy-1.2.0"}},"adp":[{"title":"CISA ADP Vulnrichment","metrics":[{"other":{"type":"ssvc","content":{"id":"CVE-2026-64320","role":"CISA Coordinator","options":[{"Exploitation":"none"},{"Automatable":"yes"},{"Technical Impact":"partial"}],"version":"2.0.3","timestamp":"2026-10-16T15:39:04.867020Z"}}}],"problemTypes":[{"descriptions":[{"cweId":"CWE-125","lang":"en","type":"CWE","description":"CWE-125 Out-of-bounds Read"}]}],"providerMetadata":{"shortName":"CISA-ADP","orgId":"134c704f-9b21-4f2e-91b3-4a467353bcc0","dateUpdated":"2026-10-19T20:38:23.729Z"}}]}}}