Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 41df7b02 authored by Hiral Shah's avatar Hiral Shah Committed by Christoph Hellwig
Browse files

Fnic: Fnic Driver crashed with NULL pointer reference



When issuing I/O request, if the I/O completes before returning from
fnic_queuecommand(), we may be referencing scsi_cmnd structure that may
be freed by interrupt handler. Acquring IO lock would synchronize
fnic_queuecommand and interrupt handler.

- Increment fnic version from 1.6.0.15 to 1.6.0.16

Signed-off-by: default avatarHiral Shah <hishah@cisco.com>
Signed-off-by: default avatarSesidhar Baddela <sebaddel@cisco.com>
Signed-off-by: default avatarAnil Chintalapati <achintal@cisco.com>
Signed-off-by: default avatarChristoph Hellwig <hch@lst.de>
parent 0ee7b871
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -39,7 +39,7 @@

#define DRV_NAME		"fnic"
#define DRV_DESCRIPTION		"Cisco FCoE HBA Driver"
#define DRV_VERSION		"1.6.0.15"
#define DRV_VERSION		"1.6.0.16"
#define PFX			DRV_NAME ": "
#define DFX                     DRV_NAME "%d: "

+18 −3
Original line number Diff line number Diff line
@@ -421,9 +421,10 @@ static int fnic_queuecommand_lck(struct scsi_cmnd *sc, void (*done)(struct scsi_
	int ret;
	u64 cmd_trace;
	int sg_count = 0;
	unsigned long flags;
	unsigned long flags = 0;
	unsigned long ptr;
	struct fc_rport_priv *rdata;
	spinlock_t *io_lock = NULL;

	if (unlikely(fnic_chk_state_flags_locked(fnic, FNIC_FLAGS_IO_BLOCKED)))
		return SCSI_MLQUEUE_HOST_BUSY;
@@ -509,6 +510,13 @@ static int fnic_queuecommand_lck(struct scsi_cmnd *sc, void (*done)(struct scsi_
		}
	}

	/*
	* Will acquire lock defore setting to IO initialized.
	*/

	io_lock = fnic_io_lock_hash(fnic, sc);
	spin_lock_irqsave(io_lock, flags);

	/* initialize rest of io_req */
	io_req->port_id = rport->port_id;
	io_req->start_time = jiffies;
@@ -525,11 +533,9 @@ static int fnic_queuecommand_lck(struct scsi_cmnd *sc, void (*done)(struct scsi_
		 * In case another thread cancelled the request,
		 * refetch the pointer under the lock.
		 */
		spinlock_t *io_lock = fnic_io_lock_hash(fnic, sc);
		FNIC_TRACE(fnic_queuecommand, sc->device->host->host_no,
			  sc->request->tag, sc, 0, 0, 0,
			  (((u64)CMD_FLAGS(sc) << 32) | CMD_STATE(sc)));
		spin_lock_irqsave(io_lock, flags);
		io_req = (struct fnic_io_req *)CMD_SP(sc);
		CMD_SP(sc) = NULL;
		CMD_STATE(sc) = FNIC_IOREQ_CMD_COMPLETE;
@@ -538,6 +544,10 @@ static int fnic_queuecommand_lck(struct scsi_cmnd *sc, void (*done)(struct scsi_
			fnic_release_ioreq_buf(fnic, io_req, sc);
			mempool_free(io_req, fnic->io_req_pool);
		}
		atomic_dec(&fnic->in_flight);
		/* acquire host lock before returning to SCSI */
		spin_lock(lp->host->host_lock);
		return ret;
	} else {
		atomic64_inc(&fnic_stats->io_stats.active_ios);
		atomic64_inc(&fnic_stats->io_stats.num_ios);
@@ -559,6 +569,11 @@ static int fnic_queuecommand_lck(struct scsi_cmnd *sc, void (*done)(struct scsi_
		  sc->request->tag, sc, io_req,
		  sg_count, cmd_trace,
		  (((u64)CMD_FLAGS(sc) >> 32) | CMD_STATE(sc)));

	/* if only we issued IO, will we have the io lock */
	if (CMD_FLAGS(sc) & FNIC_IO_INITIALIZED)
		spin_unlock_irqrestore(io_lock, flags);

	atomic_dec(&fnic->in_flight);
	/* acquire host lock before returning to SCSI */
	spin_lock(lp->host->host_lock);