diff options
author | David Herrmann <dh.herrmann@gmail.com> | 2014-01-20 14:09:55 -0500 |
---|---|---|
committer | David Herrmann <dh.herrmann@gmail.com> | 2014-03-16 07:11:01 -0400 |
commit | b28cd41f9e9bb8085f7362c80833fc129628d3d6 (patch) | |
tree | db129e135dc3e67d6cfddfd8fc63ae93efa84c97 | |
parent | 77472347972add74a3d89a0b9152b8eebc0ad2b0 (diff) |
drm/crtc: add sanity checks to create_dumb()
Lets make sure some basic expressions are always true:
bpp != NULL
width != NULL
height != NULL
stride = bpp * width < 2^32
size = stride * height < 2^32
PAGE_ALIGN(size) < 2^32
At least the udl driver doesn't check for multiplication-overflows, so
lets just make sure it will never happen. These checks allow drivers to do
any 32bit math without having to test for mult-overflows themselves.
The two divisions might hurt performance a bit, but dumb_create() is only
used for scanout-buffers, so that should be fine. We could use 64bit math
to avoid the divisions, but that may be slow on 32bit machines.. Or maybe
there should just be a "safe_mult32()" helper, which currently doesn't
exist (I think?).
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Signed-off-by: David Herrmann <dh.herrmann@gmail.com>
-rw-r--r-- | drivers/gpu/drm/drm_crtc.c | 17 |
1 files changed, 17 insertions, 0 deletions
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 35ea15d5ffff..b1c2b278005c 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c | |||
@@ -3784,9 +3784,26 @@ int drm_mode_create_dumb_ioctl(struct drm_device *dev, | |||
3784 | void *data, struct drm_file *file_priv) | 3784 | void *data, struct drm_file *file_priv) |
3785 | { | 3785 | { |
3786 | struct drm_mode_create_dumb *args = data; | 3786 | struct drm_mode_create_dumb *args = data; |
3787 | u32 cpp, stride, size; | ||
3787 | 3788 | ||
3788 | if (!dev->driver->dumb_create) | 3789 | if (!dev->driver->dumb_create) |
3789 | return -ENOSYS; | 3790 | return -ENOSYS; |
3791 | if (!args->width || !args->height || !args->bpp) | ||
3792 | return -EINVAL; | ||
3793 | |||
3794 | /* overflow checks for 32bit size calculations */ | ||
3795 | cpp = DIV_ROUND_UP(args->bpp, 8); | ||
3796 | if (cpp > 0xffffffffU / args->width) | ||
3797 | return -EINVAL; | ||
3798 | stride = cpp * args->width; | ||
3799 | if (args->height > 0xffffffffU / stride) | ||
3800 | return -EINVAL; | ||
3801 | |||
3802 | /* test for wrap-around */ | ||
3803 | size = args->height * stride; | ||
3804 | if (PAGE_ALIGN(size) == 0) | ||
3805 | return -EINVAL; | ||
3806 | |||
3790 | return dev->driver->dumb_create(file_priv, dev, args); | 3807 | return dev->driver->dumb_create(file_priv, dev, args); |
3791 | } | 3808 | } |
3792 | 3809 | ||