diff mbox series

[1/1] lpfc: Early return after marking final NLP_DROPPED flag in dev_loss_tmo

Message ID 20230908211852.37576-1-justintee8345@gmail.com (mailing list archive)
State Accepted
Commit 9c3034968ed0feeaf72e5b549b19c7767a1a04f2
Headers show
Series [1/1] lpfc: Early return after marking final NLP_DROPPED flag in dev_loss_tmo | expand

Commit Message

Justin Tee Sept. 8, 2023, 9:18 p.m. UTC
When a dev_loss_tmo event occurs, an ndlp lock is taken before checking
nlp_flag for NLP_DROPPED.  There is an attempt to restore the ndlp lock
when exiting the if statement, but the nlp_put kref could be the final
decrement causing a use-after-free memory access on a released ndlp object.

Instead of trying to reacquire the ndlp lock after checking nlp_flag, just
return after calling nlp_put.

Signed-off-by: Justin Tee <justin.tee@broadcom.com>
---
 drivers/scsi/lpfc/lpfc_hbadisc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

Comments

Ewan Milne Sept. 11, 2023, 6:43 p.m. UTC | #1
We have a very reproducible test case that hit the problem this fixes.

Reviewed-by: Ewan D. Milne <emilne@redhat.com>

On Fri, Sep 8, 2023 at 5:08 PM Justin Tee <justintee8345@gmail.com> wrote:
>
> When a dev_loss_tmo event occurs, an ndlp lock is taken before checking
> nlp_flag for NLP_DROPPED.  There is an attempt to restore the ndlp lock
> when exiting the if statement, but the nlp_put kref could be the final
> decrement causing a use-after-free memory access on a released ndlp object.
>
> Instead of trying to reacquire the ndlp lock after checking nlp_flag, just
> return after calling nlp_put.
>
> Signed-off-by: Justin Tee <justin.tee@broadcom.com>
> ---
>  drivers/scsi/lpfc/lpfc_hbadisc.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c
> index 51afb60859eb..674dd07aae72 100644
> --- a/drivers/scsi/lpfc/lpfc_hbadisc.c
> +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c
> @@ -203,7 +203,7 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport)
>                         ndlp->nlp_flag |= NLP_DROPPED;
>                         spin_unlock_irqrestore(&ndlp->lock, iflags);
>                         lpfc_nlp_put(ndlp);
> -                       spin_lock_irqsave(&ndlp->lock, iflags);
> +                       return;
>                 }
>
>                 spin_unlock_irqrestore(&ndlp->lock, iflags);
> --
> 2.38.0
>
diff mbox series

Patch

diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c
index 51afb60859eb..674dd07aae72 100644
--- a/drivers/scsi/lpfc/lpfc_hbadisc.c
+++ b/drivers/scsi/lpfc/lpfc_hbadisc.c
@@ -203,7 +203,7 @@  lpfc_dev_loss_tmo_callbk(struct fc_rport *rport)
 			ndlp->nlp_flag |= NLP_DROPPED;
 			spin_unlock_irqrestore(&ndlp->lock, iflags);
 			lpfc_nlp_put(ndlp);
-			spin_lock_irqsave(&ndlp->lock, iflags);
+			return;
 		}
 
 		spin_unlock_irqrestore(&ndlp->lock, iflags);