diff options
author | Pankaj Gupta <quic_gpankaj@quicinc.com> | 2023-02-28 14:39:57 +0530 |
---|---|---|
committer | Pankaj Gupta <quic_gpankaj@quicinc.com> | 2023-02-28 14:39:57 +0530 |
commit | 438808d164b53fb3e58e16596abc832adce344bf (patch) | |
tree | 64036fe695df5aeccab5b1f7f340b656bdaa184a | |
parent | 67887f6ac3f11fd5ee1639e18d854e6071e58c51 (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>
Signed-off-by: Pankaj Gupta <quic_gpankaj@quicinc.com>
-rw-r--r-- | drivers/gpu/msm/kgsl.c | 41 |
1 files changed, 33 insertions, 8 deletions
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c index c41c5649490d..3024efab2b58 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 @@ -2240,6 +2240,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) { @@ -2278,6 +2287,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(¤t->mm->mmap_sem); @@ -2293,13 +2304,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(¤t->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(¤t->mm->mmap_sem); + return -EBADF; + } + } } if (IS_ERR_OR_NULL(dmabuf)) { |