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.17 447/772] dma-direct: dont over-decrypt memory
    Date
    From: Robin Murphy <robin.murphy@arm.com>

    [ Upstream commit 4a37f3dd9a83186cb88d44808ab35b78375082c9 ]

    The original x86 sev_alloc() only called set_memory_decrypted() on
    memory returned by alloc_pages_node(), so the page order calculation
    fell out of that logic. However, the common dma-direct code has several
    potential allocators, not all of which are guaranteed to round up the
    underlying allocation to a power-of-two size, so carrying over that
    calculation for the encryption/decryption size was a mistake. Fix it by
    rounding to a *number* of pages, rather than an order.

    Until recently there was an even worse interaction with DMA_DIRECT_REMAP
    where we could have ended up decrypting part of the next adjacent
    vmalloc area, only averted by no architecture actually supporting both
    configs at once. Don't ask how I found that one out...

    Fixes: c10f07aa27da ("dma/direct: Handle force decryption for DMA coherent buffers in common code")
    Signed-off-by: Robin Murphy <robin.murphy@arm.com>
    Signed-off-by: Christoph Hellwig <hch@lst.de>
    Acked-by: David Rientjes <rientjes@google.com>
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    kernel/dma/direct.c | 4 ++--
    1 file changed, 2 insertions(+), 2 deletions(-)

    diff --git a/kernel/dma/direct.c b/kernel/dma/direct.c
    index 0be095579010..54b1a5d21187 100644
    --- a/kernel/dma/direct.c
    +++ b/kernel/dma/direct.c
    @@ -79,7 +79,7 @@ static int dma_set_decrypted(struct device *dev, void *vaddr, size_t size)
    {
    if (!force_dma_unencrypted(dev))
    return 0;
    - return set_memory_decrypted((unsigned long)vaddr, 1 << get_order(size));
    + return set_memory_decrypted((unsigned long)vaddr, PFN_UP(size));
    }

    static int dma_set_encrypted(struct device *dev, void *vaddr, size_t size)
    @@ -88,7 +88,7 @@ static int dma_set_encrypted(struct device *dev, void *vaddr, size_t size)

    if (!force_dma_unencrypted(dev))
    return 0;
    - ret = set_memory_encrypted((unsigned long)vaddr, 1 << get_order(size));
    + ret = set_memory_encrypted((unsigned long)vaddr, PFN_UP(size));
    if (ret)
    pr_warn_ratelimited("leaking DMA memory that can't be re-encrypted\n");
    return ret;
    --
    2.35.1


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