# DF-4216 — dc_submit_i2c indexes dc->links[] with an unvalidated, wrong-domain index (DDC line number): NULL/wild deref and wrong-connector routing

- **File**: `sys/dev/drm/amd/display/dc/core/dc.c` (consumer); caller `sys/dev/drm/amd/display/amdgpu_dm/amdgpu_dm.c:4008-4010`
- **Lines**: 1736–1748 (dc_submit_i2c), amdgpu_dm.c:3983–4015 (caller)
- **Class**: unvalidated array index / index-domain confusion (CWE-129 → CWE-476)
- **Hardware gate**: AMD GPU with DC; mis-mapped DDC line ↔ link numbering (VBIOS object table)

## Root cause

```c
bool dc_submit_i2c(struct dc *dc, uint32_t link_index, struct i2c_command *cmd)
{
	struct dc_link *link = dc->links[link_index];   /* 1742: NO check */
	struct ddc_service *ddc = link->ddc;             /* 1743: deref    */
	return dce_i2c_submit_command(dc->res_pool, ddc->ddc_pin, cmd);
}
```

`link_index` is never validated against `dc->link_count` (array is
`links[MAX_PIPES*2]` = 12, kzalloc'd — slots ≥ link_count are NULL,
`dc.h:287`, `dc.c:731`). The only in-tree caller passes

```c
	dc_submit_i2c(ddc_service->ctx->dc,
	              ddc_service->ddc_pin->hw_info.ddc_channel,   /* !!! */
	              &cmd)
```

`hw_info.ddc_channel` is `i2c_info.i2c_line` — a `enum gpio_ddc_line`
DDC **line number** from the VBIOS connector object table
(`dc_link_ddc.c:269`, `gpio_types.h:206-220`: `GPIO_DDC_LINE_UNKNOWN = -1`,
DDC1..DDC6 = 0..5, DDC_VGA = 6, VIP/I2C pad = 7), **not** a link index
(`link->link_index`). Upstream Linux later fixed exactly this — current
amdgpu passes `ddc_service->link->link_index`.

## Impact

1. `GPIO_DDC_LINE_UNKNOWN (-1)` → `dc->links[0xffffffff]` → read far out of
   the `dc` struct → wild `dc_link*` → `link->ddc` deref → panic/corruption.
2. Any DDC line ≥ `link_count` (sparse connector maps: e.g. board exposing
   2 connectors whose lines are DDC3/VGA) → `links[n] == NULL` → NULL deref
   at 1743 → kernel panic on the first DDC transaction (EDID read during
   hotplug/detect).
3. Even when in range and non-NULL, line N ≠ link N in general → DDC/I2C
   transactions are routed to the **wrong physical connector** (EDID reads
   from the wrong monitor; functional correctness / info integrity).

## Verification status

**untested — hardware-gated** (no AMD GPU on the guest, `env.txt`). Source
certainty for the missing validation and the domain mismatch; real-world
trigger depends on board/VBIOS wiring.

## Fix

`fix.diff` (defensive, in-file): bounds-check `link_index` against
`dc->link_count`. Real fix belongs in amdgpu_dm.c (pass
`ddc_service->link->link_index`), noted for the upstream report.
