dma-buf: samsung: free chunk address array with original pointer

Secure chunk heap allocations with more than one chunk allocate a small kernel array containing the physical address of each chunk. The chunk heap passes the physical address of that array to the Samsung protected memory firmware through the Trusty memory protection call.

The old allocation path for multi-chunk buffers was:

paddr_array = kmalloc_array(nr_pages, sizeof(*paddr_array), GFP_KERNEL);
...
paddr = virt_to_phys(paddr_array);

priv = samsung_dma_buffer_protect(buffer, chunk_size, nr_pages, paddr);

samsung_dma_buffer_protect() then saved that same physical address in the protection descriptor:

protdesc->bus_address = paddr;

So the stored address flow was:

paddr_array
  -> virt_to_phys(paddr_array)
  -> paddr
  -> samsung_dma_buffer_protect(..., paddr)
  -> protdesc->bus_address

The old release path rebuilt a virtual address from that physical address and freed the rebuilt pointer:

if (protdesc->chunk_count > 1)
        paddr_array = phys_to_virt(protdesc->bus_address);

kfree(paddr_array);

That rebuilt pointer is not necessarily the same pointer returned by kmalloc_array(). On KASAN kernels the original pointer carries an allocation tag, and the rebuilt pointer does not. Releasing a multi-chunk vframe-secure or vstream-secure buffer can therefore report an invalid free in kfree().

Keep the original paddr_array pointer in buffer_prot_info as bus_address_vaddr. Use that pointer for DMA mapping and freeing, while keeping bus_address as the physical address passed to the Samsung protected memory firmware.

The one-chunk case is unchanged. It never allocates paddr_array: paddr remains page_to_phys(pages[0]), bus_address_vaddr is NULL, chunk_heap_unprotect() does not enter the chunk_count > 1 branch, and kfree(NULL) remains a no-op.

  • Test: manual. Opening a game from one of the user-opened issues, loading new game, then force stopping it caused a panic previously on rango. Panic no longer occurs after patch

  • Test: atest GosCompatDmaBufReleaseTests (https://github.com/GrapheneOS/platform_frameworks_base/pull/355). These tests, running as non-privileged apps, trigger the panic without this patch, and they pass with this patch. Existing CTS tests don't seem to cover this path.

Edited by inwaves

Merge request reports

Loading