167 lines
10 KiB
JSON
167 lines
10 KiB
JSON
{
|
|
"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"
|
|
}
|
|
}
|
|
}
|
|
} |