Stable Archive on lore.kernel.org
 help / color / Atom feed
* Re: [PATCH] iommu/dma: limit iova free size to unmmaped iova
       [not found] ` <7aaa8dcc-6a47-f256-431d-2a1b034b4076@arm.com>
@ 2020-05-22  6:25   ` guptap
  2020-05-22  9:24     ` Robin Murphy
  0 siblings, 1 reply; 3+ messages in thread
From: guptap @ 2020-05-22  6:25 UTC (permalink / raw)
  To: Robin Murphy, Andrew Morton
  Cc: mhocko, joro, linux-mm, iommu, linux-kernel, owner-linux-mm, stable

On 2020-05-22 01:46, Robin Murphy wrote:
> On 2020-05-21 12:30, Prakash Gupta wrote:
>> Limit the iova size while freeing based on unmapped size. In absence 
>> of
>> this even with unmap failure, invalid iova is pushed to iova rcache 
>> and
>> subsequently can cause panic while rcache magazine is freed.
> 
> Can you elaborate on that panic?
> 
We have seen couple of stability issues around this.
Below is one such example:

kernel BUG at kernel/msm-4.19/drivers/iommu/iova.c:904!
iova_magazine_free_pfns
iova_rcache_insert
free_iova_fast
__iommu_unmap_page
iommu_dma_unmap_page


It turned out an iova pfn 0 got into iova_rcache. One possibility I see 
is
where client unmap with invalid dma_addr. The unmap call will fail and 
warn on
and still try to free iova. This will cause invalid pfn to be inserted 
into
rcache. As and when the magazine with invalid pfn will be freed
private_find_iova() will return NULL for invalid iova and meet bug 
condition.

>> Signed-off-by: Prakash Gupta <guptap@codeaurora.org>
>> 
>> :100644 100644 4959f5df21bd 098f7d377e04 M	drivers/iommu/dma-iommu.c
>> 
>> diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
>> index 4959f5df21bd..098f7d377e04 100644
>> --- a/drivers/iommu/dma-iommu.c
>> +++ b/drivers/iommu/dma-iommu.c
>> @@ -472,7 +472,8 @@ static void __iommu_dma_unmap(struct device *dev, 
>> dma_addr_t dma_addr,
>>     	if (!cookie->fq_domain)
>>   		iommu_tlb_sync(domain, &iotlb_gather);
>> -	iommu_dma_free_iova(cookie, dma_addr, size);
>> +	if (unmapped)
>> +		iommu_dma_free_iova(cookie, dma_addr, unmapped);
> 
> Frankly, if any part of the unmap fails then things have gone
> catastrophically wrong already, but either way this isn't right. The
> IOVA API doesn't support partial freeing - an IOVA *must* be freed
> with its original size, or not freed at all, otherwise it will corrupt
> the state of the rcaches and risk a cascade of further misbehaviour
> for future callers.
> 
I agree, we shouldn't be freeing the partial iova. Instead just making
sure if unmap was successful should be sufficient before freeing iova. 
So change
can instead be something like this:

-	iommu_dma_free_iova(cookie, dma_addr, size);
+	if (unmapped)
+		iommu_dma_free_iova(cookie, dma_addr, size);

> TBH my gut feeling here is that you're really just trying to treat a
> symptom of another bug elsewhere, namely some driver calling
> dma_unmap_* or dma_free_* with the wrong address or size in the first
> place.
> 
This condition would arise only if driver calling dma_unmap/free_* with 
0
iova_pfn. This will be flagged with a warning during unmap but will 
trigger
panic later on while doing unrelated dma_map/unmap_*. If unmapped has 
already
failed for invalid iova, there is no reason we should consider this as 
valid
iova and free. This part should be fixed.

On 2020-05-22 00:19, Andrew Morton wrote:
> I think we need a cc:stable here?
> 
Added now.

Thanks,
Prakash

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] iommu/dma: limit iova free size to unmmaped iova
  2020-05-22  6:25   ` [PATCH] iommu/dma: limit iova free size to unmmaped iova guptap
@ 2020-05-22  9:24     ` Robin Murphy
  2020-05-26  7:19       ` guptap
  0 siblings, 1 reply; 3+ messages in thread
From: Robin Murphy @ 2020-05-22  9:24 UTC (permalink / raw)
  To: guptap, Andrew Morton
  Cc: mhocko, joro, linux-mm, iommu, linux-kernel, owner-linux-mm, stable

On 2020-05-22 07:25, guptap@codeaurora.org wrote:
> On 2020-05-22 01:46, Robin Murphy wrote:
>> On 2020-05-21 12:30, Prakash Gupta wrote:
>>> Limit the iova size while freeing based on unmapped size. In absence of
>>> this even with unmap failure, invalid iova is pushed to iova rcache and
>>> subsequently can cause panic while rcache magazine is freed.
>>
>> Can you elaborate on that panic?
>>
> We have seen couple of stability issues around this.
> Below is one such example:
> 
> kernel BUG at kernel/msm-4.19/drivers/iommu/iova.c:904!
> iova_magazine_free_pfns
> iova_rcache_insert
> free_iova_fast
> __iommu_unmap_page
> iommu_dma_unmap_page

OK, so it's not some NULL dereference or anything completely unexpected, 
that's good.

> It turned out an iova pfn 0 got into iova_rcache. One possibility I see is
> where client unmap with invalid dma_addr. The unmap call will fail and 
> warn on
> and still try to free iova. This will cause invalid pfn to be inserted into
> rcache. As and when the magazine with invalid pfn will be freed
> private_find_iova() will return NULL for invalid iova and meet bug 
> condition.

That would indeed be a bug in whatever driver made the offending 
dma_unmap call.

>>> Signed-off-by: Prakash Gupta <guptap@codeaurora.org>
>>>
>>> :100644 100644 4959f5df21bd 098f7d377e04 M    drivers/iommu/dma-iommu.c
>>>
>>> diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
>>> index 4959f5df21bd..098f7d377e04 100644
>>> --- a/drivers/iommu/dma-iommu.c
>>> +++ b/drivers/iommu/dma-iommu.c
>>> @@ -472,7 +472,8 @@ static void __iommu_dma_unmap(struct device *dev, 
>>> dma_addr_t dma_addr,
>>>         if (!cookie->fq_domain)
>>>           iommu_tlb_sync(domain, &iotlb_gather);
>>> -    iommu_dma_free_iova(cookie, dma_addr, size);
>>> +    if (unmapped)
>>> +        iommu_dma_free_iova(cookie, dma_addr, unmapped);
>>
>> Frankly, if any part of the unmap fails then things have gone
>> catastrophically wrong already, but either way this isn't right. The
>> IOVA API doesn't support partial freeing - an IOVA *must* be freed
>> with its original size, or not freed at all, otherwise it will corrupt
>> the state of the rcaches and risk a cascade of further misbehaviour
>> for future callers.
>>
> I agree, we shouldn't be freeing the partial iova. Instead just making
> sure if unmap was successful should be sufficient before freeing iova. 
> So change
> can instead be something like this:
> 
> -    iommu_dma_free_iova(cookie, dma_addr, size);
> +    if (unmapped)
> +        iommu_dma_free_iova(cookie, dma_addr, size);
> 
>> TBH my gut feeling here is that you're really just trying to treat a
>> symptom of another bug elsewhere, namely some driver calling
>> dma_unmap_* or dma_free_* with the wrong address or size in the first
>> place.
>>
> This condition would arise only if driver calling dma_unmap/free_* with 0
> iova_pfn. This will be flagged with a warning during unmap but will trigger
> panic later on while doing unrelated dma_map/unmap_*. If unmapped has 
> already
> failed for invalid iova, there is no reason we should consider this as 
> valid
> iova and free. This part should be fixed.

I disagree. In general, if drivers call the DMA API incorrectly it is 
liable to lead to data loss, memory corruption, and various other 
unpleasant misbehaviour - it is not the DMA layer's job to attempt to 
paper over driver bugs.

There *is* an argument for downgrading the BUG_ON() in 
iova_magazine_free_pfns() to a WARN_ON(), since frankly it isn't a 
sufficiently serious condition to justify killing the whole machine 
immediately, but NAK to bodging the iommu-dma mid-layer to "fix" that. A 
serious bug already happened elsewhere, so trying to hide the fallout 
really doesn't help anyone.

Robin.

> On 2020-05-22 00:19, Andrew Morton wrote:
>> I think we need a cc:stable here?
>>
> Added now.
> 
> Thanks,
> Prakash

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] iommu/dma: limit iova free size to unmmaped iova
  2020-05-22  9:24     ` Robin Murphy
@ 2020-05-26  7:19       ` guptap
  0 siblings, 0 replies; 3+ messages in thread
From: guptap @ 2020-05-26  7:19 UTC (permalink / raw)
  To: Robin Murphy
  Cc: Andrew Morton, mhocko, joro, linux-mm, iommu, linux-kernel,
	owner-linux-mm, stable

On 2020-05-22 14:54, Robin Murphy wrote:
> On 2020-05-22 07:25, guptap@codeaurora.org wrote:
>> On 2020-05-22 01:46, Robin Murphy wrote:
>>> On 2020-05-21 12:30, Prakash Gupta wrote:
>> I agree, we shouldn't be freeing the partial iova. Instead just making
>> sure if unmap was successful should be sufficient before freeing iova. 
>> So change
>> can instead be something like this:
>> 
>> -    iommu_dma_free_iova(cookie, dma_addr, size);
>> +    if (unmapped)
>> +        iommu_dma_free_iova(cookie, dma_addr, size);
>> 
>>> TBH my gut feeling here is that you're really just trying to treat a
>>> symptom of another bug elsewhere, namely some driver calling
>>> dma_unmap_* or dma_free_* with the wrong address or size in the first
>>> place.
>>> 
>> This condition would arise only if driver calling dma_unmap/free_* 
>> with 0
>> iova_pfn. This will be flagged with a warning during unmap but will 
>> trigger
>> panic later on while doing unrelated dma_map/unmap_*. If unmapped has 
>> already
>> failed for invalid iova, there is no reason we should consider this as 
>> valid
>> iova and free. This part should be fixed.
> 
> I disagree. In general, if drivers call the DMA API incorrectly it is
> liable to lead to data loss, memory corruption, and various other
> unpleasant misbehaviour - it is not the DMA layer's job to attempt to
> paper over driver bugs.
> 
> There *is* an argument for downgrading the BUG_ON() in
> iova_magazine_free_pfns() to a WARN_ON(), since frankly it isn't a
> sufficiently serious condition to justify killing the whole machine
> immediately, but NAK to bodging the iommu-dma mid-layer to "fix" that.
> A serious bug already happened elsewhere, so trying to hide the
> fallout really doesn't help anyone.
> 
Sorry for delayed response, it was a long weekend.
I agree that invalid DMA API call can result in unexpected issues and 
client
should fix it, but then the present behavior makes it difficult to catch 
cases
when driver is making wrong DMA API calls. When invalid iova pfn is 
passed it
doesn't fail then and there, though DMA layer is aware of iova being 
invalid. It
fails much after that in the context of an valid map/unmap, with 
BUG_ON().

Downgrading BUG_ON() to WARN_ON() in iova_magazine_free_pfns() will not 
help
much as invalid iova will cause NULL pointer dereference.

I see no reason why DMA layer wants to free an iova for which unmapped 
failed.
IMHO queuing an invalid iova (which already failed unmap) to rcache 
which
eventually going to crash the system looks like iommu-dma layer issue.

Thanks,
Prakash

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, back to index

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <20200521113004.12438-1-guptap@codeaurora.org>
     [not found] ` <7aaa8dcc-6a47-f256-431d-2a1b034b4076@arm.com>
2020-05-22  6:25   ` [PATCH] iommu/dma: limit iova free size to unmmaped iova guptap
2020-05-22  9:24     ` Robin Murphy
2020-05-26  7:19       ` guptap

Stable Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/stable/0 stable/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 stable stable/ https://lore.kernel.org/stable \
		stable@vger.kernel.org
	public-inbox-index stable

Example config snippet for mirrors

Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.kernel.vger.stable


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git