On Fri, Jun 19, 2026 at 7:44 PM Bryam Vargas via B4 Relay <[email protected]> wrote: > > From: Bryam Vargas <[email protected]> > > 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: [email protected] > Signed-off-by: Bryam Vargas <[email protected]> > --- > drivers/md/dm-pcache/cache.c | 14 ++++++++++++++ > 1 file changed, 14 insertions(+) > > diff --git a/drivers/md/dm-pcache/cache.c b/drivers/md/dm-pcache/cache.c > index e6a2f4460f6e..08decbebd238 100644 > --- a/drivers/md/dm-pcache/cache.c > +++ b/drivers/md/dm-pcache/cache.c > @@ -250,6 +250,13 @@ static int get_seg_id(struct pcache_cache *cache, > } else { > *seg_id = cache->cache_info.seg_id; > } > + > + if (*seg_id >= cache_dev->seg_num) { > + pcache_dev_err(pcache, "invalid segment id %u from > cache device (seg_num %u)\n", > + *seg_id, cache_dev->seg_num); > + ret = -EIO; > + goto err; > + } > } > return 0; > err: > @@ -265,6 +272,13 @@ static int cache_segs_init(struct pcache_cache *cache) > int ret; > u32 i; > > + if (cache_info->n_segs > cache->cache_dev->seg_num) { > + pcache_dev_err(CACHE_TO_PCACHE(cache), > + "cache_info n_segs %u exceeds cache device > segments %u\n", > + cache_info->n_segs, cache->cache_dev->seg_num); > + return -EIO; > + } > + > for (i = 0; i < cache_info->n_segs; i++) { > ret = get_seg_id(cache, prev_cache_seg, new_cache, &seg_id); > if (ret) > > -- > 2.43.0 > >
Reviewed-by: Zheng Gu <[email protected]>

