lkml.org 
[lkml]   [2022]   [Jun]   [7]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.15 379/667] dma-direct: always leak memory that cant be re-encrypted
    Date
    From: Christoph Hellwig <hch@lst.de>

    [ Upstream commit a90cf30437489343b8386ae87b4827b6d6c3ed50 ]

    We must never let unencrypted memory go back into the general page pool.
    So if we fail to set it back to encrypted when freeing DMA memory, leak
    the memory instead and warn the user.

    Signed-off-by: Christoph Hellwig <hch@lst.de>
    Reviewed-by: Robin Murphy <robin.murphy@arm.com>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    kernel/dma/direct.c | 14 ++++++++++----
    1 file changed, 10 insertions(+), 4 deletions(-)

    diff --git a/kernel/dma/direct.c b/kernel/dma/direct.c
    index 473964620773..8e24455dd236 100644
    --- a/kernel/dma/direct.c
    +++ b/kernel/dma/direct.c
    @@ -84,9 +84,14 @@ static int dma_set_decrypted(struct device *dev, void *vaddr, size_t size)

    static int dma_set_encrypted(struct device *dev, void *vaddr, size_t size)
    {
    + int ret;
    +
    if (!force_dma_unencrypted(dev))
    return 0;
    - return set_memory_encrypted((unsigned long)vaddr, 1 << get_order(size));
    + ret = set_memory_encrypted((unsigned long)vaddr, 1 << get_order(size));
    + if (ret)
    + pr_warn_ratelimited("leaking DMA memory that can't be re-encrypted\n");
    + return ret;
    }

    static void __dma_direct_free_pages(struct device *dev, struct page *page,
    @@ -273,7 +278,6 @@ void *dma_direct_alloc(struct device *dev, size_t size,
    return ret;

    out_encrypt_pages:
    - /* If memory cannot be re-encrypted, it must be leaked */
    if (dma_set_encrypted(dev, page_address(page), size))
    return NULL;
    out_free_pages:
    @@ -319,7 +323,8 @@ void dma_direct_free(struct device *dev, size_t size,
    } else {
    if (IS_ENABLED(CONFIG_ARCH_HAS_DMA_CLEAR_UNCACHED))
    arch_dma_clear_uncached(cpu_addr, size);
    - dma_set_encrypted(dev, cpu_addr, 1 << page_order);
    + if (dma_set_encrypted(dev, cpu_addr, 1 << page_order))
    + return;
    }

    __dma_direct_free_pages(dev, dma_direct_to_page(dev, dma_addr), size);
    @@ -363,7 +368,8 @@ void dma_direct_free_pages(struct device *dev, size_t size,
    dma_free_from_pool(dev, vaddr, size))
    return;

    - dma_set_encrypted(dev, vaddr, 1 << page_order);
    + if (dma_set_encrypted(dev, vaddr, 1 << page_order))
    + return;
    __dma_direct_free_pages(dev, page, size);
    }

    --
    2.35.1


    \
     
     \ /
      Last update: 2022-06-07 21:22    [W:4.503 / U:0.016 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site