diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c index d7c5026c32fad26d6e0d13ddc34fc95a8dd1c46b..863782a430bcf8a63c1c7f421ffddf0c5348f51f 100644 --- a/drivers/gpu/msm/kgsl.c +++ b/drivers/gpu/msm/kgsl.c @@ -2549,6 +2549,20 @@ static int kgsl_setup_phys_file(struct kgsl_mem_entry *entry, } #endif +static int check_vma_flags(struct vm_area_struct *vma, + unsigned int flags) +{ + unsigned long flags_requested = (VM_READ | VM_WRITE); + + if (flags & KGSL_MEMFLAGS_GPUREADONLY) + flags_requested &= ~VM_WRITE; + + if ((vma->vm_flags & flags_requested) == flags_requested) + return 0; + + return -EFAULT; +} + static int check_vma(struct vm_area_struct *vma, struct file *vmfile, struct kgsl_memdesc *memdesc) { @@ -2562,7 +2576,7 @@ static int check_vma(struct vm_area_struct *vma, struct file *vmfile, if (vma->vm_start != memdesc->useraddr || (memdesc->useraddr + memdesc->size) != vma->vm_end) return -EINVAL; - return 0; + return check_vma_flags(vma, memdesc->flags); } static int memdesc_sg_virt(struct kgsl_memdesc *memdesc, struct file *vmfile) @@ -2571,7 +2585,7 @@ static int memdesc_sg_virt(struct kgsl_memdesc *memdesc, struct file *vmfile) long npages = 0; unsigned long sglen = memdesc->size / PAGE_SIZE; struct page **pages = NULL; - int write = (memdesc->flags & KGSL_MEMFLAGS_GPUREADONLY) != 0; + int write = ((memdesc->flags & KGSL_MEMFLAGS_GPUREADONLY) ? 0 : 1); pages = kgsl_malloc(sglen * sizeof(struct page *)); if (pages == NULL) @@ -2654,6 +2668,7 @@ static int kgsl_setup_useraddr(struct kgsl_mem_entry *entry, struct kgsl_map_user_mem *param = data; struct dma_buf *dmabuf = NULL; struct vm_area_struct *vma = NULL; + int ret; if (param->offset != 0 || param->hostptr == 0 || !KGSL_IS_PAGE_ALIGNED(param->hostptr) @@ -2670,6 +2685,12 @@ static int kgsl_setup_useraddr(struct kgsl_mem_entry *entry, if (vma && vma->vm_file) { int fd; + ret = check_vma_flags(vma, entry->memdesc.flags); + if (ret) { + up_read(¤t->mm->mmap_sem); + return ret; + } + /* * Check to see that this isn't our own memory that we have * already mapped @@ -2688,7 +2709,7 @@ static int kgsl_setup_useraddr(struct kgsl_mem_entry *entry, up_read(¤t->mm->mmap_sem); if (!IS_ERR_OR_NULL(dmabuf)) { - int ret = kgsl_setup_dma_buf(entry, pagetable, device, dmabuf); + ret = kgsl_setup_dma_buf(entry, pagetable, device, dmabuf); if (ret) dma_buf_put(dmabuf); else {