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

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
...@@ -1040,10 +1040,16 @@ void drm_crtc_convert_to_umode(struct drm_mode_modeinfo *out, ...@@ -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 * Convert a drm_mode_modeinfo into a drm_display_mode structure to return to
* the caller. * 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) struct drm_mode_modeinfo *in)
{ {
if (in->clock > INT_MAX || in->vrefresh > INT_MAX)
return -ERANGE;
out->clock = in->clock; out->clock = in->clock;
out->hdisplay = in->hdisplay; out->hdisplay = in->hdisplay;
out->hsync_start = in->hsync_start; out->hsync_start = in->hsync_start;
...@@ -1060,6 +1066,8 @@ void drm_crtc_convert_umode(struct drm_display_mode *out, ...@@ -1060,6 +1066,8 @@ void drm_crtc_convert_umode(struct drm_display_mode *out,
out->type = in->type; out->type = in->type;
strncpy(out->name, in->name, DRM_DISPLAY_MODE_LEN); strncpy(out->name, in->name, DRM_DISPLAY_MODE_LEN);
out->name[DRM_DISPLAY_MODE_LEN-1] = 0; out->name[DRM_DISPLAY_MODE_LEN-1] = 0;
return 0;
} }
/** /**
...@@ -1820,7 +1828,12 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data, ...@@ -1820,7 +1828,12 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
goto out; 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); drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
} }
...@@ -2492,7 +2505,12 @@ int drm_mode_attachmode_ioctl(struct drm_device *dev, ...@@ -2492,7 +2505,12 @@ int drm_mode_attachmode_ioctl(struct drm_device *dev,
goto out; 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); drm_mode_attachmode(dev, connector, mode);
out: out:
...@@ -2535,7 +2553,12 @@ int drm_mode_detachmode_ioctl(struct drm_device *dev, ...@@ -2535,7 +2553,12 @@ int drm_mode_detachmode_ioctl(struct drm_device *dev,
} }
connector = obj_to_connector(obj); 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); ret = drm_mode_detachmode(dev, connector, &mode);
out: out:
mutex_unlock(&dev->mode_config.mutex); mutex_unlock(&dev->mode_config.mutex);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment