Skip to content

Commit b6ff8ca

Browse files
doug-gilbertmartinkpetersen
authored andcommitted
scsi: scsi_debug: Parser tables and code interaction
This patch is in response to a static analyser report from Dan Carpenter titled: "[bug report] scsi: scsi_debug: Add per_host_store option". This code may not clear the static analyzer reports, but may shed light on why they occur. Amongst other things this driver has a table driven SCSI command parser which also involves some C code. There are some invariants between the table entries and the corresponding C code (i.e. the resp_*() functions) that, if broken, may lead to a NULL dereference. And the report is valid, at least in the case of the PRE-FETCH command. Alas, that is not one of the cases that the static analyzer reported. In this particular corner case: when the fake_rw flag is set and the table entry for a "store"-accessing command does not have the required F_FAKE_RW flag set, do the following. Call BUG_ON() in the devip2sip() very close to a comment block explaining why it was called and how to fix it. checkpatch.pl complains about the BUG_ON() but there is no reasonable remedial action that can be taken at run time. This change allows the code reported by the static analyzer to be simplified. Comments were also added to the table flags (e.g. F_FAKE_RW) so developers who add commands might be more inclined to use them (properly). Link: https://lore.kernel.org/r/[email protected] Reported-by: Dan Carpenter <[email protected]> Signed-off-by: Douglas Gilbert <[email protected]> Signed-off-by: Martin K. Petersen <[email protected]>
1 parent 840e1b5 commit b6ff8ca

File tree

1 file changed

+63
-50
lines changed

1 file changed

+63
-50
lines changed

drivers/scsi/scsi_debug.c

Lines changed: 63 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -236,21 +236,23 @@ static const char *sdebug_version_date = "20200421";
236236
#define SDEBUG_CANQUEUE (SDEBUG_CANQUEUE_WORDS * BITS_PER_LONG)
237237
#define DEF_CMD_PER_LUN 255
238238

239-
#define F_D_IN 1
240-
#define F_D_OUT 2
239+
/* UA - Unit Attention; SA - Service Action; SSU - Start Stop Unit */
240+
#define F_D_IN 1 /* Data-in command (e.g. READ) */
241+
#define F_D_OUT 2 /* Data-out command (e.g. WRITE) */
241242
#define F_D_OUT_MAYBE 4 /* WRITE SAME, NDOB bit */
242243
#define F_D_UNKN 8
243-
#define F_RL_WLUN_OK 0x10
244-
#define F_SKIP_UA 0x20
245-
#define F_DELAY_OVERR 0x40
246-
#define F_SA_LOW 0x80 /* cdb byte 1, bits 4 to 0 */
247-
#define F_SA_HIGH 0x100 /* as used by variable length cdbs */
248-
#define F_INV_OP 0x200
249-
#define F_FAKE_RW 0x400
250-
#define F_M_ACCESS 0x800 /* media access */
251-
#define F_SSU_DELAY 0x1000
252-
#define F_SYNC_DELAY 0x2000
253-
244+
#define F_RL_WLUN_OK 0x10 /* allowed with REPORT LUNS W-LUN */
245+
#define F_SKIP_UA 0x20 /* bypass UAs (e.g. INQUIRY command) */
246+
#define F_DELAY_OVERR 0x40 /* for commands like INQUIRY */
247+
#define F_SA_LOW 0x80 /* SA is in cdb byte 1, bits 4 to 0 */
248+
#define F_SA_HIGH 0x100 /* SA is in cdb bytes 8 and 9 */
249+
#define F_INV_OP 0x200 /* invalid opcode (not supported) */
250+
#define F_FAKE_RW 0x400 /* bypass resp_*() when fake_rw set */
251+
#define F_M_ACCESS 0x800 /* media access, reacts to SSU state */
252+
#define F_SSU_DELAY 0x1000 /* SSU command delay (long-ish) */
253+
#define F_SYNC_DELAY 0x2000 /* SYNCHRONIZE CACHE delay */
254+
255+
/* Useful combinations of the above flags */
254256
#define FF_RESPOND (F_RL_WLUN_OK | F_SKIP_UA | F_DELAY_OVERR)
255257
#define FF_MEDIA_IO (F_M_ACCESS | F_FAKE_RW)
256258
#define FF_SA (F_SA_HIGH | F_SA_LOW)
@@ -607,25 +609,25 @@ static const struct opcode_info_t sync_cache_iarr[] = {
607609
};
608610

609611
static const struct opcode_info_t pre_fetch_iarr[] = {
610-
{0, 0x90, 0, F_SYNC_DELAY | F_M_ACCESS, resp_pre_fetch, NULL,
612+
{0, 0x90, 0, F_SYNC_DELAY | FF_MEDIA_IO, resp_pre_fetch, NULL,
611613
{16, 0x2, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
612614
0xff, 0xff, 0xff, 0xff, 0x3f, 0xc7} }, /* PRE-FETCH (16) */
613615
};
614616

615617
static const struct opcode_info_t zone_out_iarr[] = { /* ZONE OUT(16) */
616-
{0, 0x94, 0x1, F_SA_LOW, resp_close_zone, NULL,
618+
{0, 0x94, 0x1, F_SA_LOW | F_M_ACCESS, resp_close_zone, NULL,
617619
{16, 0x1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
618620
0xff, 0, 0, 0xff, 0xff, 0x1, 0xc7} }, /* CLOSE ZONE */
619-
{0, 0x94, 0x2, F_SA_LOW, resp_finish_zone, NULL,
621+
{0, 0x94, 0x2, F_SA_LOW | F_M_ACCESS, resp_finish_zone, NULL,
620622
{16, 0x2, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
621623
0xff, 0, 0, 0xff, 0xff, 0x1, 0xc7} }, /* FINISH ZONE */
622-
{0, 0x94, 0x4, F_SA_LOW, resp_rwp_zone, NULL,
624+
{0, 0x94, 0x4, F_SA_LOW | F_M_ACCESS, resp_rwp_zone, NULL,
623625
{16, 0x4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
624626
0xff, 0, 0, 0xff, 0xff, 0x1, 0xc7} }, /* RESET WRITE POINTER */
625627
};
626628

627629
static const struct opcode_info_t zone_in_iarr[] = { /* ZONE IN(16) */
628-
{0, 0x95, 0x6, F_SA_LOW | F_D_IN, NULL, NULL,
630+
{0, 0x95, 0x6, F_SA_LOW | F_D_IN | F_M_ACCESS, NULL, NULL,
629631
{16, 0x6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
630632
0xff, 0xff, 0xff, 0xff, 0x3f, 0xc7} }, /* REPORT ZONES */
631633
};
@@ -726,17 +728,17 @@ static const struct opcode_info_t opcode_info_arr[SDEB_I_LAST_ELEM_P1 + 1] = {
726728
{0, 0x89, 0, F_D_OUT | FF_MEDIA_IO, resp_comp_write, NULL,
727729
{16, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0, 0,
728730
0, 0xff, 0x3f, 0xc7} }, /* COMPARE AND WRITE */
729-
{ARRAY_SIZE(pre_fetch_iarr), 0x34, 0, F_SYNC_DELAY | F_M_ACCESS,
731+
{ARRAY_SIZE(pre_fetch_iarr), 0x34, 0, F_SYNC_DELAY | FF_MEDIA_IO,
730732
resp_pre_fetch, pre_fetch_iarr,
731733
{10, 0x2, 0xff, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xff, 0xc7, 0, 0,
732734
0, 0, 0, 0} }, /* PRE-FETCH (10) */
733735

734736
/* 30 */
735-
{ARRAY_SIZE(zone_out_iarr), 0x94, 0x3, F_SA_LOW,
737+
{ARRAY_SIZE(zone_out_iarr), 0x94, 0x3, F_SA_LOW | F_M_ACCESS,
736738
resp_open_zone, zone_out_iarr, /* ZONE_OUT(16), OPEN ZONE) */
737739
{16, 0x3 /* SA */, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
738740
0xff, 0xff, 0x0, 0x0, 0xff, 0xff, 0x1, 0xc7} },
739-
{ARRAY_SIZE(zone_in_iarr), 0x95, 0x0, F_SA_LOW | F_D_IN,
741+
{ARRAY_SIZE(zone_in_iarr), 0x95, 0x0, F_SA_LOW | F_M_ACCESS,
740742
resp_report_zones, zone_in_iarr, /* ZONE_IN(16), REPORT ZONES) */
741743
{16, 0x0 /* SA */, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
742744
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xc7} },
@@ -2875,10 +2877,20 @@ static inline int check_device_access_params
28752877
return 0;
28762878
}
28772879

2878-
static inline struct sdeb_store_info *devip2sip(struct sdebug_dev_info *devip)
2880+
/*
2881+
* Note: if BUG_ON() fires it usually indicates a problem with the parser
2882+
* tables. Perhaps a missing F_FAKE_RW or FF_MEDIA_IO flag. Response functions
2883+
* that access any of the "stores" in struct sdeb_store_info should call this
2884+
* function with bug_if_fake_rw set to true.
2885+
*/
2886+
static inline struct sdeb_store_info *devip2sip(struct sdebug_dev_info *devip,
2887+
bool bug_if_fake_rw)
28792888
{
2880-
return sdebug_fake_rw ?
2881-
NULL : xa_load(per_store_ap, devip->sdbg_host->si_idx);
2889+
if (sdebug_fake_rw) {
2890+
BUG_ON(bug_if_fake_rw); /* See note above */
2891+
return NULL;
2892+
}
2893+
return xa_load(per_store_ap, devip->sdbg_host->si_idx);
28822894
}
28832895

28842896
/* Returns number of bytes copied or -1 if error. */
@@ -3015,7 +3027,7 @@ static void dif_copy_prot(struct scsi_cmnd *scp, sector_t sector,
30153027
size_t resid;
30163028
void *paddr;
30173029
struct sdeb_store_info *sip = devip2sip((struct sdebug_dev_info *)
3018-
scp->device->hostdata);
3030+
scp->device->hostdata, true);
30193031
struct t10_pi_tuple *dif_storep = sip->dif_storep;
30203032
const void *dif_store_end = dif_storep + sdebug_store_sectors;
30213033
struct sg_mapping_iter miter;
@@ -3061,7 +3073,7 @@ static int prot_verify_read(struct scsi_cmnd *scp, sector_t start_sec,
30613073
unsigned int i;
30623074
sector_t sector;
30633075
struct sdeb_store_info *sip = devip2sip((struct sdebug_dev_info *)
3064-
scp->device->hostdata);
3076+
scp->device->hostdata, true);
30653077
struct t10_pi_tuple *sdt;
30663078

30673079
for (i = 0; i < sectors; i++, ei_lba++) {
@@ -3094,7 +3106,7 @@ static int resp_read_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
30943106
u32 ei_lba;
30953107
int ret;
30963108
u64 lba;
3097-
struct sdeb_store_info *sip = devip2sip(devip);
3109+
struct sdeb_store_info *sip = devip2sip(devip, true);
30983110
rwlock_t *macc_lckp = sip ? &sip->macc_lck : &sdeb_fake_rw_lck;
30993111
u8 *cmd = scp->cmnd;
31003112
struct sdebug_queued_cmd *sqcp;
@@ -3403,8 +3415,8 @@ static int resp_write_dt0(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
34033415
u32 ei_lba;
34043416
int ret;
34053417
u64 lba;
3406-
struct sdeb_store_info *sip = devip2sip(devip);
3407-
rwlock_t *macc_lckp = sip ? &sip->macc_lck : &sdeb_fake_rw_lck;
3418+
struct sdeb_store_info *sip = devip2sip(devip, true);
3419+
rwlock_t *macc_lckp = &sip->macc_lck;
34083420
u8 *cmd = scp->cmnd;
34093421

34103422
switch (cmd[0]) {
@@ -3524,8 +3536,8 @@ static int resp_write_scat(struct scsi_cmnd *scp,
35243536
u8 *cmd = scp->cmnd;
35253537
u8 *lrdp = NULL;
35263538
u8 *up;
3527-
struct sdeb_store_info *sip = devip2sip(devip);
3528-
rwlock_t *macc_lckp = sip ? &sip->macc_lck : &sdeb_fake_rw_lck;
3539+
struct sdeb_store_info *sip = devip2sip(devip, true);
3540+
rwlock_t *macc_lckp = &sip->macc_lck;
35293541
u8 wrprotect;
35303542
u16 lbdof, num_lrd, k;
35313543
u32 num, num_by, bt_len, lbdof_blen, sg_off, cum_lb;
@@ -3695,8 +3707,8 @@ static int resp_write_same(struct scsi_cmnd *scp, u64 lba, u32 num,
36953707
u32 lb_size = sdebug_sector_size;
36963708
int ret;
36973709
struct sdeb_store_info *sip = devip2sip((struct sdebug_dev_info *)
3698-
scp->device->hostdata);
3699-
rwlock_t *macc_lckp = sip ? &sip->macc_lck : &sdeb_fake_rw_lck;
3710+
scp->device->hostdata, true);
3711+
rwlock_t *macc_lckp = &sip->macc_lck;
37003712
u8 *fs1p;
37013713
u8 *fsp;
37023714

@@ -3855,8 +3867,8 @@ static int resp_comp_write(struct scsi_cmnd *scp,
38553867
{
38563868
u8 *cmd = scp->cmnd;
38573869
u8 *arr;
3858-
struct sdeb_store_info *sip = devip2sip(devip);
3859-
rwlock_t *macc_lckp = sip ? &sip->macc_lck : &sdeb_fake_rw_lck;
3870+
struct sdeb_store_info *sip = devip2sip(devip, true);
3871+
rwlock_t *macc_lckp = &sip->macc_lck;
38603872
u64 lba;
38613873
u32 dnum;
38623874
u32 lb_size = sdebug_sector_size;
@@ -3922,8 +3934,8 @@ static int resp_unmap(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
39223934
{
39233935
unsigned char *buf;
39243936
struct unmap_block_desc *desc;
3925-
struct sdeb_store_info *sip = devip2sip(devip);
3926-
rwlock_t *macc_lckp = sip ? &sip->macc_lck : &sdeb_fake_rw_lck;
3937+
struct sdeb_store_info *sip = devip2sip(devip, true);
3938+
rwlock_t *macc_lckp = &sip->macc_lck;
39273939
unsigned int i, payload_len, descriptors;
39283940
int ret;
39293941

@@ -3980,7 +3992,6 @@ static int resp_get_lba_status(struct scsi_cmnd *scp,
39803992
struct sdebug_dev_info *devip)
39813993
{
39823994
u8 *cmd = scp->cmnd;
3983-
struct sdeb_store_info *sip = devip2sip(devip);
39843995
u64 lba;
39853996
u32 alloc_len, mapped, num;
39863997
int ret;
@@ -3996,9 +4007,11 @@ static int resp_get_lba_status(struct scsi_cmnd *scp,
39964007
if (ret)
39974008
return ret;
39984009

3999-
if (scsi_debug_lbp())
4010+
if (scsi_debug_lbp()) {
4011+
struct sdeb_store_info *sip = devip2sip(devip, true);
4012+
40004013
mapped = map_state(sip, lba, &num);
4001-
else {
4014+
} else {
40024015
mapped = 1;
40034016
/* following just in case virtual_gb changed */
40044017
sdebug_capacity = get_sdebug_capacity();
@@ -4058,9 +4071,9 @@ static int resp_pre_fetch(struct scsi_cmnd *scp,
40584071
u64 block, rest = 0;
40594072
u32 nblks;
40604073
u8 *cmd = scp->cmnd;
4061-
struct sdeb_store_info *sip = devip2sip(devip);
4062-
rwlock_t *macc_lckp = sip ? &sip->macc_lck : &sdeb_fake_rw_lck;
4063-
u8 *fsp = sip ? sip->storep : NULL;
4074+
struct sdeb_store_info *sip = devip2sip(devip, true);
4075+
rwlock_t *macc_lckp = &sip->macc_lck;
4076+
u8 *fsp = sip->storep;
40644077

40654078
if (cmd[0] == PRE_FETCH) { /* 10 byte cdb */
40664079
lba = get_unaligned_be32(cmd + 2);
@@ -4204,8 +4217,8 @@ static int resp_verify(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
42044217
u64 lba;
42054218
u8 *arr;
42064219
u8 *cmd = scp->cmnd;
4207-
struct sdeb_store_info *sip = devip2sip(devip);
4208-
rwlock_t *macc_lckp = sip ? &sip->macc_lck : &sdeb_fake_rw_lck;
4220+
struct sdeb_store_info *sip = devip2sip(devip, true);
4221+
rwlock_t *macc_lckp = &sip->macc_lck;
42094222

42104223
bytchk = (cmd[1] >> 1) & 0x3;
42114224
if (bytchk == 0) {
@@ -4283,7 +4296,7 @@ static int resp_report_zones(struct scsi_cmnd *scp,
42834296
u8 *arr = NULL, *desc;
42844297
u8 *cmd = scp->cmnd;
42854298
struct sdeb_zone_state *zsp;
4286-
struct sdeb_store_info *sip = devip2sip(devip);
4299+
struct sdeb_store_info *sip = devip2sip(devip, false);
42874300
rwlock_t *macc_lckp = sip ? &sip->macc_lck : &sdeb_fake_rw_lck;
42884301

42894302
if (!sdebug_dev_is_zoned(devip)) {
@@ -4424,7 +4437,7 @@ static int resp_open_zone(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
44244437
u8 *cmd = scp->cmnd;
44254438
struct sdeb_zone_state *zsp;
44264439
bool all = cmd[14] & 0x01;
4427-
struct sdeb_store_info *sip = devip2sip(devip);
4440+
struct sdeb_store_info *sip = devip2sip(devip, false);
44284441
rwlock_t *macc_lckp = sip ? &sip->macc_lck : &sdeb_fake_rw_lck;
44294442

44304443
if (!sdebug_dev_is_zoned(devip)) {
@@ -4503,7 +4516,7 @@ static int resp_close_zone(struct scsi_cmnd *scp,
45034516
u8 *cmd = scp->cmnd;
45044517
struct sdeb_zone_state *zsp;
45054518
bool all = cmd[14] & 0x01;
4506-
struct sdeb_store_info *sip = devip2sip(devip);
4519+
struct sdeb_store_info *sip = devip2sip(devip, false);
45074520
rwlock_t *macc_lckp = sip ? &sip->macc_lck : &sdeb_fake_rw_lck;
45084521

45094522
if (!sdebug_dev_is_zoned(devip)) {
@@ -4576,7 +4589,7 @@ static int resp_finish_zone(struct scsi_cmnd *scp,
45764589
u64 z_id;
45774590
u8 *cmd = scp->cmnd;
45784591
bool all = cmd[14] & 0x01;
4579-
struct sdeb_store_info *sip = devip2sip(devip);
4592+
struct sdeb_store_info *sip = devip2sip(devip, false);
45804593
rwlock_t *macc_lckp = sip ? &sip->macc_lck : &sdeb_fake_rw_lck;
45814594

45824595
if (!sdebug_dev_is_zoned(devip)) {
@@ -4652,7 +4665,7 @@ static int resp_rwp_zone(struct scsi_cmnd *scp, struct sdebug_dev_info *devip)
46524665
u64 z_id;
46534666
u8 *cmd = scp->cmnd;
46544667
bool all = cmd[14] & 0x01;
4655-
struct sdeb_store_info *sip = devip2sip(devip);
4668+
struct sdeb_store_info *sip = devip2sip(devip, false);
46564669
rwlock_t *macc_lckp = sip ? &sip->macc_lck : &sdeb_fake_rw_lck;
46574670

46584671
if (!sdebug_dev_is_zoned(devip)) {

0 commit comments

Comments
 (0)