The auto-generated integrity buffer for writes needs to be fully initialized before being passed to the underlying block device, otherwise the uninitialized memory can be read back by userspace or anyone with physical access to the storage device. If protection information is generated, that portion of the integrity buffer is already initialized. The integrity data is also zeroed if PI generation is disabled via sysfs or the PI tuple size is 0. However, this misses the case where PI is generated and the PI tuple size is nonzero, but the metadata size is larger than the PI tuple. In this case, the remainder ("opaque") of the metadata is left uninitialized. Generalize the BLK_INTEGRITY_CSUM_NONE check to cover any case when the metadata is larger than just the PI tuple. Signed-off-by: Caleb Sander Mateos Fixes: c546d6f43833 ("block: only zero non-PI metadata tuples in bio_integrity_prep") Reviewed-by: Anuj Gupta --- block/bio-integrity-auto.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/block/bio-integrity-auto.c b/block/bio-integrity-auto.c index 9850c338548d..cff025b06be1 100644 --- a/block/bio-integrity-auto.c +++ b/block/bio-integrity-auto.c @@ -138,11 +138,11 @@ bool bio_integrity_prep(struct bio *bio) if (bi->flags & BLK_INTEGRITY_NOGENERATE) { if (bi_offload_capable(bi)) return true; set_flags = false; gfp |= __GFP_ZERO; - } else if (bi->csum_type == BLK_INTEGRITY_CSUM_NONE) + } else if (bi->metadata_size > bi->pi_tuple_size) gfp |= __GFP_ZERO; break; default: return true; } -- 2.45.2 Since commit ec7f31b2a2d3 ("block: make bio auto-integrity deadlock safe"), the gfp_t gfp variable in bio_integrity_prep() is no longer passed to an allocation function. It's only used to compute the zero_buffer argument to bio_integrity_alloc_buf(). So change the variable to bool zero_buffer to simplify the code. Signed-off-by: Caleb Sander Mateos --- block/bio-integrity-auto.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/block/bio-integrity-auto.c b/block/bio-integrity-auto.c index cff025b06be1..605403b52c90 100644 --- a/block/bio-integrity-auto.c +++ b/block/bio-integrity-auto.c @@ -107,11 +107,11 @@ bool __bio_integrity_endio(struct bio *bio) bool bio_integrity_prep(struct bio *bio) { struct blk_integrity *bi = blk_get_integrity(bio->bi_bdev->bd_disk); struct bio_integrity_data *bid; bool set_flags = true; - gfp_t gfp = GFP_NOIO; + bool zero_buffer = false; if (!bi) return true; if (!bio_sectors(bio)) @@ -137,13 +137,14 @@ bool bio_integrity_prep(struct bio *bio) */ if (bi->flags & BLK_INTEGRITY_NOGENERATE) { if (bi_offload_capable(bi)) return true; set_flags = false; - gfp |= __GFP_ZERO; - } else if (bi->metadata_size > bi->pi_tuple_size) - gfp |= __GFP_ZERO; + zero_buffer = true; + } else { + zero_buffer = bi->metadata_size > bi->pi_tuple_size; + } break; default: return true; } @@ -152,11 +153,11 @@ bool bio_integrity_prep(struct bio *bio) bid = mempool_alloc(&bid_pool, GFP_NOIO); bio_integrity_init(bio, &bid->bip, &bid->bvec, 1); bid->bio = bio; bid->bip.bip_flags |= BIP_BLOCK_INTEGRITY; - bio_integrity_alloc_buf(bio, gfp & __GFP_ZERO); + bio_integrity_alloc_buf(bio, zero_buffer); bip_set_seed(&bid->bip, bio->bi_iter.bi_sector); if (set_flags) { if (bi->csum_type == BLK_INTEGRITY_CSUM_IP) -- 2.45.2 bi_offload_capable() returns whether a block device's metadata size matches its PI tuple size. Use pi_tuple_size instead of switching on csum_type. This makes the code considerably simpler and less branchy. Signed-off-by: Caleb Sander Mateos --- block/bio-integrity-auto.c | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/block/bio-integrity-auto.c b/block/bio-integrity-auto.c index 605403b52c90..626bbe17eb23 100644 --- a/block/bio-integrity-auto.c +++ b/block/bio-integrity-auto.c @@ -50,23 +50,11 @@ static bool bip_should_check(struct bio_integrity_payload *bip) return bip->bip_flags & BIP_CHECK_FLAGS; } static bool bi_offload_capable(struct blk_integrity *bi) { - switch (bi->csum_type) { - case BLK_INTEGRITY_CSUM_CRC64: - return bi->metadata_size == sizeof(struct crc64_pi_tuple); - case BLK_INTEGRITY_CSUM_CRC: - case BLK_INTEGRITY_CSUM_IP: - return bi->metadata_size == sizeof(struct t10_pi_tuple); - default: - pr_warn_once("%s: unknown integrity checksum type:%d\n", - __func__, bi->csum_type); - fallthrough; - case BLK_INTEGRITY_CSUM_NONE: - return false; - } + return bi->metadata_size == bi->pi_tuple_size; } /** * __bio_integrity_endio - Integrity I/O completion function * @bio: Protected bio -- 2.45.2