2020-08-31 16:20:45

by Daniel Wagner

[permalink] [raw]
Subject: [PATCH v2 1/4] qla2xxx: Warn if done() or free() are called on an already freed srb

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. By
explicitly resetting the callbacks to NULL, we workaround the memory
corruption.

An extensive search didn't bring any lights on the real problem. The
initial idea 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.

Signed-off-by: Daniel Wagner <[email protected]>
---
drivers/scsi/qla2xxx/qla_init.c | 10 ++++++++++
drivers/scsi/qla2xxx/qla_inline.h | 5 +++++
2 files changed, 15 insertions(+)

diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 57a2d76aa691..9e9360a4aeb5 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -63,6 +63,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 object\n");
+}
+
+void qla2xxx_rel_free_warning(srb_t *sp)
+{
+ WARN_ONCE(1, "Calling free() of an already freed srb object\n");
+}
+
/* Asynchronous Login/Logout Routines -------------------------------------- */

unsigned long
diff --git a/drivers/scsi/qla2xxx/qla_inline.h b/drivers/scsi/qla2xxx/qla_inline.h
index 861dc522723c..2aa6f81f87c4 100644
--- a/drivers/scsi/qla2xxx/qla_inline.h
+++ b/drivers/scsi/qla2xxx/qla_inline.h
@@ -207,10 +207,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);
}
--
2.16.4


2020-09-08 06:45:48

by Arun Easi

[permalink] [raw]
Subject: Re: [PATCH v2 1/4] qla2xxx: Warn if done() or free() are called on an already freed srb

On Mon, 31 Aug 2020, 9:18am, Daniel Wagner wrote:

>
> 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. By
> explicitly resetting the callbacks to NULL, we workaround the memory
> corruption.
>
> An extensive search didn't bring any lights on the real problem. The
> initial idea 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.
>
> Signed-off-by: Daniel Wagner <[email protected]>
> ---
> drivers/scsi/qla2xxx/qla_init.c | 10 ++++++++++
> drivers/scsi/qla2xxx/qla_inline.h | 5 +++++
> 2 files changed, 15 insertions(+)
>
> diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
> index 57a2d76aa691..9e9360a4aeb5 100644
> --- a/drivers/scsi/qla2xxx/qla_init.c
> +++ b/drivers/scsi/qla2xxx/qla_init.c
> @@ -63,6 +63,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 object\n");
> +}
> +
> +void qla2xxx_rel_free_warning(srb_t *sp)
> +{
> + WARN_ONCE(1, "Calling free() of an already freed srb object\n");
> +}

Please print the address of srb too for the above two functions.
With that, looks good.

Regards,
-Arun