Resources

People often ask me "How did you learn how to hack?" The answer: by reading. This page is a collection of the blog posts and other articles that I have accumulated over the years of my journey. Enjoy!

[DMGuard Review] The CPU Freed the Page, but the GPU Is Still Looking at It- 2157

astronaut0703Posted 1 Month Ago
  • Kernel memory has always been built around a single question: is this pointer valid? ASLR, CFI, MTE, KASAN, and others have all taken on this problem. A new type of primitive has risen with the integration of GPUs into mobile SoCs with shared RAM: physical page ownership. Since both the CPU and GPU have their own separate page pools and mappings, it's possible for the GPU or the CPU to write to each other's memory.
  • The proper pattern is Alloc, Map Unmap, and Free. There are two dangerous patterns:
    • Free Before Unmap: The page is freed while the mapping still exists. The page is already gone, and the mapping no longer points at a physical page.
    • Map After Free: A new mapping is created for a page that has already been freed.
  • In both of the situations described above, the physical page is reallocated. So, an attacker with a reference to that location can read/write to the other side's page. When moving from GPU to CPU, overwriting a credential structure can easily lead to privilege escalation on Linux.
  • So, that's the bug class. The reason existing defenses don't catch it is that they assume address translation (physical-to-virtual) is correct. In the Linux kernel, CONFIG_PAGE_TABLE_CHECK counts mappings only in the CPU context, so a map after free can't be detected. This is why DMGuard has been suggested.
  • There is a simple state machine that tackles both of the invalid states described above. The core invariant: a page should only be mapped while it's allocated. The paper suggests adding two watchdogs to hold this invariant. MapCount counts the number of user-space mappings. If a page is not zero, then it's a bug. The idea is that DMGuard would check the CPU, GPU, and IOMMU page tables.
  • The second protection is Page Tag. The idea would be to use ARM64's top-byte ignore (TBI) that's used for pointer authentication/memory tagging for tag pointers. On allocation, give it a random page tag. On map, ensure that the pointer tag and the internally tracked page tag matter. On free, invalidate the tag. This would catch 99.6% of faults.
  • The design only results in a 0.22% slowdown in the GPU workload. Given the speed at which it operates and the 24 CVEs referenced in the paper, this seems like a worthwhile add. Good writeup of the paper!