From: Alexandru Tachici alexandru.tachici@analog.com
mainline inclusion from mainline-v5.7-rc1 commit 2ddc982a6c172c141183ac954d44f01bc4f2fe72 category: bugfix bugzilla: 94099,https://gitee.com/openeuler/kernel/issues/I8KXZX CVE: NA
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i...
--------------------------------
Currently iio_debugfs_read_reg calls debugfs_reg_access every time it is ran. Reading the same hardware register multiple times during the same reading of a debugfs file can cause unintended effects.
For example for each: cat iio:device0/direct_reg_access the file_operations.read function will be called at least twice. First will return the full length of the string in bytes and the second will return 0.
This patch makes iio_debugfs_read_reg to call debugfs_reg_access only when the user's buffer position (*ppos) is 0. (meaning it is the beginning of a new reading of the debugfs file).
Fixes: e553f182d55b ("staging: iio: core: Introduce debugfs support, add support for direct register access") Signed-off-by: Alexandru Ardelean alexandru.ardelean@analog.com Signed-off-by: Alexandru Tachici alexandru.tachici@analog.com Signed-off-by: Jonathan Cameron Jonathan.Cameron@huawei.com Signed-off-by: Zhao Wenhui zhaowenhui8@huawei.com --- drivers/iio/industrialio-core.c | 15 +++++++++++---- include/linux/iio/iio.h | 2 ++ 2 files changed, 13 insertions(+), 4 deletions(-)
diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c index 49d4b4f1a457..421dcbae80f1 100644 --- a/drivers/iio/industrialio-core.c +++ b/drivers/iio/industrialio-core.c @@ -297,11 +297,14 @@ static ssize_t iio_debugfs_read_reg(struct file *file, char __user *userbuf, size_t count, loff_t *ppos) { struct iio_dev *indio_dev = file->private_data; - char buf[20]; unsigned val = 0; - ssize_t len; int ret;
+ if (*ppos > 0) + return simple_read_from_buffer(userbuf, count, ppos, + indio_dev->read_buf, + indio_dev->read_buf_len); + ret = indio_dev->info->debugfs_reg_access(indio_dev, indio_dev->cached_reg_addr, 0, &val); @@ -310,9 +313,13 @@ static ssize_t iio_debugfs_read_reg(struct file *file, char __user *userbuf, return ret; }
- len = snprintf(buf, sizeof(buf), "0x%X\n", val); + indio_dev->read_buf_len = snprintf(indio_dev->read_buf, + sizeof(indio_dev->read_buf), + "0x%X\n", val);
- return simple_read_from_buffer(userbuf, count, ppos, buf, len); + return simple_read_from_buffer(userbuf, count, ppos, + indio_dev->read_buf, + indio_dev->read_buf_len); }
static ssize_t iio_debugfs_write_reg(struct file *file, diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h index a74cb177dc6f..b715afa06aef 100644 --- a/include/linux/iio/iio.h +++ b/include/linux/iio/iio.h @@ -569,6 +569,8 @@ struct iio_dev { #if defined(CONFIG_DEBUG_FS) struct dentry *debugfs_dentry; unsigned cached_reg_addr; + char read_buf[20]; + unsigned int read_buf_len; #endif };