[PATCH v4 4/4] scsi: target: rd: Avoid 32-bit overflow in protection space size

From: Sanan Hasanov

Date: Thu Oct 08 2026 - 20:37:33 EST


From: Sanan Hasanov <sanan.hasanov@xxxxxxx>

rd_build_prot_space() computes the number of protection pages as
rd_page_count * prot_length / block_size. rd_page_count is a u32 and
prot_length an int, so the multiplication is done in 32 bits and wraps
once rd_page_count reaches 2^29 with 8-byte protection information,
that is for a 2 TiB ramdisk. The protection sg tables are then
allocated much smaller than the device needs. A command whose
protection data starts inside the allocated range but extends past its
end makes sbc_dif_copy_prot() walk off the last scatterlist and
dereference the NULL returned by sg_next().

Do the multiplication in 64 bits. The quotient still fits in a u32
because prot_length is smaller than block_size.

Fixes: d7e8eb5d9216 ("target/rd: Add support for protection SGL setup + release")
Signed-off-by: Sanan Hasanov <sanan.hasanov@xxxxxxx>
---
drivers/target/target_core_rd.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/target/target_core_rd.c b/drivers/target/target_core_rd.c
index 2613342be..d7752fd34 100644
--- a/drivers/target/target_core_rd.c
+++ b/drivers/target/target_core_rd.c
@@ -253,7 +253,8 @@ static int rd_build_prot_space(struct rd_dev *rd_dev, int prot_length, int block
* (prot_length/block_size) + pad
* PGSZ canceled each other.
*/
- total_sg_needed = (rd_dev->rd_page_count * prot_length / block_size) + 1;
+ total_sg_needed = div_u64((u64)rd_dev->rd_page_count * prot_length,
+ block_size) + 1;

sg_tables = (total_sg_needed / max_sg_per_table) + 1;
sg_table = kvzalloc_objs(*sg_table, sg_tables);
--
2.48.1