scst_targ: Avoid incorrect block size changes

The scst_block_generic_dev_done() function parses the READ CAPACITY
response without checking whether the response buffer contains
valid data. This can lead to incorrect block size changes and also
to the following kernel warning:

WARNING: at scst/src/scst_lib.c:7353 scst_calc_block_shift+0x7f/0xb0 [scst]()
1 << 23 != 12595456
 [<ffffffff816071e3>] dump_stack+0x19/0x1b
 [<ffffffff8106e23d>] warn_slowpath_common+0x7d/0xc0
 [<ffffffff8106e336>] warn_slowpath_fmt+0x46/0x50
 [<ffffffffa0712e2f>] scst_calc_block_shift+0x7f/0xb0 [scst]
 [<ffffffffa072dbd7>] scst_block_generic_dev_done.part.39+0x6a/0x7d [scst]
 [<ffffffffa07162a4>] scst_block_generic_dev_done+0x34/0x40 [scst]
 [<ffffffffa0066205>] dev_user_disk_done+0x15/0x20 [scst_user]
 [<ffffffffa070c119>] scst_dev_done+0x49/0x150 [scst]
 [<ffffffffa070e1a0>] scst_process_active_cmd+0x240/0x390 [scst]
 [<ffffffffa070e7e1>] scst_process_redirect_cmd+0x121/0x1e0 [scst]
 [<ffffffffa070e916>] scst_cmd_done_local+0x76/0x120 [scst]
 [<ffffffffa006843a>] dev_user_process_reply_exec+0x8a/0x370 [scst_user]
 [<ffffffffa00699e2>] dev_user_process_reply+0x242/0x2e0 [scst_user]
 [<ffffffffa0069b80>] dev_user_reply_get_cmd.isra.17+0x100/0x2d0 [scst_user]
 [<ffffffffa0069ea7>] dev_user_ioctl+0x157/0x428 [scst_user]
 [<ffffffff811d999a>] do_vfs_ioctl+0x7a/0x2e0
 [<ffffffff811d9c91>] SyS_ioctl+0x91/0xb0
 [<ffffffff8161b269>] system_call_fastpath+0x16/0x1b

Avoid this by calling dev_done() handlers only for completed commands
and not for aborted commands.

Reported-by: Gal Rosen <galr@storone.com>
Reported-by: Abacus Liang <abacusl@hotmail.com>
Reported-by: Shahar Salzman <shahar.salzman@kaminario.com>
Signed-off-by: Bart Van Assche <bart.vanassche@sandisk.com>
This commit is contained in:
Bart Van Assche
2015-04-13 09:29:27 +02:00
parent 85a3c5691d
commit acacb09327
2 changed files with 9 additions and 2 deletions

View File

@@ -8264,6 +8264,9 @@ int scst_block_generic_dev_done(struct scst_cmd *cmd,
TRACE_ENTRY();
/* Do not call this function for aborted commands. */
WARN_ON_ONCE(!cmd->completed);
if (unlikely(opcode == READ_CAPACITY)) {
if ((status == SAM_STAT_GOOD) || (status == SAM_STAT_CONDITION_MET)) {
/* Always keep track of disk capacity */
@@ -8314,6 +8317,9 @@ int scst_tape_generic_dev_done(struct scst_cmd *cmd,
TRACE_ENTRY();
/* Do not call this function for aborted commands. */
WARN_ON_ONCE(!cmd->completed);
if (unlikely(cmd->status != SAM_STAT_GOOD))
goto out;

View File

@@ -3762,8 +3762,9 @@ static int scst_dev_done(struct scst_cmd *cmd)
state = SCST_CMD_STATE_PRE_XMIT_RESP1;
if (likely((cmd->op_flags & SCST_FULLY_LOCAL_CMD) == 0) &&
likely(devt->dev_done != NULL)) {
if (likely(cmd->completed &&
!(cmd->op_flags & SCST_FULLY_LOCAL_CMD) &&
devt->dev_done)) {
int rc;
if (unlikely(!devt->dev_done_atomic &&