mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-27 19:29:37 +00:00
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: Ville Syrjälä <ville.syrjala@linux.intel.com> Reviewed-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
This commit is contained in:
parent
ee34ab5b01
commit
90367bf6e9
1 changed files with 28 additions and 5 deletions
|
@ -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,
|
||||||
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,
|
||||||
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,
|
||||||
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,
|
||||||
}
|
}
|
||||||
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);
|
||||||
|
|
Loading…
Reference in a new issue