From 80be46ae7befbedc07eab27eb628d9a7bdac16bd Mon Sep 17 00:00:00 2001 From: Vladislav Bolkhovitin Date: Sat, 2 May 2015 01:01:15 +0000 Subject: [PATCH] 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 has been initialized. 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 [] dump_stack+0x19/0x1b [] warn_slowpath_common+0x7d/0xc0 [] warn_slowpath_fmt+0x46/0x50 [] scst_calc_block_shift+0x7f/0xb0 [scst] [] scst_block_generic_dev_done.part.39+0x6a/0x7d [scst] [] scst_block_generic_dev_done+0x34/0x40 [scst] [] dev_user_disk_done+0x15/0x20 [scst_user] [] scst_dev_done+0x49/0x150 [scst] [] scst_process_active_cmd+0x240/0x390 [scst] [] scst_process_redirect_cmd+0x121/0x1e0 [scst] [] scst_cmd_done_local+0x76/0x120 [scst] [] dev_user_process_reply_exec+0x8a/0x370 [scst_user] [] dev_user_process_reply+0x242/0x2e0 [scst_user] [] dev_user_reply_get_cmd.isra.17+0x100/0x2d0 [scst_user] [] dev_user_ioctl+0x157/0x428 [scst_user] [] do_vfs_ioctl+0x7a/0x2e0 [] SyS_ioctl+0x91/0xb0 [] system_call_fastpath+0x16/0x1b Avoid this by additionally checking cmd->completed Reported-by: Gal Rosen Reported-by: Abacus Liang Reported-by: Shahar Salzman git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@6196 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- scst/include/scst.h | 6 ++++++ scst/src/scst_lib.c | 5 ++--- scst/src/scst_targ.c | 2 +- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/scst/include/scst.h b/scst/include/scst.h index e9e8c5dc9..b0cd1e388 100644 --- a/scst/include/scst.h +++ b/scst/include/scst.h @@ -3958,6 +3958,12 @@ static inline bool scst_cmd_atomic(struct scst_cmd *cmd) return res; } +/* Returns TRUE if cmd completed with SAM_STAT_GOOD */ +static inline bool scst_cmd_completed_good(struct scst_cmd *cmd) +{ + return cmd->completed && (cmd->status == SAM_STAT_GOOD); +} + /* * Returns TRUE if cmd has been preliminary completed, i.e. completed or * aborted. diff --git a/scst/src/scst_lib.c b/scst/src/scst_lib.c index 3f38d6d60..79e1a9588 100644 --- a/scst/src/scst_lib.c +++ b/scst/src/scst_lib.c @@ -10933,7 +10933,6 @@ int scst_block_generic_dev_done(struct scst_cmd *cmd, void (*set_block_shift)(struct scst_cmd *cmd, int block_shift)) { int opcode = cmd->cdb[0]; - int status = cmd->status; int res = SCST_CMD_STATE_DEFAULT; TRACE_ENTRY(); @@ -10945,7 +10944,7 @@ int scst_block_generic_dev_done(struct scst_cmd *cmd, */ if (unlikely(opcode == READ_CAPACITY)) { - if ((status == SAM_STAT_GOOD) || (status == SAM_STAT_CONDITION_MET)) { + if (scst_cmd_completed_good(cmd)) { /* Always keep track of disk capacity */ int buffer_size, sector_size, sh; uint8_t *buffer; @@ -11003,7 +11002,7 @@ int scst_tape_generic_dev_done(struct scst_cmd *cmd, * therefore change them only if necessary */ - if (unlikely(cmd->status != SAM_STAT_GOOD)) + if (unlikely(!scst_cmd_completed_good(cmd))) goto out; switch (opcode) { diff --git a/scst/src/scst_targ.c b/scst/src/scst_targ.c index 6f97d960a..9dd794190 100644 --- a/scst/src/scst_targ.c +++ b/scst/src/scst_targ.c @@ -3590,7 +3590,7 @@ next: goto out; } - if (likely(cmd->status == SAM_STAT_GOOD)) { + if (likely(scst_cmd_completed_good(cmd))) { if (cmd->deferred_dif_read_check) { int rc = scst_dif_process_read(cmd); if (unlikely(rc != 0)) {