diff options
| -rw-r--r-- | drivers/gpu/msm/kgsl.c | 57 |
1 files changed, 26 insertions, 31 deletions
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c index 1e30cd9e3524..e081e579d142 100644 --- a/drivers/gpu/msm/kgsl.c +++ b/drivers/gpu/msm/kgsl.c @@ -2091,13 +2091,6 @@ long kgsl_ioctl_cmdstream_freememontimestamp_ctxtid( return ret; } -static inline int _check_region(unsigned long start, unsigned long size, - uint64_t len) -{ - uint64_t end = ((uint64_t) start) + size; - return (end > len); -} - static int check_vma_flags(struct vm_area_struct *vma, unsigned int flags) { @@ -2112,23 +2105,27 @@ static int check_vma_flags(struct vm_area_struct *vma, return -EFAULT; } -static int check_vma(struct vm_area_struct *vma, struct file *vmfile, - struct kgsl_memdesc *memdesc) +static int check_vma(unsigned long hostptr, u64 size) { - if (vma == NULL || vma->vm_file != vmfile) - return -EINVAL; + struct vm_area_struct *vma; + unsigned long cur = hostptr; - /* userspace may not know the size, in which case use the whole vma */ - if (memdesc->size == 0) - memdesc->size = vma->vm_end - vma->vm_start; - /* range checking */ - if (vma->vm_start != memdesc->useraddr || - (memdesc->useraddr + memdesc->size) != vma->vm_end) - return -EINVAL; - return check_vma_flags(vma, memdesc->flags); + while (cur < (hostptr + size)) { + vma = find_vma(current->mm, cur); + if (!vma) + return false; + + /* Don't remap memory that we already own */ + if (vma->vm_file && vma->vm_file->f_op == &kgsl_fops) + return false; + + cur = vma->vm_end; + } + + return true; } -static int memdesc_sg_virt(struct kgsl_memdesc *memdesc, struct file *vmfile) +static int memdesc_sg_virt(struct kgsl_memdesc *memdesc) { int ret = 0; long npages = 0, i; @@ -2150,19 +2147,17 @@ static int memdesc_sg_virt(struct kgsl_memdesc *memdesc, struct file *vmfile) } down_read(¤t->mm->mmap_sem); - /* If we have vmfile, make sure we map the correct vma and map it all */ - if (vmfile != NULL) - ret = check_vma(find_vma(current->mm, memdesc->useraddr), - vmfile, memdesc); - - if (ret == 0) { - npages = get_user_pages(current, current->mm, memdesc->useraddr, - sglen, write ? FOLL_WRITE : 0, - pages, NULL); - ret = (npages < 0) ? (int)npages : 0; + if (!check_vma(memdesc->useraddr, memdesc->size)) { + up_read(¤t->mm->mmap_sem); + ret = ~EFAULT; + goto out; } + + npages = get_user_pages(current, current->mm, memdesc->useraddr, + sglen, write ? FOLL_WRITE : 0, pages, NULL); up_read(¤t->mm->mmap_sem); + ret = (npages < 0) ? (int)npages : 0; if (ret) goto out; @@ -2213,7 +2208,7 @@ static int kgsl_setup_anon_useraddr(struct kgsl_pagetable *pagetable, entry->memdesc.gpuaddr = (uint64_t) entry->memdesc.useraddr; } - return memdesc_sg_virt(&entry->memdesc, NULL); + return memdesc_sg_virt(&entry->memdesc); } static int match_file(const void *p, struct file *file, unsigned int fd) |
