
PoCs and evidence for two NVIDIA Linux GPU driver findings closed by the vendor as expected/intended behavior: cross-UID GPU process telemetry via NVML, and an unprivileged Xid 31 copy-engine MMU fault via a peer-access teardown race.
Proof-of-concept code and raw evidence for two findings in the NVIDIA Linux GPU driver, both reported through NVIDIA's VDP and both closed by NVIDIA as intended/expected behavior. Published so the behaviour is documented and reproducible; neither has a CVE and neither will be fixed.
| # | Finding | Class | Vendor outcome | Directory |
|---|
| 1 | Cross-UID GPU process telemetry via NVML | Information disclosure (CWE-200 / CWE-862) | "expected behavior"; public disclosure authorized in writing 2026-08-20 | 01-nvml-cross-uid-telemetry/ |
| 2 | Unprivileged Xid 31 copy-engine MMU fault via P2P teardown race | GPU fault, unprivileged and deterministic | "intended behavior and as such is not a bug", closed 2026-08-04 | 02-xid31-p2p-teardown-race/ |
Tested on driver 595.71.05-open, A100-SXM4-80GB x4 (NV4 full mesh, no NVSwitch, MIG off), Ubuntu 24.04 / kernel 6.8.0, CUDA toolkit 12.9. Finding 1 also reproduced on 565.57.01-open.
Finding 1 is a real cross-UID exposure. Finding 2 is an unproven-impact fault. They are not equally strong and are not presented as such.
Finding 2 demonstrates that an unprivileged user can deterministically fault an NVLink GPU pair
(5/5, PID-attributed, against 4/4 clean negative controls). It does not demonstrate that the
fault outlives the triggering process. That measurement was never taken — the harness reset the
GPU reflexively before probing, and the node was deprovisioned before it could be repeated. Two
independent pieces of evidence argue the fault self-clears: NVIDIA's Xid catalog classifies
Xid 31 with immediate action RESTART_APP, and the GPU's own Recovery Action field read None
before the reset. Until someone runs the post-kill canary in
02-xid31-p2p-teardown-race/, treat this as a fault with
unproven blast radius, not a denial of service.
If you have an NVLink pair to spare, that one experiment is the highest-value thing anyone can contribute here. It takes a few minutes.
git clone https://github.com/abhinavagarwal07/nvidia-gpu-security-poc
cd nvidia-gpu-security-poc
./capture_env.sh # record your host's device perms, driver, topology, /proc opts
# Finding 1 — needs a second user running any CUDA workload
(cd 01-nvml-cross-uid-telemetry/poc && make && ./nvml_harvest)
# Finding 2 — needs two NVLink-connected GPUs. Faults a GPU pair. Do not run on shared hardware.
(cd 02-xid31-p2p-teardown-race/poc && ./build.sh && \
CUDA_VISIBLE_DEVICES=0,1 ./p2p_teardown_race_verbose --a 0 --p 1)
capture_env.sh output is what to attach if you report a difference from our results — it
records ls -l /dev/nvidia*, the /proc/driver/nvidia/params device-mode entries, /proc
mount options (a hidepid= mount changes what Finding 1 yields), topology, driver and pynvml
versions.
Finding 2 deliberately faults a GPU pair. It produces Xid 31 entries in the kernel log and may
require nvidia-smi --gpu-reset to clear — and on Ampere-generation NVLink/NVSwitch systems
NVIDIA documents that recovery in the fatal-trunk-link case is a fabric-wide operation, not a
single-GPU one. Run it only on hardware you own or have written authorization to disrupt, with
no co-tenants. All original testing was done on a sole-tenant, researcher-controlled node under
an authorized cluster lease.
Finding 1 is read-only and passive. It reads telemetry the driver already exposes to every local user; it writes nothing and injects nothing.
results/ in each directory holds the original machine-scored per-run verdict JSON, captured
dmesg Xid lines, positive and negative controls, the observer privilege audit, and environment
captures from the test node. GPU UUIDs, hardware serials and node IPs are redacted; nothing else
has been altered.
Full Disclosure posts for both findings, including vendor correspondence and disclosure timelines: https://abhinavagarwal07.github.io
PoC code and documentation: see LICENSE.