From: Bryam Vargas <[email protected]>

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: [email protected]
Signed-off-by: Bryam Vargas <[email protected]>
---
 drivers/md/dm-pcache/cache_key.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/md/dm-pcache/cache_key.c b/drivers/md/dm-pcache/cache_key.c
index d00497f9e462..2284dbc0807b 100644
--- a/drivers/md/dm-pcache/cache_key.c
+++ b/drivers/md/dm-pcache/cache_key.c
@@ -768,7 +768,7 @@ int cache_replay(struct pcache_cache *cache)
        struct pcache_cache_pos pos_tail;
        struct pcache_cache_pos *pos;
        struct pcache_cache_kset_onmedia *kset_onmedia;
-       u32 to_copy, count = 0;
+       u32 to_copy, count = 0, last_hops = 0;
        int ret = 0;
 
        kset_onmedia = kzalloc(PCACHE_KSET_ONMEDIA_SIZE_MAX, GFP_KERNEL);
@@ -808,6 +808,11 @@ int cache_replay(struct pcache_cache *cache)
                                goto out;
                        }
 
+                       if (++last_hops > cache->n_segs) {
+                               ret = -EIO;
+                               goto out;
+                       }
+
                        next_seg = 
&cache->segments[kset_onmedia->next_cache_seg_id];
 
                        pos->cache_seg = next_seg;

-- 
2.43.0



Reply via email to