Thread (50 messages) flat view 50 messages, 4 authors, 3d ago

Re: [PATCH v4 09/25] md/md-llbitmap: track bitmap sync_size explicitly

From: sashiko-bot@kernel.org
Date: 2026-08-01 17:44:13

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] Missing bounds check on `sync_size` causes out-of-bounds memory accesses and disk overwrites.
--
--- Patch [9]: [PATCH v4 09/25] md/md-llbitmap: track bitmap sync_size explicitly ---
commit b06a020ec2776bd2bc0418543c90f7ea1a1e754b
Author: Yu Kuai [off-list ref]

md/md-llbitmap: track bitmap sync_size explicitly

Track llbitmap's own sync_size instead of always using
mddev->resync_max_sectors directly. This is the minimal bookkeeping needed
before llbitmap can track old and new reshape geometry independently.
quoted hunk ↗ jump to hunk
diff --git a/drivers/md/md-llbitmap.c b/drivers/md/md-llbitmap.c
index 1fa2adf0ada1c..3417da288e994 100644
--- a/drivers/md/md-llbitmap.c
+++ b/drivers/md/md-llbitmap.c
[ ... ]
quoted hunk ↗ jump to hunk
@@ -987,6 +991,9 @@ static int llbitmap_read_sb(struct llbitmap *llbitmap)
 		goto out_put_page;
 	}
 
+	sync_size = le64_to_cpu(sb->sync_size);
+	if (!sync_size)
+		sync_size = mddev->resync_max_sectors;
[Severity: High]
Does this code bypass capacity validation if the superblock is corrupted or
tampered?

If an array is assembled with a bitmap superblock where sb->sync_size is
artificially large or small, this untrusted sync_size is read here.

However, it appears the bounds check later in llbitmap_read_sb() still
validates against mddev->resync_max_sectors instead of the new sync_size:

	if (chunksize < DIV_ROUND_UP_SECTOR_T(mddev->resync_max_sectors,
					      mddev->bitmap_info.space << SECTOR_SHIFT)) {

Could this allow maliciously large or small chunk requirements to bypass
capacity validation?
 	chunksize = le32_to_cpu(sb->chunksize);
 	if (!is_power_of_2(chunksize)) {
 		pr_err("md/llbitmap: %s: chunksize not a power of 2",
[ ... ]
quoted hunk ↗ jump to hunk
@@ -1022,8 +1029,9 @@ static int llbitmap_read_sb(struct llbitmap *llbitmap)
 
 	llbitmap->barrier_idle = DEFAULT_BARRIER_IDLE;
 	llbitmap->chunksize = chunksize;
-	llbitmap->chunks = DIV_ROUND_UP_SECTOR_T(mddev->resync_max_sectors, chunksize);
+	llbitmap->chunks = DIV_ROUND_UP_SECTOR_T(sync_size, chunksize);
[Severity: High]
Is it safe to compute llbitmap->chunks using the unvalidated sync_size here?

Since the validation check above still uses mddev->resync_max_sectors, an
artificially large sync_size will cause llbitmap->chunks to exceed the
allocated metadata space. This breaks the capacity validation invariant.

Could this cause __llbitmap_flush() and llbitmap_write_page() to write bitmap
data out-of-bounds on the underlying disk, overwriting adjacent partitions?

Additionally, if sync_size is artificially small, the llbitmap->pctl array
allocation (nr_pages) will be undersized. When IO arrives at valid offsets
bounded by the block layer capacity, fast paths like llbitmap_start_write()
could calculate a page_start index that exceeds nr_pages:

drivers/md/md-llbitmap.c:llbitmap_start_write() {
    ...
	int page_start = (start + BITMAP_DATA_OFFSET) >> PAGE_SHIFT;
	int page_end = (end + BITMAP_DATA_OFFSET) >> PAGE_SHIFT;

	while (page_start <= page_end) {
		llbitmap_raise_barrier(llbitmap, page_start);
		page_start++;
	}
    ...
}

Could this lead to an out-of-bounds memory access on the pctl array when
calling llbitmap_raise_barrier()?
 	llbitmap->chunkshift = ffz(~chunksize);
+	llbitmap->sync_size = sync_size;
 	ret = llbitmap_cache_pages(llbitmap);
-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260801172519.2982121-1-yukuai@kernel.org?part=9
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help