⬢ DragonFlyBSD Kernel Audit
DF-3885 / fix.diff
← back to finding ↓ download raw
--- a/sys/dev/drm/drm_fb_helper.c	2026-09-16 21:05:17.781704991 +0000
+++ b/sys/dev/drm/drm_fb_helper.c	2026-09-16 21:05:17.793704839 +0000
@@ -2422,7 +2422,8 @@
 static int drm_pick_crtcs(struct drm_fb_helper *fb_helper,
 			  struct drm_fb_helper_crtc **best_crtcs,
 			  struct drm_display_mode **modes,
-			  int n, int width, int height)
+			  int n, int width, int height,
+			  unsigned long *budget)
 {
 	int c, o;
 	struct drm_connector *connector;
@@ -2433,11 +2434,23 @@
 	if (n == fb_helper->connector_count)
 		return 0;
 
+	/*
+	 * The recursion below is (crtcs + 1)^connectors calls when every
+	 * connector has a mode.  A hostile MST hub can enumerate dozens of
+	 * connectors, which would pin a kms worker (holding fb_helper->lock)
+	 * for days.  Bail out of the exhaustive search once the budget is
+	 * spent and keep the best configuration found so far.
+	 */
+	if (!*budget)
+		return 0;
+	(*budget)--;
+
 	fb_helper_conn = fb_helper->connector_info[n];
 	connector = fb_helper_conn->connector;
 
 	best_crtcs[n] = NULL;
-	best_score = drm_pick_crtcs(fb_helper, best_crtcs, modes, n+1, width, height);
+	best_score = drm_pick_crtcs(fb_helper, best_crtcs, modes, n+1, width, height,
+				    budget);
 	if (modes[n] == NULL)
 		return best_score;
 
@@ -2481,7 +2494,9 @@
 		crtcs[n] = crtc;
 		memcpy(crtcs, best_crtcs, n * sizeof(struct drm_fb_helper_crtc *));
 		score = my_score + drm_pick_crtcs(fb_helper, crtcs, modes, n + 1,
-						  width, height);
+						  width, height, budget);
+		if (!*budget)
+			break;	/* budget exhausted, keep best so far */
 		if (score > best_score) {
 			best_score = score;
 			memcpy(best_crtcs, crtcs,
@@ -2599,7 +2614,13 @@
 		DRM_DEBUG_KMS("picking CRTCs for %dx%d config\n",
 			      width, height);
 
-		drm_pick_crtcs(fb_helper, crtcs, modes, 0, width, height);
+		{
+			/* ~1M pick_crtcs invocations is already seconds of KMS work */
+			unsigned long budget = 1 << 20;
+
+			drm_pick_crtcs(fb_helper, crtcs, modes, 0, width, height,
+				       &budget);
+		}
 	}
 	mutex_unlock(&fb_helper->dev->mode_config.mutex);