Re: [PATCH 2/3] dm-pcache: validate geometry fields from on-disk cache_info

From: Zheng Gu

Date: Sat Jun 27 2026 - 04:05:24 EST


On Fri, Jun 19, 2026 at 7:44 PM Bryam Vargas via B4 Relay
<devnull+hexlabsecurity.proton.me@xxxxxxxxxx> wrote:
>
> From: Bryam Vargas <hexlabsecurity@xxxxxxxxx>
>
> 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@xxxxxxxxxxxxxxx
> Signed-off-by: Bryam Vargas <hexlabsecurity@xxxxxxxxx>
> ---
> 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 <cengku@xxxxxxxxx>