# DF-4632 — radeon MST connector leaks one EDID blob per probe and per destroy

## What

`radeon_dp_mst_get_ddc_modes()` (sys/dev/drm/radeon/radeon_dp_mst.c:186-204)
does:

```c
edid = drm_dp_mst_get_edid(connector, &master->mst_mgr, radeon_connector->port);
radeon_connector->edid = edid;            /* <-- old pointer dropped, no kfree */
```

`drm_dp_mst_get_edid()` (sys/dev/drm/drm_dp_mst_topology.c:2553-2571) returns a
**fresh allocation on every call** — `drm_edid_duplicate(port->cached_edid)`
when cached, `drm_get_edid()` otherwise. The previous
`radeon_connector->edid` allocation is never freed, and neither destroy path
frees it either (`radeon_dp_destroy_mst_connector` :307-320 and
`radeon_dp_mst_connector_destroy` :248-258 both omit `kfree(edid)`).

## Trigger (unprivileged)

Every `drm_helper_probe_single_connector_modes` → `get_modes` for an MST
connector allocates a new EDID (128–512 bytes, `drm_edid` block(s)) and
abandons the previous one. A user with `/dev/dri/card0` access can force probes
in a loop (`DRM_IOCTL_MODE_GETCONNECTOR` without a cached mode set, or the
sysfs status read path) — each iteration leaks one EDID blob. Every hub
connect/disconnect cycle additionally leaks the last EDID of each destroyed
child connector.

Impact: unbounded kernel heap growth (memory-exhaustion DoS) driven by an
unprivileged desktop user; needs a DP MST topology (radeon DCE5+). Same reach
class as DF-1778's malicious-hub model.

## Upstream

Upstream radeon has the same historical pattern but its probe path for MST was
reworked; regardless, the in-tree fix is a one-liner (kfree before overwrite +
kfree in the destroy path).

## Fix

```diff
--- a/sys/dev/drm/radeon/radeon_dp_mst.c
+++ b/sys/dev/drm/radeon/radeon_dp_mst.c
@@ -191,6 +191,7 @@ static int radeon_dp_mst_get_ddc_modes(struct drm_connector *connector)
 	int ret = 0;
 
 	edid = drm_dp_mst_get_edid(connector, &master->mst_mgr, radeon_connector->port);
+	kfree(radeon_connector->edid);
 	radeon_connector->edid = edid;
@@ (radeon_dp_mst_connector_destroy / radeon_dp_destroy_mst_connector)
+	kfree(radeon_connector->edid);   /* before kfree(radeon_connector) */
```
