[PATCH] DRM: ensure fbdev helper arrays are appropriately dimensioned

Russell King rmk+kernel at arm.linux.org.uk
Fri Feb 7 13:12:54 PST 2014


If the number of connectors changes, then it is possible for the fbdev
helper to overrun/underrun some arrays which it allocates.  It allocates
these arrays based on mode_config.num_connector but then walks lists
using fb_helper->connector_count to limit the array index.  This can
lead to writes off the end of the arrays.

Fix this by allocating the arrays using fb_helper->connector_count.

A similar thing exists for some of the CRTC arrays.  For these, use
fb_helper->crtc_count.

Signed-off-by: Russell King <rmk+kernel at arm.linux.org.uk>
---
David,

Would you consider the following patch to clean up the DRM fb helper a
little - we already record the number of CRTCs and connectors in the
fb_helper structure.  While we officially don't support hotplugging,
this is more a consistency cleanup, so that we're dimensioning the
arrays using the same sizing that we will then use to walk over them.

Thanks.

 drivers/gpu/drm/drm_fb_helper.c | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index 0a19401aff80..0da727e55fd2 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -1360,7 +1360,7 @@ static int drm_pick_crtcs(struct drm_fb_helper *fb_helper,
 	if (modes[n] == NULL)
 		return best_score;
 
-	crtcs = kzalloc(dev->mode_config.num_connector *
+	crtcs = kcalloc(fb_helper->crtc_count,
 			sizeof(struct drm_fb_helper_crtc *), GFP_KERNEL);
 	if (!crtcs)
 		return best_score;
@@ -1406,7 +1406,7 @@ static int drm_pick_crtcs(struct drm_fb_helper *fb_helper,
 		if (score > best_score) {
 			best_score = score;
 			memcpy(best_crtcs, crtcs,
-			       dev->mode_config.num_connector *
+			       fb_helper->crtc_count *
 			       sizeof(struct drm_fb_helper_crtc *));
 		}
 	}
@@ -1430,11 +1430,11 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper)
 	width = dev->mode_config.max_width;
 	height = dev->mode_config.max_height;
 
-	crtcs = kcalloc(dev->mode_config.num_connector,
+	crtcs = kcalloc(fb_helper->connector_count,
 			sizeof(struct drm_fb_helper_crtc *), GFP_KERNEL);
-	modes = kcalloc(dev->mode_config.num_connector,
+	modes = kcalloc(fb_helper->connector_count,
 			sizeof(struct drm_display_mode *), GFP_KERNEL);
-	enabled = kcalloc(dev->mode_config.num_connector,
+	enabled = kcalloc(fb_helper->connector_count,
 			  sizeof(bool), GFP_KERNEL);
 	if (!crtcs || !modes || !enabled) {
 		DRM_ERROR("Memory allocation failed\n");
@@ -1447,8 +1447,8 @@ static void drm_setup_crtcs(struct drm_fb_helper *fb_helper)
 	if (!(fb_helper->funcs->initial_config &&
 	      fb_helper->funcs->initial_config(fb_helper, crtcs, modes,
 					       enabled, width, height))) {
-		memset(modes, 0, dev->mode_config.num_connector*sizeof(modes[0]));
-		memset(crtcs, 0, dev->mode_config.num_connector*sizeof(crtcs[0]));
+		memset(modes, 0, fb_helper->connector_count * sizeof(modes[0]));
+		memset(crtcs, 0, fb_helper->connector_count * sizeof(crtcs[0]));
 
 		if (!drm_target_cloned(fb_helper,
 				       modes, enabled, width, height) &&
-- 
1.8.3.1



More information about the dri-devel mailing list