β¬’ DragonFlyBSD Kernel Audit
← triage Β· dashboard
DF-4588

ttm_bo_vm_fault_dfly maps SG (prime-imported) foreign pages through the card node β€” the upstream TTM_PAGE_FLAG_SG refusal is dead code in #if 0

Summary

Upstream refuses to fault imported pages (redirecting mmap to the exporter); the live DFly fault has no such check: for prime-imported BOs it returns the exporter's ttm->pages into the importer's address space via the card-node mapping and mutates their cache attributes (pmap_page_set_memattr) with attributes chosen from the importer's placement - degrading coherency for every other mapping of those pages. Cross-driver cache-attribute DoS/coherency corruption via prime self-import. Port-the-SG-refusal fix.

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-4588 Β· 3 files
FileTypeDescriptionSize
README.md β€” 2.2 KB ↓ raw
df4588.c β€” 2.3 KB view raw
verdict.json β€” 2.5 KB view raw

DF-4588 β€” ttm_bo_vm_fault_dfly maps SG (prime-imported) pages via the card node; upstream refusal check is dead code

File: sys/dev/drm/ttm/ttm_bo_vm.c β€” the DFly fault ttm_bo_vm_fault_dfly (lines 499-725) has no TTM_PAGE_FLAG_SG refusal. Upstream's check (bo->ttm && (bo->ttm->page_flags & TTM_PAGE_FLAG_SG) -> VM_FAULT_SIGBUS, "Refuse to fault imported pages … handled by redirecting mmap to the exporter") sits dead inside the #if 0'd Linux body at lines 161-168.

Effect (radeon/amdgpu with prime import β€” wired on DFly: drm_ioctl.c:651-652, amdgpu_ttm.c:1272-1280 sets TTM_PAGE_FLAG_SG for imported BOs):

  • The imported BO's ttm->pages are the exporter's pages.
  • ttm_bo_vm_fault_dfly returns them to the importer's address space (m = ttm->pages[OFF_TO_IDX(offset)], :690; *mres = m, :714) through the card node mapping instead of the exporter's mmap path.
  • pmap_page_set_memattr(m, ...) (:695-697) and pmap_page_set_memattr(m, ttm_io_prot(...)) (:669) mutate the cache attribute of pages the TTM layer does not own β€” affecting every other mapping of those pages (exporter's CPU mapping included).

Impact: cross-driver page-attribute mutation (cache-mode downgrade / coherency break for foreign mappings) + mapping imported pages through the wrong node with driver-chosen attributes. Linux deliberately refuses this fault (correctness + caching reasons); not kernel memory corruption by itself. Low severity, hardware-gated (needs radeon/amdgpu).

Fix

Port the upstream check into the live DFly fault:

--- a/sys/dev/drm/ttm/ttm_bo_vm.c
+++ b/sys/dev/drm/ttm/ttm_bo_vm.c
@@ -584,6 +584,14 @@ ttm_bo_vm_fault_dfly(vm_object_t vm_obj, vm_ooffset_t offset,
        }
    }

+   /*
+    * Refuse to fault imported (SG) pages; mmap of such objects
+    * must be handled by the exporter (upstream ttm_bo_vm_fault).
+    */
+   if (bo->ttm && (bo->ttm->page_flags & TTM_PAGE_FLAG_SG)) {
+       retval = VM_PAGER_ERROR;
+       goto out_unlock1;
+   }
+
    if (bdev->driver->fault_reserve_notify) {

PoC (df4588.c) is a documentation stub: the full trigger needs amdgpu-specific GEM ioctls on real hardware. Untested on the audit guest (no DRM device β€” same gate as DF-4587/DF-4458).

Fix verification

not_testable
baseline no→ patch + rebuild →patched clean

one-line port of the upstream check (README.md); not compile-validated separately β€” trivially contained in the same fault function rebuilt for DF-4587's fix (ttm_bo_vm.c compiles -Werror clean in drm.ko)

README.md diff hunk
per-fix-DF-4588

Confirmed kernel references

Detail

Exploit chain

on amdgpu/radeon hardware: GEM_CREATE -> PRIME_HANDLE_TO_FD -> PRIME_FD_TO_HANDLE (self-import creates SG ttm_tt) -> GEM_MMAP ioctl -> mmap(card node, fake offset) -> touch -> foreign SG pages mapped with TTM-chosen attributes

Evidence (decisive lines)

README.md (code cites + ported upstream check); df4588.c (flow documentation)

PoC changes

no seed; documentation stub (full trigger requires amdgpu UAPI + hardware)

Verified recommended fix

Port the upstream TTM_PAGE_FLAG_SG refusal from the #if 0 body into ttm_bo_vm_fault_dfly (return VM_PAGER_ERROR before fault_reserve_notify)

Verdict

Upstream-divergence defect, certain in code, runtime hardware-gated: ttm_bo_vm_fault_dfly (ttm_bo_vm.c:499-725) lacks the upstream TTM_PAGE_FLAG_SG refusal (dead in #if 0 at ttm_bo_vm.c:161-168), so prime-imported BOs (TTM_PAGE_FLAG_SG set by amdgpu_ttm.c:1272-1280 / radeon_ttm.c:747; prime ioctls live at drm_ioctl.c:651-652) fault the exporter's pages through the card node and pmap_page_set_memattr mutates the cache attribute of pages TTM does not own (ttm_bo_vm.c:669,695-697). No kernel memory corruption by itself; cross-driver page-attribute/coherency impact. Not runnable on the audit guest (no DRM device); no runtime attempt made β€” PoC is a documentation stub plus the one-line port fix in README.md.