[PATCH RFC v2 0/8] memcg: dma-buf cgroup accounting and charge transfer

Albert Esteve aesteve at redhat.com
Wed Oct 21 15:42:21 UTC 2026


This series adds memory cgroup accounting for dma-buf allocations,
building on T.J. Mercier's earlier series [1] and incorporating
feedback from the v1 and LPC discussions.

Patch 1 introduces the MEMCG_DMABUF stat and charge/uncharge helpers.
Rather than charging at the page level via __GFP_ACCOUNT (which would
require every dma-buf exporter to implement charging, and makes
cross-cgroup transfer impractical without access to backing pages),
we track charges externally on struct dma_buf via a MEMCG_DMABUF stat
counter and route all accounting through a single path, removing the
__GFP_ACCOUNT flag from system-heap allocations to avoid double
counting.

Patch 2 adds a charge_fd field to DMA_HEAP_IOCTL_ALLOC, accepting
either a pidfd or a cgroupfd to identify the target cgroup at
allocation time. If the target cgroup cannot accommodate the charge,
the allocation returns -ENOMEM.

Patches 3-4 add LSM hooks for the two charge_fd flavours:
security_dma_buf_charge_task() gates the pidfd path (target
identified by task credentials) and security_dma_buf_charge_cgroup()
gates the cgroupfd path (target identified by cgroup directory label).

Patches 5-6 implement the SELinux side under a dma_buf object class
with charge_task and charge_cgroup permissions. For charge_cgroup,
the target SID is derived from the cgroup directory's SELinux label.

Patch 7 adds DMA_BUF_IOCTL_XFER_CHARGE, a general ioctl on any
dma-buf fd to transfer charges (or charge) post-allocation. This
covers the double-hop allocator case (SurfaceFlinger -> gralloc) and
works for buffers from any exporter (DRM, V4L2, etc.). If the
receiving cgroup lacks capacity for the charge, the ioctl returns
-ENOMEM and the original charge is preserved.

Patch 8 adds selftests.

Known limitations:

- Single-owner model: a dma-buf carries one memcg charge regardless
  of how many processes share it.
- Only memcg accounting. CMA heaps would additionally need dmem
  controller integration.
- Charging CMA-backed heaps to memcg charges unreclaimable memory:
  when a cgroup hits its limit, try_charge_memcg() may trigger a
  reclaim pass that cannot free CMA pages. A future version could
  move charging into per-heap callbacks.
- If a transfer of an uncharged buffer fails, the buffer remains
  uncharged. The allocator (userspace) is expected to handle this
  (e.g., retry, free, ...).
- The LSM hook is intentionally narrow. Broader cgroup access controls
  could be a separate effort.

[1] https://lore.kernel.org/cgroups/20230109213809.418135-1-tjmercier@google.com/

Signed-off-by: Albert Esteve <aesteve at redhat.com>
---
Changes in v2:
- Move charge_pid_fd to charge_fd, accepting cgroupfd in addition
  to pidfd per Christian König.
- New DMA_BUF_IOCTL_XFER_CHARGE ioctl for post-allocation charge
  transfer on any dma-buf, not just dma-heap buffers per Christian König
  and T.J. Mercier.
- Moved __GFP_ACCOUNT removal to patch 1 per Barry Song.
- dma-buf charge/uncharge helpers take struct dma_buf * directly
  to avoid the need for caller to manage size calculations.
- Added test_xfer_charge_cgroupfd_self to dmabuf-heap selftests.
- Added LSM and SELinux hooks for cgroupfd-based charging.
- Rebased to v7.3-rc7.
- Link to v1: https://lore.kernel.org/r/20260512-v2_20230123_tjmercier_google_com-v1-0-6326701c3691@redhat.com

---
Albert Esteve (7):
      dma-heap: charge dma-buf memory via explicit memcg
      security: dma-buf: Add dma_buf_charge_task LSM hook
      security: dma-buf: Add dma_buf_charge_cgroup LSM hook
      selinux: Restrict cross-cgroup dma-buf charging
      selinux: Restrict dma-buf direct cgroup charging
      dma-buf: transfer memcg charges via DMA_BUF_IOCTL_XFER_CHARGE
      selftests/dmabuf-heaps: Add dma-buf memcg accounting tests

T.J. Mercier (1):
      memcg: Add MEMCG_DMABUF accounting infrastructure

 Documentation/admin-guide/cgroup-v2.rst            |   5 +
 drivers/dma-buf/dma-buf.c                          |  80 ++++++++
 drivers/dma-buf/dma-heap.c                         |  72 ++++++-
 drivers/dma-buf/heaps/system_heap.c                |   2 -
 include/linux/dma-buf.h                            |   4 +
 include/linux/lsm_hook_defs.h                      |   2 +
 include/linux/memcontrol.h                         |  29 +++
 include/linux/security.h                           |  14 ++
 include/uapi/linux/dma-buf.h                       |  26 +++
 include/uapi/linux/dma-heap.h                      |   7 +
 mm/memcontrol.c                                    |  94 +++++++++
 security/security.c                                |  32 +++
 security/selinux/hooks.c                           |  40 ++++
 security/selinux/include/classmap.h                |   1 +
 tools/testing/selftests/cgroup/Makefile            |   2 +-
 tools/testing/selftests/cgroup/test_memcontrol.c   | 145 +++++++++++++-
 tools/testing/selftests/dmabuf-heaps/config        |   1 +
 tools/testing/selftests/dmabuf-heaps/dmabuf-heap.c | 222 ++++++++++++++++++++-
 tools/testing/selftests/dmabuf-heaps/vmtest.sh     | 205 +++++++++++++++++++
 19 files changed, 974 insertions(+), 9 deletions(-)
---
base-commit: 24a19b953e2a3d0ea5a8c4951a0ab8f32720c907
change-id: 20260508-v2_20230123_tjmercier_google_com-f44fcfb16530

Best regards,
-- 
Albert Esteve <aesteve at redhat.com>




More information about the Linux-security-module-archive mailing list