From: Bryam Vargas <[email protected]>

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

diff --git a/drivers/md/dm-pcache/cache_key.c b/drivers/md/dm-pcache/cache_key.c
index 2284dbc0807b..86cc9565ffc7 100644
--- a/drivers/md/dm-pcache/cache_key.c
+++ b/drivers/md/dm-pcache/cache_key.c
@@ -90,10 +90,19 @@ int cache_key_decode(struct pcache_cache *cache,
                        struct pcache_cache_key *key)
 {
        struct dm_pcache *pcache = CACHE_TO_PCACHE(cache);
+       u64 dev_bytes = (u64)cache->dev_size << SECTOR_SHIFT;
 
        key->off = key_onmedia->off;
        key->len = key_onmedia->len;
 
+       if (key_onmedia->len == 0 ||
+           key_onmedia->len > dev_bytes ||
+           key_onmedia->off > dev_bytes - key_onmedia->len) {
+               pcache_dev_err(pcache, "key off %llu + len %u exceeds device 
size\n",
+                               key_onmedia->off, key_onmedia->len);
+               return -EIO;
+       }
+
        if (!cache_seg_id_valid(cache, key_onmedia->cache_seg_id)) {
                pcache_dev_err(pcache, "invalid cache_seg_id %u in cache key 
(n_segs %u)\n",
                                key_onmedia->cache_seg_id, cache->n_segs);

-- 
2.43.0



Reply via email to