From nobody Sat Jul 25 05:28:12 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B2E1C3F12E8; Fri, 17 Jul 2026 11:26:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784287615; cv=none; b=YcW/nLieaoZjDdMifzIpnH3cbIOJ+RD3IeWtSHePYqdbAMhKSliRgj8btqqPaaxvbmz5tEXfyj3DmzvjuOGY9prfQR0KrLX1jE2STA8C9ksoyYrEgCXW735PXXO7Jeh3r/5HTA1ONIyIsKPk7fgm8sw1aGj75sB9Fz4eVDABxVs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784287615; c=relaxed/simple; bh=WCWTrGJPjpKGrMhPKAv0k5YF3Pyz/OABBWk16CwOws4=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=iyNnuHGEPvi/jqRCT6ZTUq+zCptk+1NlMRG1woPg5c6vAORzH401NnZUiI5IbZqVvhnaEQCjU34awncEAEiBZp25IlymbimJ20LJmZ4/hKLFdO7Fp/cz446GdTRgpgdRpcFVU7/DK5HAuNlJ6fvZ5V6k2xzjUF1yX/UHxGqPtvo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=GPpfB5sg; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="GPpfB5sg" Received: by smtp.kernel.org (Postfix) with ESMTPS id 06013C2BCB8; Fri, 17 Jul 2026 11:26:55 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1784287615; bh=WCWTrGJPjpKGrMhPKAv0k5YF3Pyz/OABBWk16CwOws4=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=GPpfB5sgC0sfx90SzmOO0dkGJr/W9nqrK+0wrn40h6pfxSyHgEgRFu0daFmd0SsZV Sikgf9ECCLV2QOLwGV2HekgwbpgN8HuKs/nMb3qil2Jm90Cma00OuG4kPGseItnj+H A/PezjD9aPCqt/YG6UZnklLo053ln39UPXrp2mhw8SueASx7NPsehqBytdQa2ycv4G 9wDWD+FV/XAxzPVxcJwh7HsmWYOXvnOzsUbMhvyT3AHz1zu3Nrw6/cPsKL/d4d7kuF wkyoIGrNMwqD1GVjwXIF32jZoamBTbTcik4VeEhmBNfupeESqODcnOrYzxdo6Bqjar uiE5wgT8Jmcdw== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id DBABBC44516; Fri, 17 Jul 2026 11:26:54 +0000 (UTC) From: Bryam Vargas via B4 Relay Date: Fri, 17 Jul 2026 06:26:54 -0500 Subject: [PATCH v2 01/11] dm-pcache: validate seg_id fields from persistent memory Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260717-b4-disp-4c0a0039-v2-1-19227d6e313c@proton.me> References: <20260717-b4-disp-4c0a0039-v2-0-19227d6e313c@proton.me> In-Reply-To: <20260717-b4-disp-4c0a0039-v2-0-19227d6e313c@proton.me> To: Zheng Gu , Dongsheng Yang Cc: dm-devel@lists.linux.dev, Mikulas Patocka , linux-kernel@vger.kernel.org X-Mailer: b4 0.13.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1784287613; l=8861; i=hexlabsecurity@proton.me; s=proton; h=from:subject:message-id; bh=gx6bjz1FQtrra3y13vv1tAq57E8F+9xcRi54L7st570=; b=xcJBDQKwxqbOv3YTrqYbPmDlFPud3KskH9RwLLCZegjeoXxoYVMQBFawEGpSOKIkVJZMOFaV5 woKUt6NHYN9ATzhl4W69W8eCvk8QaJys+NjQv9PaTSnO3y0r5C/aAKo X-Developer-Key: i=hexlabsecurity@proton.me; a=ed25519; pk=dmppBMZNLLoPzxHi9l8tZDzEZUunPbgsYqIZYXeUrL0= X-Endpoint-Received: by B4 Relay for hexlabsecurity@proton.me/proton with auth_id=814 X-Original-From: Bryam Vargas Reply-To: hexlabsecurity@proton.me From: Bryam Vargas cache_pos_decode(), cache_key_decode() and the last-kset branches of cache_replay(), the writeback worker and the GC worker take a cache segment id from the cache device metadata and index cache->segments[] with it without checking it against cache->n_segs. That metadata is only CRC-protected with a fixed public seed, so whoever supplies the cache device on a table load (CAP_SYS_ADMIN) controls the id; an out-of-range value forms a wild pcache_cache_segment pointer that is dereferenced and written through -- an out-of-bounds read and write driven by on-disk data. Add cache_seg_id_valid() and reject an out-of-range id at each decode site, failing the operation with -EIO instead of indexing past the array. Bound the id against the initialized-segment count (cache_info.n_segs) rather than the physical device total. A forged cache_info.n_segs below seg_num otherwise leaves segments[cache_info.n_segs..seg_num) as zeroed structs whose data pointer is NULL, so a forged id in that window would still be dereferenced. A later patch guarantees cache_info.n_segs <=3D seg_num, and a driver-created cache sets the two equal, so valid images are unaffected. Fixes: 1d57628ff95b ("dm-pcache: add persistent cache target in device-mapp= er") Cc: stable@vger.kernel.org Signed-off-by: Bryam Vargas --- drivers/md/dm-pcache/cache.c | 4 ++++ drivers/md/dm-pcache/cache.h | 15 +++++++++++++++ drivers/md/dm-pcache/cache_gc.c | 16 ++++++++++++++-- drivers/md/dm-pcache/cache_key.c | 11 +++++++++++ drivers/md/dm-pcache/cache_writeback.c | 23 +++++++++++++++++++---- 5 files changed, 63 insertions(+), 6 deletions(-) diff --git a/drivers/md/dm-pcache/cache.c b/drivers/md/dm-pcache/cache.c index bb1ada31e483..e9d2b87174d7 100644 --- a/drivers/md/dm-pcache/cache.c +++ b/drivers/md/dm-pcache/cache.c @@ -118,6 +118,9 @@ int cache_pos_decode(struct pcache_cache *cache, if (!latest_addr) return -EIO; =20 + if (!cache_seg_id_valid(cache, latest.cache_seg_id)) + return -EIO; + pos->cache_seg =3D &cache->segments[latest.cache_seg_id]; pos->seg_off =3D latest.seg_off; *seq =3D latest.header.seq; @@ -155,6 +158,7 @@ static int cache_init(struct dm_pcache *pcache) cache->cache_dev =3D &pcache->cache_dev; cache->n_segs =3D cache_dev->seg_num; atomic_set(&cache->gc_errors, 0); + atomic_set(&cache->writeback_errors, 0); spin_lock_init(&cache->seg_map_lock); spin_lock_init(&cache->key_head_lock); =20 diff --git a/drivers/md/dm-pcache/cache.h b/drivers/md/dm-pcache/cache.h index 27613b56be54..919736379b76 100644 --- a/drivers/md/dm-pcache/cache.h +++ b/drivers/md/dm-pcache/cache.h @@ -180,6 +180,7 @@ struct pcache_cache { u32 advance; int ret; } writeback_ctx; + atomic_t writeback_errors; =20 char gc_kset_onmedia_buf[PCACHE_KSET_ONMEDIA_SIZE_MAX]; struct delayed_work gc_work; @@ -420,6 +421,20 @@ static inline bool cache_seg_is_ctrl_seg(u32 cache_seg= _id) return (cache_seg_id =3D=3D 0); } =20 +/** + * cache_seg_id_valid - Validate a cache segment id read from the cache de= vice. + * @cache: Pointer to the pcache_cache structure. + * @cache_seg_id: Segment id decoded from on-media metadata. + * + * On-media segment ids are only protected by a CRC, which an attacker who= can + * format the cache device computes over their chosen value. Reject any id= that + * would index cache->segments[] out of bounds before it is dereferenced. + */ +static inline bool cache_seg_id_valid(struct pcache_cache *cache, u32 cach= e_seg_id) +{ + return cache_seg_id < cache->cache_info.n_segs; +} + /** * cache_key_cutfront - Cuts a specified length from the front of a cache = key. * @key: Pointer to pcache_cache_key structure. diff --git a/drivers/md/dm-pcache/cache_gc.c b/drivers/md/dm-pcache/cache_g= c.c index 94f8b276a021..02fa0ce03134 100644 --- a/drivers/md/dm-pcache/cache_gc.c +++ b/drivers/md/dm-pcache/cache_gc.c @@ -74,11 +74,17 @@ static bool need_gc(struct pcache_cache *cache, struct = pcache_cache_pos *dirty_t * @cache: Pointer to the pcache_cache structure. * @kset_onmedia: Pointer to the kset_onmedia structure for the last kset. */ -static void last_kset_gc(struct pcache_cache *cache, struct pcache_cache_k= set_onmedia *kset_onmedia) +static int last_kset_gc(struct pcache_cache *cache, struct pcache_cache_ks= et_onmedia *kset_onmedia) { struct dm_pcache *pcache =3D CACHE_TO_PCACHE(cache); struct pcache_cache_segment *cur_seg, *next_seg; =20 + if (!cache_seg_id_valid(cache, kset_onmedia->next_cache_seg_id)) { + pcache_dev_err(pcache, "invalid next_cache_seg_id %u in gc (n_segs %u)\n= ", + kset_onmedia->next_cache_seg_id, cache->n_segs); + return -EIO; + } + cur_seg =3D cache->key_tail.cache_seg; =20 next_seg =3D &cache->segments[kset_onmedia->next_cache_seg_id]; @@ -94,6 +100,8 @@ static void last_kset_gc(struct pcache_cache *cache, str= uct pcache_cache_kset_on spin_lock(&cache->seg_map_lock); __clear_bit(cur_seg->cache_seg_id, cache->seg_map); spin_unlock(&cache->seg_map_lock); + + return 0; } =20 void pcache_cache_gc_fn(struct work_struct *work) @@ -130,7 +138,11 @@ void pcache_cache_gc_fn(struct work_struct *work) if (dirty_tail.cache_seg =3D=3D key_tail.cache_seg) break; =20 - last_kset_gc(cache, kset_onmedia); + ret =3D last_kset_gc(cache, kset_onmedia); + if (ret) { + atomic_inc(&cache->gc_errors); + return; + } continue; } =20 diff --git a/drivers/md/dm-pcache/cache_key.c b/drivers/md/dm-pcache/cache_= key.c index e068e878231b..8eec5238c5da 100644 --- a/drivers/md/dm-pcache/cache_key.c +++ b/drivers/md/dm-pcache/cache_key.c @@ -94,6 +94,12 @@ int cache_key_decode(struct pcache_cache *cache, key->off =3D key_onmedia->off; key->len =3D key_onmedia->len; =20 + 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); + return -EIO; + } + key->cache_pos.cache_seg =3D &cache->segments[key_onmedia->cache_seg_id]; key->cache_pos.seg_off =3D key_onmedia->cache_seg_off; =20 @@ -789,6 +795,11 @@ int cache_replay(struct pcache_cache *cache) =20 pcache_dev_debug(pcache, "last kset replay, next: %u\n", kset_onmedia->= next_cache_seg_id); =20 + if (!cache_seg_id_valid(cache, kset_onmedia->next_cache_seg_id)) { + ret =3D -EIO; + goto out; + } + next_seg =3D &cache->segments[kset_onmedia->next_cache_seg_id]; =20 pos->cache_seg =3D next_seg; diff --git a/drivers/md/dm-pcache/cache_writeback.c b/drivers/md/dm-pcache/= cache_writeback.c index 87a82b3fe836..7751468d5118 100644 --- a/drivers/md/dm-pcache/cache_writeback.c +++ b/drivers/md/dm-pcache/cache_writeback.c @@ -196,12 +196,18 @@ static int cache_kset_insert_tree(struct pcache_cache= *cache, struct pcache_cach return ret; } =20 -static void last_kset_writeback(struct pcache_cache *cache, +static int last_kset_writeback(struct pcache_cache *cache, struct pcache_cache_kset_onmedia *last_kset_onmedia) { struct dm_pcache *pcache =3D CACHE_TO_PCACHE(cache); struct pcache_cache_segment *next_seg; =20 + if (!cache_seg_id_valid(cache, last_kset_onmedia->next_cache_seg_id)) { + pcache_dev_err(pcache, "invalid next_cache_seg_id %u in writeback (n_seg= s %u)\n", + last_kset_onmedia->next_cache_seg_id, cache->n_segs); + return -EIO; + } + pcache_dev_debug(pcache, "last kset, next: %u\n", last_kset_onmedia->next= _cache_seg_id); =20 next_seg =3D &cache->segments[last_kset_onmedia->next_cache_seg_id]; @@ -211,6 +217,8 @@ static void last_kset_writeback(struct pcache_cache *ca= che, cache->dirty_tail.seg_off =3D 0; cache_encode_dirty_tail(cache); mutex_unlock(&cache->dirty_tail_lock); + + return 0; } =20 void cache_writeback_fn(struct work_struct *work) @@ -229,6 +237,9 @@ void cache_writeback_fn(struct work_struct *work) if (pcache_is_stopping(pcache)) goto unlock; =20 + if (atomic_read(&cache->writeback_errors)) + goto unlock; + kset_onmedia =3D (struct pcache_cache_kset_onmedia *)cache->wb_kset_onmed= ia_buf; =20 mutex_lock(&cache->dirty_tail_lock); @@ -241,15 +252,19 @@ void cache_writeback_fn(struct work_struct *work) } =20 if (kset_onmedia->flags & PCACHE_KSET_FLAGS_LAST) { - last_kset_writeback(cache, kset_onmedia); + ret =3D last_kset_writeback(cache, kset_onmedia); + if (ret) { + atomic_inc(&cache->writeback_errors); + goto unlock; + } delay =3D 0; goto queue_work; } =20 ret =3D cache_kset_insert_tree(cache, kset_onmedia); if (ret) { - delay =3D PCACHE_CACHE_WRITEBACK_INTERVAL; - goto queue_work; + atomic_inc(&cache->writeback_errors); + goto unlock; } =20 cache_wb_tree_writeback(cache, get_kset_onmedia_size(kset_onmedia)); --=20 2.43.0 From nobody Sat Jul 25 05:28:12 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B2CD13D9536; Fri, 17 Jul 2026 11:26:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784287615; cv=none; b=FBudCvHjFvy8IwrgIAn0qohBdgTI46Ym50aDWLgJuemsXPvIvR6ZduYtZ+jp13gasz27+p1kRlJMO2e2/hyz4p0gYlYalQz0F1roLj+40H551C4KWvfgzCp+eX4jZBSnPUeNpBexd39fhn3kQUsk9HZbX41by3mfpE2vHGXJ2Xg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784287615; c=relaxed/simple; bh=FU4TB9foOjTAzfRZBxEplTNJb811gkIkuYzaTO0yq48=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=sWpQeTiFQae8A7FbTKLNuOTyNSqpY4yPFm9Y/oBbuTDPG3Ei2J0UM3g8bnN7wkzLcf42e5ZfXkdS8XNnNK0xG7R2tX81fnXwJrYJ4wCyLMfuRyTQMUmqoKwoRxmIAV85uCv2vGnRF4h/L6wUfNMAgwpp605n4ITjkn+Kc2w9J78= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=QhnYq2cD; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="QhnYq2cD" Received: by smtp.kernel.org (Postfix) with ESMTPS id 0FF75C2BCF4; Fri, 17 Jul 2026 11:26:55 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1784287615; bh=FU4TB9foOjTAzfRZBxEplTNJb811gkIkuYzaTO0yq48=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=QhnYq2cDp8uze6laRAKffOpD/HGdfkDpnpRHQ0uESM/eJSOlK5v6rHecOIWG73bnv kCRd1WRpNvX30zKsWcxf3e3q3KMe2FHK3pmcDDZACNQ6T4nbv9mA4gyOSgm1MLs0IQ nqH6btYqHaIVY7yKYJcbPEFfHUWZTUcbTS6wpN8iZkYjxaKsboCjP83YaTsGHkMV+y 8yBfQxlCyWJOQWrT6AFDxyycDu0Y/P+m5dPH4DchEoAKPdqcFcOqBvlFeTo7LcTOJj v0PeylQt/13okE7cBBOhc6jzUftU5bYrOf6bHdEhiauPKZIszBDPi7m835WEcPDNrV orA9+qaJ4DfsQ== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id E856AC44520; Fri, 17 Jul 2026 11:26:54 +0000 (UTC) From: Bryam Vargas via B4 Relay Date: Fri, 17 Jul 2026 06:26:55 -0500 Subject: [PATCH v2 02/11] dm-pcache: validate geometry fields from on-disk cache_info Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260717-b4-disp-4c0a0039-v2-2-19227d6e313c@proton.me> References: <20260717-b4-disp-4c0a0039-v2-0-19227d6e313c@proton.me> In-Reply-To: <20260717-b4-disp-4c0a0039-v2-0-19227d6e313c@proton.me> To: Zheng Gu , Dongsheng Yang Cc: dm-devel@lists.linux.dev, Mikulas Patocka , linux-kernel@vger.kernel.org X-Mailer: b4 0.13.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1784287613; l=2084; i=hexlabsecurity@proton.me; s=proton; h=from:subject:message-id; bh=GCHE1PL/rUxoLoC9YQBxjQe4fFzhqS5ltYxbiHXbkRg=; b=SqdujfX6WK0cZuhU3P+/HjIYYk/pnJEoHQNxbOtE7SY5MSzZq5lkwa00RVFxttWRR0BIiJKG5 GBcD3GTe0eBDE1LYvPEK1QE5ycjrq75kJvibXYGPDRVQWoalvewntKq X-Developer-Key: i=hexlabsecurity@proton.me; a=ed25519; pk=dmppBMZNLLoPzxHi9l8tZDzEZUunPbgsYqIZYXeUrL0= X-Endpoint-Received: by B4 Relay for hexlabsecurity@proton.me/proton with auth_id=814 X-Original-From: Bryam Vargas Reply-To: hexlabsecurity@proton.me From: Bryam Vargas 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-mapp= er") Cc: stable@vger.kernel.org Signed-off-by: Bryam Vargas --- 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 e9d2b87174d7..e4784578b9af 100644 --- a/drivers/md/dm-pcache/cache.c +++ b/drivers/md/dm-pcache/cache.c @@ -251,6 +251,13 @@ static int get_seg_id(struct pcache_cache *cache, } else { *seg_id =3D cache->cache_info.seg_id; } + + if (*seg_id >=3D cache_dev->seg_num) { + pcache_dev_err(pcache, "invalid segment id %u from cache device (seg_nu= m %u)\n", + *seg_id, cache_dev->seg_num); + ret =3D -EIO; + goto err; + } } return 0; err: @@ -266,6 +273,13 @@ static int cache_segs_init(struct pcache_cache *cache) int ret; u32 i; =20 + 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 =3D 0; i < cache_info->n_segs; i++) { ret =3D get_seg_id(cache, prev_cache_seg, new_cache, &seg_id); if (ret) --=20 2.43.0 From nobody Sat Jul 25 05:28:12 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BC7453F44D0; Fri, 17 Jul 2026 11:26:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784287615; cv=none; b=KwjkyqL0EsSB3P+UqM0G5EdDJ073LgmrZFx7ZHFrSwyRsrjnAxn7HnpLKFwIOKkBNkkZFZbKN6qhg0+lqrPVAOP+I66M+LLvppX+yAv2c3GmGywRlqUtBUaHQbK2hMlCqzM6Uv62otjJatPfsGJ2fDDTHwFuDV0nrTV5e64ch1E= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784287615; c=relaxed/simple; bh=jvADCg6nk8lQ0L9apmZVhJQvCS/k+/aUVaN8asyYCdg=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=T6TCIBm8KPw2JXeqbT+d0QW2nITKAUGVV/J+ZGNnBtwvX8oiQLnpQTTA0mbh89gcVJYMgEMf184m+K0bNZm8bkN3zT8Wf9jeyPnWantVcvvHg7aFIqavRrW2futtGJPhjWARLzH4TcE6pRBhkaW8x0F14CR0s0sfX4d7JQ8mBp8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=shnjWP6g; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="shnjWP6g" Received: by smtp.kernel.org (Postfix) with ESMTPS id 1C301C2BCF5; Fri, 17 Jul 2026 11:26:55 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1784287615; bh=jvADCg6nk8lQ0L9apmZVhJQvCS/k+/aUVaN8asyYCdg=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=shnjWP6gneALulcbmZpzQhDm83zyDHXHH1DsKgyVOhUSeIqHH9Wa9mbtGqJFt5hmD 6QSLr7MPEhZRiea01Nl75ynDe/dr9Jg4H2tH/9+ocIK0vSEbBqFhgn/KiPzkL+N9jZ Q2Ev6AMmQyxLBoW+vWwRedIXl2lEPFWyegfJf3R5Jdvw1pvoljIMU+IFeaoVfltcld hUXYp6xLa+UOI7MFmHSDxCO3a2yQdYOPO8nzKgpjagu1qTxZ22gfrPZi4fBBkAkEHV FizZSmH1Ui5iQ/aj6wLT0XqIGaq0Z+f2Xg2nrAAAOKStOKc6/XcKUfliWb8585I2eJ 3oqG3qoM8iG2Q== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 003D4C44521; Fri, 17 Jul 2026 11:26:55 +0000 (UTC) From: Bryam Vargas via B4 Relay Date: Fri, 17 Jul 2026 06:26:56 -0500 Subject: [PATCH v2 03/11] dm-pcache: validate kset key_num and intra-segment bounds Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260717-b4-disp-4c0a0039-v2-3-19227d6e313c@proton.me> References: <20260717-b4-disp-4c0a0039-v2-0-19227d6e313c@proton.me> In-Reply-To: <20260717-b4-disp-4c0a0039-v2-0-19227d6e313c@proton.me> To: Zheng Gu , Dongsheng Yang Cc: dm-devel@lists.linux.dev, Mikulas Patocka , linux-kernel@vger.kernel.org X-Mailer: b4 0.13.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1784287613; l=5615; i=hexlabsecurity@proton.me; s=proton; h=from:subject:message-id; bh=vmHcXjyHD4CeDO70qCWNVMIG5lczK7IUtU3PlSvOgfs=; b=6vpkyJtIgh2eYee7sOcg2BFaSEU49E6MKyEVe3qIh7Ux2SQsKo9XJEed+RS0vZfHsvMgAJHk7 RUK8wYbe4KXCMZh2nK1NgmFJ6PzB7CyI3lGyjiatG4Gs/sMACwvU/0s X-Developer-Key: i=hexlabsecurity@proton.me; a=ed25519; pk=dmppBMZNLLoPzxHi9l8tZDzEZUunPbgsYqIZYXeUrL0= X-Endpoint-Received: by B4 Relay for hexlabsecurity@proton.me/proton with auth_id=814 X-Original-From: Bryam Vargas Reply-To: hexlabsecurity@proton.me From: Bryam Vargas 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-mapp= er") Cc: stable@vger.kernel.org Signed-off-by: Bryam Vargas --- drivers/md/dm-pcache/cache.h | 21 +++++++++++++++++++++ drivers/md/dm-pcache/cache_gc.c | 8 ++++---- drivers/md/dm-pcache/cache_key.c | 10 +++++++++- drivers/md/dm-pcache/cache_writeback.c | 8 ++++---- 4 files changed, 38 insertions(+), 9 deletions(-) diff --git a/drivers/md/dm-pcache/cache.h b/drivers/md/dm-pcache/cache.h index 919736379b76..d9e3e09f18e3 100644 --- a/drivers/md/dm-pcache/cache.h +++ b/drivers/md/dm-pcache/cache.h @@ -506,6 +506,27 @@ static inline u32 cache_key_data_crc(struct pcache_cac= he_key *key) return crc32c(PCACHE_CRC_SEED, data, key->len); } =20 +/** + * kset_onmedia_valid - Validate a kset header read from the cache device. + * @kset_onmedia: Pointer to the kset copied from on-media metadata. + * + * The magic and CRC are attacker-computable (fixed public seed). A non-la= st + * kset stores key_num keys inline, and cache_kset_crc() and the replay lo= op + * read struct_size(.., data, key_num) bytes from a buffer sized for + * PCACHE_KSET_KEYS_MAX keys, so key_num must be bounded before any such u= se. + */ +static inline bool kset_onmedia_valid(struct pcache_cache_kset_onmedia *ks= et_onmedia) +{ + if (kset_onmedia->magic !=3D PCACHE_KSET_MAGIC) + return false; + + if (!(kset_onmedia->flags & PCACHE_KSET_FLAGS_LAST) && + kset_onmedia->key_num > PCACHE_KSET_KEYS_MAX) + return false; + + return true; +} + static inline u32 cache_kset_crc(struct pcache_cache_kset_onmedia *kset_on= media) { u32 crc_size; diff --git a/drivers/md/dm-pcache/cache_gc.c b/drivers/md/dm-pcache/cache_g= c.c index 02fa0ce03134..1ed513745023 100644 --- a/drivers/md/dm-pcache/cache_gc.c +++ b/drivers/md/dm-pcache/cache_gc.c @@ -44,11 +44,11 @@ static bool need_gc(struct pcache_cache *cache, struct = pcache_cache_pos *dirty_t return false; } =20 - /* Check if kset_onmedia is corrupted */ - if (kset_onmedia->magic !=3D PCACHE_KSET_MAGIC) { - pcache_dev_debug(pcache, "gc error: magic is not as expected. key_tail: = %u:%u magic: %llx, expected: %llx\n", + /* Reject a corrupted or out-of-bounds kset before reading its keys */ + if (!kset_onmedia_valid(kset_onmedia)) { + pcache_dev_debug(pcache, "gc error: invalid kset. key_tail: %u:%u magic:= %llx, key_num: %u\n", key_tail->cache_seg->cache_seg_id, key_tail->seg_off, - kset_onmedia->magic, PCACHE_KSET_MAGIC); + kset_onmedia->magic, kset_onmedia->key_num); return false; } =20 diff --git a/drivers/md/dm-pcache/cache_key.c b/drivers/md/dm-pcache/cache_= key.c index 8eec5238c5da..f4459b2e1b3b 100644 --- a/drivers/md/dm-pcache/cache_key.c +++ b/drivers/md/dm-pcache/cache_key.c @@ -103,6 +103,14 @@ int cache_key_decode(struct pcache_cache *cache, key->cache_pos.cache_seg =3D &cache->segments[key_onmedia->cache_seg_id]; key->cache_pos.seg_off =3D key_onmedia->cache_seg_off; =20 + if ((u64)key->cache_pos.seg_off + key->len > + key->cache_pos.cache_seg->segment.data_size) { + pcache_dev_err(pcache, "key seg_off %u + len %u exceeds segment data siz= e %u\n", + key->cache_pos.seg_off, key->len, + key->cache_pos.cache_seg->segment.data_size); + return -EIO; + } + key->seg_gen =3D key_onmedia->seg_gen; key->flags =3D key_onmedia->flags; =20 @@ -784,7 +792,7 @@ int cache_replay(struct pcache_cache *cache) goto out; } =20 - if (kset_onmedia->magic !=3D PCACHE_KSET_MAGIC || + if (!kset_onmedia_valid(kset_onmedia) || kset_onmedia->crc !=3D cache_kset_crc(kset_onmedia)) { break; } diff --git a/drivers/md/dm-pcache/cache_writeback.c b/drivers/md/dm-pcache/= cache_writeback.c index 7751468d5118..34c34b448e04 100644 --- a/drivers/md/dm-pcache/cache_writeback.c +++ b/drivers/md/dm-pcache/cache_writeback.c @@ -55,11 +55,11 @@ static inline bool is_cache_clean(struct pcache_cache *= cache, struct pcache_cach return true; } =20 - /* Check if the magic number matches the expected value */ - if (kset_onmedia->magic !=3D PCACHE_KSET_MAGIC) { - pcache_dev_debug(pcache, "dirty_tail: %u:%u magic: %llx, not expected: %= llx\n", + /* Reject a corrupted or out-of-bounds kset before reading its keys */ + if (!kset_onmedia_valid(kset_onmedia)) { + pcache_dev_debug(pcache, "dirty_tail: %u:%u invalid kset magic: %llx, ke= y_num: %u\n", dirty_tail->cache_seg->cache_seg_id, dirty_tail->seg_off, - kset_onmedia->magic, PCACHE_KSET_MAGIC); + kset_onmedia->magic, kset_onmedia->key_num); return true; } =20 --=20 2.43.0 From nobody Sat Jul 25 05:28:12 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B2F513F413D; Fri, 17 Jul 2026 11:26:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784287615; cv=none; b=H4cTAoFXjMFStr7wsRcNlKW39a0PtyB4D8Ztz13ipet3eWBeR/hiS5IcMWbe6Xxon/NQx0jmv8doDJsO0o7bZMcsMrOcrpbV34atSVVPzdv57I1Z6xmPDHnS9sSGUDNWiKstYcsEPdUVTRD6mePQU+CJ1/QiKPgO0u0DSDmMy18= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784287615; c=relaxed/simple; bh=ZJBA5lMyaRfZ5DRdvY28maqTnwsC+q/oQgWf5cSx6EE=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=keuilez8hstVWCA7dKSHyfZsNGkvlhBkagYyfV6oce1fK0KHqZZieRo3OSKBunATmSjWeBFj0I9q8ApusrESkWp0udUPOYdzmqz26IOPK68drU+Zx3/c1CWPW+NwwC+Z7EtzjksBT7cITyju1NGM2g7h7qJG+qGZEfYI6JFBPvU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=uq/H1l4D; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="uq/H1l4D" Received: by smtp.kernel.org (Postfix) with ESMTPS id 2219BC2BCF6; Fri, 17 Jul 2026 11:26:55 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1784287615; bh=ZJBA5lMyaRfZ5DRdvY28maqTnwsC+q/oQgWf5cSx6EE=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=uq/H1l4D6pDQDn61RzQ5wvaZ0w8FOrAsT3aS+A+BpnhatEmYmn+Jnz62SREI17k/Q NjE848KS4iIN9Y+xZzGWFYEeWsNPR5FHpt2I2jV8y1rPD3pJ7uuUMcaWid+uvoCMR5 OEm7H7B51jJvlyOJiEhYMLEYWOHN6rOp0OJdM4S8es7MwbZggaPiMmE5LTsJSUR4aV f4oaSK1T+c8qsnO/3ukA+arDwjTPOQnvTtn3dCvptPQCDC5pfcaLq0PbRjWBuyfW9Z s/SVIF6SOr1/TGf8kkz6FtHPdoR2Xa0A3pLbg+uVjrJxgb674n4u5xBl1NEN+CmkVj lYX4ExJBQcI2Q== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0DD3EC4451F; Fri, 17 Jul 2026 11:26:55 +0000 (UTC) From: Bryam Vargas via B4 Relay Date: Fri, 17 Jul 2026 06:26:57 -0500 Subject: [PATCH v2 04/11] dm-pcache: bound the persisted tail-position offset Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260717-b4-disp-4c0a0039-v2-4-19227d6e313c@proton.me> References: <20260717-b4-disp-4c0a0039-v2-0-19227d6e313c@proton.me> In-Reply-To: <20260717-b4-disp-4c0a0039-v2-0-19227d6e313c@proton.me> To: Zheng Gu , Dongsheng Yang Cc: dm-devel@lists.linux.dev, Mikulas Patocka , linux-kernel@vger.kernel.org X-Mailer: b4 0.13.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1784287613; l=1129; i=hexlabsecurity@proton.me; s=proton; h=from:subject:message-id; bh=hN9K2tznX8h1QG7GfDCqM9oGo/1YYUnmVCUIvgXpICk=; b=c2HibsNGq9PxA8UzqkT0stULoj1gCQtVqGCnfhMPLoa9x4nKTbuPlkhkC+6Y4Dl+KKaXJXibs WAOkYPB93BED92xic8EJWQN1a3dkwaVS6AtP8IhcgtK6I33AZgxv6IW X-Developer-Key: i=hexlabsecurity@proton.me; a=ed25519; pk=dmppBMZNLLoPzxHi9l8tZDzEZUunPbgsYqIZYXeUrL0= X-Endpoint-Received: by B4 Relay for hexlabsecurity@proton.me/proton with auth_id=814 X-Original-From: Bryam Vargas Reply-To: hexlabsecurity@proton.me From: Bryam Vargas 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-mapp= er") Cc: stable@vger.kernel.org Signed-off-by: Bryam Vargas --- drivers/md/dm-pcache/cache.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/md/dm-pcache/cache.c b/drivers/md/dm-pcache/cache.c index e4784578b9af..a94eadb7affd 100644 --- a/drivers/md/dm-pcache/cache.c +++ b/drivers/md/dm-pcache/cache.c @@ -122,6 +122,10 @@ int cache_pos_decode(struct pcache_cache *cache, return -EIO; =20 pos->cache_seg =3D &cache->segments[latest.cache_seg_id]; + + if (latest.seg_off >=3D pos->cache_seg->segment.data_size) + return -EIO; + pos->seg_off =3D latest.seg_off; *seq =3D latest.header.seq; *index =3D (latest_addr - pos_onmedia); --=20 2.43.0 From nobody Sat Jul 25 05:28:12 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B10773C199C; Fri, 17 Jul 2026 11:26:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784287616; cv=none; b=sIvIiBkdsj7GRhS40KEehMUiIPtC3fj3uFE6bk71agJwtDJQp9BvzEjX+Pp2Y4AbVGFpSAlW4N98WHtXA9jlfnzrwV7LIVa+8Pl8NZsG7IsT8Q8+aujvt0w0LE3dFnRr1RNsupdpHPJMl4V/WM999IHY1Htxj/eIJjBsqhFoeNo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784287616; c=relaxed/simple; bh=lpydZFZOaGYCWBb7v/yW09iPNNSvU0qbM47gUMZfWaY=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=n+dlnM+T0WKW33L55UYM9nNYP7yHDSXJMS+9Yp6Ikz2P9fygUYfouxvMBOiVzNV4NMzcc4MeRZ4MqwV6yOS9HlSiO3OzGhqZqKtCSGoIm9b75syO/lBnOpz9yVVlTqzoCNY6sRP4tNXFe00fgTTQWZ1/Sy9eNgFD92SCmGJ/XsI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=li7r6Y/l; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="li7r6Y/l" Received: by smtp.kernel.org (Postfix) with ESMTPS id 2E5FCC2BCFB; Fri, 17 Jul 2026 11:26:55 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1784287615; bh=lpydZFZOaGYCWBb7v/yW09iPNNSvU0qbM47gUMZfWaY=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=li7r6Y/lVistP+fSkNYjKuiOxL1i+53AX+qiX2elB/ZaNyEPDqLtDQfbYJ1hjzG17 MHg69jZ8yEaq7kVxcgjdxdS9VftLDnjvndj8RXESlm35sAFlFKcAWLRAyYIK+2Uwkh CZ6AkWhC5vF/FJaT0I8JdFRKok6lk7I5chIFhaXW91tDdtEoww13g1GyQp/eOMfZFC 8WKBx6j5ULeuCtpxtVUhVOo3HLZZz0TRhfIYOCpwrXdH7ophcksblYAAM3Dc5pcrtB 2WjM93mUkD/h5AGKQ34bjXpqHCjxw0wL9+2F/vIvMPawlKk4EyJaj7WAUAdNUIVWEs SUDSvjm9Rqm5w== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1DF7FC44516; Fri, 17 Jul 2026 11:26:55 +0000 (UTC) From: Bryam Vargas via B4 Relay Date: Fri, 17 Jul 2026 06:26:58 -0500 Subject: [PATCH v2 05/11] dm-pcache: reject a kset that overruns its segment Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260717-b4-disp-4c0a0039-v2-5-19227d6e313c@proton.me> References: <20260717-b4-disp-4c0a0039-v2-0-19227d6e313c@proton.me> In-Reply-To: <20260717-b4-disp-4c0a0039-v2-0-19227d6e313c@proton.me> To: Zheng Gu , Dongsheng Yang Cc: dm-devel@lists.linux.dev, Mikulas Patocka , linux-kernel@vger.kernel.org X-Mailer: b4 0.13.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1784287613; l=2364; i=hexlabsecurity@proton.me; s=proton; h=from:subject:message-id; bh=VDNrRdx1QgfmUKR1cmC1fUFZHKtUK1mTEMdKllWQ9/k=; b=9jXwTIWCfMx/ewKKdUozqL/UtY0fI2YFUov6Fk/PIiEsUsFXnY7wsSso7WeZU23B3MgEGNEG/ Bhs3DhxCbccCdWQRbBsyPSyPbOsNz2K2MomT+sVOnNKfGnsHhG5Z3iE X-Developer-Key: i=hexlabsecurity@proton.me; a=ed25519; pk=dmppBMZNLLoPzxHi9l8tZDzEZUunPbgsYqIZYXeUrL0= X-Endpoint-Received: by B4 Relay for hexlabsecurity@proton.me/proton with auth_id=814 X-Original-From: Bryam Vargas Reply-To: hexlabsecurity@proton.me From: Bryam Vargas 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-mapp= er") Cc: stable@vger.kernel.org Signed-off-by: Bryam Vargas --- drivers/md/dm-pcache/cache_gc.c | 5 +++++ drivers/md/dm-pcache/cache_key.c | 5 +++++ drivers/md/dm-pcache/cache_writeback.c | 5 +++++ 3 files changed, 15 insertions(+) diff --git a/drivers/md/dm-pcache/cache_gc.c b/drivers/md/dm-pcache/cache_g= c.c index 1ed513745023..c483c7a3afaf 100644 --- a/drivers/md/dm-pcache/cache_gc.c +++ b/drivers/md/dm-pcache/cache_gc.c @@ -146,6 +146,11 @@ void pcache_cache_gc_fn(struct work_struct *work) continue; } =20 + if (get_kset_onmedia_size(kset_onmedia) > cache_seg_remain(&key_tail)) { + atomic_inc(&cache->gc_errors); + return; + } + for (i =3D 0; i < kset_onmedia->key_num; i++) { struct pcache_cache_key key_tmp =3D { 0 }; =20 diff --git a/drivers/md/dm-pcache/cache_key.c b/drivers/md/dm-pcache/cache_= key.c index f4459b2e1b3b..d00497f9e462 100644 --- a/drivers/md/dm-pcache/cache_key.c +++ b/drivers/md/dm-pcache/cache_key.c @@ -818,6 +818,11 @@ int cache_replay(struct pcache_cache *cache) } =20 /* Replay the kset and check for errors. */ + if (get_kset_onmedia_size(kset_onmedia) > cache_seg_remain(pos)) { + ret =3D -EIO; + goto out; + } + ret =3D kset_replay(cache, kset_onmedia); if (ret) goto out; diff --git a/drivers/md/dm-pcache/cache_writeback.c b/drivers/md/dm-pcache/= cache_writeback.c index 34c34b448e04..7a85a9aed18e 100644 --- a/drivers/md/dm-pcache/cache_writeback.c +++ b/drivers/md/dm-pcache/cache_writeback.c @@ -261,6 +261,11 @@ void cache_writeback_fn(struct work_struct *work) goto queue_work; } =20 + if (get_kset_onmedia_size(kset_onmedia) > cache_seg_remain(&dirty_tail)) { + atomic_inc(&cache->writeback_errors); + goto unlock; + } + ret =3D cache_kset_insert_tree(cache, kset_onmedia); if (ret) { atomic_inc(&cache->writeback_errors); --=20 2.43.0 From nobody Sat Jul 25 05:28:12 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 728863DDB02; Fri, 17 Jul 2026 11:26:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784287617; cv=none; b=oqE1btVIg6apjfnqSh8j938HOCamHHsyGiXhY9THzrpC9bS2X/DAtPefQcypdCbpEwyyVyW0CgEhb+uKrWMpNliby+6/RVpiOMC2xqczL6l4IhYB8bbGQ7GcZLCjUyly4R6bvB9vYpGqNfgCCZ7t3n67DT1l483hStnqABLkS7s= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784287617; c=relaxed/simple; bh=qZgHoupFF7+MLm4NslKOOanE3bOGe4JYnq1g8Efs/tM=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=NJTT8rw+KqZTFgeuS72RpdB8ookSpm/oipyCXT3dHT7PBBYVI8QAxH20QE0W06GhIUmZ1ftSywHGbPzczVm/ihGgDzXIff6EYhG1pi/uEo4IW8LKSVReUDk52pI5M4szAgaDPgbxK6+3aeCTQQ2OLoRO2iuVGUpA6GqqWi3k7lU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=pcUXXeEN; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="pcUXXeEN" Received: by smtp.kernel.org (Postfix) with ESMTPS id 39C95C2BCFC; Fri, 17 Jul 2026 11:26:55 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1784287615; bh=qZgHoupFF7+MLm4NslKOOanE3bOGe4JYnq1g8Efs/tM=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=pcUXXeENpoQD/guG0NVM2eZxHfvzqGOablch7U49PB9wR+coq4B+bdQjUyTIW/dar VvzlooTTpHlrRnHEuleNl+Z2LUVkMRUxY3pcwdvq4V3kRf7OB01hpofrLHMIDrZgnI pto/yWIRu3tgnGIZjC391sN7b41ubb2qyi1P47d/5Jjgs0i1bJdjmcKYR9lCaisxfn tUesXvjkMghjbhwOlrjKrKkuazl2N7P84fPRVbg93WueuC2ocx+Xn5hJ0D+slXCl3U Yda7PgKwOR6PEeEUGaINlR79478eq2Q8r0076baxSfMyBJQ6Wjfw1GWtV7A0pQI1+7 ND28HcEuqu4jA== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 2A20BC44520; Fri, 17 Jul 2026 11:26:55 +0000 (UTC) From: Bryam Vargas via B4 Relay Date: Fri, 17 Jul 2026 06:26:59 -0500 Subject: [PATCH v2 06/11] dm-pcache: detect a cycle in the last-kset chain during replay Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260717-b4-disp-4c0a0039-v2-6-19227d6e313c@proton.me> References: <20260717-b4-disp-4c0a0039-v2-0-19227d6e313c@proton.me> In-Reply-To: <20260717-b4-disp-4c0a0039-v2-0-19227d6e313c@proton.me> To: Zheng Gu , Dongsheng Yang Cc: dm-devel@lists.linux.dev, Mikulas Patocka , linux-kernel@vger.kernel.org X-Mailer: b4 0.13.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1784287613; l=1415; i=hexlabsecurity@proton.me; s=proton; h=from:subject:message-id; bh=ZwCcFfHgFT+HQDBZxOs1rAKOfWWhRa9VFuMd2jR4RIs=; b=2QfF3AR5XbVtkeYQvFhpMG0sqALSKUkx498zGe5TuNgDe9Quf9uV1zxQIIq85/+9UkYdd/y0d RPSpPZV7Vx1BUAyHYLrbyuso+MYylindUlaDZckla5kiJbUkmjQKUOC X-Developer-Key: i=hexlabsecurity@proton.me; a=ed25519; pk=dmppBMZNLLoPzxHi9l8tZDzEZUunPbgsYqIZYXeUrL0= X-Endpoint-Received: by B4 Relay for hexlabsecurity@proton.me/proton with auth_id=814 X-Original-From: Bryam Vargas Reply-To: hexlabsecurity@proton.me From: Bryam Vargas 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-mapp= er") Cc: stable@vger.kernel.org Signed-off-by: Bryam Vargas --- 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 =3D 0; + u32 to_copy, count =3D 0, last_hops =3D 0; int ret =3D 0; =20 kset_onmedia =3D kzalloc(PCACHE_KSET_ONMEDIA_SIZE_MAX, GFP_KERNEL); @@ -808,6 +808,11 @@ int cache_replay(struct pcache_cache *cache) goto out; } =20 + if (++last_hops > cache->n_segs) { + ret =3D -EIO; + goto out; + } + next_seg =3D &cache->segments[kset_onmedia->next_cache_seg_id]; =20 pos->cache_seg =3D next_seg; --=20 2.43.0 From nobody Sat Jul 25 05:28:12 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id CD2B63F44FF; Fri, 17 Jul 2026 11:26:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784287616; cv=none; b=Qy9ru3yda02RDggSU5F5KeaFgyg9KDdTi2a15/fXdeeOqBcEIIolSycxme99IyDTL30C9xh8W/VIYpQf/MVmRcoiizFa34bChKHv42F0wQ31ZBeedRaGLC9mNP5YPXLu/ckp053RJbmHvD/Fo5sIKVyU81vivi25XuIlpO1RMJU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784287616; c=relaxed/simple; bh=mPI64MmYZoWWQXNsbHfgB7P2LGr5N2K3QKdxlYPucYw=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=YWkOl5bVIICqD1MKqccFt7Iixv7bOEmx4DtpEykXoo4S0ZkOW9gCTKjpnsu0WwL8AxP4fj9yfcddEgKwB6poKygobiskM1aRYR0taHycyEQVjfkFesLU5WkG/3tkfO/PqAzANAgH4MGNs74Vf9CiJIz+xUY0dKqAYWfDG1iN6NI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=BOuP+UyI; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="BOuP+UyI" Received: by smtp.kernel.org (Postfix) with ESMTPS id 48BEFC2BCFD; Fri, 17 Jul 2026 11:26:55 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1784287615; bh=mPI64MmYZoWWQXNsbHfgB7P2LGr5N2K3QKdxlYPucYw=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=BOuP+UyIDyWOJHxBNBtwskSIUUtPi+m4pptJgwmlLSIjnwMijM0hC+M44URR8xoi2 KaeyAaSK24JPzGIk8rXQGjKLnsTHGT1X1e49OTIhT/1fSMb1ax6HtL83sIcLDg5zSt 1JGiDV+hwNt/iT42c208tkqmgwgTEMIXJA7/WTJm6zbKx0TeNO2dNNSfelb258L6Vs +IwUfRx1Mj0mAg640JZUvTviiYxOXR65X2dNGmPcQmU/MuYnCAmvkDLHcvSel3Y42G vlF8vlmsgo9SEjLD2fP9EHV5mV9kUw9ULX90FNUqMk8SEwE8L6YwGUx6aoXvlzQFuI +yeO0tJwThshA== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 368EAC4451C; Fri, 17 Jul 2026 11:26:55 +0000 (UTC) From: Bryam Vargas via B4 Relay Date: Fri, 17 Jul 2026 06:27:00 -0500 Subject: [PATCH v2 07/11] dm-pcache: bound the logical key offset from persistent memory Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260717-b4-disp-4c0a0039-v2-7-19227d6e313c@proton.me> References: <20260717-b4-disp-4c0a0039-v2-0-19227d6e313c@proton.me> In-Reply-To: <20260717-b4-disp-4c0a0039-v2-0-19227d6e313c@proton.me> To: Zheng Gu , Dongsheng Yang Cc: dm-devel@lists.linux.dev, Mikulas Patocka , linux-kernel@vger.kernel.org X-Mailer: b4 0.13.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1784287613; l=1598; i=hexlabsecurity@proton.me; s=proton; h=from:subject:message-id; bh=GP1/4GJNnNWJdMna2c7wHajzFf/3a0JDLm0ELeLq69s=; b=0XhksriEfsf3e91wOyEQ7BqAw66e85dX2S/LsXvGVVzRpelMQJ7wQnKWj/oPOiHVzm+S7tVDb A9KKsTuQBYIAxJLeaNjUZA7hnWXOJiYs/lYqgfQ5bHMGRyZeCs74zYv X-Developer-Key: i=hexlabsecurity@proton.me; a=ed25519; pk=dmppBMZNLLoPzxHi9l8tZDzEZUunPbgsYqIZYXeUrL0= X-Endpoint-Received: by B4 Relay for hexlabsecurity@proton.me/proton with auth_id=814 X-Original-From: Bryam Vargas Reply-To: hexlabsecurity@proton.me From: Bryam Vargas 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-mapp= er") Cc: stable@vger.kernel.org Signed-off-by: Bryam Vargas --- 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 =3D CACHE_TO_PCACHE(cache); + u64 dev_bytes =3D (u64)cache->dev_size << SECTOR_SHIFT; =20 key->off =3D key_onmedia->off; key->len =3D key_onmedia->len; =20 + if (key_onmedia->len =3D=3D 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); --=20 2.43.0 From nobody Sat Jul 25 05:28:12 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id CD1C03F44F6; Fri, 17 Jul 2026 11:26:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784287616; cv=none; b=XemC9wH1CjoHTGG0uKsg1n2+RM/+ok92uPt/lZgcAZWgc8EQFmSrVvX/MQEwcqju8Vh6n82V4zJZMV2v2gDhirOIrlbdGsfWoBg54DozS8zPEGiqv7fAKJ3+77BbaEsBH1iVRp8y/rijh+GbzxG009UsrdIHyDPTpSmRYtHn4uc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784287616; c=relaxed/simple; bh=Usa3x/tTafYQCV7IO1VV/mtgaTzMSkOJweMxgvUeN0k=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Rs+uyKWiW34AV2NpeXjl312pDeXXCWmTjfsOCQsWpzVR4bBdQFRtha0GaeoF0VKTXB7SXrhk0x3R898Zob3Tqdg558LGzp7x4hNQyOFMmC4wNahMYJuC9/1S9u8yVU4qQ1gzvoxDBWyUdqw7z65rHzTfQK/runbHbc0EhyWi/DU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=LxA99hsR; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="LxA99hsR" Received: by smtp.kernel.org (Postfix) with ESMTPS id 53BCBC2BCFF; Fri, 17 Jul 2026 11:26:55 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1784287615; bh=Usa3x/tTafYQCV7IO1VV/mtgaTzMSkOJweMxgvUeN0k=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=LxA99hsRcP4h2PmYQWNLSM90u6u2sDj3Ro+cSFrFGz5Zd6Ek9aOLTNN0/m1y0Bexb y6XZCrTadj1x0RVLoy9/mGir8aHb+qURXaFIHueCQCaCRDhd2EUy3x0s/Ggf9Sf/BT VFBjqSO+Cw3qD/z9zCxQRec8OvPJm0ZwYvYJD6e085AAEn/aC9G2Sli0Cwgk7gsYNk bTOY0jMCEN9DSk3qvPZTy/p//9T4UgfO+ZK9R2Xr+doOqtvNw0IMNnW1DetyG4xyr8 pFHCOYRiKkH5+g+Q1bzFXYPfgJ04/tx75oRDYU57qJ9IvzeaUCd7aPjIzwxZvhg7jY UgoJBWvm4H7PA== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 44246C44521; Fri, 17 Jul 2026 11:26:55 +0000 (UTC) From: Bryam Vargas via B4 Relay Date: Fri, 17 Jul 2026 06:27:01 -0500 Subject: [PATCH v2 08/11] dm-pcache: clamp the tail kset read to the segment data region Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260717-b4-disp-4c0a0039-v2-8-19227d6e313c@proton.me> References: <20260717-b4-disp-4c0a0039-v2-0-19227d6e313c@proton.me> In-Reply-To: <20260717-b4-disp-4c0a0039-v2-0-19227d6e313c@proton.me> To: Zheng Gu , Dongsheng Yang Cc: dm-devel@lists.linux.dev, Mikulas Patocka , linux-kernel@vger.kernel.org X-Mailer: b4 0.13.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1784287613; l=2745; i=hexlabsecurity@proton.me; s=proton; h=from:subject:message-id; bh=E5WY/heNRdOuUSIYPvzHn8WEjCPo/EDvLcmW1MLvc+Y=; b=p2edeCDryLm/44W8WP1BxLnQnCv9Uio2larwFqIGpC5JBK1XhzAG/W2Z9dyv14Cx4yq/r+LIz gbEzP4R+KccDbf6Ej2690rQ98s9NcmcV5rObP42Kfp7P/AB8VWka+cg X-Developer-Key: i=hexlabsecurity@proton.me; a=ed25519; pk=dmppBMZNLLoPzxHi9l8tZDzEZUunPbgsYqIZYXeUrL0= X-Endpoint-Received: by B4 Relay for hexlabsecurity@proton.me/proton with auth_id=814 X-Original-From: Bryam Vargas Reply-To: hexlabsecurity@proton.me From: Bryam Vargas 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-mapp= er") Cc: stable@vger.kernel.org Signed-off-by: Bryam Vargas --- drivers/md/dm-pcache/cache_gc.c | 2 +- drivers/md/dm-pcache/cache_key.c | 2 +- drivers/md/dm-pcache/cache_writeback.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/md/dm-pcache/cache_gc.c b/drivers/md/dm-pcache/cache_g= c.c index c483c7a3afaf..d551848912b4 100644 --- a/drivers/md/dm-pcache/cache_gc.c +++ b/drivers/md/dm-pcache/cache_gc.c @@ -37,7 +37,7 @@ static bool need_gc(struct pcache_cache *cache, struct pc= ache_cache_pos *dirty_t =20 kset_onmedia =3D (struct pcache_cache_kset_onmedia *)cache->gc_kset_onmed= ia_buf; =20 - to_copy =3D min(PCACHE_KSET_ONMEDIA_SIZE_MAX, PCACHE_SEG_SIZE - key_tail-= >seg_off); + to_copy =3D min(PCACHE_KSET_ONMEDIA_SIZE_MAX, cache_seg_remain(key_tail)); ret =3D copy_mc_to_kernel(kset_onmedia, key_addr, to_copy); if (ret) { pcache_dev_err(pcache, "error to read kset: %d", ret); diff --git a/drivers/md/dm-pcache/cache_key.c b/drivers/md/dm-pcache/cache_= key.c index 86cc9565ffc7..f3ce319037be 100644 --- a/drivers/md/dm-pcache/cache_key.c +++ b/drivers/md/dm-pcache/cache_key.c @@ -794,7 +794,7 @@ int cache_replay(struct pcache_cache *cache) __set_bit(pos->cache_seg->cache_seg_id, cache->seg_map); =20 while (true) { - to_copy =3D min(PCACHE_KSET_ONMEDIA_SIZE_MAX, PCACHE_SEG_SIZE - pos->seg= _off); + to_copy =3D min(PCACHE_KSET_ONMEDIA_SIZE_MAX, cache_seg_remain(pos)); ret =3D copy_mc_to_kernel(kset_onmedia, cache_pos_addr(pos), to_copy); if (ret) { ret =3D -EIO; diff --git a/drivers/md/dm-pcache/cache_writeback.c b/drivers/md/dm-pcache/= cache_writeback.c index 7a85a9aed18e..c8a4c8110a58 100644 --- a/drivers/md/dm-pcache/cache_writeback.c +++ b/drivers/md/dm-pcache/cache_writeback.c @@ -48,7 +48,7 @@ static inline bool is_cache_clean(struct pcache_cache *ca= che, struct pcache_cach addr =3D cache_pos_addr(dirty_tail); kset_onmedia =3D (struct pcache_cache_kset_onmedia *)cache->wb_kset_onmed= ia_buf; =20 - to_copy =3D min(PCACHE_KSET_ONMEDIA_SIZE_MAX, PCACHE_SEG_SIZE - dirty_tai= l->seg_off); + to_copy =3D min(PCACHE_KSET_ONMEDIA_SIZE_MAX, cache_seg_remain(dirty_tail= )); ret =3D copy_mc_to_kernel(kset_onmedia, addr, to_copy); if (ret) { pcache_dev_err(pcache, "error to read kset: %d", ret); --=20 2.43.0 From nobody Sat Jul 25 05:28:12 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B488B3F44F0; Fri, 17 Jul 2026 11:26:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784287616; cv=none; b=eEFoBo3eK907CyeQH1+KzgWZWyRQV6VDNFVlFbJ7edQfD1UaDTLzM4FxS9BSsLGMqwSYZZJcZfTD26zw1CBRER96GTY/AARI0VaRT462Clv/nt83+qTzk/AytnRwe3Bb1VOGgrDH8mut/PV71oTe7B4x7hVlPyGd02sNvTpG3VM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784287616; c=relaxed/simple; bh=toOq+vx1LshhMROiRD+qXw+ukIgvO0pG1BBImQ4T9qg=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=c4kLuB96+Yn+PZ4lhqbKmwdfRoJBL95iw1/4yA+7D+fGpTFqbabodHrzTKZqty9OpakAYpsi8HpJCb1D6TSN59CuyDq3LdEuk3QDs57afxYncbghT8C6K2fnVa02iE+rdzg6x3weFg6k4hg3jC83IMR3zrIeFbIFt2TudtMocXk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=DBt2NZLr; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="DBt2NZLr" Received: by smtp.kernel.org (Postfix) with ESMTPS id 62CADC2BD01; Fri, 17 Jul 2026 11:26:55 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1784287615; bh=toOq+vx1LshhMROiRD+qXw+ukIgvO0pG1BBImQ4T9qg=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=DBt2NZLriGsjLNSWX01WUAskzCUgDDsxhuJHvjRYb5yh1x6UllowNYFe5KRt/rVxT +iA3dfsTcYNSD/057R1Y0pSeJMp12lcDf6AzRRN2ZtbUOJSCRXckHdTYrzYIHK+hiv GymfTwR8V0YCXG7Qu6vpMfyPLLHZ0blvBabAfHVyHm3GJ2aaUraqejRLPdbvLGf1tE YeiDWcrc0Ee4OzwZD/zRQ+PuReTcp/5/aGaDWpaYcFd+dwe26FJHVfnPpbf9m7uOrX vxZH1ExAGglPW0mXHCYp5b62lHsZagfgQwTQWXHdybXEnZ7+UbpProMjOc6iRcogpi tEyNQyGhBfhuw== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 51489C44520; Fri, 17 Jul 2026 11:26:55 +0000 (UTC) From: Bryam Vargas via B4 Relay Date: Fri, 17 Jul 2026 06:27:02 -0500 Subject: [PATCH v2 09/11] dm-pcache: validate on-media seg_num against the cache device size Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260717-b4-disp-4c0a0039-v2-9-19227d6e313c@proton.me> References: <20260717-b4-disp-4c0a0039-v2-0-19227d6e313c@proton.me> In-Reply-To: <20260717-b4-disp-4c0a0039-v2-0-19227d6e313c@proton.me> To: Zheng Gu , Dongsheng Yang Cc: dm-devel@lists.linux.dev, Mikulas Patocka , linux-kernel@vger.kernel.org X-Mailer: b4 0.13.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1784287613; l=2643; i=hexlabsecurity@proton.me; s=proton; h=from:subject:message-id; bh=GthnvJEXiCUPMv2Rfmb/8dJm5Xyaa9i+Wnb6pzB7iBk=; b=HVS2YD+agpjZ6SfKOPiAwIPHvjqy//dbl2WTXDLjTpn8J4iYH8AxlVB48mgszmjljCmH1BYmj scXSqd9+hSrA5vYD7BZnK11/pd9xneoZhnmvPdhPViJBvDZ9ryhEm1l X-Developer-Key: i=hexlabsecurity@proton.me; a=ed25519; pk=dmppBMZNLLoPzxHi9l8tZDzEZUunPbgsYqIZYXeUrL0= X-Endpoint-Received: by B4 Relay for hexlabsecurity@proton.me/proton with auth_id=814 X-Original-From: Bryam Vargas Reply-To: hexlabsecurity@proton.me From: Bryam Vargas 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-mapp= er") Cc: stable@vger.kernel.org Signed-off-by: Bryam Vargas --- drivers/md/dm-pcache/cache_dev.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/drivers/md/dm-pcache/cache_dev.c b/drivers/md/dm-pcache/cache_= dev.c index ece689e6ce59..f0259353ee39 100644 --- a/drivers/md/dm-pcache/cache_dev.c +++ b/drivers/md/dm-pcache/cache_dev.c @@ -242,6 +242,8 @@ int cache_dev_start(struct dm_pcache *pcache) struct pcache_cache_dev *cache_dev =3D &pcache->cache_dev; struct pcache_sb sb; bool format =3D false; + u32 seg_num; + u64 max_segs; int ret; =20 mutex_init(&cache_dev->seg_lock); @@ -269,7 +271,25 @@ int cache_dev_start(struct dm_pcache *pcache) goto dax_release; =20 cache_dev->sb_flags =3D le32_to_cpu(sb.flags); - ret =3D cache_dev_init(cache_dev, le32_to_cpu(sb.seg_num)); + + /* + * seg_num is read from the crc32c-only superblock, so whoever supplies + * the cache device controls it. It is the ceiling every later on-media + * segment id is validated against, so bound it against what the device + * physically holds before it is trusted, or a forged seg_num lets a + * segment id address past the DAX mapping. + */ + seg_num =3D le32_to_cpu(sb.seg_num); + max_segs =3D (bdev_nr_bytes(cache_dev->dm_dev->bdev) - PCACHE_SEGMENTS_OF= F) / + PCACHE_SEG_SIZE; + if (seg_num =3D=3D 0 || seg_num > max_segs || seg_num > PCACHE_CACHE_SEGS= _MAX) { + pcache_dev_err(pcache, "invalid seg_num %u from cache device (device hol= ds %llu, max %u)\n", + seg_num, max_segs, (u32)PCACHE_CACHE_SEGS_MAX); + ret =3D -EIO; + goto dax_release; + } + + ret =3D cache_dev_init(cache_dev, seg_num); if (ret) goto dax_release; =20 --=20 2.43.0 From nobody Sat Jul 25 05:28:12 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7D97D1E51E0; Fri, 17 Jul 2026 11:26:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784287616; cv=none; b=HUZzdI6mAXkbHkok629t9f5yLQYSFJfGhzTjTJMwAmGDJ4X4cdbt7/Lhx213weftgvj9wEge0GlQSj9V0Qh5HUHKMzhKYMFLfWL5dABmpNoIgOMq0pgGzfhxwSyBthMfgeGa3CxQt4OZ0MjaiCNoSvPgzrBox/pw44TMntrk8q0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784287616; c=relaxed/simple; bh=ERcu6kCNUxAcquaH0yB/iMSPFPaCkVyShsw6S0i8QgM=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=RlAK5jeNkZiq2Svfxn1Tf7oDa21FKexcLjCJneqhJPIHx2q43keD0KOJWC5b1m7rWhCPdcXXzotLRc/etmBKePTY4YvrcWwBzgUAfa+q3/N4zHbhrjvGN3K4Txee4dXPVZpHkTp1G8HzgZTjYxhK9ErFQPvteeFMONC4voIVvNE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=biSDPVhe; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="biSDPVhe" Received: by smtp.kernel.org (Postfix) with ESMTPS id 6C17AC2BD00; Fri, 17 Jul 2026 11:26:55 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1784287615; bh=ERcu6kCNUxAcquaH0yB/iMSPFPaCkVyShsw6S0i8QgM=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=biSDPVhed08eFZfs6ZzrtKQ+baCo4iSrnBUAXSQMXXT8sf+gkdh67cFKXkXZtbF9k Uj2dB4odNhQyvjwg81yZCm3P5T4FjMJbRZonXIcpJuQAavvEGKdSG5pGmASWCSMjzR 9i4veDxUcI5SLlyAUUkW2mL/Q/BY3myfagR42jicMMmTEFBM38a1hGjxxUvcCG/SDg F9YyCHR8yT8gGcxy6Hg1cAsoE8WstsWKDIqjhK0T/T2/OwzFBBP9Egut5mH+oeKK/h UeOmJCjeypRmISMAnrsRYQjyAUFEce5UDFsIOx86g/XdIM4VFAjTuEABQmSP/TNIJ/ EbxsZWTYc4Uyg== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 5C935C44523; Fri, 17 Jul 2026 11:26:55 +0000 (UTC) From: Bryam Vargas via B4 Relay Date: Fri, 17 Jul 2026 06:27:03 -0500 Subject: [PATCH v2 10/11] dm-pcache: validate the persisted dirty_tail chain at load Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260717-b4-disp-4c0a0039-v2-10-19227d6e313c@proton.me> References: <20260717-b4-disp-4c0a0039-v2-0-19227d6e313c@proton.me> In-Reply-To: <20260717-b4-disp-4c0a0039-v2-0-19227d6e313c@proton.me> To: Zheng Gu , Dongsheng Yang Cc: dm-devel@lists.linux.dev, Mikulas Patocka , linux-kernel@vger.kernel.org X-Mailer: b4 0.13.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1784287613; l=4613; i=hexlabsecurity@proton.me; s=proton; h=from:subject:message-id; bh=bNrMJfcaZ3IUI818Tg/YEhJH8afOwWWZ2M+Aul8IBEs=; b=WGqXGJN+dCGZbeGA72CMoAhMPr8N4EEbFNOXVga0k5kVvixemCZ6d3TuubNCi2uXSBUAPEoxw iAMW/FTWRMbB9FuOHYmplHc+9WBQrSfV+B1072Rwt6Uen4N+6n9szTe X-Developer-Key: i=hexlabsecurity@proton.me; a=ed25519; pk=dmppBMZNLLoPzxHi9l8tZDzEZUunPbgsYqIZYXeUrL0= X-Endpoint-Received: by B4 Relay for hexlabsecurity@proton.me/proton with auth_id=814 X-Original-From: Bryam Vargas Reply-To: hexlabsecurity@proton.me From: Bryam Vargas 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-mapp= er") Cc: stable@vger.kernel.org Signed-off-by: Bryam Vargas --- drivers/md/dm-pcache/cache.c | 7 ++++ drivers/md/dm-pcache/cache.h | 2 ++ drivers/md/dm-pcache/cache_key.c | 69 ++++++++++++++++++++++++++++++++++++= ++++ 3 files changed, 78 insertions(+) diff --git a/drivers/md/dm-pcache/cache.c b/drivers/md/dm-pcache/cache.c index a94eadb7affd..b0b3e21677de 100644 --- a/drivers/md/dm-pcache/cache.c +++ b/drivers/md/dm-pcache/cache.c @@ -202,6 +202,7 @@ static int cache_tail_init(struct pcache_cache *cache) { struct dm_pcache *pcache =3D CACHE_TO_PCACHE(cache); bool new_cache =3D !(cache->cache_info.flags & PCACHE_CACHE_FLAGS_INIT_DO= NE); + int ret; =20 if (new_cache) { __set_bit(0, cache->seg_map); @@ -218,6 +219,12 @@ static int cache_tail_init(struct pcache_cache *cache) pcache_dev_err(pcache, "Corrupted key tail or dirty tail.\n"); return -EIO; } + + ret =3D cache_verify_dirty_tail(cache); + if (ret) { + pcache_dev_err(pcache, "dirty tail chain does not terminate (crafted ca= che image?)\n"); + return ret; + } } =20 return 0; diff --git a/drivers/md/dm-pcache/cache.h b/drivers/md/dm-pcache/cache.h index d9e3e09f18e3..8809ec5ae943 100644 --- a/drivers/md/dm-pcache/cache.h +++ b/drivers/md/dm-pcache/cache.h @@ -666,6 +666,8 @@ static inline int cache_decode_dirty_tail(struct pcache= _cache *cache) &cache->dirty_tail_index); } =20 +int cache_verify_dirty_tail(struct pcache_cache *cache); + int pcache_cache_init(void); void pcache_cache_exit(void); #endif /* _PCACHE_CACHE_H */ diff --git a/drivers/md/dm-pcache/cache_key.c b/drivers/md/dm-pcache/cache_= key.c index f3ce319037be..1caea11a61a3 100644 --- a/drivers/md/dm-pcache/cache_key.c +++ b/drivers/md/dm-pcache/cache_key.c @@ -858,6 +858,75 @@ int cache_replay(struct pcache_cache *cache) return ret; } =20 +/* + * cache_verify_dirty_tail - reject a persisted dirty_tail whose last-kset + * chain does not terminate. + * + * dirty_tail is decoded independently of the key_tail chain cache_replay() + * walks, so replay's hop cap does not cover it. A crafted chain that loops + * back on itself makes the writeback worker re-arm forever; walk it once = here + * with the same cap and fail the load if it does not end within n_segs ho= ps. + */ +int cache_verify_dirty_tail(struct pcache_cache *cache) +{ + struct pcache_cache_pos pos; + struct pcache_cache_kset_onmedia *kset_onmedia; + u32 to_copy, last_hops =3D 0, count =3D 0; + int ret =3D 0; + + kset_onmedia =3D kzalloc(PCACHE_KSET_ONMEDIA_SIZE_MAX, GFP_KERNEL); + if (!kset_onmedia) + return -ENOMEM; + + cache_pos_copy(&pos, &cache->dirty_tail); + + while (true) { + to_copy =3D min(PCACHE_KSET_ONMEDIA_SIZE_MAX, cache_seg_remain(&pos)); + ret =3D copy_mc_to_kernel(kset_onmedia, cache_pos_addr(&pos), to_copy); + if (ret) { + ret =3D -EIO; + goto out; + } + + /* A missing, short or corrupt kset is the normal end of the chain. */ + if (!kset_onmedia_valid(kset_onmedia) || + kset_onmedia->crc !=3D cache_kset_crc(kset_onmedia)) { + ret =3D 0; + goto out; + } + + if (kset_onmedia->flags & PCACHE_KSET_FLAGS_LAST) { + if (!cache_seg_id_valid(cache, kset_onmedia->next_cache_seg_id)) { + ret =3D -EIO; + goto out; + } + + if (++last_hops > cache->n_segs) { + ret =3D -EIO; + goto out; + } + + pos.cache_seg =3D &cache->segments[kset_onmedia->next_cache_seg_id]; + pos.seg_off =3D 0; + continue; + } + + if (get_kset_onmedia_size(kset_onmedia) > cache_seg_remain(&pos)) { + ret =3D -EIO; + goto out; + } + + cache_pos_advance(&pos, get_kset_onmedia_size(kset_onmedia)); + if (++count > 512) { + cond_resched(); + count =3D 0; + } + } +out: + kfree(kset_onmedia); + return ret; +} + int cache_tree_init(struct pcache_cache *cache, struct pcache_cache_tree *= cache_tree, u32 n_subtrees) { int ret; --=20 2.43.0 From nobody Sat Jul 25 05:28:12 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7DA7A3CB567; Fri, 17 Jul 2026 11:26:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784287616; cv=none; b=Plwn66JsjsjCVrABHdS/0+2vL2gHHkH5PonYukUL1GKp0U/a5eN2F5C9P/5Nb9A6Lgh2aH94FcxiMkQT0qNhlwMOiepGOSDt+fdVU23pBkIc6U1dflHINIZDquKyKtgnnNvMjvZWZCovgPf6mf8b3GvC03izBMRNa1KQjpg/eqQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1784287616; c=relaxed/simple; bh=Fv5kQO8JwT/hd619eIfk4htygMwkT5dcOMhgEIGtyp4=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=pSTK/wG7otiSP+/lTLUuQjYRCOg6Dadz2f2Hr/Rf7pOGt3CBCx9jAL7foDO4xZkkSkhY6e0Cl3r1mZh/MjDc4CWAX6+NvSz0KOa2MjCFkrxUmGhvuGxcAkm983NFSLQGK62qv94EDy16dFAXMZDBSDFERjSa0cSYlSK6feXFOOQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=t6cw0ZY9; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="t6cw0ZY9" Received: by smtp.kernel.org (Postfix) with ESMTPS id 77C4DC2BCF7; Fri, 17 Jul 2026 11:26:55 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1784287615; bh=Fv5kQO8JwT/hd619eIfk4htygMwkT5dcOMhgEIGtyp4=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=t6cw0ZY9+38JhULrHVMZE0drdwraL0h24CnNE2RbZChbKc9rTGqB/1GF4poU3XSlJ 8R6+nTSfvhEKUo0MvxTiZzE4ZZFY4KzV6Mq+EZa3LRqfiuS6Jny9dylKNuEjP1rFrh qyG6THvaIKTH7k1oLSgi25rw/XJS2FnlUiSk/O6ws6Hs/JG5Z2APzOYykCKGn9QXL3 onbVkR+CSNwPJrdDQPVJt/wze7LqTmAAU57U+fxE+rEwR3hE9jetNV/q68btvclrIs ZwvhaO8gkal95uHvxxHMMR/MV99Xe9bRL2aAKoycERHcIWti6SEvQZ7NnW7odzsh2u fXgnEoiW2kFrw== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 68221C44516; Fri, 17 Jul 2026 11:26:55 +0000 (UTC) From: Bryam Vargas via B4 Relay Date: Fri, 17 Jul 2026 06:27:04 -0500 Subject: [PATCH v2 11/11] dm-pcache: only hand out initialized cache segments Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260717-b4-disp-4c0a0039-v2-11-19227d6e313c@proton.me> References: <20260717-b4-disp-4c0a0039-v2-0-19227d6e313c@proton.me> In-Reply-To: <20260717-b4-disp-4c0a0039-v2-0-19227d6e313c@proton.me> To: Zheng Gu , Dongsheng Yang Cc: dm-devel@lists.linux.dev, Mikulas Patocka , linux-kernel@vger.kernel.org X-Mailer: b4 0.13.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1784287613; l=2107; i=hexlabsecurity@proton.me; s=proton; h=from:subject:message-id; bh=piR/cvm0pEPSywfzzIIYfNS8IxFVEBQOSYdmjR0YuKw=; b=mnkOMdV3CZk/LMNGJI8zlCZTkI98OTRWD76o+IOKs7ih4+2/tU55/NMe7B+0pwaM7QEjm9vjg u00TuVYay3pAnmEBzwKYBkjd5GohtY4N/XesNN//tsCyQPSRocZ8hJ3 X-Developer-Key: i=hexlabsecurity@proton.me; a=ed25519; pk=dmppBMZNLLoPzxHi9l8tZDzEZUunPbgsYqIZYXeUrL0= X-Endpoint-Received: by B4 Relay for hexlabsecurity@proton.me/proton with auth_id=814 X-Original-From: Bryam Vargas Reply-To: hexlabsecurity@proton.me From: Bryam Vargas 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 =3D=3D 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-mapp= er") Cc: stable@vger.kernel.org Signed-off-by: Bryam Vargas --- drivers/md/dm-pcache/cache_segment.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/md/dm-pcache/cache_segment.c b/drivers/md/dm-pcache/ca= che_segment.c index 9d92e2b067ed..c698ebbc626d 100644 --- a/drivers/md/dm-pcache/cache_segment.c +++ b/drivers/md/dm-pcache/cache_segment.c @@ -243,8 +243,16 @@ struct pcache_cache_segment *get_cache_segment(struct = pcache_cache *cache) =20 spin_lock(&cache->seg_map_lock); again: - seg_id =3D find_next_zero_bit(cache->seg_map, cache->n_segs, cache->last_= cache_seg); - if (seg_id =3D=3D cache->n_segs) { + /* + * Only allocate initialized segments. cache_segs_init() initializes + * cache_info.n_segs of the cache->n_segs device segments; a forged + * smaller cache_info.n_segs leaves the rest as zeroed structs whose data + * pointer is NULL. Bounding the search to cache_info.n_segs keeps such a + * segment from reaching cache_kset_close(), which writes through it. + */ + seg_id =3D find_next_zero_bit(cache->seg_map, cache->cache_info.n_segs, + cache->last_cache_seg); + if (seg_id =3D=3D cache->cache_info.n_segs) { /* reset the hint of ->last_cache_seg and retry */ if (cache->last_cache_seg) { cache->last_cache_seg =3D 0; --=20 2.43.0