⬢ DragonFlyBSD Kernel Audit
DF-3881 / fix.diff
← back to finding ↓ download raw
--- a/sys/dev/drm/drm_dp_mst_topology.c	2026-09-16 21:03:55.846742995 +0000
+++ b/sys/dev/drm/drm_dp_mst_topology.c	2026-09-16 21:04:11.754541465 +0000
@@ -845,6 +858,16 @@
 	if (!mstb)
 		return NULL;
 
+	/*
+	 * A RAD is at most 8 bytes (DP 1.2a), i.e. LCT <= 16.  Deeper chains
+	 * can only come from a hostile hub; refuse instead of running
+	 * memcpy(mstb->rad, rad, lct / 2) past rad[8].
+	 */
+	if (lct > 16) {
+		DRM_ERROR("MST: refusing topology deeper than LCT 16\n");
+		kfree(mstb);
+		return NULL;
+	}
 	mstb->lct = lct;
 	if (lct > 1)
 		memcpy(mstb->rad, rad, lct / 2);
@@ -1055,6 +1078,18 @@
 	int parent_lct = port->parent->lct;
 	int shift = 4;
 	int idx = (parent_lct - 1) / 2;
+
+	/*
+	 * rad[] in drm_dp_port_setup_pdt() is 6 bytes = 12 nibbles, so the
+	 * deepest addressable parent LCT is 12.  This also stops the
+	 * unbounded topology recursion: drm_dp_add_mst_branch_device()
+	 * rejects the returned lct, port->mstb stays NULL and no
+	 * LINK_ADDRESS is sent for the phantom child.
+	 */
+	if (parent_lct > 12) {
+		DRM_ERROR("MST: RAD overflow at parent LCT %d\n", parent_lct);
+		return 0xff;
+	}
 	if (parent_lct > 1) {
 		memcpy(rad, port->parent->rad, idx + 1);
 		shift = (parent_lct % 2) ? 4 : 0;
@@ -2956,7 +3006,7 @@
 {
 	struct drm_dp_mst_port *port;
 	int tabs = mstb->lct;
-	char prefix[10];
+	char prefix[18];	/* LCT capped at 16 by drm_dp_add_mst_branch_device */
 	int i;
 
 	for (i = 0; i < tabs; i++)