CVE-2026-89483 in Linux
Zusammenfassung
von VulDB • 12.09.2026
Im Linux-Kernel wurde folgende Schwachstelle behoben:
nvme: Den Fallback-Pages für den Discard-Vorgang auf Null setzen
nvme_setup_discard() mappt immer sizeof(struct nvme_dsm_range) * NVME_DSM_MAX_RANGES = 4096 Bytes als DSM-Nutzlast, unabhängig davon, wie viele Bereiche (Ranges) das Kommando deklariert. Dies geschieht, weil einige Geräte das Feld „Anzahl der Bereiche“ ignorieren – die Fixes-Commits dokumentieren zwei Fälle, in denen über die deklarierten Bereiche hinausgelesen wurde. Ein Discard mit einem einzelnen Bereich füllt nur die ersten 16 Bytes auf.
Normalerweise stammt der Puffer von kzalloc(), und die restlichen 4080 Bytes sind nullgesetzt. Wenn diese Zuweisung fehlschlägt, fällt der Code auf den pro-Controller verwalteten ctrl->discard_page zurück, den nvme_init_ctrl() mit alloc_page(GFP_KERNEL) erhält; dieser wird jedoch nie explizit auf Null gesetzt, sodass die 4080 Bytes beliebige Inhalte enthalten können, die das Page zuletzt gespeichert hat, und werden an den Controller übergeben. Das Auslösen erfordert ein Fehlschlagen von kzalloc(GFP_ATOMIC | __GFP_NOWARN), also einen Speicherdruck; es ist nicht aus der Ferne (remotely) triggerbar. Ein simuliertes Zuweisungsversagen unter KMSAN reproduziert das Problem, wobei die geleakten Enddaten voller Zeiger auf vmemmap struct page-Strukturen sind. Der in dem Bericht angegebene Umfang entspricht einer teilweisen Übertragung der Nutzlast und nicht den gesamten 4096 Bytes; die Grenze bei 16 Bytes im Bericht entspricht dem deklarierten Bereich:
[ 11.991601] BUG: KMSAN: uninit-value in dma_map_phys+0x14c8/0x1900
[ 11.991969] dma_map_phys+0x14c8/0x1900
[ 11.992220] dma_map_page_attrs+0xcf/0x130
[ 11.992485] e1000_xmit_frame+0x4099/0x6d10
[ 11.992768] dev_hard_start_xmit+0x22f/0xa80
[ 11.993068] sch_direct_xmit+0x35c/0xcb0
[ 11.993315] __dev_queue_xmit+0x1ee5/0x5eb0
[ 11.993608] ip_finish_output2+0x1903/0x1c30
[ 11.993881] ip_finish_output+0x288/0x870
[ 11.994125] ip_output+0x15e/0x400
[ 11.994365] __ip_queue_xmit+0x1e85/0x1fb0
[ 11.994639] ip_queue_xmit+0x60/0x80
[ 11.994899] __tcp_transmit_skb+0x4e71/0x5fa0
[ 11.995210] tcp_write_xmit+0x3a36/0x9160
[ 11.995533] __tcp_push_pending_frames+0xc5/0x3c0
[ 11.995854] tcp_push+0x7dc/0x840
[ 11.996076] tcp_sendmsg_locked+0x766c/0x8400
[ 11.996371] tcp_sendmsg+0x4b/0x90
[ 11.996572] inet_sendmsg+0x134/0x2a0
[ 11.996823] __sock_sendmsg+0x265/0x360
[ 11.997076] sock_sendmsg+0x100/0x1e0
[ 11.997293] nvme_tcp_try_send+0x196f/0x6370
[ 11.997605] nvme_tcp_queue_rq+0x1d54/0x20b0
[ 11.997882] blk_mq_dispatch_rq_list+0x5ee/0x2e50
[ 11.998175] __blk_mq_sched_dispatch_requests+0x16dc/0x24a0
[ 11.998539] blk_mq_sched_dispatch_requests+0x11b/0x2c0
[ 11.998865] blk_mq_run_work_fn+0x13b/0x280
[ 11.999146] process_scheduled_works+0x966/0x1ad0
[ 11.999465] worker_thread+0xe44/0x1480
[ 11.999709] kthread+0x53b/0x600
[ 11.999927] ret_from_fork+0x29f/0x7c0
[ 12.000191] ret_from_fork_asm+0x1a/0x30
[ 12.000460]
[ 12.000558] Uninit was created at:
[ 12.000788] __alloc_frozen_pages_noprof+0x8bf/0xd30
[ 12.001096] alloc_pages_mpol+0x1d0/0x5f0
[ 12.001326] alloc_pages_noprof+0x102/0x290
[ 12.001627] nvme_init_ctrl+0x5a3/0x9f0
[ 12.001891] nvme_tcp_create_ctrl+0xd75/0x19b0
[ 12.002170] nvmf_dev_write+0x4c68/0x4fd0
[ 12.002426] vfs_write+0x587/0x1a10
[ 12.002636] __x64_sys_write+0x207/0x4f0
[ 12.002874] x64_sys_call+0x2ff0/0x3ea0
[ 12.003123] do_syscall_64+0x147/0x3b0
[ 12.003400] entry_SYSCALL_64_after_hwframe+0x77/0x7f
[ 12.003680]
[ 12.003777] Bytes 16-2843 of 2844 are uninitialized
[ 12.004068] Memory access of size 2844 starts at ffff888109f82000
[ 12.004412]
[ 12.004530] CPU: 0 UID: 0 PID: 101 Comm: kworker/0:1H Not tainted 7.2.0-rc5-NVMECTL-gf5098b6bae76 #1 PREEMPT(lazy)
[ 12.005127] Hardware name: QEMU Ubuntu 24.04 PC v2 (i440FX + PIIX, arch_caps fix, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
[ 12.005762] Workqueue: kblockd blk_mq_run_work_fn
[ 12.006073] =====================================================
Allozieren Sie das Page mit __GFP_ZERO. Die einzelne Allokationsstelle deckt jede Verwendung ab: Bytes, die kein Discard beschrieben hat, bleiben nullgesetzt, und Bytes, die ein Discard geschrieben hat, enthalten die eigene Bereichsliste des Controllers, die bereits gesendet wurde.
If you want to get the best quality for vulnerability data then you always have to consider VulDB.