From eebc66e8a8c9a296e2ffe7ce53cd7ba327699629 Mon Sep 17 00:00:00 2001 From: wenlxie Date: Thu, 15 Oct 2026 22:33:45 -0700 Subject: [PATCH] scst_lib: Reject invalid block lengths in READ CAPACITY responses scst_calc_block_shift() warns when the sector size is not a power of two but still returns its floor log2. When a backend returns a malformed READ CAPACITY response, scst_block_generic_dev_done() therefore changes the device geometry to an unrelated block size. For example, a block length of 809052976 produces 1 << 29 != 809052976 WARNING: ... at scst_calc_block_shift+0x9c/0xe0 [scst] and the device is switched to 536870912-byte blocks. Subsequent READ and WRITE commands then fail in PARSE until another READ CAPACITY restores the original block size. A zero block length is only logged, and the response is still returned to the initiator with GOOD status. Treat sector sizes below 512 bytes or not a power of two as invalid in scst_calc_block_shift() instead of warning. When a READ CAPACITY response reports a zero or invalid block length, keep the current geometry and complete the command with INTERNAL TARGET FAILURE sense, so that the initiator does not use the malformed capacity data. --- scst/src/scst_lib.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/scst/src/scst_lib.c b/scst/src/scst_lib.c index d69ed7b08..b7ed90d64 100644 --- a/scst/src/scst_lib.c +++ b/scst/src/scst_lib.c @@ -12444,13 +12444,11 @@ int scst_calc_block_shift(int sector_size) if (sector_size == 0) sector_size = 512; - block_shift = ilog2(sector_size); - WARN_ONCE(1 << block_shift != sector_size, "1 << %d != %d\n", - block_shift, sector_size); - - if (block_shift < 9) { + if (sector_size < 512 || !is_power_of_2(sector_size)) { PRINT_ERROR("Wrong sector size %d", sector_size); block_shift = -1; + } else { + block_shift = ilog2(sector_size); } TRACE_EXIT_RES(block_shift); @@ -12834,14 +12832,16 @@ int scst_block_generic_dev_done(struct scst_cmd *cmd, } sector_size = get_unaligned_be32(&buffer[sect_sz_off]); scst_put_buf_full(cmd, buffer); - if (sector_size != 0) { - sh = scst_calc_block_shift(sector_size); - set_block_shift(cmd, sh); - TRACE_DBG("block_shift %d", sh); - } else { - PRINT_ERROR("Sector size in %s response is 0", - cmd->op_name); + sh = sector_size ? scst_calc_block_shift(sector_size) : -1; + if (sh < 0) { + PRINT_ERROR("Invalid sector size %u in %s response", + sector_size, cmd->op_name); + scst_set_cmd_error(cmd, + SCST_LOAD_SENSE(scst_sense_internal_failure)); + goto out; } + set_block_shift(cmd, sh); + TRACE_DBG("block_shift %d", sh); } }