From nobody Fri Oct 2 12:21:53 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 C5FC53A8739; Sat, 1 Aug 2026 02:32:04 +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=1785551524; cv=none; b=Om2VmGCVUxhJccGEUcLCYMBg84rZTPsrpBcRTsKoR1+0Mp/YfE2m+CCOET8Pym4sFQcKxGErOM9iveKFC7NjUju3RLS0D5j1JvPpa/GECx/0sAUIlVj8ZtsF32UgQhcSnI3F0Nv1oli/Sp96uLepaYYMC1BqbOhpwDSLZ/DIq3A= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785551524; c=relaxed/simple; bh=Y+GO4cGJr2DyQF9toXB4QmMs42LMVZ0lwdGnls3VSTo=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Kqh4nLeThIZooi0QwtgU7zXOhRxZD3GvwaidLjSI0RDT+OQklZqTZIutTRq2kutZ8ZRAzEph0AFPk0sIEA9rib0i/gxsZDlCwg2w6/0RJ6QGn3X/5NeJcLFSN1DFsqWMY7EuxpyixiTqdRoTe5Z0kfQfbUvNgHi0AZzEpJBdwMA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=R6w8Y1pi; 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="R6w8Y1pi" Received: by smtp.kernel.org (Postfix) with ESMTPS id 794EAC2BCF5; Sat, 1 Aug 2026 02:32:04 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1785551524; bh=Y+GO4cGJr2DyQF9toXB4QmMs42LMVZ0lwdGnls3VSTo=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=R6w8Y1pi2uU2LqqGjjWsbw1+5w3xEzDZHUu+83RFSvJsJuAyVIKWmntN5DZcTyzHA AMuzQsnNwUDjvyELyLCqHhtrtsSuFidGbWzntP7drCFUUOqLZiq5kZvc79efjdQtVJ yk7ho2HIyfbxLsSsJ3aL6dSj1QT+AdZiJlU43gQWsimPZT8hwP0AgV9U+pIxMC5JF5 SXz/V22aK5e9cEBNH1Hxd8o50cmyOo5OEZu1ZyigayqnrYcdtXkn0/2EXkTOfCArT5 WKfkNmjrcNUzHO7ZLULA1/7p7GLCmzG8AtxEdv8ikHExHjheuBYPrXihT4MC9cNwT4 I8++Lv1itDo0g== 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 53CA4C55171; Sat, 1 Aug 2026 02:32:04 +0000 (UTC) From: Bryam Vargas via B4 Relay Date: Fri, 31 Jul 2026 21:32:03 -0500 Subject: [PATCH 1/2] dm btree: hold a node header to the geometry its writers guarantee 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: <20260731-b4-disp-1fdddbbb-v1-1-4879ae1012a2@proton.me> References: <20260731-b4-disp-1fdddbbb-v1-0-4879ae1012a2@proton.me> In-Reply-To: <20260731-b4-disp-1fdddbbb-v1-0-4879ae1012a2@proton.me> To: Mike Snitzer , Mikulas Patocka Cc: Joe Thornber , Ming-Hung Tsai , Heinz Mauelshagen , Alasdair Kergon , dm-devel@lists.linux.dev, linux-kernel@vger.kernel.org, Benjamin Marzinski X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1785551523; l=3926; i=hexlabsecurity@proton.me; s=default; h=from:subject:message-id; bh=SnIoIuUzdET3sEwmH/NlsmiMJYNEfOw+g2ZqpCChPcQ=; b=xxC02AzzptIh1Qei8U7/FuEVMTtkd8cyQf3at4duF5do4FTaVkJnK2LDcUsIhDasBzMGRXoNu XpmBRdmUeXVDU6bVcor/7qVrr5DIYMsMmA8JXLBlwtElzCjE8oTotLL X-Developer-Key: i=hexlabsecurity@proton.me; a=ed25519; pk=xw1AhCtQdvuoQc+bOQIYy9o8G++cp4/VniI2G/tc3G8= X-Endpoint-Received: by B4 Relay for hexlabsecurity@proton.me/default with auth_id=893 X-Original-From: Bryam Vargas Reply-To: hexlabsecurity@proton.me From: Bryam Vargas node_check() weighs a node header against itself and nothing else, which leaves three shapes the writers never produce and the reader accepts: a zero value_size, which collapses value_ptr()'s stride so max_entries alone places the value area, off the end of the block; an internal node whose value_size is not the __le64 stride value64() indexes it with; and a max_entries that disagrees with calc_max_entries(), the formula every writer computes it from. Reject all three. Conforming metadata satisfies them by construction: dm_btree_empty() and btree_split_beneath() take max_entries from calc_max_entries() and write sizeof(__le64) for an internal node, and the split paths copy flags, max_entries and value_size together. calc_max_entries() gains a declaration in dm-btree-internal.h so the validator shares the formula rather than open-coding it. Fixes: 3241b1d3e0aa ("dm: add persistent data library") Cc: stable@vger.kernel.org Signed-off-by: Bryam Vargas --- drivers/md/persistent-data/dm-btree-internal.h | 2 ++ drivers/md/persistent-data/dm-btree-spine.c | 20 +++++++++++++++++++- drivers/md/persistent-data/dm-btree.c | 2 +- 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/drivers/md/persistent-data/dm-btree-internal.h b/drivers/md/pe= rsistent-data/dm-btree-internal.h index acebd32858a7..404739149d02 100644 --- a/drivers/md/persistent-data/dm-btree-internal.h +++ b/drivers/md/persistent-data/dm-btree-internal.h @@ -43,6 +43,8 @@ struct btree_node { } __packed __aligned(8); =20 =20 +uint32_t calc_max_entries(size_t value_size, size_t block_size); + /* * Locks a block using the btree node validator. */ diff --git a/drivers/md/persistent-data/dm-btree-spine.c b/drivers/md/persi= stent-data/dm-btree-spine.c index c46fc50c274e..076f836912c8 100644 --- a/drivers/md/persistent-data/dm-btree-spine.c +++ b/drivers/md/persistent-data/dm-btree-spine.c @@ -57,6 +57,25 @@ static int node_check(const struct dm_block_validator *v, nr_entries =3D le32_to_cpu(h->nr_entries); max_entries =3D le32_to_cpu(h->max_entries); value_size =3D le32_to_cpu(h->value_size); + flags =3D le32_to_cpu(h->flags); + + if (!value_size) { + DMERR_LIMIT("%s failed: value_size is zero", __func__); + return -EILSEQ; + } + + if ((flags & INTERNAL_NODE) && value_size !=3D sizeof(__le64)) { + DMERR_LIMIT("%s failed: internal node value_size %zu !=3D %zu", + __func__, value_size, sizeof(__le64)); + return -EILSEQ; + } + + if (max_entries !=3D calc_max_entries(value_size, block_size)) { + DMERR_LIMIT("%s failed: max_entries %u !=3D wanted %u for value_size %zu= ", + __func__, max_entries, + calc_max_entries(value_size, block_size), value_size); + return -EILSEQ; + } =20 if (sizeof(struct node_header) + (sizeof(__le64) + value_size) * max_entries > block_size) { @@ -72,7 +91,6 @@ static int node_check(const struct dm_block_validator *v, /* * The node must be either INTERNAL or LEAF. */ - flags =3D le32_to_cpu(h->flags); if (!(flags & INTERNAL_NODE) && !(flags & LEAF_NODE)) { DMERR_LIMIT("%s failed: node is neither INTERNAL or LEAF", __func__); return -EILSEQ; diff --git a/drivers/md/persistent-data/dm-btree.c b/drivers/md/persistent-= data/dm-btree.c index dd02eee4a23c..5ed3b3e9abb9 100644 --- a/drivers/md/persistent-data/dm-btree.c +++ b/drivers/md/persistent-data/dm-btree.c @@ -114,7 +114,7 @@ static int insert_at(size_t value_size, struct btree_no= de *node, unsigned int in * We want 3n entries (for some n). This works more nicely for repeated * insert remove loops than (2n + 1). */ -static uint32_t calc_max_entries(size_t value_size, size_t block_size) +uint32_t calc_max_entries(size_t value_size, size_t block_size) { uint32_t total, n; size_t elt_size =3D sizeof(uint64_t) + value_size; /* key + value */ --=20 2.55.0 From nobody Fri Oct 2 12:21:53 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 C5EA82236F0; Sat, 1 Aug 2026 02:32:04 +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=1785551524; cv=none; b=JFuhEYUXIVGnpT6VvkspBieUr5PYGAiwUMB6GhaWTT6txg+kwa+Z5v1QDaDhEC7pwegTH0y8mM8rbPg1NWVKdm40P8Q94sMntd7LGjJYrTrVeMIPL5t+C9ZfYfI6kuBBrArpHn7iIINospEmx2yU/yl6s6e4cyqUp9cjdYiOB6A= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1785551524; c=relaxed/simple; bh=saWzOSuWgq/kh+bp5MI1Ci2ayR+nRFZdO54m4i5PEtQ=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=qWW/zUyKPnMrOin4AmAP4VOhzBpYul1tMDp38VLZ/zxDnwguCqAQR9P+a3pyski+Zwm8g5mSXOTlI9l9ROBwOR7sM5rVkZ2uLz6v12oppPwgsMMVBTMTSc5IlqJeLEc+yOMgtBwURwkem1/yDavSSj6FZnNv9v7h0pZKuYO0/bM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=r6tMP5uf; 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="r6tMP5uf" Received: by smtp.kernel.org (Postfix) with ESMTPS id 863A5C2BCF4; Sat, 1 Aug 2026 02:32:04 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1785551524; bh=saWzOSuWgq/kh+bp5MI1Ci2ayR+nRFZdO54m4i5PEtQ=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=r6tMP5ufdWU0y68Nem04mEy4/jXgk8zhy/ZByKOP3BCNP1hqHAelkv52wrH2kp6cN VGwIVRKQ0Y3YcAWmFB+BI00mlFD79iQgeDCSyOFQGohn4WRmySrZ6MReDgtj/Uy9CG S2q3TJ8tDkHq5TvY5k5QXVeVWPPY6RbO/IG8ut0IzVz2rtnIWGubn2ZZsMAR/XG701 lJC0Jnd0ifLLAlC6NyvhwYX5CkX/GTrDEXzw9FRNpQQRv6ps6PWCOwy1fhgBAmkZmw CPZ3KpvcqDm5CQ0KBeUfpsF0+krcFjU1cQQ2Tx1Uxccbhxkr6qZYIowhyPsLC/r1SU YsevrfMn+fL3g== 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 62CEEC5516F; Sat, 1 Aug 2026 02:32:04 +0000 (UTC) From: Bryam Vargas via B4 Relay Date: Fri, 31 Jul 2026 21:32:04 -0500 Subject: [PATCH 2/2] dm btree: reject a node whose value size is not the reading level's 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: <20260731-b4-disp-1fdddbbb-v1-2-4879ae1012a2@proton.me> References: <20260731-b4-disp-1fdddbbb-v1-0-4879ae1012a2@proton.me> In-Reply-To: <20260731-b4-disp-1fdddbbb-v1-0-4879ae1012a2@proton.me> To: Mike Snitzer , Mikulas Patocka Cc: Joe Thornber , Ming-Hung Tsai , Heinz Mauelshagen , Alasdair Kergon , dm-devel@lists.linux.dev, linux-kernel@vger.kernel.org, Benjamin Marzinski X-Mailer: b4 0.15.2 X-Developer-Signature: v=1; a=ed25519-sha256; t=1785551523; l=9192; i=hexlabsecurity@proton.me; s=default; h=from:subject:message-id; bh=nPH9k1cM6UEOPHSiszBBTRgFy6NWqXca3CfwP+ScfsA=; b=EQa0PMaDo1tlSXV0HLqVcQFMOqDFl49SHQbH7NZgWIgF8AXfuhk9t+DhDJB7BkJ9lkBKkAqah d9wzeMVyJM3B9zg2wEumak1QdnvFlGjJXyHhSvmrQF60GXuuKrEX0A1 X-Developer-Key: i=hexlabsecurity@proton.me; a=ed25519; pk=xw1AhCtQdvuoQc+bOQIYy9o8G++cp4/VniI2G/tc3G8= X-Endpoint-Received: by B4 Relay for hexlabsecurity@proton.me/default with auth_id=893 X-Original-From: Bryam Vargas Reply-To: hexlabsecurity@proton.me From: Bryam Vargas value_ptr() takes an entry's address from the value_size on disk while the caller supplies the length it copies; a validator cannot compare the two, since it sees the block and never the caller. A leaf can pass every check the previous patch adds and still be laid out for a narrower value, leaving insert_at() and btree_split_beneath() striding with the caller's size over a base placed by the node's -- writes that land kilobytes past the block. Compare the sizes wherever both are in hand. Everything that modifies a node reaches it through bn_shadow(), so one check there covers insert, the splits, remove and the space map's refcount overflow leaf; the readers and the two paths that bypass the spine take it where the expected size is known. A node is only ever read through the level that wrote it, so conforming metadata is unaffected. Fixes: 3241b1d3e0aa ("dm: add persistent data library") Cc: stable@vger.kernel.org Signed-off-by: Bryam Vargas --- drivers/md/persistent-data/dm-btree-internal.h | 6 +- drivers/md/persistent-data/dm-btree-remove.c | 24 ++++++-- drivers/md/persistent-data/dm-btree-spine.c | 13 ++++- drivers/md/persistent-data/dm-btree.c | 79 ++++++++++++++++++++++= +--- 4 files changed, 108 insertions(+), 14 deletions(-) diff --git a/drivers/md/persistent-data/dm-btree-internal.h b/drivers/md/pe= rsistent-data/dm-btree-internal.h index 404739149d02..7d5741572b16 100644 --- a/drivers/md/persistent-data/dm-btree-internal.h +++ b/drivers/md/persistent-data/dm-btree-internal.h @@ -51,8 +51,10 @@ uint32_t calc_max_entries(size_t value_size, size_t bloc= k_size); int bn_read_lock(struct dm_btree_info *info, dm_block_t b, struct dm_block **result); =20 -void inc_children(struct dm_transaction_manager *tm, struct btree_node *n, - struct dm_btree_value_type *vt); +int check_value_size(struct btree_node *n, size_t expected); + +int inc_children(struct dm_transaction_manager *tm, struct btree_node *n, + struct dm_btree_value_type *vt); =20 int new_block(struct dm_btree_info *info, struct dm_block **result); void unlock_block(struct dm_btree_info *info, struct dm_block *b); diff --git a/drivers/md/persistent-data/dm-btree-remove.c b/drivers/md/pers= istent-data/dm-btree-remove.c index aeec5b9a1dd5..64f3313f5a1c 100644 --- a/drivers/md/persistent-data/dm-btree-remove.c +++ b/drivers/md/persistent-data/dm-btree-remove.c @@ -175,8 +175,14 @@ static int init_child(struct dm_btree_info *info, stru= ct dm_btree_value_type *vt =20 result->n =3D dm_block_data(result->block); =20 - if (inc) - inc_children(info->tm, result->n, vt); + r =3D check_value_size(result->n, vt->size); + if (!r && inc) + r =3D inc_children(info->tm, result->n, vt); + + if (r) { + dm_tm_unlock(info->tm, result->block); + return r; + } =20 *((__le64 *) value_ptr(parent, index)) =3D cpu_to_le64(dm_block_location(result->block)); @@ -501,8 +507,18 @@ static int rebalance_children(struct shadow_spine *s, if (r) return r; =20 - if (is_shared) - inc_children(info->tm, dm_block_data(child), vt); + /* + * The child is copied over the node the spine already + * checked, so it has to answer for itself first. + */ + r =3D check_value_size(dm_block_data(child), vt->size); + if (!r && is_shared) + r =3D inc_children(info->tm, dm_block_data(child), vt); + + if (r) { + dm_tm_unlock(info->tm, child); + return r; + } =20 memcpy(n, dm_block_data(child), dm_bm_block_size(dm_tm_get_bm(info->tm))); diff --git a/drivers/md/persistent-data/dm-btree-spine.c b/drivers/md/persi= stent-data/dm-btree-spine.c index 076f836912c8..2527af9460fe 100644 --- a/drivers/md/persistent-data/dm-btree-spine.c +++ b/drivers/md/persistent-data/dm-btree-spine.c @@ -121,8 +121,19 @@ static int bn_shadow(struct dm_btree_info *info, dm_bl= ock_t orig, =20 r =3D dm_tm_shadow_block(info->tm, orig, &btree_node_validator, result, &inc); + if (r) + return r; + + /* + * Everything that modifies a node reaches it through here, so this is + * where a leaf laid out for a different value size is caught. + */ + r =3D check_value_size(dm_block_data(*result), vt->size); if (!r && inc) - inc_children(info->tm, dm_block_data(*result), vt); + r =3D inc_children(info->tm, dm_block_data(*result), vt); + + if (r) + unlock_block(info, *result); =20 return r; } diff --git a/drivers/md/persistent-data/dm-btree.c b/drivers/md/persistent-= data/dm-btree.c index 5ed3b3e9abb9..b74c41fe6213 100644 --- a/drivers/md/persistent-data/dm-btree.c +++ b/drivers/md/persistent-data/dm-btree.c @@ -71,16 +71,47 @@ static int upper_bound(struct btree_node *n, uint64_t k= ey) return bsearch(n, key, 1); } =20 -void inc_children(struct dm_transaction_manager *tm, struct btree_node *n, - struct dm_btree_value_type *vt) +/* + * value_ptr() takes an entry's address from the value_size stored on disk, + * but the caller supplies the length it copies. node_check() sees the bl= ock + * and never the caller, so the two are compared here, wherever both are in + * hand. Internal nodes are exempt: node_check() already holds them to + * sizeof(__le64), which is what value64() assumes. + */ +int check_value_size(struct btree_node *n, size_t expected) +{ + uint32_t value_size =3D le32_to_cpu(n->header.value_size); + + if (le32_to_cpu(n->header.flags) & INTERNAL_NODE) + return 0; + + if (value_size !=3D expected) { + DMERR_LIMIT("%s failed: value_size %u !=3D %zu expected by the caller", + __func__, value_size, expected); + return -EILSEQ; + } + + return 0; +} + +int inc_children(struct dm_transaction_manager *tm, struct btree_node *n, + struct dm_btree_value_type *vt) { uint32_t nr_entries =3D le32_to_cpu(n->header.nr_entries); =20 if (le32_to_cpu(n->header.flags) & INTERNAL_NODE) dm_tm_with_runs(tm, value_ptr(n, 0), nr_entries, dm_tm_inc_range); =20 - else if (vt->inc) + else if (vt->inc) { + int r =3D check_value_size(n, vt->size); + + if (r) + return r; + vt->inc(vt->context, value_ptr(n, 0), nr_entries); + } + + return 0; } =20 static int insert_at(size_t value_size, struct btree_node *node, unsigned = int index, @@ -314,6 +345,10 @@ int dm_btree_del(struct dm_btree_info *info, dm_block_= t root) goto out; =20 } else if (is_internal_level(info, f)) { + r =3D check_value_size(f->n, sizeof(__le64)); + if (r) + goto out; + b =3D value64(f->n, f->current_child); f->current_child++; r =3D push_frame(s, b, f->level + 1); @@ -321,9 +356,14 @@ int dm_btree_del(struct dm_btree_info *info, dm_block_= t root) goto out; =20 } else { - if (info->value_type.dec) + if (info->value_type.dec) { + r =3D check_value_size(f->n, info->value_type.size); + if (r) + goto out; + info->value_type.dec(info->value_type.context, value_ptr(f->n, 0), f->nr_children); + } pop_frame(s); } } @@ -365,8 +405,13 @@ static int btree_lookup_raw(struct ro_spine *s, dm_blo= ck_t block, uint64_t key, } while (!(flags & LEAF_NODE)); =20 *result_key =3D le64_to_cpu(ro_node(s)->keys[i]); - if (v) + if (v) { + r =3D check_value_size(ro_node(s), value_size); + if (r) + return r; + memcpy(v, value_ptr(ro_node(s), i), value_size); + } =20 return 0; } @@ -460,6 +505,10 @@ static int dm_btree_lookup_next_single(struct dm_btree= _info *info, dm_block_t ro } =20 *rkey =3D le64_to_cpu(n->keys[i]); + r =3D check_value_size(n, info->value_type.size); + if (r) + goto out; + memcpy(value_le, value_ptr(n, i), info->value_type.size); } out: @@ -721,8 +770,14 @@ static int shadow_child(struct dm_btree_info *info, st= ruct dm_btree_value_type * =20 node =3D dm_block_data(*result); =20 - if (inc) - inc_children(info->tm, node, vt); + r =3D check_value_size(node, vt->size); + if (!r && inc) + r =3D inc_children(info->tm, node, vt); + + if (r) { + unlock_block(info, *result); + return r; + } =20 *((__le64 *) value_ptr(parent, index)) =3D cpu_to_le64(dm_block_location(*result)); @@ -1441,6 +1496,10 @@ static int walk_node(struct dm_btree_info *info, dm_= block_t block, if (r) goto out; } else { + r =3D check_value_size(n, info->value_type.size); + if (r) + goto out; + keys =3D le64_to_cpu(*key_ptr(n, i)); r =3D fn(context, &keys, value_ptr(n, i)); if (r) @@ -1474,6 +1533,9 @@ static void prefetch_values(struct dm_btree_cursor *c) =20 BUG_ON(c->info->value_type.size !=3D sizeof(value_le)); =20 + if (check_value_size(bn, sizeof(value_le))) + return; + nr =3D le32_to_cpu(bn->header.nr_entries); for (i =3D 0; i < nr; i++) { memcpy(&value_le, value_ptr(bn, i), sizeof(value_le)); @@ -1627,6 +1689,9 @@ int dm_btree_cursor_get_value(struct dm_btree_cursor = *c, uint64_t *key, void *va if (le32_to_cpu(bn->header.flags) & INTERNAL_NODE) return -EINVAL; =20 + if (check_value_size(bn, c->info->value_type.size)) + return -EILSEQ; + *key =3D le64_to_cpu(*key_ptr(bn, n->index)); memcpy(value_le, value_ptr(bn, n->index), c->info->value_type.size); return 0; --=20 2.55.0