{ "dataType": "CVE_RECORD", "dataVersion": "5.2", "cveMetadata": { "cveId": "CVE-2026-93201", "assignerOrgId": "416baaa9-dc9f-4396-8d5f-8c081fb06d67", "state": "PUBLISHED", "assignerShortName": "Linux", "dateReserved": "2026-09-17T16:02:15.092Z", "datePublished": "2026-09-17T16:12:22.392Z", "dateUpdated": "2026-10-19T09:07:13.558Z" }, "containers": { "cna": { "providerMetadata": { "orgId": "416baaa9-dc9f-4396-8d5f-8c081fb06d67", "shortName": "Linux", "dateUpdated": "2026-10-19T09:07:13.558Z" }, "descriptions": [ { "lang": "en", "value": "In the Linux kernel, the following vulnerability has been resolved:\n\ndm-pcache: validate seg_id fields from persistent memory\n\ncache_pos_decode(), cache_key_decode() and the last-kset branches of\ncache_replay(), the writeback worker and the GC worker take a cache\nsegment id from the cache device metadata and index cache->segments[]\nwith it without checking it against cache->n_segs. That metadata is only\nCRC-protected with a fixed public seed, so whoever supplies the cache\ndevice on a table load (CAP_SYS_ADMIN) controls the id; an out-of-range\nvalue forms a wild pcache_cache_segment pointer that is dereferenced and\nwritten through -- an out-of-bounds read and write driven by on-disk data.\n\nAdd cache_seg_id_valid() and reject an out-of-range id at each decode\nsite, failing the operation with -EIO instead of indexing past the array.\nBound the id against the initialized-segment count (cache_info.n_segs)\nrather than the physical device total. A forged cache_info.n_segs below\nseg_num otherwise leaves segments[cache_info.n_segs..seg_num) as zeroed\nstructs whose data pointer is NULL, so a forged id in that window would\nstill be dereferenced. A later patch guarantees cache_info.n_segs <=\nseg_num, and a driver-created cache sets the two equal, so valid images\nare unaffected." } ], "metrics": [ { "cvssV3_1": { "version": "3.1", "vectorString": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H", "baseScore": 7.8, "baseSeverity": "HIGH" }, "scenarios": [ { "lang": "en", "value": "AV:L - Attacker-controlled cache_seg_id/next_cache_seg_id bytes are consumed only on a local DM_TABLE_LOAD of a pcache target (ctl_ioctl → table_load → dm_pcache_ctr → pcache_cache_start → cache_pos_decode/cache_key_decode/cache_replay) from a supplied DAX cache device; no network, Bluetooth, or USB receive path parses those on-media ids.\nAC:L - The attacker forges pos_onmedia.cache_seg_id, key_onmedia.cache_seg_id and last-kset next_cache_seg_id with a valid CRC because PCACHE_CRC_SEED (0x3B15A) is public, so a crafted INIT_DONE image makes cache_pos_decode/cache_key_decode/cache_replay index cache->segments[] out of bounds on every table load with no race.\nPR:L - ctl_ioctl in dm-ioctl.c gates DM_TABLE_LOAD with capable(CAP_SYS_ADMIN); kernel-CNA scoring of dm-pcache table-load bugs treats that delegated capability (privileged containers, LVM/storage helpers that already hold mapper and DAX/pmem nodes) as Low rather than exclusive init-namespace root.\nUI:N - The attacker writes the forged cache_seg_id fields onto their DAX cache device and issues DM_TABLE_LOAD for the pcache target themselves; no separate victim must mount media, open a file, or otherwise interact.\nS:U - The wild pcache_cache_segment taken as &cache->segments[id] and the resulting kvalloc/DAX-mapping corruption stay inside the host kernel that loaded the table; this is not a VM escape, IOMMU bypass, or other cross-authority boundary.\nC:H - An out-of-range id makes cache_pos_decode, cache_key_decode and cache_replay's last-kset branch take &cache->segments[id] past the kvalloc'd array; cache_pos_addr() then copy_mc_to_kernel of a kset, and cache_key_data_crc() crc32c of key->len bytes, read through the fake object's segment.data — an unbounded kernel over-read.\nI:H - last_kset_gc/last_kset_writeback store the wild segment pointer into key_tail/dirty_tail; cache_replay then __set_bit()s cache_seg_id from that OOB object into cache->seg_map, and cache_seg_get/cache_seg_put → cache_seg_ctrl_write memcpy_flushcache through the fake cache_seg_ctrl pointer, an out-of-bounds kernel write.\nA:H - Indexing past cache->segments[], or a forged id in [cache_info.n_segs, seg_num) whose kvzalloc'd slot has segment.data NULL, makes cache_pos_addr() and later copy_mc_to_kernel/memcpy_flushcache walk a NULL or unmapped kernel VA during table load or in the GC/writeback workers, oopsing or panicking the host." } ] } ], "affected": [ { "product": "Linux", "vendor": "Linux", "defaultStatus": "unaffected", "repo": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git", "programFiles": [ "drivers/md/dm-pcache/cache.c", "drivers/md/dm-pcache/cache.h", "drivers/md/dm-pcache/cache_gc.c", "drivers/md/dm-pcache/cache_key.c", "drivers/md/dm-pcache/cache_writeback.c" ], "versions": [ { "version": "1d57628ff95b32d5cfa8d8f50e07690c161e9cf0", "lessThan": "96d4b275281b45aacd0f0510fa8bec85d9f7dc5a", "status": "affected", "versionType": "git" }, { "version": "1d57628ff95b32d5cfa8d8f50e07690c161e9cf0", "lessThan": "b4bf8af5e7d7db4c5e179e15017da55857761ac4", "status": "affected", "versionType": "git" }, { "version": "1d57628ff95b32d5cfa8d8f50e07690c161e9cf0", "lessThan": "90c990a68460d7b5720e5634cf650eccdf0f4098", "status": "affected", "versionType": "git" } ] }, { "product": "Linux", "vendor": "Linux", "defaultStatus": "affected", "repo": "https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git", "programFiles": [ "drivers/md/dm-pcache/cache.c", "drivers/md/dm-pcache/cache.h", "drivers/md/dm-pcache/cache_gc.c", "drivers/md/dm-pcache/cache_key.c", "drivers/md/dm-pcache/cache_writeback.c" ], "versions": [ { "version": "6.18", "status": "affected" }, { "version": "0", "lessThan": "6.18", "status": "unaffected", "versionType": "semver" }, { "version": "6.18.57", "lessThanOrEqual": "6.18.*", "status": "unaffected", "versionType": "semver" }, { "version": "7.2.6", "lessThanOrEqual": "7.2.*", "status": "unaffected", "versionType": "semver" }, { "version": "7.3", "lessThanOrEqual": "*", "status": "unaffected", "versionType": "original_commit_for_fix" } ] } ], "cpeApplicability": [ { "nodes": [ { "operator": "OR", "negate": false, "cpeMatch": [ { "vulnerable": true, "criteria": "cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*", "versionStartIncluding": "6.18", "versionEndExcluding": "6.18.57" }, { "vulnerable": true, "criteria": "cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*", "versionStartIncluding": "6.18", "versionEndExcluding": "7.2.6" }, { "vulnerable": true, "criteria": "cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*", "versionStartIncluding": "6.18", "versionEndExcluding": "7.3" } ] } ] } ], "references": [ { "url": "https://git.kernel.org/stable/c/96d4b275281b45aacd0f0510fa8bec85d9f7dc5a" }, { "url": "https://git.kernel.org/stable/c/b4bf8af5e7d7db4c5e179e15017da55857761ac4" }, { "url": "https://git.kernel.org/stable/c/90c990a68460d7b5720e5634cf650eccdf0f4098" } ], "title": "dm-pcache: validate seg_id fields from persistent memory", "x_generator": { "engine": "bippy-1.2.0" } } } }