block/bio-integrity-auto.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)
From: "Samin Y. Chowdhury" <samin_c@outlook.com>
Abort early with BLK_STS_PROTECTION if a namespace revalidation changed
bi->metadata_size after bio_integrity_prep() sized the allocation.
Found by FuzzNvme (Syzkaller with FEMU fuzzing framework).
When a namespace is revalidated between bio_integrity_prep() and
bio_integrity_verify_fn(), the integrity profile's metadata_size may
change under the in-flight bio. bio_integrity_verify_fn() re-reads the
live blk_integrity via blk_get_integrity(), so blk_integrity_iterate()
uses the new metadata_size as the per-interval step size against a
buffer sized for the old one, advancing iter->prot_buf past the end of
the allocation.
task 1:
bio_integrity_prep()
bio_integrity_alloc_buf()
len = bio_integrity_bytes(bi, bio_sectors(bio)) ...(1)
bip->bip_iter.bi_size = len
task 2:
nvme_update_ns_info_block()
blk_mq_freeze_queue()
nvme_init_integrity()
bi->metadata_size = head->ms ...(2)
blk_mq_unfreeze_queue()
task 3:
bio_integrity_verify_fn()
bio_integrity_verify()
blk_integrity_iterate()
bi = blk_get_integrity() ...(3)
iter->interval_remaining = 1 << bi->interval_exp
iter->prot_buf += bi->metadata_size per interval
/* step size from (3), buffer sized at (1): overrun */
Fixes: 8098514bd5ca ("block: always allocate integrity buffer when required")
Signed-off-by: Samin Y. Chowdhury <samin_c@outlook.com>
Acked-by: Sungwoo Kim <iam@sung-woo.kim>
Acked-by: Dave Tian <daveti@purdue.edu>
Acked-by: Weidong Zhu <weizhu@fiu.edu>
Acked-by: Ruimin Sun <rsun@fiu.edu>
---
When a namespace is revalidated between bio_integrity_prep() and
bio_integrity_verify_fn(), the integrity profile's metadata_size may
change under the in-flight bio. bio_integrity_verify_fn() re-reads the
live blk_integrity via blk_get_integrity(), so blk_integrity_iterate()
uses the new metadata_size as the per-interval step size against a
buffer sized for the old one, advancing iter->prot_buf past the end of
the allocation.
task 1:
bio_integrity_prep()
bio_integrity_alloc_buf()
len = bio_integrity_bytes(bi, bio_sectors(bio)) ...(1)
bip->bip_iter.bi_size = len
task 2:
nvme_update_ns_info_block()
blk_mq_freeze_queue()
nvme_init_integrity()
bi->metadata_size = head->ms ...(2)
blk_mq_unfreeze_queue()
task 3:
bio_integrity_verify_fn()
bio_integrity_verify()
blk_integrity_iterate()
bi = blk_get_integrity() ...(3)
iter->interval_remaining = 1 << bi->interval_exp
iter->prot_buf += bi->metadata_size per interval
/* step size from (3), buffer sized at (1): overrun */
---
block/bio-integrity-auto.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/block/bio-integrity-auto.c b/block/bio-integrity-auto.c
index 353eed632fc..b404dbaa9f8 100644
--- a/block/bio-integrity-auto.c
+++ b/block/bio-integrity-auto.c
@@ -38,6 +38,18 @@ static void bio_integrity_verify_fn(struct work_struct *work)
struct bio_integrity_data *bid =
container_of(work, struct bio_integrity_data, work);
struct bio *bio = bid->bio;
+ struct blk_integrity *bi = blk_get_integrity(bio->bi_bdev->bd_disk);
+
+ if (bi) {
+ unsigned int required = bio_integrity_bytes(bi, bio_sectors(bio));
+
+ if (unlikely(required > bid->bip.bip_iter.bi_size)) {
+ bio->bi_status = BLK_STS_PROTECTION;
+ bio_integrity_finish(bid);
+ bio_endio(bio);
+ return;
+ }
+ }
bio->bi_status = bio_integrity_verify(bio, &bid->saved_bio_iter);
bio_integrity_finish(bid);
---
base-commit: 174914ea551314c52a61713b9c4bde9e42d48073
change-id: 20260531-blk-integrity-fix-e8109008af54
Best regards,
--
Samin Y. Chowdhury <samin_c@outlook.com>
On Sun, May 31, 2026 at 06:45:07PM -0400, Samin Y. Chowdhury via B4 Relay wrote: > When a namespace is revalidated between bio_integrity_prep() and > bio_integrity_verify_fn(), the integrity profile's metadata_size may > change under the in-flight bio. bio_integrity_verify_fn() re-reads the > live blk_integrity via blk_get_integrity(), so blk_integrity_iterate() > uses the new metadata_size as the per-interval step size against a > buffer sized for the old one, advancing iter->prot_buf past the end of > the allocation. I don't think changing fundamental device properies such as the LBA or integrity tag size under a live device is a good model. So instead of coming up with bandaids like this, we should probably just fail any such revalidation when there are openers instead of trying to deal with the fallout.
© 2016 - 2026 Red Hat, Inc.