Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ad53897e authored by Puranam V G Tejaswi's avatar Puranam V G Tejaswi Committed by Gerrit - the friendly Code Review server
Browse files

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: default avatarPuranam V G Tejaswi <quic_pvgtejas@quicinc.com>
parent d4996007
Loading
Loading
Loading
Loading
+33 −8
Original line number Original line Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-License-Identifier: GPL-2.0-only
/*
/*
 * Copyright (c) 2008-2021, The Linux Foundation. All rights reserved.
 * 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.
 */
 */


#include <uapi/linux/sched/types.h>
#include <uapi/linux/sched/types.h>
@@ -2677,6 +2677,15 @@ static int kgsl_setup_anon_useraddr(struct kgsl_pagetable *pagetable,
}
}


#ifdef CONFIG_DMA_SHARED_BUFFER
#ifdef CONFIG_DMA_SHARED_BUFFER
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,
static void _setup_cache_mode(struct kgsl_mem_entry *entry,
		struct vm_area_struct *vma)
		struct vm_area_struct *vma)
{
{
@@ -2714,6 +2723,8 @@ static int kgsl_setup_dmabuf_useraddr(struct kgsl_device *device,
	vma = find_vma(current->mm, hostptr);
	vma = find_vma(current->mm, hostptr);


	if (vma && vma->vm_file) {
	if (vma && vma->vm_file) {
		int fd;

		ret = check_vma_flags(vma, entry->memdesc.flags);
		ret = check_vma_flags(vma, entry->memdesc.flags);
		if (ret) {
		if (ret) {
			up_read(&current->mm->mmap_sem);
			up_read(&current->mm->mmap_sem);
@@ -2729,13 +2740,27 @@ static int kgsl_setup_dmabuf_useraddr(struct kgsl_device *device,
			return -EFAULT;
			return -EFAULT;
		}
		}


		/* 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);
			}
			/*
			/*
		 * Take a refcount because dma_buf_put() decrements the
			 * It is possible that the fd obtained from iterate_fd
		 * refcount
			 * 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.
			 */
			 */
		get_file(vma->vm_file);
			if (dmabuf != vma->vm_file->private_data) {

				dma_buf_put(dmabuf);
		dmabuf = vma->vm_file->private_data;
				up_read(&current->mm->mmap_sem);
				return -EBADF;
			}
		}
	}
	}


	if (IS_ERR_OR_NULL(dmabuf)) {
	if (IS_ERR_OR_NULL(dmabuf)) {