⬢ DragonFlyBSD Kernel Audit
DF-5075 / verdict.json
← back to finding ↓ download raw
{
  "finding_id": "DF-5075",
  "status": "untested",
  "reproduced": false,
  "impact": "none",
  "confidence": "certain",
  "verdict": "Pass-2 audit of the v1 command-table helper hub (command_table_helper.c). The hub covers only DCE 8.0/8.1/8.3/10.0/11.0/11.2/11.22 (:38-56); for DCE_VERSION_12_0, DCN_VERSION_1_0, DCN_VERSION_1_01 and DCE_VERSION_UNKNOWN the default path (:58-61) returns false leaving *h untouched. The sole caller, bios_parser_construct, IGNORES the return (bios_parser.c:2936) inside a construct whose bp is kzallocd (bios_parser.c:100) -- so the failure leaves bp->cmd_helper == NULL while construct returns true. Reachability: the parser choice partitions on the VBIOS ROM header revision (parser2 requires >=2.2, bios_parser2.c:1948; parser1 requires <2.2, bios_parser.c:2895), NOT on ASIC generation, and dal_bios_parser_create falls back to parser1 whenever firmware_parser_create fails (bios_parser_interface.c:41-45). A DCE12/DCN ASIC (dc.c:626, dc_resource.c:84-95) with a legacy-format or header-corrupted VBIOS therefore gets parser1, a NULL cmd_helper, a SUCCESSFUL dc_construct (pools exist for 12.0/DCN, dc_resource.c:138-146), and then a whole-vtable NULL dereference at the first BIOS command -- e.g. bp->cmd_helper->assign_control_parameter at command_table.c:204/219 loads a function pointer from NULL+0x20 -- a kernel page-fault panic at display bring-up. The sibling hub proves the omission is a gap, not a design choice: command_table_helper2.c:63-75 serves the dce112 helper2 table for exactly DCE_VERSION_12_0/DCN1_0/1_01. Distinct from DF-4047/DF-4985/DF-5000 (initialized tables with NULL *members*): here the table pointer itself is NULL. Threat model equals DF-3942/DF-4985/DF-5000 (crafted/corrupt or cross-generation-paired VBIOS on modern silicon; physical prerequisite) -> Low. Kernel path untestable on this guest (no AMD GPU, env.txt); the C-semantics chain was demonstrated on the guest as an unprivileged user (trigger_nullhelper.c: ignored init failure -> NULL vtable -> SIGSEGV at the indirect call, exit 42, run.log). fix.diff (hub coverage mirroring helper2 + caller return-check) passes git apply --check; not applied to sys/.",
  "exploit_chain": "",
  "evidence": "VERDICT.md sections 1-3 (hub default path :58-61, caller ignoring at bios_parser.c:2936, the ROM-header-revision parser partition bios_parser.c:2895 / bios_parser2.c:1948, fallback bios_parser_interface.c:41-45, pool support dc_resource.c:138-146); run.log (guest userspace semantics demo, exit 42); env.txt (guest has no AMD GPU); fix.diff (git apply --check passes)",
  "kernel_refs": [
    "sys/dev/drm/amd/display/dc/bios/command_table_helper.c:34-63",
    "sys/dev/drm/amd/display/dc/bios/command_table_helper.c:58-61",
    "sys/dev/drm/amd/display/dc/bios/bios_parser.c:2936",
    "sys/dev/drm/amd/display/dc/bios/bios_parser.c:100",
    "sys/dev/drm/amd/display/dc/bios/bios_parser.c:2895",
    "sys/dev/drm/amd/display/dc/bios/bios_parser2.c:1948",
    "sys/dev/drm/amd/display/dc/bios/bios_parser_interface.c:41-45",
    "sys/dev/drm/amd/display/dc/core/dc.c:626",
    "sys/dev/drm/amd/display/dc/core/dc.c:641",
    "sys/dev/drm/amd/display/dc/core/dc_resource.c:84-95",
    "sys/dev/drm/amd/display/dc/core/dc_resource.c:138-146",
    "sys/dev/drm/amd/display/dc/bios/command_table_helper2.c:63-75",
    "sys/dev/drm/amd/display/dc/bios/command_table.c:204",
    "sys/dev/drm/amd/display/dc/bios/command_table.c:219",
    "sys/dev/drm/amd/display/dc/bios/command_table.c:507"
  ],
  "poc_changes": "evidence pack authored fresh in pass 2 (no seed). trigger_nullhelper.c is a guest userspace semantics harness mirroring steps (1)-(4) of the kernel chain, not a kernel PoC: no AMD GPU exists on the audit guest.",
  "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": 20,
  "guest_dirty": 0,
  "build_cmd": "sh build.sh   (cc -O2 -Wall -o trigger_nullhelper trigger_nullhelper.c)",
  "run_cmd": "sh run.sh     (expect exit 42)",
  "code_hash": "87797be86d632111767f486b4b0ac3c46e670e8044d7585e105ef687fd884c70",
  "notes": "pass 2 (GLM 5.3). Known family findings NOT re-reported: DF-2030/DF-4934/DF-4936 (dead return-0 dig_encoder_sel), DF-4935/DF-4937 (uninit clock-type output), DF-4985 (dce110 member-NULL matrix), DF-5000 (dce80 member-NULL + SetPixelClock-V7), DF-4047 (member-NULL via BIOS revisions on command_table.c). DF-5075 is the complementary row: the *table pointer* NULL via version-dispatch gap + ignored init failure. Family NULL-matrix completed in VERDICT.md section 5. Guest left clean (only /tmp/df5075); guest was already up, no reset needed.",
  "recommended_fix": "Mirror helper2 coverage: serve dal_cmd_tbl_helper_dce112_get_table2() for DCE_VERSION_12_0/DCN1_0/1_01 in the v1 hub, and make bios_parser.c:2936 check the return and fail construct -- see fix.diff.",
  "fix_status": "not_testable",
  "fix_baseline_reproduced": 0,
  "fix_patched_reproduced": 0,
  "fix_verdict": "not_testable - requires AMD DCE12/DCN hardware with a legacy-format VBIOS; the audit guest has no AMD GPU, so neither baseline nor patched kernel path can execute. fix.diff is git-apply --check verified against the pristine sys/ tree; it mirrors the only in-tree handling of these generations (command_table_helper2.c:63-75) plus the caller-side return check.",
  "fix_evidence": "findings/poc/DF-5075/fix.diff (git apply --check passes; never applied to sys/)"
}