diff mbox series

mhi: Fix double dma free

Message ID 1612885989-12288-1-git-send-email-loic.poulain@linaro.org (mailing list archive)
State Superseded
Headers show
Series mhi: Fix double dma free | expand

Commit Message

Loic Poulain Feb. 9, 2021, 3:53 p.m. UTC
mhi_deinit_chan_ctxt functionthat takes care of unitializing channel
resources, including unmapping coherent MHI areas, can be called
from different path in case of controller unregistering/removal:
 - From a client driver remove callback, via mhi_unprepare_channel
 - From mhi_driver_remove that unitialize all channels

mhi_driver_remove()
|-> driver->remove()
|    |-> mhi_unprepare_channel()
|        |-> mhi_deinit_chan_ctxt()
|...
|-> mhi_deinit_chan_ctxt()

This leads to double dma freeing...

Fix that by preventing deinit for already uninitialized channel.

Signed-off-by: Loic Poulain <loic.poulain@linaro.org>
Reported-by: Kalle Valo <kvalo@codeaurora.org>
---
 drivers/bus/mhi/core/init.c | 3 +++
 1 file changed, 3 insertions(+)

Comments

Loic Poulain Feb. 9, 2021, 3:55 p.m. UTC | #1
Hi Kalle,

On Tue, 9 Feb 2021 at 16:45, Loic Poulain <loic.poulain@linaro.org> wrote:
>
> mhi_deinit_chan_ctxt functionthat takes care of unitializing channel
> resources, including unmapping coherent MHI areas, can be called
> from different path in case of controller unregistering/removal:
>  - From a client driver remove callback, via mhi_unprepare_channel
>  - From mhi_driver_remove that unitialize all channels
>
> mhi_driver_remove()
> |-> driver->remove()
> |    |-> mhi_unprepare_channel()
> |        |-> mhi_deinit_chan_ctxt()
> |...
> |-> mhi_deinit_chan_ctxt()
>
> This leads to double dma freeing...
>
> Fix that by preventing deinit for already uninitialized channel.
>
> Signed-off-by: Loic Poulain <loic.poulain@linaro.org>
> Reported-by: Kalle Valo <kvalo@codeaurora.org>

This is a 'blind' fix tentative, can you please check if it resolves
the issue on your side?

Thanks,
Loic
Jeffrey Hugo Feb. 9, 2021, 3:55 p.m. UTC | #2
On 2/9/2021 8:53 AM, Loic Poulain wrote:
> mhi_deinit_chan_ctxt functionthat takes care of unitializing channel
> resources, including unmapping coherent MHI areas, can be called
> from different path in case of controller unregistering/removal:
>   - From a client driver remove callback, via mhi_unprepare_channel
>   - From mhi_driver_remove that unitialize all channels
> 
> mhi_driver_remove()
> |-> driver->remove()
> |    |-> mhi_unprepare_channel()
> |        |-> mhi_deinit_chan_ctxt()
> |...
> |-> mhi_deinit_chan_ctxt()
> 
> This leads to double dma freeing...
> 
> Fix that by preventing deinit for already uninitialized channel.
> 
> Signed-off-by: Loic Poulain <loic.poulain@linaro.org>
> Reported-by: Kalle Valo <kvalo@codeaurora.org>
> ---

Seems like this should have a Fixes: tag, no?
Loic Poulain Feb. 9, 2021, 4:06 p.m. UTC | #3
On Tue, 9 Feb 2021 at 16:55, Jeffrey Hugo <jhugo@codeaurora.org> wrote:
>
> On 2/9/2021 8:53 AM, Loic Poulain wrote:
> > mhi_deinit_chan_ctxt functionthat takes care of unitializing channel
> > resources, including unmapping coherent MHI areas, can be called
> > from different path in case of controller unregistering/removal:
> >   - From a client driver remove callback, via mhi_unprepare_channel
> >   - From mhi_driver_remove that unitialize all channels
> >
> > mhi_driver_remove()
> > |-> driver->remove()
> > |    |-> mhi_unprepare_channel()
> > |        |-> mhi_deinit_chan_ctxt()
> > |...
> > |-> mhi_deinit_chan_ctxt()
> >
> > This leads to double dma freeing...
> >
> > Fix that by preventing deinit for already uninitialized channel.
> >
> > Signed-off-by: Loic Poulain <loic.poulain@linaro.org>
> > Reported-by: Kalle Valo <kvalo@codeaurora.org>
> > ---
>
> Seems like this should have a Fixes: tag, no?

Right, thanks, i'll add it in V2 once I get feedback.
Kalle Valo Feb. 9, 2021, 5:02 p.m. UTC | #4
Loic Poulain <loic.poulain@linaro.org> writes:

> Hi Kalle,
>
> On Tue, 9 Feb 2021 at 16:45, Loic Poulain <loic.poulain@linaro.org> wrote:
>>
>> mhi_deinit_chan_ctxt functionthat takes care of unitializing channel
>> resources, including unmapping coherent MHI areas, can be called
>> from different path in case of controller unregistering/removal:
>>  - From a client driver remove callback, via mhi_unprepare_channel
>>  - From mhi_driver_remove that unitialize all channels
>>
>> mhi_driver_remove()
>> |-> driver->remove()
>> |    |-> mhi_unprepare_channel()
>> |        |-> mhi_deinit_chan_ctxt()
>> |...
>> |-> mhi_deinit_chan_ctxt()
>>
>> This leads to double dma freeing...
>>
>> Fix that by preventing deinit for already uninitialized channel.
>>
>> Signed-off-by: Loic Poulain <loic.poulain@linaro.org>
>> Reported-by: Kalle Valo <kvalo@codeaurora.org>
>
> This is a 'blind' fix tentative, can you please check if it resolves
> the issue on your side?

I did a quick test few times and I don't see any crashes anymore, thanks!

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

And like Jeffrey said:

Fixes: a7f422f2f89e ("bus: mhi: Fix channel close issue on driver remove")

Is it too late to push this to v5.11? But this should go to v5.12.
Bhaumik Bhatt Feb. 9, 2021, 5:27 p.m. UTC | #5
On 2021-02-09 08:06 AM, Loic Poulain wrote:
> On Tue, 9 Feb 2021 at 16:55, Jeffrey Hugo <jhugo@codeaurora.org> wrote:
>> 
>> On 2/9/2021 8:53 AM, Loic Poulain wrote:
>> > mhi_deinit_chan_ctxt functionthat takes care of unitializing channel
>> > resources, including unmapping coherent MHI areas, can be called
>> > from different path in case of controller unregistering/removal:
>> >   - From a client driver remove callback, via mhi_unprepare_channel
>> >   - From mhi_driver_remove that unitialize all channels
>> >
>> > mhi_driver_remove()
>> > |-> driver->remove()
>> > |    |-> mhi_unprepare_channel()
>> > |        |-> mhi_deinit_chan_ctxt()
>> > |...
>> > |-> mhi_deinit_chan_ctxt()
>> >
>> > This leads to double dma freeing...
>> >
>> > Fix that by preventing deinit for already uninitialized channel.
>> >
>> > Signed-off-by: Loic Poulain <loic.poulain@linaro.org>
>> > Reported-by: Kalle Valo <kvalo@codeaurora.org>
>> > ---
>> 
>> Seems like this should have a Fixes: tag, no?
> 
> Right, thanks, i'll add it in V2 once I get feedback.

Hi Loic, Mani,

I saw this same issue a while back but could not collect the logs for 
it.

I had already pushed a patch to fix this differently [1] which was 
recently reviewed by Hemant.

Although there wasn't a purposeful fixes tag for it. I think the culprit 
for this issue is [2]:

As it allows the unprepare to go through on remove(), which was 
traditionally not allowed and
ends up uncovering this issue as it fixes another.

Channel updates [3] address that and provide a bunch of other 
improvements. Please consider them.

Thanks,
Bhaumik

[1] https://lkml.org/lkml/2021/2/4/1161
[2] 
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/drivers/bus/mhi?h=v5.11-rc7&id=a7f422f2f89e7d48aa66e6488444a4c7f01269d5
[3] https://lkml.org/lkml/2021/2/4/1155

---
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora 
Forum,
a Linux Foundation Collaborative Project
Loic Poulain Feb. 9, 2021, 6:17 p.m. UTC | #6
Hi Bhaumik,

On Tue, 9 Feb 2021 at 18:27, Bhaumik Bhatt <bbhatt@codeaurora.org> wrote:
>
> On 2021-02-09 08:06 AM, Loic Poulain wrote:
> > On Tue, 9 Feb 2021 at 16:55, Jeffrey Hugo <jhugo@codeaurora.org> wrote:
> >>
> >> On 2/9/2021 8:53 AM, Loic Poulain wrote:
> >> > mhi_deinit_chan_ctxt functionthat takes care of unitializing channel
> >> > resources, including unmapping coherent MHI areas, can be called
> >> > from different path in case of controller unregistering/removal:
> >> >   - From a client driver remove callback, via mhi_unprepare_channel
> >> >   - From mhi_driver_remove that unitialize all channels
> >> >
> >> > mhi_driver_remove()
> >> > |-> driver->remove()
> >> > |    |-> mhi_unprepare_channel()
> >> > |        |-> mhi_deinit_chan_ctxt()
> >> > |...
> >> > |-> mhi_deinit_chan_ctxt()
> >> >
> >> > This leads to double dma freeing...
> >> >
> >> > Fix that by preventing deinit for already uninitialized channel.
> >> >
> >> > Signed-off-by: Loic Poulain <loic.poulain@linaro.org>
> >> > Reported-by: Kalle Valo <kvalo@codeaurora.org>
> >> > ---
> >>
> >> Seems like this should have a Fixes: tag, no?
> >
> > Right, thanks, i'll add it in V2 once I get feedback.
>
> Hi Loic, Mani,
>
> I saw this same issue a while back but could not collect the logs for
> it.
>
> I had already pushed a patch to fix this differently [1] which was
> recently reviewed by Hemant.
>
> Although there wasn't a purposeful fixes tag for it. I think the culprit
> for this issue is [2]:
>
> As it allows the unprepare to go through on remove(), which was
> traditionally not allowed and
> ends up uncovering this issue as it fixes another.
>
> Channel updates [3] address that and provide a bunch of other
> improvements. Please consider them.

Yes, patch [2] is the culprit. I would recommend merging this tiny fix
so that it can be easily grab for 5.11 or backported, and keep your
series (rebased on top), for mhi-next (going to review/test it btw).

Regards,
Loic
Bhaumik Bhatt Feb. 10, 2021, 4:37 a.m. UTC | #7
Hi Loic, Mani, Hemant,

On 2021-02-09 10:17 AM, Loic Poulain wrote:
> Hi Bhaumik,
> 
> On Tue, 9 Feb 2021 at 18:27, Bhaumik Bhatt <bbhatt@codeaurora.org> 
> wrote:
>> 
>> On 2021-02-09 08:06 AM, Loic Poulain wrote:
>> > On Tue, 9 Feb 2021 at 16:55, Jeffrey Hugo <jhugo@codeaurora.org> wrote:
>> >>
>> >> On 2/9/2021 8:53 AM, Loic Poulain wrote:
>> >> > mhi_deinit_chan_ctxt functionthat takes care of unitializing channel
>> >> > resources, including unmapping coherent MHI areas, can be called
>> >> > from different path in case of controller unregistering/removal:
>> >> >   - From a client driver remove callback, via mhi_unprepare_channel
>> >> >   - From mhi_driver_remove that unitialize all channels
>> >> >
>> >> > mhi_driver_remove()
>> >> > |-> driver->remove()
>> >> > |    |-> mhi_unprepare_channel()
>> >> > |        |-> mhi_deinit_chan_ctxt()
>> >> > |...
>> >> > |-> mhi_deinit_chan_ctxt()
>> >> >
>> >> > This leads to double dma freeing...
>> >> >
>> >> > Fix that by preventing deinit for already uninitialized channel.
>> >> >
>> >> > Signed-off-by: Loic Poulain <loic.poulain@linaro.org>
>> >> > Reported-by: Kalle Valo <kvalo@codeaurora.org>
>> >> > ---
>> >>
>> >> Seems like this should have a Fixes: tag, no?
>> >
>> > Right, thanks, i'll add it in V2 once I get feedback.
>> 
>> Hi Loic, Mani,
>> 
>> I saw this same issue a while back but could not collect the logs for
>> it.
>> 
>> I had already pushed a patch to fix this differently [1] which was
>> recently reviewed by Hemant.
>> 
>> Although there wasn't a purposeful fixes tag for it. I think the 
>> culprit
>> for this issue is [2]:
>> 
>> As it allows the unprepare to go through on remove(), which was
>> traditionally not allowed and
>> ends up uncovering this issue as it fixes another.
>> 
>> Channel updates [3] address that and provide a bunch of other
>> improvements. Please consider them.
> 
> Yes, patch [2] is the culprit. I would recommend merging this tiny fix
> so that it can be easily grab for 5.11 or backported, and keep your
> series (rebased on top), for mhi-next (going to review/test it btw).
> 
> Regards,
> Loic

If priority is to get this fix in ASAP, your suggestion is OK. I just 
see some
typo fixes and a title update to "bus: mhi: core: Fix double dma free() 
call"
or something as review comments for your patch.

Another option is that I can send my patch [1] separately and remove it 
from my
"channel updates" patch series, if that helps.

I'd like to see what Mani and Hemant on what they prefer. Please advise.

Thanks,
Bhaumik

[1] https://lkml.org/lkml/2021/2/4/1161

---
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora 
Forum,
a Linux Foundation Collaborative Project
Manivannan Sadhasivam Feb. 10, 2021, 8:17 a.m. UTC | #8
On Tue, Feb 09, 2021 at 08:37:21PM -0800, Bhaumik Bhatt wrote:
> Hi Loic, Mani, Hemant,
> 

[...]

> If priority is to get this fix in ASAP, your suggestion is OK. I just see
> some
> typo fixes and a title update to "bus: mhi: core: Fix double dma free()
> call"
> or something as review comments for your patch.
> 
> Another option is that I can send my patch [1] separately and remove it from
> my
> "channel updates" patch series, if that helps.
> 
> I'd like to see what Mani and Hemant on what they prefer. Please advise.
> 

Both patches looks good to me although your patch needs to be resubmitted. But
since the fix needs to go in quickly, I'm going to apply Loic's patch.

Thanks,
Mani

> Thanks,
> Bhaumik
> 
> [1] https://lkml.org/lkml/2021/2/4/1161
> 
> ---
> The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
> a Linux Foundation Collaborative Project
diff mbox series

Patch

diff --git a/drivers/bus/mhi/core/init.c b/drivers/bus/mhi/core/init.c
index aa575d3..be4eebb 100644
--- a/drivers/bus/mhi/core/init.c
+++ b/drivers/bus/mhi/core/init.c
@@ -557,6 +557,9 @@  void mhi_deinit_chan_ctxt(struct mhi_controller *mhi_cntrl,
 	tre_ring = &mhi_chan->tre_ring;
 	chan_ctxt = &mhi_cntrl->mhi_ctxt->chan_ctxt[mhi_chan->chan];
 
+	if (!chan_ctxt->rbase) /* Already uninitialized */
+		return;
+
 	mhi_free_coherent(mhi_cntrl, tre_ring->alloc_size,
 			  tre_ring->pre_aligned, tre_ring->dma_handle);
 	vfree(buf_ring->base);