⬢ DragonFlyBSD Kernel Audit
DF-4201 / verdict.json
← back to finding ↓ download raw
{
  "finding_id": "DF-4201",
  "status": "not_reproduced",
  "reproduced": 0,
  "impact": "none",
  "confidence": "certain",
  "verdict": "DF-4033 radeon twin in amdgpu: three sites dereference the result of best_encoder()/enc_priv without NULL checks \u2014 amdgpu_connector_get_monitor_bpc:139-143 (best_encoder NULL from amdgpu_connector_best_single_encoder :346-357 / dvi_encoder :1122-1148 on an empty possible-encoder list, plus enc_priv NULL because dce_v*_0_encoder_add initializes it to NULL and only fills it if get_lcd_info/get_dig_info kzallocs succeed, dce_v10_0.c:3494/3520), amdgpu_connector_set_property:583-594 and amdgpu_connector_set_lcd_property:792-803 (scaling-mode branch, deref rmx_type/native_mode). Possible encoders are attached only by amdgpu_link_encoder_connector (amdgpu_encoders.c:45-56) \u2014 a VBIOS connector whose device bits match no encoder stays encoder-less while remaining registered. The monitor-bpc path fires on every modeset (atombios_crtc.c:773); the property paths via DRM_MASTER-gated MODE_SETPROPERTY/OBJ_SETPROPERTY (drm_ioctl.c:667/679). to_amdgpu_encoder(NULL) deref = deterministic NULL-page panic. The same file guards enc_priv at :484 \u2014 the omission is provable in-source. Not reproduced at runtime: guest has no AMD GPU (env.txt); trigger built and ran on the guest. Identical unguarded code in upstream Linux.",
  "exploit_chain": "display-session owner (DRM master) writes a connectors scaling-mode property on an encoder-less amdgpu connector (VBIOS misconfiguration), or any modeset on an eDP/LVDS panel with bpc-less EDID and failed dig/lcd-info allocation -> NULL deref panic",
  "evidence": "VERDICT.md (NULL-source proof at both levels: encoder list and enc_priv allocation); trigger_df4201.c + run.log (guest run, hardware-gated); fix.diff (three guards); env.txt",
  "kernel_refs": [
    "sys/dev/drm/amd/amdgpu/amdgpu_connectors.c:137-147",
    "sys/dev/drm/amd/amdgpu/amdgpu_connectors.c:577-604",
    "sys/dev/drm/amd/amdgpu/amdgpu_connectors.c:789-808",
    "sys/dev/drm/amd/amdgpu/amdgpu_connectors.c:346-357",
    "sys/dev/drm/amd/amdgpu/amdgpu_connectors.c:484-485",
    "sys/dev/drm/amd/amdgpu/amdgpu_encoders.c:45-56",
    "sys/dev/drm/amd/amdgpu/dce_v10_0.c:3494",
    "sys/dev/drm/drm_ioctl.c:667"
  ],
  "poc_changes": "trigger written from scratch (raw ioctls, self-contained struct defs, no libdrm); __u32/__u64 typedefs added after first guest compile",
  "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": "./build.sh  (guest cc -O2 -Wall)",
  "run_cmd": "./run.sh",
  "code_hash": "aef2cf69333a29c09c4765b0307c70de1f208f192e5b34af38095eb639e8ba16",
  "notes": "Hardware-gated: guest has no amdgpu device (env.txt). Shared-DDC walk NULL ddc_bus at :1038 analyzed and killed: shared_ddc=true provably implies ddc_bus!=NULL (it is only set when an existing connector with a live ddc_bus matched, and the same-id lookup then succeeds for the new connector).",
  "recommended_fix": "NULL-check best_encoder() results at the two scaling-mode sites and both encoder and enc_priv in the monitor-bpc branch (see fix.diff).",
  "fix_status": "not_testable",
  "fix_baseline_reproduced": 0,
  "fix_patched_reproduced": 0,
  "fix_verdict": "fix.diff applies cleanly to a pristine copy of the real amdgpu_connectors.c (verified, cumulative with DF-4200/4202 diffs), consistent with the in-file guard pattern at :484; kernel-build validation not possible on this guest (no AMD GPU).",
  "fix_evidence": "fix.diff; local patch --dry-run + applied-copy verification noted in VERDICT.md"
}