mirror of
https://github.com/SCST-project/scst.git
synced 2026-10-22 06:02:33 +00:00
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.
This commit is contained in:
+12
-12
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user