{
  "finding_id": "DF-3656",
  "status": "inconclusive",
  "reproduced": 0,
  "impact": "none",
  "confidence": "certain",
  "verdict": "Source-certain error-path UAF, not runnable on the audit guest. (1) amdgpu_dm_connector_init() registers the DDC adapter with i2c_add_adapter (amdgpu_dm.c:4080) but its out_free handler kfrees it on any later failure (4133) without i2c_del_adapter \u2014 the adapter stays in the i2c core with adapdata pointing at freed memory; the next DDC/EDID/CEC transaction is a UAF. (2) amdgpu_dm_initialize_drm_device()s fail path (1937-1942) unconditionally kfrees the last aencoder/aconnector and all mode_info->planes[] even when they were fully registered into dev->mode_config.{encoder,connector,plane}_lists (encoder via amdgpu_dm_encoder_init:4164, connector via drm_connector_init:4089, planes via drm_universal_plane_init:3647+) \u2014 and the drivers own error unwind immediately calls drm_mode_config_cleanup() (amdgpu_dm_destroy_drm_device:1947) which walks those lists and invokes the freed objects destroy hooks; HPD IRQs also use the freed aconnector cookie (handle_hpd_irq -> aconnector->hpd_lock, 1083). Trigger requires an allocation or debugfs failure during DM init (fault-injection class) \u2014 hence Low severity. Guest is virtio-only (env.txt) and the trigger additionally needs induced OOM, so runtime reproduction is impossible here: inconclusive, source-certain. Distinct from DF-1153 (reset-function kzalloc failures), different functions and lifetime owners.",
  "exploit_chain": "Fault-injected amdgpu init failure after registration (e.g. amdgpu_irq_add_id failure at 1915, or connector_debugfs_init failure at 4120) -> fail path kfrees registered objects -> amdgpu_dm_fini -> drm_mode_config_cleanup iterates mode_config lists over freed memory -> use-after-free write/read during teardown (or freed i2c adapter dereference on the next DDC access).",
  "evidence": "VERDICT.md (full ownership trace with registration/free line proofs); fix.diff (de-register i2c before free; only free not-yet-registered objects, let drm_mode_config_cleanup own the rest; git apply --check clean); env.txt (guest has no AMD GPU)",
  "kernel_refs": [
    "sys/dev/drm/amd/display/amdgpu_dm/amdgpu_dm.c:4080",
    "sys/dev/drm/amd/display/amdgpu_dm/amdgpu_dm.c:4131",
    "sys/dev/drm/amd/display/amdgpu_dm/amdgpu_dm.c:1937",
    "sys/dev/drm/amd/display/amdgpu_dm/amdgpu_dm.c:1947",
    "sys/dev/drm/amd/display/amdgpu_dm/amdgpu_dm.c:4164"
  ],
  "poc_changes": "n/a \u2014 no seeded PoC; no harness is meaningful for an OOM-timing kernel-object ownership bug",
  "attempts": 1,
  "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT DragonFly 6.5-DEVELOPMENT #0: Thu Jul  2 06:02:54 UTC 2026     root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC  x86_64",
  "runtime_sec": 10,
  "guest_dirty": 0,
  "build_cmd": "n/a",
  "run_cmd": "n/a",
  "code_hash": "",
  "notes": "pass 2 amdgpu_dm.c error-path lifetime class (briefing item 5/6 adjacent); guest left clean",
  "recommended_fix": "In amdgpu_dm_connector_init failure paths call i2c_del_adapter() before kfree(i2c); in amdgpu_dm_initialize_drm_devices fail path only free objects DRM core does not yet own (sentinel ids) and leave registered objects to drm_mode_config_cleanup().",
  "fix_status": "not_testable",
  "fix_baseline_reproduced": 0,
  "fix_patched_reproduced": 0,
  "fix_verdict": "Requires amdgpu hardware plus fault injection to validate (baseline UAF vs patched clean teardown). fix.diff implements de-registration/ownership fix; git apply --check verified against sys/; not applied (read-only audit target).",
  "fix_evidence": "fix.diff in this pack"
}