⬢ DragonFlyBSD Kernel Audit
DF-3942 / verdict.json
← back to finding ↓ download raw
{
  "finding_id": "DF-3942",
  "status": "inconclusive",
  "reproduced": 0,
  "impact": "panic",
  "confidence": "certain",
  "verdict": "Hardware-gated: the audit guest has no AMD/ATI PCI device and no amdgpu KLD, so the in-kernel path cannot execute \u2014 runtime reproduction inconclusive on this machine. The NULL dereference is proven at source level and by an executed userland logic replica of the exact kernel decision path (bios_get_image bounds semantics + probe order): with a crafted VBIOS whose AsicInternalSS_Info u16 points 10 bytes before the image end, the 4-byte revision probe at bios_parser.c:952 succeeds and gates rev 2.1 entry, the full-struct GET_IMAGE at :1041 returns NULL, and :1046 loads header->sHeader.usStructureSize from NULL -> kernel panic at amdgpu/dc attach. Five sites share the omission (:1041/:1046, :1114/:1140, :1645/:1671, :1723/:1726, :1759/:1761); every sibling parser in the file checks. The replica run.log shows the reached NULL (SIGSEGV rc=139).",
  "exploit_chain": "",
  "evidence": "run.log (replica: revision probe ok at off=bios_size-10, struct GET_IMAGE NULL, SIGSEGV on replicated deref); VERDICT.md (full per-site trace); fix_build.log (amdgpu.ko rebuilt with the 5 NULL guards, -Werror, rc=0)",
  "kernel_refs": [
    "sys/dev/drm/amd/display/dc/bios/bios_parser.c:1041",
    "sys/dev/drm/amd/display/dc/bios/bios_parser.c:1046",
    "sys/dev/drm/amd/display/dc/bios/bios_parser.c:1114",
    "sys/dev/drm/amd/display/dc/bios/bios_parser.c:1140",
    "sys/dev/drm/amd/display/dc/bios/bios_parser.c:1645",
    "sys/dev/drm/amd/display/dc/bios/bios_parser.c:1671",
    "sys/dev/drm/amd/display/dc/bios/bios_parser.c:1723",
    "sys/dev/drm/amd/display/dc/bios/bios_parser.c:1726",
    "sys/dev/drm/amd/display/dc/bios/bios_parser.c:1759",
    "sys/dev/drm/amd/display/dc/bios/bios_parser.c:1761",
    "sys/dev/drm/amd/display/dc/bios/bios_parser_helper.c:36"
  ],
  "poc_changes": "Authored as a logic replica (no seed existed): exact copies of bios_get_image() bounds semantics and the revision-gate order, packed ATOM struct layouts from atombios.h, live NULL load (first iteration was DCE-eliminated; fixed with noinline + observable result)",
  "attempts": 2,
  "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": 380,
  "guest_dirty": 0,
  "build_cmd": "cc -O2 -Wall -o /tmp/bios_ss_null_deref_replica bios_ss_null_deref_replica.c",
  "run_cmd": "/tmp/bios_ss_null_deref_replica",
  "code_hash": "fb436e54da53599302c57ce3614901964cada6d62e11b12a62b6754c5a22836a",
  "notes": "Knowns excluded: DF-1298/DF-1413 (bracket-layout write OOB), DF-1299 (usStructureSize/ucNumberOfObjects count walks incl. get_ss_info_v3_1:675 and get_gpio_pin_info:1812 in this file), DF-1414/1415 (bios_parser2.c). Additional DF-1299-class sibling instances observed but NOT re-filed: get_encoder_cap_record/bios_parser_get_encoder_cap_info (:1530-1545, record-content read past 2-byte validated window), get_gpio_i2c_info (:1866 `count < bfI2C_LineMux` off-by-one \u2014 harmless here because asGPIO_Info[16] is fully validated and the mux is 4 bits), get_ss_info_from_ss_info_table/get_ss_entry_number_from_ss_info_tbl SS_Info loops (:1140/:1671, count up to (0xffff-4)/8 vs asSS_Info[16] validated), get_bracket_layout_record (:2735 asObjects walk). Negative results: all five record walks break on ucRecordSize==0 (no DF-3741-style zero-stride infinite loop); no transmitter/analog/dig/TV/DFP/VESA-RB table walks exist in this file (they live in command_table*.c / bios_parser2.c); LVDS/LCD and integrated-info v1_2/v1_3/v8/v9 parsers read fixed structs fully covered by GET_IMAGE; bios_size is taken from the image byte (construct:2878) but the buffer is allocated from the same byte by amdgpu_get_bios (consistent); spread_percentage_divider is set to constants 100/1000, never zero (no DF-3743-style parse-side #DE in this file; downstream clk_mgr consumers are out of scope).",
  "recommended_fix": "Add NULL checks after each of the five GET_IMAGE() calls (fix.diff, matching the files own existing checks)",
  "fix_status": "not_testable",
  "fix_baseline_reproduced": 0,
  "fix_patched_reproduced": 0,
  "fix_verdict": "fix.diff (5 NULL guards) applied to guest /usr/src/sys; full amdgpu.ko module rebuilt under -Werror with rc=0 (fix_build.log). Runtime baseline/patched comparison impossible: no AMD GPU on the guest.",
  "fix_evidence": "fix_build.log (bios_parser.c recompiled, amdgpu.ko relinked, AMDGPU_FIX_MAKE_RC=0); fix.diff is git-apply-able (git apply --check passed on the audit tree)"
}