⬢ DragonFlyBSD Kernel Audit
DF-4635 / fix.diff
← back to finding ↓ download raw
--- a/sys/dev/drm/radeon/radeon_audio.c
+++ b/sys/dev/drm/radeon/radeon_audio.c
@@ -262,9 +262,20 @@
 	if (rdev->mode_info.mode_config_initialized) {
 		list_for_each_entry(encoder, &rdev->ddev->mode_config.encoder_list, head) {
 			if (radeon_encoder_is_digital(encoder)) {
+				/*
+				 * Only TMDS-typed digital encoders carry a
+				 * radeon_encoder_atom_dig in enc_priv.
+				 * Digital transmitters wired to an LCD panel
+				 * (eDP, DRM_MODE_ENCODER_LVDS) carry the
+				 * smaller radeon_encoder_lvds instead; reading
+				 * dig->pin/dig->afmt past its end corrupts the
+				 * adjacent slab chunk.
+				 */
+				if (encoder->encoder_type != DRM_MODE_ENCODER_TMDS)
+					continue;
 				radeon_encoder = to_radeon_encoder(encoder);
 				dig = radeon_encoder->enc_priv;
-				if (dig->pin == pin)
+				if (dig && dig->pin == pin)
 					pin_count++;
 			}
 		}
@@ -456,7 +467,17 @@
 	if (!radeon_encoder_is_digital(encoder))
 		return;
 
+	/*
+	 * Same as above: enc_priv is a radeon_encoder_atom_dig only for
+	 * TMDS-typed digital encoders.  Mirrors the encoder_type gate already
+	 * used by the DVI/HDMI detect path in radeon_connectors.c.
+	 */
+	if (encoder->encoder_type != DRM_MODE_ENCODER_TMDS)
+		return;
+
 	dig = radeon_encoder->enc_priv;
+	if (!dig)
+		return;
 
 	if (status == connector_status_connected) {
 		if (connector->connector_type == DRM_MODE_CONNECTOR_DisplayPort) {