diff mbox series

[v3,1/1] bus: mhi: host: Fix up null pointer access in mhi_irq_handler

Message ID 1658459838-30802-1-git-send-email-quic_qianyu@quicinc.com (mailing list archive)
State Not Applicable
Headers show
Series [v3,1/1] bus: mhi: host: Fix up null pointer access in mhi_irq_handler | expand

Commit Message

Qiang Yu July 22, 2022, 3:17 a.m. UTC
The irq handler for a shared IRQ ought to be prepared for running
even now it's being freed. So let's check the pointer used by
mhi_irq_handler to avoid null pointer access since it is probably
released before freeing IRQ.

Signed-off-by: Qiang Yu <quic_qianyu@quicinc.com>
---
v2->v3: add comments
v1->v2: change dev_err to dev_dbg

 drivers/bus/mhi/host/main.c | 19 ++++++++++++++++---
 1 file changed, 16 insertions(+), 3 deletions(-)

Comments

Manivannan Sadhasivam July 26, 2022, 8:05 a.m. UTC | #1
+ath11k, Kalle

On Fri, Jul 22, 2022 at 11:17:18AM +0800, Qiang Yu wrote:
> The irq handler for a shared IRQ ought to be prepared for running
> even now it's being freed. So let's check the pointer used by
> mhi_irq_handler to avoid null pointer access since it is probably
> released before freeing IRQ.
> 
> Signed-off-by: Qiang Yu <quic_qianyu@quicinc.com>

Reviewed-by: Manivannan Sadhasivam <mani@kernel.org>

Thanks,
Mani

> ---
> v2->v3: add comments
> v1->v2: change dev_err to dev_dbg
> 
>  drivers/bus/mhi/host/main.c | 19 ++++++++++++++++---
>  1 file changed, 16 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/bus/mhi/host/main.c b/drivers/bus/mhi/host/main.c
> index f3aef77a..df0fbfe 100644
> --- a/drivers/bus/mhi/host/main.c
> +++ b/drivers/bus/mhi/host/main.c
> @@ -430,12 +430,25 @@ irqreturn_t mhi_irq_handler(int irq_number, void *dev)
>  {
>  	struct mhi_event *mhi_event = dev;
>  	struct mhi_controller *mhi_cntrl = mhi_event->mhi_cntrl;
> -	struct mhi_event_ctxt *er_ctxt =
> -		&mhi_cntrl->mhi_ctxt->er_ctxt[mhi_event->er_index];
> +	struct mhi_event_ctxt *er_ctxt;
>  	struct mhi_ring *ev_ring = &mhi_event->ring;
> -	dma_addr_t ptr = le64_to_cpu(er_ctxt->rp);
> +	dma_addr_t ptr;
>  	void *dev_rp;
>  
> +	/*
> +	 * If CONFIG_DEBUG_SHIRQ is set, the IRQ handler will get invoked during __free_irq()
> +	 * and by that time mhi_ctxt() would've freed. So check for the existence of mhi_ctxt
> +	 * before handling the IRQs.
> +	 */
> +	if (!mhi_cntrl->mhi_ctxt) {
> +		dev_dbg(&mhi_cntrl->mhi_dev->dev,
> +			"mhi_ctxt has been freed\n");
> +		return IRQ_HANDLED;
> +	}
> +
> +	er_ctxt = &mhi_cntrl->mhi_ctxt->er_ctxt[mhi_event->er_index];
> +	ptr = le64_to_cpu(er_ctxt->rp);
> +
>  	if (!is_valid_ring_ptr(ev_ring, ptr)) {
>  		dev_err(&mhi_cntrl->mhi_dev->dev,
>  			"Event ring rp points outside of the event ring\n");
> -- 
> Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project.
>
Manivannan Sadhasivam July 26, 2022, 8:06 a.m. UTC | #2
+ath11k, Kalle

On Fri, Jul 22, 2022 at 11:17:18AM +0800, Qiang Yu wrote:
> The irq handler for a shared IRQ ought to be prepared for running
> even now it's being freed. So let's check the pointer used by
> mhi_irq_handler to avoid null pointer access since it is probably
> released before freeing IRQ.
> 
> Signed-off-by: Qiang Yu <quic_qianyu@quicinc.com>

Reviewed-by: Manivannan Sadhasivam <mani@kernel.org>

Thanks,
Mani

> ---
> v2->v3: add comments
> v1->v2: change dev_err to dev_dbg
> 
>  drivers/bus/mhi/host/main.c | 19 ++++++++++++++++---
>  1 file changed, 16 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/bus/mhi/host/main.c b/drivers/bus/mhi/host/main.c
> index f3aef77a..df0fbfe 100644
> --- a/drivers/bus/mhi/host/main.c
> +++ b/drivers/bus/mhi/host/main.c
> @@ -430,12 +430,25 @@ irqreturn_t mhi_irq_handler(int irq_number, void *dev)
>  {
>  	struct mhi_event *mhi_event = dev;
>  	struct mhi_controller *mhi_cntrl = mhi_event->mhi_cntrl;
> -	struct mhi_event_ctxt *er_ctxt =
> -		&mhi_cntrl->mhi_ctxt->er_ctxt[mhi_event->er_index];
> +	struct mhi_event_ctxt *er_ctxt;
>  	struct mhi_ring *ev_ring = &mhi_event->ring;
> -	dma_addr_t ptr = le64_to_cpu(er_ctxt->rp);
> +	dma_addr_t ptr;
>  	void *dev_rp;
>  
> +	/*
> +	 * If CONFIG_DEBUG_SHIRQ is set, the IRQ handler will get invoked during __free_irq()
> +	 * and by that time mhi_ctxt() would've freed. So check for the existence of mhi_ctxt
> +	 * before handling the IRQs.
> +	 */
> +	if (!mhi_cntrl->mhi_ctxt) {
> +		dev_dbg(&mhi_cntrl->mhi_dev->dev,
> +			"mhi_ctxt has been freed\n");
> +		return IRQ_HANDLED;
> +	}
> +
> +	er_ctxt = &mhi_cntrl->mhi_ctxt->er_ctxt[mhi_event->er_index];
> +	ptr = le64_to_cpu(er_ctxt->rp);
> +
>  	if (!is_valid_ring_ptr(ev_ring, ptr)) {
>  		dev_err(&mhi_cntrl->mhi_dev->dev,
>  			"Event ring rp points outside of the event ring\n");
> -- 
> Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project.
>
Kalle Valo July 26, 2022, 5:53 p.m. UTC | #3
Manivannan Sadhasivam <mani@kernel.org> writes:

> +ath11k, Kalle
>
> On Fri, Jul 22, 2022 at 11:17:18AM +0800, Qiang Yu wrote:
>> The irq handler for a shared IRQ ought to be prepared for running
>> even now it's being freed. So let's check the pointer used by
>> mhi_irq_handler to avoid null pointer access since it is probably
>> released before freeing IRQ.
>> 
>> Signed-off-by: Qiang Yu <quic_qianyu@quicinc.com>
>
> Reviewed-by: Manivannan Sadhasivam <mani@kernel.org>

This fixes the crash and my regression tests pass now, thanks. But
please see my question below.

Tested-by: Kalle Valo <kvalo@kernel.org>

>> +	/*
>> +	 * If CONFIG_DEBUG_SHIRQ is set, the IRQ handler will get invoked during __free_irq()
>> +	 * and by that time mhi_ctxt() would've freed. So check for the existence of mhi_ctxt
>> +	 * before handling the IRQs.
>> +	 */
>> +	if (!mhi_cntrl->mhi_ctxt) {
>> +		dev_dbg(&mhi_cntrl->mhi_dev->dev,
>> +			"mhi_ctxt has been freed\n");
>> +		return IRQ_HANDLED;
>> +	}

I don't see any protection accessing mhi_cntrl->mhi_ctxt, is this really
free of race conditions?
Manivannan Sadhasivam July 29, 2022, 2:22 p.m. UTC | #4
On Tue, Jul 26, 2022 at 08:53:58PM +0300, Kalle Valo wrote:
> Manivannan Sadhasivam <mani@kernel.org> writes:
> 
> > +ath11k, Kalle
> >
> > On Fri, Jul 22, 2022 at 11:17:18AM +0800, Qiang Yu wrote:
> >> The irq handler for a shared IRQ ought to be prepared for running
> >> even now it's being freed. So let's check the pointer used by
> >> mhi_irq_handler to avoid null pointer access since it is probably
> >> released before freeing IRQ.
> >> 
> >> Signed-off-by: Qiang Yu <quic_qianyu@quicinc.com>
> >
> > Reviewed-by: Manivannan Sadhasivam <mani@kernel.org>
> 
> This fixes the crash and my regression tests pass now, thanks. But
> please see my question below.
> 
> Tested-by: Kalle Valo <kvalo@kernel.org>
> 

Thanks Kalle!

> >> +	/*
> >> +	 * If CONFIG_DEBUG_SHIRQ is set, the IRQ handler will get invoked during __free_irq()
> >> +	 * and by that time mhi_ctxt() would've freed. So check for the existence of mhi_ctxt
> >> +	 * before handling the IRQs.
> >> +	 */
> >> +	if (!mhi_cntrl->mhi_ctxt) {
> >> +		dev_dbg(&mhi_cntrl->mhi_dev->dev,
> >> +			"mhi_ctxt has been freed\n");
> >> +		return IRQ_HANDLED;
> >> +	}
> 
> I don't see any protection accessing mhi_cntrl->mhi_ctxt, is this really
> free of race conditions?
> 

As Qiang said, it is safe to access mhi_ctxt here.

Thanks,
Mani

> -- 
> https://patchwork.kernel.org/project/linux-wireless/list/
> 
> https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches
Manivannan Sadhasivam July 29, 2022, 2:26 p.m. UTC | #5
On Fri, Jul 22, 2022 at 11:17:18AM +0800, Qiang Yu wrote:
> The irq handler for a shared IRQ ought to be prepared for running
> even now it's being freed. So let's check the pointer used by
> mhi_irq_handler to avoid null pointer access since it is probably
> released before freeing IRQ.
> 
> Signed-off-by: Qiang Yu <quic_qianyu@quicinc.com>

Applied to mhi-next! This patch is targeted for v5.20-rcS.

Thanks,
Mani

> ---
> v2->v3: add comments
> v1->v2: change dev_err to dev_dbg
> 
>  drivers/bus/mhi/host/main.c | 19 ++++++++++++++++---
>  1 file changed, 16 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/bus/mhi/host/main.c b/drivers/bus/mhi/host/main.c
> index f3aef77a..df0fbfe 100644
> --- a/drivers/bus/mhi/host/main.c
> +++ b/drivers/bus/mhi/host/main.c
> @@ -430,12 +430,25 @@ irqreturn_t mhi_irq_handler(int irq_number, void *dev)
>  {
>  	struct mhi_event *mhi_event = dev;
>  	struct mhi_controller *mhi_cntrl = mhi_event->mhi_cntrl;
> -	struct mhi_event_ctxt *er_ctxt =
> -		&mhi_cntrl->mhi_ctxt->er_ctxt[mhi_event->er_index];
> +	struct mhi_event_ctxt *er_ctxt;
>  	struct mhi_ring *ev_ring = &mhi_event->ring;
> -	dma_addr_t ptr = le64_to_cpu(er_ctxt->rp);
> +	dma_addr_t ptr;
>  	void *dev_rp;
>  
> +	/*
> +	 * If CONFIG_DEBUG_SHIRQ is set, the IRQ handler will get invoked during __free_irq()
> +	 * and by that time mhi_ctxt() would've freed. So check for the existence of mhi_ctxt
> +	 * before handling the IRQs.
> +	 */
> +	if (!mhi_cntrl->mhi_ctxt) {
> +		dev_dbg(&mhi_cntrl->mhi_dev->dev,
> +			"mhi_ctxt has been freed\n");
> +		return IRQ_HANDLED;
> +	}
> +
> +	er_ctxt = &mhi_cntrl->mhi_ctxt->er_ctxt[mhi_event->er_index];
> +	ptr = le64_to_cpu(er_ctxt->rp);
> +
>  	if (!is_valid_ring_ptr(ev_ring, ptr)) {
>  		dev_err(&mhi_cntrl->mhi_dev->dev,
>  			"Event ring rp points outside of the event ring\n");
> -- 
> Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project.
>
Kalle Valo Aug. 29, 2022, 4:20 p.m. UTC | #6
Manivannan Sadhasivam <mani@kernel.org> writes:

> On Tue, Jul 26, 2022 at 08:53:58PM +0300, Kalle Valo wrote:
>> Manivannan Sadhasivam <mani@kernel.org> writes:
>> 
>> > +ath11k, Kalle
>> >
>> > On Fri, Jul 22, 2022 at 11:17:18AM +0800, Qiang Yu wrote:
>> >> The irq handler for a shared IRQ ought to be prepared for running
>> >> even now it's being freed. So let's check the pointer used by
>> >> mhi_irq_handler to avoid null pointer access since it is probably
>> >> released before freeing IRQ.
>> >> 
>> >> Signed-off-by: Qiang Yu <quic_qianyu@quicinc.com>
>> >
>> > Reviewed-by: Manivannan Sadhasivam <mani@kernel.org>
>> 
>> This fixes the crash and my regression tests pass now, thanks. But
>> please see my question below.
>> 
>> Tested-by: Kalle Valo <kvalo@kernel.org>
>> 
>
> Thanks Kalle!

I just tested v6.0-rc3 and it's still crashing. What's the plan to get
this fix to Linus?
Manivannan Sadhasivam Aug. 29, 2022, 5:26 p.m. UTC | #7
On Mon, Aug 29, 2022 at 07:20:10PM +0300, Kalle Valo wrote:
> Manivannan Sadhasivam <mani@kernel.org> writes:
> 
> > On Tue, Jul 26, 2022 at 08:53:58PM +0300, Kalle Valo wrote:
> >> Manivannan Sadhasivam <mani@kernel.org> writes:
> >> 
> >> > +ath11k, Kalle
> >> >
> >> > On Fri, Jul 22, 2022 at 11:17:18AM +0800, Qiang Yu wrote:
> >> >> The irq handler for a shared IRQ ought to be prepared for running
> >> >> even now it's being freed. So let's check the pointer used by
> >> >> mhi_irq_handler to avoid null pointer access since it is probably
> >> >> released before freeing IRQ.
> >> >> 
> >> >> Signed-off-by: Qiang Yu <quic_qianyu@quicinc.com>
> >> >
> >> > Reviewed-by: Manivannan Sadhasivam <mani@kernel.org>
> >> 
> >> This fixes the crash and my regression tests pass now, thanks. But
> >> please see my question below.
> >> 
> >> Tested-by: Kalle Valo <kvalo@kernel.org>
> >> 
> >
> > Thanks Kalle!
> 
> I just tested v6.0-rc3 and it's still crashing. What's the plan to get
> this fix to Linus?

Sorry for the delay. Just sent the PR to Greg for including it as a fix for
v6.0.

Thanks,
Mani

> 
> -- 
> https://patchwork.kernel.org/project/linux-wireless/list/
> 
> https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches
Kalle Valo Aug. 30, 2022, 5:25 a.m. UTC | #8
Manivannan Sadhasivam <mani@kernel.org> writes:

> On Mon, Aug 29, 2022 at 07:20:10PM +0300, Kalle Valo wrote:
>> Manivannan Sadhasivam <mani@kernel.org> writes:
>> 
>> > On Tue, Jul 26, 2022 at 08:53:58PM +0300, Kalle Valo wrote:
>> >> Manivannan Sadhasivam <mani@kernel.org> writes:
>> >> 
>> >> > +ath11k, Kalle
>> >> >
>> >> > On Fri, Jul 22, 2022 at 11:17:18AM +0800, Qiang Yu wrote:
>> >> >> The irq handler for a shared IRQ ought to be prepared for running
>> >> >> even now it's being freed. So let's check the pointer used by
>> >> >> mhi_irq_handler to avoid null pointer access since it is probably
>> >> >> released before freeing IRQ.
>> >> >> 
>> >> >> Signed-off-by: Qiang Yu <quic_qianyu@quicinc.com>
>> >> >
>> >> > Reviewed-by: Manivannan Sadhasivam <mani@kernel.org>
>> >> 
>> >> This fixes the crash and my regression tests pass now, thanks. But
>> >> please see my question below.
>> >> 
>> >> Tested-by: Kalle Valo <kvalo@kernel.org>
>> >> 
>> >
>> > Thanks Kalle!
>> 
>> I just tested v6.0-rc3 and it's still crashing. What's the plan to get
>> this fix to Linus?
>
> Sorry for the delay. Just sent the PR to Greg for including it as a fix for
> v6.0.

Excellent, thank you.
diff mbox series

Patch

diff --git a/drivers/bus/mhi/host/main.c b/drivers/bus/mhi/host/main.c
index f3aef77a..df0fbfe 100644
--- a/drivers/bus/mhi/host/main.c
+++ b/drivers/bus/mhi/host/main.c
@@ -430,12 +430,25 @@  irqreturn_t mhi_irq_handler(int irq_number, void *dev)
 {
 	struct mhi_event *mhi_event = dev;
 	struct mhi_controller *mhi_cntrl = mhi_event->mhi_cntrl;
-	struct mhi_event_ctxt *er_ctxt =
-		&mhi_cntrl->mhi_ctxt->er_ctxt[mhi_event->er_index];
+	struct mhi_event_ctxt *er_ctxt;
 	struct mhi_ring *ev_ring = &mhi_event->ring;
-	dma_addr_t ptr = le64_to_cpu(er_ctxt->rp);
+	dma_addr_t ptr;
 	void *dev_rp;
 
+	/*
+	 * If CONFIG_DEBUG_SHIRQ is set, the IRQ handler will get invoked during __free_irq()
+	 * and by that time mhi_ctxt() would've freed. So check for the existence of mhi_ctxt
+	 * before handling the IRQs.
+	 */
+	if (!mhi_cntrl->mhi_ctxt) {
+		dev_dbg(&mhi_cntrl->mhi_dev->dev,
+			"mhi_ctxt has been freed\n");
+		return IRQ_HANDLED;
+	}
+
+	er_ctxt = &mhi_cntrl->mhi_ctxt->er_ctxt[mhi_event->er_index];
+	ptr = le64_to_cpu(er_ctxt->rp);
+
 	if (!is_valid_ring_ptr(ev_ring, ptr)) {
 		dev_err(&mhi_cntrl->mhi_dev->dev,
 			"Event ring rp points outside of the event ring\n");