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

Commit 3441b34d authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "dma-buf: fix race while reading the dma_buf in dmabuffs_dname"

parents 28d4157e cdc117e0
Loading
Loading
Loading
Loading
+24 −3
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@
#include <linux/list_sort.h>
#include <linux/hashtable.h>
#include <linux/mount.h>
#include <linux/dcache.h>

#include <uapi/linux/dma-buf.h>
#include <uapi/linux/magic.h>
@@ -69,18 +70,34 @@ struct dma_proc {

static struct dma_buf_list db_list;

static void dmabuf_dent_put(struct dma_buf *dmabuf)
{
	if (atomic_dec_and_test(&dmabuf->dent_count)) {
		kfree(dmabuf->name);
		kfree(dmabuf);
	}
}


static char *dmabuffs_dname(struct dentry *dentry, char *buffer, int buflen)
{
	struct dma_buf *dmabuf;
	char name[DMA_BUF_NAME_LEN];
	size_t ret = 0;

	spin_lock(&dentry->d_lock);
	dmabuf = dentry->d_fsdata;
	if (!dmabuf || !atomic_add_unless(&dmabuf->dent_count, 1, 0)) {
		spin_unlock(&dentry->d_lock);
		goto out;
	}
	spin_unlock(&dentry->d_lock);
	mutex_lock(&dmabuf->lock);
	if (dmabuf->name)
		ret = strlcpy(name, dmabuf->name, DMA_BUF_NAME_LEN);
	mutex_unlock(&dmabuf->lock);

	dmabuf_dent_put(dmabuf);
out:
	return dynamic_dname(dentry, buffer, buflen, "/%s:%s",
			     dentry->d_name.name, ret > 0 ? name : "");
}
@@ -107,6 +124,7 @@ static struct file_system_type dma_buf_fs_type = {
static int dma_buf_release(struct inode *inode, struct file *file)
{
	struct dma_buf *dmabuf;
	struct dentry *dentry = file->f_path.dentry;
	int dtor_ret = 0;

	if (!is_dma_buf_file(file))
@@ -114,6 +132,9 @@ static int dma_buf_release(struct inode *inode, struct file *file)

	dmabuf = file->private_data;

	spin_lock(&dentry->d_lock);
	dentry->d_fsdata = NULL;
	spin_unlock(&dentry->d_lock);
	BUG_ON(dmabuf->vmapping_counter);

	/*
@@ -145,8 +166,7 @@ static int dma_buf_release(struct inode *inode, struct file *file)
		reservation_object_fini(dmabuf->resv);

	module_put(dmabuf->owner);
	kfree(dmabuf->buf_name);
	kfree(dmabuf);
	dmabuf_dent_put(dmabuf);
	return 0;
}

@@ -604,6 +624,7 @@ struct dma_buf *dma_buf_export(const struct dma_buf_export_info *exp_info)
	dmabuf->cb_excl.active = dmabuf->cb_shared.active = 0;
	dmabuf->buf_name = bufname;
	dmabuf->ktime = ktime_get();
	atomic_set(&dmabuf->dent_count, 1);

	if (!resv) {
		resv = (struct reservation_object *)&dmabuf[1];
+1 −0
Original line number Diff line number Diff line
@@ -445,6 +445,7 @@ struct dma_buf {
	struct list_head refs;
	dma_buf_destructor dtor;
	void *dtor_data;
	atomic_t dent_count;
};

/**