Skip to content

Commit

Permalink
scsi: qla2xxx: Warn if done() or free() are called on an already free…
Browse files Browse the repository at this point in the history
…d srb

[ Upstream commit c0014f9 ]

Emit a warning when ->done or ->free are called on an already freed
srb. There is a hidden use-after-free bug in the driver which corrupts
the srb memory pool which originates from the cleanup callbacks.

An extensive search didn't bring any lights on the real problem. The
initial fix was to set both pointers to NULL and try to catch invalid
accesses. But instead the memory corruption was gone and the driver
didn't crash. Since not all calling places check for NULL pointer, add
explicitly default handlers. With this we workaround the memory
corruption and add a debug help.

Link: https://lore.kernel.org/r/20200908081516.8561-2-dwagner@suse.de
Reviewed-by: Martin Wilck <mwilck@suse.com>
Reviewed-by: Arun Easi <aeasi@marvell.com>
Signed-off-by: Daniel Wagner <dwagner@suse.de>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
  • Loading branch information
igaw authored and gregkh committed Oct 29, 2020
1 parent 0bb4a0b commit d399015
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 0 deletions.
10 changes: 10 additions & 0 deletions drivers/scsi/qla2xxx/qla_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,16 @@ void qla2x00_sp_free(srb_t *sp)
qla2x00_rel_sp(sp);
}

void qla2xxx_rel_done_warning(srb_t *sp, int res)
{
WARN_ONCE(1, "Calling done() of an already freed srb %p object\n", sp);
}

void qla2xxx_rel_free_warning(srb_t *sp)
{
WARN_ONCE(1, "Calling free() of an already freed srb %p object\n", sp);
}

/* Asynchronous Login/Logout Routines -------------------------------------- */

unsigned long
Expand Down
5 changes: 5 additions & 0 deletions drivers/scsi/qla2xxx/qla_inline.h
Original file line number Diff line number Diff line change
Expand Up @@ -183,10 +183,15 @@ qla2xxx_get_qpair_sp(scsi_qla_host_t *vha, struct qla_qpair *qpair,
return sp;
}

void qla2xxx_rel_done_warning(srb_t *sp, int res);
void qla2xxx_rel_free_warning(srb_t *sp);

static inline void
qla2xxx_rel_qpair_sp(struct qla_qpair *qpair, srb_t *sp)
{
sp->qpair = NULL;
sp->done = qla2xxx_rel_done_warning;
sp->free = qla2xxx_rel_free_warning;
mempool_free(sp, qpair->srb_mempool);
QLA_QPAIR_MARK_NOT_BUSY(qpair);
}
Expand Down

0 comments on commit d399015

Please sign in to comment.