summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKamal Agrawal <kamaagra@codeaurora.org>2020-10-19 21:18:24 +0530
committerKamal Agrawal <kamaagra@codeaurora.org>2020-10-20 10:52:06 +0530
commitb81c4ac933f0bcbfa2bad5886c4013f8da52c86a (patch)
tree2d2879fabe844482f450e85f9107e9528e391f8f
parentdce57d817758260a14181dece4a2c8b92887e6e9 (diff)
msm: kgsl: Don't allow re-importing memory owned by KGSL
Don't allow IOCTL_KGSL_MAP_USER_MEM to import user memory that was already allocated and mapped by KGSL in the first place. Remapping memory never makes sense and it messes up reference counting in the pools. Change-Id: Ic0dedbade96ac6b30dcbbb794bf57a597f1bb351 Signed-off-by: Jordan Crouse <jcrouse@codeaurora.org> Signed-off-by: Kamal Agrawal <kamaagra@codeaurora.org>
-rw-r--r--drivers/gpu/msm/kgsl.c57
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(&current->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(&current->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(&current->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)