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

Commit 23480320 authored by Da Hoon Pyun's avatar Da Hoon Pyun Committed by Gerrit - the friendly Code Review server
Browse files

msm: npu: Allocate buffer per client for register read



In order to avoid double free or use after free the buffer
allocated while reading registers, it is needed to allocate the
buffer per client and free it in release function.

Change-Id: I96b6b8671b517f9123b28ce07f546de06fe19eab
Signed-off-by: default avatarDa Hoon Pyun <dpyun@codeaurora.org>
parent 2dbb6bf7
Loading
Loading
Loading
Loading
+6 −2
Original line number Diff line number Diff line
@@ -113,8 +113,6 @@ struct npu_debugfs_ctx {
	struct dentry *root;
	uint32_t reg_off;
	uint32_t reg_cnt;
	char *buf;
	size_t buf_len;
	uint8_t *log_buf;
	struct mutex log_lock;
	uint32_t log_num_bytes_buffered;
@@ -123,6 +121,12 @@ struct npu_debugfs_ctx {
	uint32_t log_buf_size;
};

struct npu_debugfs_reg_ctx {
	char *buf;
	size_t buf_len;
	struct npu_device *npu_dev;
};

struct npu_mbox {
	struct mbox_client client;
	struct mbox_chan *chan;
+35 −21
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@
 */
static int npu_debug_open(struct inode *inode, struct file *file);
static int npu_debug_release(struct inode *inode, struct file *file);
static int npu_debug_reg_open(struct inode *inode, struct file *file);
static int npu_debug_reg_release(struct inode *inode, struct file *file);
static ssize_t npu_debug_reg_read(struct file *file,
		char __user *user_buf, size_t count, loff_t *ppos);
@@ -47,7 +48,7 @@ static ssize_t npu_debug_ctrl_write(struct file *file,
static struct npu_device *g_npu_dev;

static const struct file_operations npu_reg_fops = {
	.open = npu_debug_open,
	.open = npu_debug_reg_open,
	.release = npu_debug_reg_release,
	.read = npu_debug_reg_read,
};
@@ -89,16 +90,28 @@ static int npu_debug_release(struct inode *inode, struct file *file)
	return 0;
}

static int npu_debug_reg_release(struct inode *inode, struct file *file)
static int npu_debug_reg_open(struct inode *inode, struct file *file)
{
	struct npu_device *npu_dev = file->private_data;
	struct npu_debugfs_ctx *debugfs;
	struct npu_debugfs_reg_ctx *reg_ctx;

	debugfs = &npu_dev->debugfs_ctx;
	reg_ctx = kzalloc(sizeof(*reg_ctx), GFP_KERNEL);
	if (!reg_ctx)
		return -ENOMEM;

	kfree(debugfs->buf);
	debugfs->buf_len = 0;
	debugfs->buf = NULL;
	/* non-seekable */
	file->f_mode &= ~(FMODE_LSEEK | FMODE_PREAD | FMODE_PWRITE);
	reg_ctx->npu_dev = inode->i_private;
	file->private_data = reg_ctx;
	return 0;
}

static int npu_debug_reg_release(struct inode *inode, struct file *file)
{
	struct npu_debugfs_reg_ctx *reg_ctx = file->private_data;

	kfree(reg_ctx->buf);
	kfree(reg_ctx);
	file->private_data = NULL;
	return 0;
}

@@ -108,7 +121,8 @@ static int npu_debug_reg_release(struct inode *inode, struct file *file)
static ssize_t npu_debug_reg_read(struct file *file,
			char __user *user_buf, size_t count, loff_t *ppos)
{
	struct npu_device *npu_dev = file->private_data;
	struct npu_debugfs_reg_ctx *reg_ctx = file->private_data;
	struct npu_device *npu_dev = reg_ctx->npu_dev;
	struct npu_debugfs_ctx *debugfs;
	size_t len;

@@ -117,16 +131,16 @@ static ssize_t npu_debug_reg_read(struct file *file,
	if (debugfs->reg_cnt == 0)
		return 0;

	if (!debugfs->buf) {
	if (!reg_ctx->buf) {
		char dump_buf[64];
		char *ptr;
		int cnt, tot, off;

		debugfs->buf_len = sizeof(dump_buf) *
		reg_ctx->buf_len = sizeof(dump_buf) *
			DIV_ROUND_UP(debugfs->reg_cnt, ROW_BYTES);
		debugfs->buf = kzalloc(debugfs->buf_len, GFP_KERNEL);
		reg_ctx->buf = kzalloc(reg_ctx->buf_len, GFP_KERNEL);

		if (!debugfs->buf)
		if (!reg_ctx->buf)
			return -ENOMEM;

		ptr = (char *) (npu_dev->core_io.base + debugfs->reg_off);
@@ -140,28 +154,28 @@ static ssize_t npu_debug_reg_read(struct file *file,
			hex_dump_to_buffer(ptr, min(cnt, ROW_BYTES),
					   ROW_BYTES, GROUP_BYTES, dump_buf,
					   sizeof(dump_buf), false);
			len = scnprintf(debugfs->buf + tot,
				debugfs->buf_len - tot, "0x%08x: %s\n",
			len = scnprintf(reg_ctx->buf + tot,
				reg_ctx->buf_len - tot, "0x%08x: %s\n",
				((int) (unsigned long) ptr) -
				((int) (unsigned long) npu_dev->core_io.base),
				dump_buf);

			ptr += ROW_BYTES;
			tot += len;
			if (tot >= debugfs->buf_len)
			if (tot >= reg_ctx->buf_len)
				break;
		}
		npu_disable_core_power(npu_dev);

		debugfs->buf_len = tot;
		reg_ctx->buf_len = tot;
	}

	if (*ppos >= debugfs->buf_len)
	if (*ppos >= reg_ctx->buf_len)
		return 0; /* done reading */

	len = min(count, debugfs->buf_len - (size_t) *ppos);
	NPU_DBG("read %zi %zi\n", count, debugfs->buf_len - (size_t) *ppos);
	if (copy_to_user(user_buf, debugfs->buf + *ppos, len)) {
	len = min(count, reg_ctx->buf_len - (size_t) *ppos);
	NPU_DBG("read %zi %zi\n", count, reg_ctx->buf_len - (size_t) *ppos);
	if (copy_to_user(user_buf, reg_ctx->buf + *ppos, len)) {
		NPU_ERR("failed to copy to user\n");
		return -EFAULT;
	}