From: Hyesoo Yu Date: Tue, 27 Mar 2018 10:57:16 +0000 (+0900) Subject: [COMMON] g2d: fix the compat ioctl X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=f7b2532f780c02de1adc8f4d4da6eed90afcad28;p=GitHub%2FLineageOS%2Fandroid_kernel_motorola_exynos9610.git [COMMON] g2d: fix the compat ioctl The variable of buffer is corrupted while looping, so incorrect data is written to the user's area in the loop. And user address of buffer is possible to be corrupted when union variable is not initialized, so fix it. Change-Id: I5bb38eb4dd548a868153a32ebd5b31a76a20f112 Signed-off-by: Hyesoo Yu --- diff --git a/drivers/gpu/exynos/g2d/g2d_drv.c b/drivers/gpu/exynos/g2d/g2d_drv.c index a3ef84183eb5..178458c7e590 100644 --- a/drivers/gpu/exynos/g2d/g2d_drv.c +++ b/drivers/gpu/exynos/g2d/g2d_drv.c @@ -520,7 +520,7 @@ static int g2d_compat_get_layerdata(struct device *dev, struct g2d_layer_data __user *img, struct compat_g2d_layer_data __user *cimg) { - __u32 uw; + __u32 uw, num_buffers, buftype; __s32 sw; compat_ulong_t l; unsigned int i; @@ -530,18 +530,21 @@ static int g2d_compat_get_layerdata(struct device *dev, ret |= put_user(uw, &img->flags); ret |= get_user(sw, &cimg->fence); ret |= put_user(sw, &img->fence); - ret |= get_user(uw, &cimg->buffer_type); - ret |= put_user(uw, &img->buffer_type); - ret |= get_user(uw, &cimg->num_buffers); - ret |= put_user(uw, &img->num_buffers); - - for (i = 0; i < uw; i++) { /* uw contains num_buffers */ - ret |= get_user(l, &cimg->buffer[i].userptr); - ret |= put_user(l, &img->buffer[i].userptr); - ret |= get_user(uw, &cimg->buffer[i].dmabuf.offset); - ret |= put_user(uw, &img->buffer[i].dmabuf.offset); - ret |= get_user(sw, &cimg->buffer[i].dmabuf.fd); - ret |= put_user(sw, &img->buffer[i].dmabuf.fd); + ret |= get_user(buftype, &cimg->buffer_type); + ret |= put_user(buftype, &img->buffer_type); + ret |= get_user(num_buffers, &cimg->num_buffers); + ret |= put_user(num_buffers, &img->num_buffers); + + for (i = 0; i < num_buffers; i++) { + if (buftype == G2D_BUFTYPE_DMABUF) { + ret |= get_user(uw, &cimg->buffer[i].dmabuf.offset); + ret |= put_user(uw, &img->buffer[i].dmabuf.offset); + ret |= get_user(sw, &cimg->buffer[i].dmabuf.fd); + ret |= put_user(sw, &img->buffer[i].dmabuf.fd); + } else { + ret |= get_user(l, &cimg->buffer[i].userptr); + ret |= put_user(l, &img->buffer[i].userptr); + } ret |= get_user(uw, &cimg->buffer[i].length); ret |= put_user(uw, &img->buffer[i].length); }