mirror of
https://github.com/SCST-project/scst.git
synced 2026-05-19 03:31:26 +00:00
scst_lib: Avoid integer overflows
This patch fixes the following kernel oops: [3696]: scst: scst_parse_cmd:826:Warning: expected transfer length 522240 for opcode 0x08 (handler vcdrom, target iscsi) doesn't match decoded value -2048 [3696]: scst_parse_cmd:828:Suspicious CDB: (h)___0__1__2__3__4__5__6__7__8__9__A__B__C__D__E__F 0: 08 1f ff ff ff 00 ...... BUG: unable to handle kernel paging request at ffff88283597f0c8 IP: [<ffffffff8135c3af>] sg_init_table+0x5f/0x90 Call Trace: [<ffffffffa021eb48>] sgv_pool_alloc+0x3b8/0xbf0 [scst] [<ffffffffa0204c16>] scst_alloc_space+0xb6/0x290 [scst] [<ffffffffa01e2d28>] scst_prepare_space+0x3b8/0x6e0 [scst] [<ffffffffa01ef4a5>] scst_process_active_cmd+0x455/0x7e0 [scst] [<ffffffffa01efb22>] scst_cmd_init_done+0x2f2/0x5c0 [scst] [<ffffffffa0156ac2>] scst_cmd_init_stage1_done.constprop.37+0x12/0x20 [iscsi_scst] [<ffffffffa015d9fa>] scsi_cmnd_start+0x25a/0x550 [iscsi_scst] [<ffffffffa015e4b8>] cmnd_rx_start+0x148/0x1a0 [iscsi_scst] [<ffffffffa0161598>] process_read_io+0x3b8/0x800 [iscsi_scst] [<ffffffffa0161aa7>] scst_do_job_rd+0xc7/0x220 [iscsi_scst] [<ffffffffa016208d>] istrd+0x16d/0x2e0 [iscsi_scst] [<ffffffff81075bad>] kthread+0xed/0x110 [<ffffffff816dd5bc>] ret_from_fork+0x7c/0xb0 and causes the following message to be reported instead: [11269]: scst: scst_generic_parse:7402:***WARNING***: bufflen 16777215, data_len 16777215 or out_bufflen 0 too large for device disk12 (block size 2048) scst_generic_parse:CDB: (h)___0__1__2__3__4__5__6__7__8__9__A__B__C__D__E__F 0: 08 1f ff ff ff 00 ...... Signed-off-by: Bart Van Assche <bvanassche@acm.org> git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@5464 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
@@ -7343,9 +7343,10 @@ EXPORT_SYMBOL_GPL(scst_calc_block_shift);
|
||||
#define shift_left_overflows(a, b) \
|
||||
({ \
|
||||
typeof(a) _minus_one = -1LL; \
|
||||
typeof(a) _plus_one = 1; \
|
||||
bool _a_is_signed = _minus_one < 0; \
|
||||
int _shift = sizeof(1ULL) * 8 - ((b) + _a_is_signed); \
|
||||
_shift < 0 || ((a) & ~((1ULL << _shift) - 1)) != 0; \
|
||||
int _shift = sizeof(a) * 8 - ((b) + _a_is_signed); \
|
||||
_shift < 0 || ((a) & ~((_plus_one << _shift) - 1)) != 0;\
|
||||
})
|
||||
|
||||
/**
|
||||
@@ -7370,6 +7371,20 @@ static inline int scst_generic_parse(struct scst_cmd *cmd, const int timeout[3])
|
||||
* No need for locks here, since *_detach() can not be
|
||||
* called, when there are existing commands.
|
||||
*/
|
||||
bool overflow = shift_left_overflows(cmd->bufflen, block_shift) ||
|
||||
shift_left_overflows(cmd->data_len, block_shift) ||
|
||||
shift_left_overflows(cmd->out_bufflen, block_shift);
|
||||
if (unlikely(overflow)) {
|
||||
PRINT_WARNING("bufflen %u, data_len %llu or out_bufflen"
|
||||
" %u too large for device %s (block size"
|
||||
" %u)", cmd->bufflen, cmd->data_len,
|
||||
cmd->out_bufflen, cmd->dev->virt_name,
|
||||
1 << block_shift);
|
||||
PRINT_BUFFER("CDB", cmd->cdb, cmd->cdb_len);
|
||||
scst_set_cmd_error(cmd, SCST_LOAD_SENSE(
|
||||
scst_sense_block_out_range_error));
|
||||
goto out;
|
||||
}
|
||||
cmd->bufflen = cmd->bufflen << block_shift;
|
||||
cmd->data_len = cmd->data_len << block_shift;
|
||||
cmd->out_bufflen = cmd->out_bufflen << block_shift;
|
||||
|
||||
Reference in New Issue
Block a user