Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 90367bf6 authored by Ville Syrjälä's avatar Ville Syrjälä Committed by Dave Airlie
Browse files

drm: Check user mode against overflows



The internal mode representation drm_display_mode uses signed data
types. When converting the user mode to internal representation,
check that the unsigned values don't overflow the signed datatypes.

Signed-off-by: default avatarVille Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: default avatarAlex Deucher <alexander.deucher@amd.com>
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent ee34ab5b
Loading
Loading
Loading
Loading
+28 −5
Original line number Diff line number Diff line
@@ -1040,10 +1040,16 @@ void drm_crtc_convert_to_umode(struct drm_mode_modeinfo *out,
 *
 * Convert a drm_mode_modeinfo into a drm_display_mode structure to return to
 * the caller.
 *
 * RETURNS:
 * Zero on success, errno on failure.
 */
void drm_crtc_convert_umode(struct drm_display_mode *out,
int drm_crtc_convert_umode(struct drm_display_mode *out,
			   struct drm_mode_modeinfo *in)
{
	if (in->clock > INT_MAX || in->vrefresh > INT_MAX)
		return -ERANGE;

	out->clock = in->clock;
	out->hdisplay = in->hdisplay;
	out->hsync_start = in->hsync_start;
@@ -1060,6 +1066,8 @@ void drm_crtc_convert_umode(struct drm_display_mode *out,
	out->type = in->type;
	strncpy(out->name, in->name, DRM_DISPLAY_MODE_LEN);
	out->name[DRM_DISPLAY_MODE_LEN-1] = 0;

	return 0;
}

/**
@@ -1820,7 +1828,12 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
			goto out;
		}

		drm_crtc_convert_umode(mode, &crtc_req->mode);
		ret = drm_crtc_convert_umode(mode, &crtc_req->mode);
		if (ret) {
			DRM_DEBUG_KMS("Invalid mode\n");
			goto out;
		}

		drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
	}

@@ -2492,7 +2505,12 @@ int drm_mode_attachmode_ioctl(struct drm_device *dev,
		goto out;
	}

	drm_crtc_convert_umode(mode, umode);
	ret = drm_crtc_convert_umode(mode, umode);
	if (ret) {
		DRM_DEBUG_KMS("Invalid mode\n");
		drm_mode_destroy(dev, mode);
		goto out;
	}

	drm_mode_attachmode(dev, connector, mode);
out:
@@ -2535,7 +2553,12 @@ int drm_mode_detachmode_ioctl(struct drm_device *dev,
	}
	connector = obj_to_connector(obj);

	drm_crtc_convert_umode(&mode, umode);
	ret = drm_crtc_convert_umode(&mode, umode);
	if (ret) {
		DRM_DEBUG_KMS("Invalid mode\n");
		goto out;
	}

	ret = drm_mode_detachmode(dev, connector, &mode);
out:
	mutex_unlock(&dev->mode_config.mutex);