lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <b662e137-5d2a-4ee7-b1f7-b4545388d4fe@arm.com>
Date: Tue, 20 Jan 2026 19:22:01 +0000
From: Robin Murphy <robin.murphy@....com>
To: "Aneesh Kumar K.V" <aneesh.kumar@...nel.org>,
 Suzuki K Poulose <suzuki.poulose@....com>, linux-kernel@...r.kernel.org,
 iommu@...ts.linux.dev, linux-coco@...ts.linux.dev
Cc: Catalin Marinas <catalin.marinas@....com>, will@...nel.org, jgg@...pe.ca,
 steven.price@....com, Marek Szyprowski <m.szyprowski@...sung.com>
Subject: Re: [PATCH 1/2] dma-direct: Validate DMA mask against canonical DMA
 addresses

On 2026-01-20 2:25 pm, Aneesh Kumar K.V wrote:
> Robin Murphy <robin.murphy@....com> writes:
> 
>> On 2026-01-20 9:59 am, Suzuki K Poulose wrote:
>>> On 20/01/2026 06:42, Aneesh Kumar K.V (Arm) wrote:
>>>> On systems that apply an address encryption tag or mask to DMA addresses,
>>>> DMA mask validation must be performed against the canonical DMA address.
>>>> Using a non-canonical (e.g. encrypted or unencrypted) DMA address
>>>> can incorrectly fail capability checks, since architecture-specific
>>>> encryption bits are not part of the device’s actual DMA addressing
>>>> capability. For example, arm64 adds PROT_NS_SHARED to unencrypted DMA
>>>> addresses.
>>>>
>>>> Fix this by validating device DMA masks against __phys_to_dma(), ensuring
>>>> that the architecture encryption mask does not influence the check.
>>>>
>>>> Fixes: b66e2ee7b6c8 ("dma: Introduce generic dma_addr_*crypted helpers")
>>>
>>>
>>>> Signed-off-by: Aneesh Kumar K.V (Arm) <aneesh.kumar@...nel.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 8e04f72baaa3..a5639e9415f5 100644
>>>> --- a/kernel/dma/direct.c
>>>> +++ b/kernel/dma/direct.c
>>>> @@ -580,12 +580,12 @@ int dma_direct_supported(struct device *dev, u64
>>>> mask)
>>>>        /*
>>>>         * This check needs to be against the actual bit mask value, so use
>>>> -     * phys_to_dma_unencrypted() here so that the SME encryption mask
>>>> isn't
>>>> +     * __phys_to_dma() here so that the arch specific encryption mask
>>>> isn't
>>>>         * part of the check.
>>>>         */
>>>>        if (IS_ENABLED(CONFIG_ZONE_DMA))
>>>>            min_mask = min_t(u64, min_mask, zone_dma_limit);
>>>> -    return mask >= phys_to_dma_unencrypted(dev, min_mask);
>>>> +    return mask >= __phys_to_dma(dev, min_mask);
>>>
>>> This is wrong, isn't it ? For e.g., for CCA, even though the "Flag" is
>>> added to the PA, it is really part of the actual "PA" and thus must be
>>> checked against the full PA ?
>>
>> Yes, it's much the same as for AMD SEV (albeit the other way round) -
>> the encryption/decryption bit is part of the DMA address because it
>> needs to be driven by the device, so it is crucial that the device's DMA
>> mask is capable of expressing that.
>>
> 
> Commit c92a54cfa0257e8ffd66b2a17d49e9c0bd4b769f explains these details.

See x86's force_dma_unencrypted() implementation - the reason dma-direct 
doesn't need to be so strict for that is because things are the right 
way round that it can always fall back to shared/untrusted DMA as the 
general case, and a device can only access an encrypted page directly if 
it *can* drive the SME bit in the input address to trigger the inline 
encryption engine.

For CCA we have rather the opposite, where dma-direct requires a device 
to be able to address any IPA directly to be sure of working at all, but 
if we do happen to have a stage 1 IOMMU then we could rely on that to 
map smaller IOVAs to the upper IPA space.

> I was wondering whether the DMA-enable operation should live outside the
> set_mask operation. Conceptually, set_mask should be derived purely from
> max_pfn, while the DMA enablement path could additionally verify whether
> the device requires access to an alias address, depending on whether it
> is operating in trusted or untrusted mode?

No, the point of the set_mask check is "is this mask big enough to 
accommodate any *DMA address* we might need to give the device?" - that 
includes offsets, magic bits, magic bits encoded as fake offsets (yes 
you, Raspberry Pi...) and whatever else might comprise an actual DMA 
address as handed off to the hardware. It is *not* directly a "can this 
device DMA to all RAM we know about?" check - that is in the assumption 
that if necessary the SWIOTLB buffer will be reachable at a <=32-bit DMA 
address, and thus we should not *need* to give >32-bit addresses to 
devices. It is only that assumption which fundamentally falls apart for 
CCA (with more than 2GB of IPA space, at least).

Thanks,
Robin.

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ