public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/1] fix handling of decrypted pages
@ 2023-11-02  9:36 Petr Tesarik
  2023-11-02  9:36 ` [PATCH v2 1/1] swiotlb: do not free decrypted pages if dynamic Petr Tesarik
  0 siblings, 1 reply; 4+ messages in thread
From: Petr Tesarik @ 2023-11-02  9:36 UTC (permalink / raw)
  To: Christoph Hellwig, Marek Szyprowski, Robin Murphy,
	Greg Kroah-Hartman, Petr Tesarik, open list:DMA MAPPING HELPERS,
	open list, patchwork
  Cc: Wangkefeng, Roberto Sassu, petr, Petr Tesarik, miaoxie,
	weiyongjun1, guohanjun, huawei.libin, yuehaibing, johnny.chenyi,
	leijitang, ming.fu, zhujianwei7, linuxarm

Changes from v1
---------------
- try to re-encrypt pages after set_memory_decrypted() fails

Petr Tesarik (1):
  swiotlb: do not free decrypted pages if dynamic TLB allocation fails

 kernel/dma/swiotlb.c | 25 ++++++++++++++++---------
 1 file changed, 16 insertions(+), 9 deletions(-)

-- 
2.34.1


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

* [PATCH v2 1/1] swiotlb: do not free decrypted pages if dynamic
  2023-11-02  9:36 [PATCH v2 0/1] fix handling of decrypted pages Petr Tesarik
@ 2023-11-02  9:36 ` Petr Tesarik
  2023-11-02 15:57   ` Edgecombe, Rick P
  2023-11-03  8:35   ` Christoph Hellwig
  0 siblings, 2 replies; 4+ messages in thread
From: Petr Tesarik @ 2023-11-02  9:36 UTC (permalink / raw)
  To: Christoph Hellwig, Marek Szyprowski, Robin Murphy,
	Greg Kroah-Hartman, Petr Tesarik, open list:DMA MAPPING HELPERS,
	open list, patchwork
  Cc: Wangkefeng, Roberto Sassu, petr, Petr Tesarik, miaoxie,
	weiyongjun1, guohanjun, huawei.libin, yuehaibing, johnny.chenyi,
	leijitang, ming.fu, zhujianwei7, linuxarm, stable, Rick Edgecombe

Fix these two error paths:

1. When set_memory_decrypted() fails, pages may be left fully or partially
   decrypted.

2. Decrypted pages may be freed if swiotlb_alloc_tlb() determines that the
   physical address is too high.

To fix the first issue, call set_memory_encrypted() on the allocated region
after a failed decryption attempt. If that also fails, leak the pages.

To fix the second issue, check that the TLB physical address is below the
requested limit before decrypting.

Let the caller differentiate between unsuitable physical address (=> retry
from a lower zone) and allocation failures (=> no point in retrying).

Cc: stable@vger.kernel.org
Cc: Rick Edgecombe <rick.p.edgecombe@intel.com>
Fixes: 79636caad361 ("swiotlb: if swiotlb is full, fall back to a transient memory pool")
Signed-off-by: Petr Tesarik <petr.tesarik1@huawei-partners.com>
---
 kernel/dma/swiotlb.c | 25 ++++++++++++++++---------
 1 file changed, 16 insertions(+), 9 deletions(-)

diff --git a/kernel/dma/swiotlb.c b/kernel/dma/swiotlb.c
index dff067bd56b1..0e1632f75421 100644
--- a/kernel/dma/swiotlb.c
+++ b/kernel/dma/swiotlb.c
@@ -558,29 +558,40 @@ void __init swiotlb_exit(void)
  * alloc_dma_pages() - allocate pages to be used for DMA
  * @gfp:	GFP flags for the allocation.
  * @bytes:	Size of the buffer.
+ * @phys_limit:	Maximum allowed physical address of the buffer.
  *
  * Allocate pages from the buddy allocator. If successful, make the allocated
  * pages decrypted that they can be used for DMA.
  *
- * Return: Decrypted pages, or %NULL on failure.
+ * Return: Decrypted pages, %NULL on allocation failure, or ERR_PTR(-EAGAIN)
+ * if the allocated physical address was above @phys_limit.
  */
-static struct page *alloc_dma_pages(gfp_t gfp, size_t bytes)
+static struct page *alloc_dma_pages(gfp_t gfp, size_t bytes, u64 phys_limit)
 {
 	unsigned int order = get_order(bytes);
 	struct page *page;
+	phys_addr_t paddr;
 	void *vaddr;
 
 	page = alloc_pages(gfp, order);
 	if (!page)
 		return NULL;
 
-	vaddr = page_address(page);
+	paddr = page_to_phys(page);
+	if (paddr + bytes - 1 > phys_limit) {
+		__free_pages(page, order);
+		return ERR_PTR(-EAGAIN);
+	}
+
+	vaddr = phys_to_virt(paddr);
 	if (set_memory_decrypted((unsigned long)vaddr, PFN_UP(bytes)))
 		goto error;
 	return page;
 
 error:
-	__free_pages(page, order);
+	/* Intentional leak if pages cannot be encrypted again. */
+	if (!set_memory_encrypted((unsigned long)vaddr, PFN_UP(bytes)))
+		__free_pages(page, order);
 	return NULL;
 }
 
@@ -618,11 +629,7 @@ static struct page *swiotlb_alloc_tlb(struct device *dev, size_t bytes,
 	else if (phys_limit <= DMA_BIT_MASK(32))
 		gfp |= __GFP_DMA32;
 
-	while ((page = alloc_dma_pages(gfp, bytes)) &&
-	       page_to_phys(page) + bytes - 1 > phys_limit) {
-		/* allocated, but too high */
-		__free_pages(page, get_order(bytes));
-
+	while (IS_ERR(page = alloc_dma_pages(gfp, bytes, phys_limit))) {
 		if (IS_ENABLED(CONFIG_ZONE_DMA32) &&
 		    phys_limit < DMA_BIT_MASK(64) &&
 		    !(gfp & (__GFP_DMA32 | __GFP_DMA)))
-- 
2.34.1


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

* Re: [PATCH v2 1/1] swiotlb: do not free decrypted pages if dynamic
  2023-11-02  9:36 ` [PATCH v2 1/1] swiotlb: do not free decrypted pages if dynamic Petr Tesarik
@ 2023-11-02 15:57   ` Edgecombe, Rick P
  2023-11-03  8:35   ` Christoph Hellwig
  1 sibling, 0 replies; 4+ messages in thread
From: Edgecombe, Rick P @ 2023-11-02 15:57 UTC (permalink / raw)
  To: robin.murphy@arm.com, hch@lst.de, gregkh@linuxfoundation.org,
	patchwork@huawei.com, petrtesarik@huaweicloud.com,
	iommu@lists.linux.dev, m.szyprowski@samsung.com,
	petr.tesarik1@huawei-partners.com, linux-kernel@vger.kernel.org
  Cc: miaoxie@huawei.com, stable@vger.kernel.org, guohanjun@huawei.com,
	leijitang@huawei.com, weiyongjun1@huawei.com,
	huawei.libin@huawei.com, wangkefeng.wang@huawei.com,
	linuxarm@huawei.com, johnny.chenyi@huawei.com,
	yuehaibing@huawei.com, petr@tesarici.cz,
	roberto.sassu@huaweicloud.com, ming.fu@huawei.com,
	zhujianwei7@huawei.com

On Thu, 2023-11-02 at 10:36 +0100, Petr Tesarik wrote:
> +       vaddr = phys_to_virt(paddr);
>         if (set_memory_decrypted((unsigned long)vaddr,
> PFN_UP(bytes)))
>                 goto error;
>         return page;
>  
>  error:
> -       __free_pages(page, order);
> +       /* Intentional leak if pages cannot be encrypted again. */
> +       if (!set_memory_encrypted((unsigned long)vaddr,
> PFN_UP(bytes)))
> +               __free_pages(page, order);
>         return NULL;
>  }

My patch was going to just leak the pages if set_memory_decrypted()
fails, and not try to re-encrypt. It didn't seem worth the extra logic
for the rare case. But this works too.

Reviewed-by: Rick Edgecombe <rick.p.edgecombe@intel.com>

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

* Re: [PATCH v2 1/1] swiotlb: do not free decrypted pages if dynamic
  2023-11-02  9:36 ` [PATCH v2 1/1] swiotlb: do not free decrypted pages if dynamic Petr Tesarik
  2023-11-02 15:57   ` Edgecombe, Rick P
@ 2023-11-03  8:35   ` Christoph Hellwig
  1 sibling, 0 replies; 4+ messages in thread
From: Christoph Hellwig @ 2023-11-03  8:35 UTC (permalink / raw)
  To: Petr Tesarik
  Cc: Christoph Hellwig, Marek Szyprowski, Robin Murphy,
	Greg Kroah-Hartman, Petr Tesarik, open list:DMA MAPPING HELPERS,
	open list, patchwork, Wangkefeng, Roberto Sassu, petr, miaoxie,
	weiyongjun1, guohanjun, huawei.libin, yuehaibing, johnny.chenyi,
	leijitang, ming.fu, zhujianwei7, linuxarm, stable, Rick Edgecombe

Thanks, applied.

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

end of thread, other threads:[~2023-11-03  8:35 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-11-02  9:36 [PATCH v2 0/1] fix handling of decrypted pages Petr Tesarik
2023-11-02  9:36 ` [PATCH v2 1/1] swiotlb: do not free decrypted pages if dynamic Petr Tesarik
2023-11-02 15:57   ` Edgecombe, Rick P
2023-11-03  8:35   ` Christoph Hellwig

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox