From cc1de524d8cea869daacc652108c76f403eb542d Mon Sep 17 00:00:00 2001 From: Arthur Hanson Rasmusson Date: Mon, 28 Sep 2026 09:31:48 -0400 Subject: sema: never execute work decoded from swept RAM; pin only tracker sems The content sweep reads arbitrary guest RAM and ran the full push decoder on every page, so fabricated method streams in unrelated data executed fills/copies: one boot scanned 65M pages, 'decoded' 124k pushes and ran dozens of memsets from false positives - writes into live guest memory (a guest kernel crashed in nvidia_uvm right after such a boot). - Swept pages now only permit the bounded semaphore-release writes; fills and copies execute only for pushes the pump read through a trusted ring translation. - Pushes read for a compute (GR) channel apply releases only: their method space is not the copy engine's, so aliased encodings must never become memory writes. - sempages.py derives the pages to pin from the client's tracker objects (sem object + sem memory) instead of matching bare sem-object shapes, which pinned 140 pages where the client has ~53 sems; shape scan remains as a fallback when no tracker resolves. --- tools/guest-diag/sempages.py | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) (limited to 'tools') diff --git a/tools/guest-diag/sempages.py b/tools/guest-diag/sempages.py index ad4dae6..f8d15b2 100755 --- a/tools/guest-diag/sempages.py +++ b/tools/guest-diag/sempages.py @@ -29,9 +29,25 @@ else: raise SystemExit(1) fd = os.open('/proc/%d/mem' % pid, os.O_RDONLY) -sems = m.sem_objs(pid, fd, lo, hi) +# Pin what libcuda actually polls: the semaphore objects referenced by the +# client's trackers (and the semaphore memory they point at). Scanning for +# bare sem-object shapes matches far too many pages once the ring/pushbuffer +# windows are in range; trackers are a structural reference, so pinning is +# limited to pages the client really waits on. Fall back to the shape scan +# only when no tracker resolves. +pages = set() +trackers = m.find_trackers(pid, fd, lo, hi, limit=256) +for _p, _sub, _last, _cur, sem, mem in trackers: + if sem: + pages.add(sem & ~0xfff) + if mem: + pages.add(mem & ~0xfff) +if not pages: + sems = m.sem_objs(pid, fd, lo, hi) + pages = {va & ~0xfff for va in sems} os.close(fd) -pages = sorted({va & ~0xfff for va in sems}) -print('sem VAs: %d pages: %d (window 0x%x..0x%x)' % (len(sems), len(pages), lo, hi)) +pages = sorted(pages) +print('trackers: %d pages: %d (window 0x%x..0x%x)' % + (len(trackers), len(pages), lo, hi)) for pg in pages: print('0x%x' % pg) -- cgit v1.2.3