summaryrefslogtreecommitdiff
path: root/drivers/gpu
diff options
context:
space:
mode:
authorPuranam V G Tejaswi <quic_pvgtejas@quicinc.com>2023-02-14 16:09:02 +0530
committerMichael Bestas <mkbestas@lineageos.org>2023-05-02 21:01:53 +0300
commit59ceabe0d2423b929530d080c75a69f6feedabf0 (patch)
tree447f5f5ce313ea66b4036feb4e7008daa1afffe2 /drivers/gpu
parentd1f19956d6b9d29e0355fe10aa8eb29c75a0851a (diff)
msm: kgsl: Use dma_buf_get() to get dma_buf structure
Currently we don't ensure if vma->vm_file is associated with dma_buf. This can cause issues later when private_data from a non dma_buf file is used as dma_buf structure. Hence get the fd that is associated with vma->vm_file and use dma_buf_get() to get pointer to dma_buf structure. dma_buf_get() ensures that the file from the input fd is associated with dma_buf. Change-Id: Ib78aef8b16bedca5ca86d3a132278ff9f07dce73 Signed-off-by: Puranam V G Tejaswi <quic_pvgtejas@quicinc.com>
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/msm/kgsl.c41
1 files changed, 33 insertions, 8 deletions
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index fc6ab898ccaa..4b9f779e525e 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -1,5 +1,5 @@
/* Copyright (c) 2008-2021, The Linux Foundation. All rights reserved.
- * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -2241,6 +2241,15 @@ static int kgsl_setup_anon_useraddr(struct kgsl_pagetable *pagetable,
return ret;
}
+static int match_file(const void *p, struct file *file, unsigned int fd)
+{
+ /*
+ * We must return fd + 1 because iterate_fd stops searching on
+ * non-zero return, but 0 is a valid fd.
+ */
+ return (p == file) ? (fd + 1) : 0;
+}
+
static void _setup_cache_mode(struct kgsl_mem_entry *entry,
struct vm_area_struct *vma)
{
@@ -2279,6 +2288,8 @@ static int kgsl_setup_dmabuf_useraddr(struct kgsl_device *device,
vma = find_vma(current->mm, hostptr);
if (vma && vma->vm_file) {
+ int fd;
+
ret = check_vma_flags(vma, entry->memdesc.flags);
if (ret) {
up_read(&current->mm->mmap_sem);
@@ -2294,13 +2305,27 @@ static int kgsl_setup_dmabuf_useraddr(struct kgsl_device *device,
return -EFAULT;
}
- /*
- * Take a refcount because dma_buf_put() decrements the
- * refcount
- */
- get_file(vma->vm_file);
-
- dmabuf = vma->vm_file->private_data;
+ /* Look for the fd that matches this vma file */
+ fd = iterate_fd(current->files, 0, match_file, vma->vm_file);
+ if (fd) {
+ dmabuf = dma_buf_get(fd - 1);
+ if (IS_ERR(dmabuf)) {
+ up_read(&current->mm->mmap_sem);
+ return PTR_ERR(dmabuf);
+ }
+ /*
+ * It is possible that the fd obtained from iterate_fd
+ * was closed before passing the fd to dma_buf_get().
+ * Hence dmabuf returned by dma_buf_get() could be
+ * different from vma->vm_file->private_data. Return
+ * failure if this happens.
+ */
+ if (dmabuf != vma->vm_file->private_data) {
+ dma_buf_put(dmabuf);
+ up_read(&current->mm->mmap_sem);
+ return -EBADF;
+ }
+ }
}
if (IS_ERR_OR_NULL(dmabuf)) {