# DF-3942 VERDICT — unchecked GET_IMAGE() NULL derefs in bios_parser.c SS parsers

## Bottom line

**inconclusive at runtime (no AMD GPU on the audit guest); the reachable
NULL dereference is proven at source level and by an executed logic replica
of the exact kernel decision path.** With a crafted or corrupt VBIOS whose
spread-spectrum table pointer points near the end of the ROM image, the
kernel dereferences a NULL `GET_IMAGE()` result and panics during driver
attach.

## The five sites

`GET_IMAGE(type, off)` is `(type *)bios_get_image(bp, off, sizeof(type))`
(bios_parser_helper.h) and returns NULL when `off + sizeof(type)` leaves the
image (bios_parser_helper.c:36-44). All five functions below fetch the
4-byte revision probe successfully (which gates entry), then fetch the full
struct **without checking for NULL** and immediately dereference
`->sHeader.usStructureSize`:

| # | function | GET_IMAGE | deref |
|---|----------|-----------|-------|
| 1 | `get_ss_info_from_internal_ss_info_tbl_V2_1` | bios_parser.c:1041 | :1046 |
| 2 | `get_ss_info_from_ss_info_table` | bios_parser.c:1114 | :1140 |
| 3 | `get_ss_entry_number_from_ss_info_tbl` | bios_parser.c:1645 | :1671 |
| 4 | `get_ss_entry_number_from_internal_ss_info_tbl_v2_1` | bios_parser.c:1723 | :1726 |
| 5 | `get_ss_entry_number_from_internal_ss_info_tbl_V3_1` | bios_parser.c:1759 | :1761 |

Reachability (site 1 traced; the others are the same shape):

1. `bios_parser_construct()` accepts any `usMasterDataTableOffset` whose
   ATOM_MASTER_DATA_TABLE fits (bios_parser.c:2898-2903);
2. `master_data_tbl->ListOfDataTables.AsicInternalSS_Info` is a raw VBIOS
   u16 — a crafted VBIOS points it at `bios_size - 10`;
3. `bios_parser_get_spread_spectrum_info()` (called during DC init / SS
   setup) probes `GET_IMAGE(ATOM_COMMON_TABLE_HEADER, off)`
   (bios_parser.c:952-954) — 4 bytes fit, the header claims rev 2.1 →
   gate passes;
4. `get_ss_info_from_tbl()` dispatches to site 1;
5. `GET_IMAGE(ATOM_ASIC_INTERNAL_SS_INFO_V2, off)` needs
   `4 + sizeof(ATOM_ASIC_SS_ASSIGNMENT_V2)` bytes — only 10 remain → NULL;
6. line 1046 loads `header->sHeader.usStructureSize` from NULL → **panic**.

Every sibling parser in the file *does* check: `get_gpio_pin_info`
(:1802), `get_gpio_i2c_info` (:1852), `get_embedded_panel_info_v1_2`
(:1233), `get_integrated_info_v8/v9` (:2248/:2398). The five missing checks
are plain omissions (upstream added them in later revisions).

Impact: deterministic kernel NULL-page dereference → panic at amdgpu/dc
attach (or first SS query). Attacker model: crafted VBIOS (flashed ROM,
passthrough ROM override, or bit-rotted image). DoS only — no info leak, no
write. Severity Low per the project rubric (crafted-VBIOS-gated DoS),
consistent with the class of DF-3741/DF-3745.

## What ran on the guest

* Hardware absence documented: no 1002: PCI device, no drm/amdgpu KLD.
* `bios_ss_null_deref_replica.c` (build.log, run.log): replicates
  `bios_get_image()` and the probe order exactly; prints the trace, then
  executes the replicated deref and dies with SIGSEGV (rc=139) — the same
  load the kernel would take. This demonstrates the NULL is reachable; it
  is honestly labeled a replica, not the in-kernel path.
* **Fix compile-validated**: `fix.diff` (5 NULL guards) applied to the
  guest's `/usr/src`, `amdgpu.ko` fully rebuilt with `-Werror`, rc=0
  (fix_build.log). Runtime baseline/patched comparison impossible without
  an AMD card → fix_status not_testable for that reason only.

## Kernel references

* sys/dev/drm/amd/display/dc/bios/bios_parser.c:1041,1046
* sys/dev/drm/amd/display/dc/bios/bios_parser.c:1114,1140
* sys/dev/drm/amd/display/dc/bios/bios_parser.c:1645,1671
* sys/dev/drm/amd/display/dc/bios/bios_parser.c:1723,1726
* sys/dev/drm/amd/display/dc/bios/bios_parser.c:1759,1761
* sys/dev/drm/amd/display/dc/bios/bios_parser_helper.c:36-44 — GET_IMAGE semantics

## Fix status (batch validation)
Applied with the 36 sibling fix.diffs of this batch in findings/poc/_batch41/all_fixes.patch; single in-guest `make -j6 nativekernel KERNCONF=X86_64_GENERIC` completed RC=0 with zero errors under -Werror (full log: findings/poc/_batch41/fix_build8.log). Behavior A/B intentionally skipped for this Info-tier item.
