Linux Btrfs filesystem development
 help / color / mirror / Atom feed
* [PATCH] btrfs: handle highmem folios in read_key_bytes
@ 2026-08-17  2:20 Hongling Zeng
  2026-08-17  2:55 ` Qu Wenruo
  0 siblings, 1 reply; 5+ messages in thread
From: Hongling Zeng @ 2026-08-17  2:20 UTC (permalink / raw)
  To: clm, dsterba, lizetao1
  Cc: linux-btrfs, linux-kernel, zhongling0719, Hongling Zeng, stable

On 32-bit systems with highmem, folio_address() can return NULL for
unmapped highmem folios. When this NULL is passed as the dest parameter
to read_key_bytes() with a non-NULL dest_folio, it violates the function's
contract (which requires dest to be non-NULL when dest_folio is provided).

The original bug had two symptoms:
1. Unsigned len underflow when len -= copy_bytes executes (infinite loop)
2. The folio remains uninitialized because the copy block is skipped

Fix requires two changes:

1. Change "if (!dest)" to "if (!dest && !dest_folio)"
   - Prevents the "counting-only" mode when dest_folio is provided
   - Fixes the underflow/infinite loop

2. Change "if (dest)" to "if (dest || dest_folio)"
   - Ensures the copy block executes when dest_folio is provided
   - Allows kmap_local_folio() to properly map the highmem folio
   - Actually writes data to the folio

Without the second change, the highmem folio is not populated even
though the read succeeds, causing subsequent fs-verity verification to
operate on stale or uninitialized data.

Fixes: 884937793db5 ("btrfs: convert read_key_bytes() to take a folio")
Cc: stable@vger.kernel.org
Signed-off-by: Hongling Zeng <zenghongling@kylinos.cn>
---
 fs/btrfs/verity.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/fs/btrfs/verity.c b/fs/btrfs/verity.c
index 983365a73541..80bc945c7dcb 100644
--- a/fs/btrfs/verity.c
+++ b/fs/btrfs/verity.c
@@ -351,7 +351,7 @@ static int read_key_bytes(struct btrfs_inode *inode, u8 key_type, u64 offset,
 		}
 
 		/* desc = NULL to just sum all the item lengths */
-		if (!dest)
+		if (!dest && !dest_folio)
 			copy_end = item_end;
 		else
 			copy_end = min(offset + len, item_end);
@@ -362,7 +362,7 @@ static int read_key_bytes(struct btrfs_inode *inode, u8 key_type, u64 offset,
 		/* Offset from the start of item for copying */
 		copy_offset = offset - key.offset;
 
-		if (dest) {
+		if (dest || dest_folio) {
 			if (dest_folio)
 				kaddr = kmap_local_folio(dest_folio, 0);
 
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2026-08-17  6:37 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-17  2:20 [PATCH] btrfs: handle highmem folios in read_key_bytes Hongling Zeng
2026-08-17  2:55 ` Qu Wenruo
2026-08-17  4:14   ` Hongling Zeng
2026-08-17  6:02     ` Qu Wenruo
2026-08-17  6:37       ` Hongling Zeng

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox