__adpt_reset() invokes adpt_hba_reset(), which can free "pHba" on error paths and return an negative error code in those situations. The problem is that "pHba" is from the global pointer "cmd->device->host->hostdata[0]", regardless of the possible free of "pHba", that original global pointer is never nullified and thus may become a dangling pointer and be dereferenced later, potentially causing a use-after-free. Fix the issue by nullifying "cmd->device->host->hostdata[0]" if adpt_hba_reset() returns a negative error code to __adpt_reset(), which indicates the free of "pHba". Also add a NULL check before any dereference of "pHba", or the aliased global pointer. Note that the similar NULL check already exists at other places, like in adpt_queue_lck(). Signed-off-by: Hang Zhang <zh.nvgt@xxxxxxxxx> --- drivers/scsi/dpt_i2o.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c index 2e9155ba7408..9827517a1898 100644 --- a/drivers/scsi/dpt_i2o.c +++ b/drivers/scsi/dpt_i2o.c @@ -753,6 +753,9 @@ static int __adpt_reset(struct scsi_cmnd* cmd) char name[32]; pHba = (adpt_hba*)cmd->device->host->hostdata[0]; + if (!pHba) { + return FAILED; + } strncpy(name, pHba->name, sizeof(name)); printk(KERN_WARNING"%s: Hba Reset: scsi id %d: tid: %d\n", name, cmd->device->channel, pHba->channel[cmd->device->channel].tid); rcode = adpt_hba_reset(pHba); @@ -760,6 +763,7 @@ static int __adpt_reset(struct scsi_cmnd* cmd) printk(KERN_WARNING"%s: HBA reset complete\n", name); return SUCCESS; } else { + cmd->device->host->hostdata[0] = NULL; printk(KERN_WARNING"%s: HBA reset failed (%x)\n", name, rcode); return FAILED; } -- 2.39.0