Re: dma_heap and protected memory

Andrew Davis via OP-TEE <[email protected]> Thu, 21 May 2026 09:40:37 -0500
Newsgroups org.trustedfirmware.lists.op-tee
Message-ID <[email protected]>
On 5/20/26 6:18 AM, Jens Wiklander wrote:
> Hi Amir,
> 
> On Wed, May 20, 2026 at 9:10 AM Amirreza Zarrabi
> <[email protected]> wrote:
>>
>> Hi Jens,
>>
>> On 5/20/2026 1:29 AM, Jens Wiklander wrote:
>>> Hi Amir,
>>>
>>> On Fri, May 15, 2026 at 5:10 AM Amirreza Zarrabi
>>> <[email protected]> wrote:
>>>>
>>>> Hi Jens,
>>>>
>>>> Recently protected heap support has been added for the TEE subsystem.
>>>> This allows dma-heaps to be managed by the TEE subsystem itself.
>>>>
>>>> For standard, non-protected heaps such as the system heap or CMA heap,
>>>> I am trying to understand the expected usage model. One possible workaround
>>>> appears to be to mmap the dma-buf fd in userspace, then register the
>>>> resulting userspace VA with the TEE subsystem to obtain a TEE shared-memory
>>>> object, for example:
>>>>
>>>> fd = dma_heap_alloc(...);
>>>> va = mmap(fd, ...);
>>>>
>>>> shm_fd = tee_shm_register(va, size);
>>>> tee_invoke(shm_fd);
>>>>
>>>> close(shm_fd);
>>>> munmap(va, size);
>>>> close(fd);
>>>>
>>>> This seems reasonable when the lifetime of the registered shared memory
>>>> is limited to a single invocation or callback. However, I am concerned about
>>>> cases (multiple exits in qcomtee) where the TEE side needs to retain access
>>>> to the memory after the ioctl/invocation returns.
>>>>
>>>> In that case, registering only the userspace VA does not appear
>>>> to keep the underlying dma-buf object alive. The TEE core pins the pages,
>>>> but it does not hold a dma-buf reference or attachment. If userspace later
>>>> closes the dma-buf fd and unmaps the VA, the dma-buf exporter may consider
>>>> the buffer released, while the TEE side may still have the memory registered.
>>>
>>> That's surprising. Are the pages returned to the heap also? If so,
>>> there's an issue.
>>>
>>
>> Yes, that is my understanding. For dma-heaps, after the final dma-buf
>> reference is released, the exporter is free to return the backing pages to
>> the heap.
> 
> This should be a generic problem. Surely there must be something to
> stop the exporter from returning the pages.
> 

This is a standard use-after-free issue. The above sequence would be:
allocate a buffer from the Heap, mmap it to get a VA, save the VA (either
locally or giving it to the TEE framework), then unmap and close the dma-buf,
TEE tries to use the VA. This would be an issue no matter how you allocated
the memory, don't free memory still being used.

But the core question is:

> where the TEE side needs to retain access to the memory after the
> ioctl/invocation returns.

For this case, are you talking about when the TEE needs to keep memory
past one invocation for a whole session or for even longer than that?
(such as a supplicant helper allocating memory for a long running TEE/TA
process)

For either case the ownership of the buffer must pass to the TEE from
the application, and that is something we would need the ability to
register generic DMA-BUFs, so adding this support does seem valid.

>>
>>>>
>>>> Is there a recommended way to use standard heaps, such as the system or
>>>> CMA dma-buf heaps, when the sharing lifetime is longer than a single TEE call?
>>>
>>> No, I think you're pioneering this.
>>>
>>
>> ;-).
>>
>>>>
>>>> Would it make sense to extend tee_shm_register_fd() so that it can handle
>>>> dma-buf fds from regular dma-heaps as well, not only dma-bufs managed by
>>>> the TEE subsystem? That would allow the TEE core or backend driver to keep
>>>> the dma-buf reference for the lifetime of the TEE shared-memory object.
>>>
>>> It seems like a workaround, since I assume that the purpose is to
>>> share memory between the user space process and the TEE. I think this
>>> might be a last resort or something.
>>>
>>
>> Yes, I agree.
>>
>> The specific case I am looking at is qcomtee without an FF-A backend. In
>> that configuration, qcomtee currently requires physically contiguous shared
>> memory, so registering anonymous userspace memory is not very practical.
> 
> Agreed.
> 
>>
>> Today the qcomtee shared-memory pool is implemented on top of
>> tee_dyn_shm_alloc_helper(), which allocates memory from the normal page
>> allocator. This makes larger allocations subject to the usual high-order
>> allocation / MAX_ORDER limitations.
>>
>> One option would be to move, or extend, the qcomtee shared-memory pool to use
>> a cma backed allocation path. That would address the default allocation case
>> through TEE_IOC_SHM_ALLOC (without restriction).
> 
> CMA maintainers might have a view on that.
> 
>>
>> However, I am wondering whether it is better to also allow userspace to choose
>> the source of the memory, for example when the memory must come from a specific
>> carveout or from a cma dma-heap selected by the client.
>>
>> If you feel it is not a correct direction, I totally understand considering
>> it is workaround for a limitation.
> 
> It has an advantage by moving the problem to user-space. I can't say
> for sure what I think of it before I've seen the needed changes.
> tee_ioctl_shm_register_fd() or one of the helper functions will need
> some updates to handle generic DMA-bufs from elsewhere.
> 

Goes back to the original issues that folks brought up when upstreaming
the "secure" Heaps. How do we signal to the TEE that a buffer is safe
to consume and use. We can check things like if it is contiguous easy
enough, but is it a "secure" buffer, etc.. now we end up needing to
think about all kinds of flags and signalling. (just things to think
about, not that any of this is a true blocker).

Andrew

> Cheers,
> Jens