| 3a643cca | 23-Jul-2026 |
Jianyun Gao <jianyungao89@gmail.com> |
dm-pcache: remove unused 'cache' parameter from cache_key_gc()
The 'cache' parameter is never used in the function body, remove it.
Signed-off-by: Jianyun Gao <jianyungao89@gmail.com> Signed-off-by
dm-pcache: remove unused 'cache' parameter from cache_key_gc()
The 'cache' parameter is never used in the function body, remove it.
Signed-off-by: Jianyun Gao <jianyungao89@gmail.com> Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
show more ...
|
| a46fd918 | 17-Jul-2026 |
Jianyun Gao <jianyungao89@gmail.com> |
dm-pcache: remove unused 'allocated' variable in cache_data_alloc()
The 'allocated' variable is never non-zero when its value is consumed. 'to_alloc' was always equal to key->len, so replace them wi
dm-pcache: remove unused 'allocated' variable in cache_data_alloc()
The 'allocated' variable is never non-zero when its value is consumed. 'to_alloc' was always equal to key->len, so replace them with key->len directly.
Signed-off-by: Jianyun Gao <jianyungao89@gmail.com> Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
show more ...
|
| 8765dcb9 | 17-Jul-2026 |
Jianyun Gao <jianyungao89@gmail.com> |
dm-pcache: replace tabs with spaces in comments to fix ASCII diagram alignment
Some editors interpret tabs as 4 spaces while others use 2, causing ASCII art diagrams in comments to misalign and hurt
dm-pcache: replace tabs with spaces in comments to fix ASCII diagram alignment
Some editors interpret tabs as 4 spaces while others use 2, causing ASCII art diagrams in comments to misalign and hurt readability. Replace tabs with spaces to ensure consistent display across all editors.
Signed-off-by: Jianyun Gao <jianyungao89@gmail.com> Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
show more ...
|
| c2e894ea | 20-Jul-2026 |
Jianyun Gao <jianyungao89@gmail.com> |
dm-pcache: fix use-after-free and invalid seg operations in kset_replay()
In kset_replay, when key->seg_gen is stale (key->seg_gen < key->cache_pos.cache_seg->gen), cache_key_put(key) is called but
dm-pcache: fix use-after-free and invalid seg operations in kset_replay()
In kset_replay, when key->seg_gen is stale (key->seg_gen < key->cache_pos.cache_seg->gen), cache_key_put(key) is called but then key->cache_pos.cache_seg is accessed as the argument to cache_seg_get(). This is a use-after-free on the freed key memory. Although mempool recycled memory is not immediately reclaimed or overwritten in practice, this is still a potential UAF bug.
Additionally, for expired invalid keys, setting the cache->seg_map bit and calling cache_seg_get() is unreasonable since the corresponding segment data is no longer valid.
Fix both issues by moving cache_seg_get() and __set_bit() after the gen check, so they only execute for valid keys, and using continue to skip invalid keys.
Cc: stable@vger.kernel.org Fixes: 1d57628ff95b ("dm-pcache: add persistent cache target in device-mapper") Signed-off-by: Jianyun Gao <jianyungao89@gmail.com> Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
show more ...
|
| fb9e1728 | 20-Jul-2026 |
Jianyun Gao <jianyungao89@gmail.com> |
dm-pcache: fix implicit u8 truncation of gc_percent in message handler
When setting gc_percent via message, kstrtoul parses the input into an unsigned long, which is then implicitly truncated to u8
dm-pcache: fix implicit u8 truncation of gc_percent in message handler
When setting gc_percent via message, kstrtoul parses the input into an unsigned long, which is then implicitly truncated to u8 when passed to pcache_cache_set_gc_percent(). For example, value 266 (0x10A) silently truncates to 10 (0x0A), successfully bypassing the > 90 upper bound check in pcache_cache_set_gc_percent(), and setting a different value than the user intended.
Use kstrtou8 directly instead of kstrtoul, so that overflow values are properly rejected.
Cc: stable@vger.kernel.org Fixes: 1d57628ff95b ("dm-pcache: add persistent cache target in device-mapper") Signed-off-by: Jianyun Gao <jianyungao89@gmail.com> Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
show more ...
|
| 2df0fc04 | 17-Jul-2026 |
Bryam Vargas <hexlabsecurity@proton.me> |
dm-pcache: only hand out initialized cache segments
get_cache_segment() scans the segment map up to cache->n_segs, the physical device segment count, but cache_segs_init() only initializes the first
dm-pcache: only hand out initialized cache segments
get_cache_segment() scans the segment map up to cache->n_segs, the physical device segment count, but cache_segs_init() only initializes the first cache_info->n_segs segments. A crafted image with cache_info->n_segs smaller than the device count leaves the remaining pcache_cache_segment structs zeroed (segment.data == NULL), and the allocator can hand one to cache_kset_close(), which writes through the returned segment's data pointer with no NULL check.
Bound the allocator's search to cache_info->n_segs so only initialized segments are ever returned. A conforming cache sets n_segs equal to the device segment count, so this rejects nothing legitimate.
Fixes: 1d57628ff95b ("dm-pcache: add persistent cache target in device-mapper") Cc: stable@vger.kernel.org Signed-off-by: Bryam Vargas <hexlabsecurity@proton.me> Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
show more ...
|
| 58d620ee | 17-Jul-2026 |
Bryam Vargas <hexlabsecurity@proton.me> |
dm-pcache: validate the persisted dirty_tail chain at load
The writeback worker follows the persisted dirty_tail chain, which is decoded from the cache device independently of the key_tail chain tha
dm-pcache: validate the persisted dirty_tail chain at load
The writeback worker follows the persisted dirty_tail chain, which is decoded from the cache device independently of the key_tail chain that cache_replay() walks and bounds. A crafted image, whose on-media fields are authenticated only by a crc32c with a fixed seed, can aim dirty_tail at a chain of last ksets that never terminates, so cache_writeback_fn() re-arms itself with no delay forever.
Walk the dirty_tail chain once at load with the same hop cap cache_replay() uses and fail the table load with -EIO if it does not reach an end within n_segs hops.
Fixes: 1d57628ff95b ("dm-pcache: add persistent cache target in device-mapper") Cc: stable@vger.kernel.org Signed-off-by: Bryam Vargas <hexlabsecurity@proton.me> Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
show more ...
|
| 62d92e45 | 17-Jul-2026 |
Bryam Vargas <hexlabsecurity@proton.me> |
dm-pcache: validate on-media seg_num against the cache device size
seg_num is read from the crc32c-only superblock, so whoever supplies the cache device on a table load (CAP_SYS_ADMIN) controls it.
dm-pcache: validate on-media seg_num against the cache device size
seg_num is read from the crc32c-only superblock, so whoever supplies the cache device on a table load (CAP_SYS_ADMIN) controls it. It sizes cache->segments[] and is the value every later on-media segment id is bounded against, yet it is never checked against the device. Because cache_dev->mapping is the direct map of the pmem, CACHE_DEV_SEGMENT() for a segment id past the device resolves to ordinary kernel memory beyond the mapping; a new-cache init reaching such an id has cache_seg_init() -> cache_dev_zero_range() memset() 12 KiB over that memory -- an out-of-bounds write into the kernel heap at table load. A zero seg_num makes the segment allocations ZERO_SIZE_PTR.
Reject a seg_num that is zero, larger than the device can hold, or larger than PCACHE_CACHE_SEGS_MAX before it is used.
Fixes: 1d57628ff95b ("dm-pcache: add persistent cache target in device-mapper") Cc: stable@vger.kernel.org Signed-off-by: Bryam Vargas <hexlabsecurity@proton.me> Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
show more ...
|
| becf07e2 | 17-Jul-2026 |
Bryam Vargas <hexlabsecurity@proton.me> |
dm-pcache: clamp the tail kset read to the segment data region
The tail-kset read in cache_replay(), the writeback worker and the GC worker bounds its length by PCACHE_SEG_SIZE - seg_off, the raw se
dm-pcache: clamp the tail kset read to the segment data region
The tail-kset read in cache_replay(), the writeback worker and the GC worker bounds its length by PCACHE_SEG_SIZE - seg_off, the raw segment size rather than the data region. A tail near the segment end reads past the segment data into the following control area.
Clamp the read to cache_seg_remain(), the data region.
Fixes: 1d57628ff95b ("dm-pcache: add persistent cache target in device-mapper") Cc: stable@vger.kernel.org Signed-off-by: Bryam Vargas <hexlabsecurity@proton.me> Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
show more ...
|
| 97fc4b53 | 17-Jul-2026 |
Bryam Vargas <hexlabsecurity@proton.me> |
dm-pcache: bound the logical key offset from persistent memory
cache_key_decode() takes a key's logical off from the cache device and later indexes req_key_tree->subtrees[] by it in get_subtree(). A
dm-pcache: bound the logical key offset from persistent memory
cache_key_decode() takes a key's logical off from the cache device and later indexes req_key_tree->subtrees[] by it in get_subtree(). An off past the device forms a subtree pointer outside the array, which rb_insert() writes through during replay.
Reject a key of zero length, or whose off+len (computed in 64 bits) exceeds the device size, before it is used.
Fixes: 1d57628ff95b ("dm-pcache: add persistent cache target in device-mapper") Cc: stable@vger.kernel.org Signed-off-by: Bryam Vargas <hexlabsecurity@proton.me> Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
show more ...
|
| 16c3b3a3 | 17-Jul-2026 |
Bryam Vargas <hexlabsecurity@proton.me> |
dm-pcache: detect a cycle in the last-kset chain during replay
cache_replay() follows the on-media last-kset chain by next_cache_seg_id with no cond_resched(). A forged chain that points back into a
dm-pcache: detect a cycle in the last-kset chain during replay
cache_replay() follows the on-media last-kset chain by next_cache_seg_id with no cond_resched(). A forged chain that points back into a segment it has already visited makes the replay loop follow it forever.
Cap the last-kset hops at cache->n_segs; a valid chain visits each segment at most once.
Fixes: 1d57628ff95b ("dm-pcache: add persistent cache target in device-mapper") Cc: stable@vger.kernel.org Signed-off-by: Bryam Vargas <hexlabsecurity@proton.me> Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
show more ...
|
| 7ac1f10f | 17-Jul-2026 |
Bryam Vargas <hexlabsecurity@proton.me> |
dm-pcache: reject a kset that overruns its segment
cache_replay(), the writeback worker and the GC worker read a kset of get_kset_onmedia_size() bytes and advance the position by it. A forged key_nu
dm-pcache: reject a kset that overruns its segment
cache_replay(), the writeback worker and the GC worker read a kset of get_kset_onmedia_size() bytes and advance the position by it. A forged key_num makes that size exceed the segment's remaining space, so the advance walks past the segment and trips the cache_pos_advance() BUG_ON.
Reject a kset whose on-media size exceeds cache_seg_remain() before use.
Fixes: 1d57628ff95b ("dm-pcache: add persistent cache target in device-mapper") Cc: stable@vger.kernel.org Signed-off-by: Bryam Vargas <hexlabsecurity@proton.me> Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
show more ...
|
| d1898576 | 17-Jul-2026 |
Bryam Vargas <hexlabsecurity@proton.me> |
dm-pcache: bound the persisted tail-position offset
cache_pos_decode() takes the persisted key_tail and dirty_tail seg_off from the cache device and addresses within the segment with it. A seg_off a
dm-pcache: bound the persisted tail-position offset
cache_pos_decode() takes the persisted key_tail and dirty_tail seg_off from the cache device and addresses within the segment with it. A seg_off at or past the segment data_size, controllable by whoever supplies the device (CAP_SYS_ADMIN), reads past the segment data.
Reject a decoded seg_off that is not below the segment data_size.
Fixes: 1d57628ff95b ("dm-pcache: add persistent cache target in device-mapper") Cc: stable@vger.kernel.org Signed-off-by: Bryam Vargas <hexlabsecurity@proton.me> Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
show more ...
|
| f11deb03 | 17-Jul-2026 |
Bryam Vargas <hexlabsecurity@proton.me> |
dm-pcache: validate kset key_num and intra-segment bounds
Two more fields decoded from the cache device go unbounded. The kset key_num drives cache_kset_crc() and the replay loop in cache_replay(),
dm-pcache: validate kset key_num and intra-segment bounds
Two more fields decoded from the cache device go unbounded. The kset key_num drives cache_kset_crc() and the replay loop in cache_replay(), the writeback worker and the GC worker, but only the magic and a fixed-seed CRC are checked first, so a non-last kset whose key_num exceeds the PCACHE_KSET_KEYS_MAX buffer reads past its end before the CRC compare. A key's intra-segment offset and length in cache_key_decode() are taken verbatim, so a key running past its segment is replayed into the cache tree and the data CRC check and every later read hit then copy adjacent persistent memory into the caller's bio -- an out-of-bounds read that leaks to user space. Both fields are controlled by whoever supplies the cache device (CAP_SYS_ADMIN); the CRC seed is public.
Add kset_onmedia_valid() to bound key_num before any kset read, and reject a key whose offset plus length, computed in 64 bits, exceeds the segment data_size. Valid metadata is unaffected.
Fixes: 1d57628ff95b ("dm-pcache: add persistent cache target in device-mapper") Cc: stable@vger.kernel.org Signed-off-by: Bryam Vargas <hexlabsecurity@proton.me> Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
show more ...
|
| 32d1809d | 17-Jul-2026 |
Bryam Vargas <hexlabsecurity@proton.me> |
dm-pcache: validate geometry fields from on-disk cache_info
cache_segs_init() iterates cache_info->n_segs times indexing cache->segments[], which is sized to the cache device geometry, and get_seg_i
dm-pcache: validate geometry fields from on-disk cache_info
cache_segs_init() iterates cache_info->n_segs times indexing cache->segments[], which is sized to the cache device geometry, and get_seg_id() takes each segment id from the on-media cache_info and the per-segment next_seg link. Both come from cache device metadata that is only CRC-protected with a fixed public seed, so whoever supplies the cache device on a table load (CAP_SYS_ADMIN) controls them: an oversized n_segs or an out-of-range id drives an out-of-bounds access of cache->segments[] and a wild CACHE_DEV_SEGMENT() pointer into the device mapping -- an out-of-bounds read and write from on-disk data.
Reject an n_segs that exceeds the device segment count and a segment id that is out of range before either is used. Valid metadata is unaffected.
Fixes: 1d57628ff95b ("dm-pcache: add persistent cache target in device-mapper") Cc: stable@vger.kernel.org Signed-off-by: Bryam Vargas <hexlabsecurity@proton.me> Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
show more ...
|
| 13ea55ea | 05-Dec-2025 |
Li Chen <chenl311@chinatelecom.cn> |
dm pcache: fix segment info indexing
Segment info indexing also used sizeof(struct) instead of the 4K metadata stride, so info_index could point between slots and subsequent writes would advance inc
dm pcache: fix segment info indexing
Segment info indexing also used sizeof(struct) instead of the 4K metadata stride, so info_index could point between slots and subsequent writes would advance incorrectly. Derive info_index from the pointer returned by the segment meta search using PCACHE_SEG_INFO_SIZE and advance to the next slot for future updates.
Signed-off-by: Li Chen <chenl311@chinatelecom.cn> Signed-off-by: Dongsheng Yang <dongsheng.yang@linux.dev> Signed-off-by: Mikulas Patocka <mpatocka@redhat.com> Reviewed-by: Zheng Gu <cengku@gmail.com> Cc: stable@vger.kernel.org # 6.18
show more ...
|