lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date: Thu, 11 Apr 2024 09:12:59 -0600
From: Jens Axboe <axboe@...nel.dk>
To: linux-kernel@...r.kernel.org
Cc: Jens Axboe <axboe@...nel.dk>
Subject: [PATCH 039/437] libfs: switch to read iter and add copy helpers

Signed-off-by: Jens Axboe <axboe@...nel.dk>
---
 fs/debugfs/file.c       | 44 +++++++++++++++++++++
 fs/libfs.c              | 87 +++++++++++++++++++++++++++++++++++++++++
 include/linux/debugfs.h | 25 +++++++++++-
 include/linux/fs.h      |  7 +++-
 4 files changed, 159 insertions(+), 4 deletions(-)

diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c
index c6ff9084bc0f..31749d8c35f8 100644
--- a/fs/debugfs/file.c
+++ b/fs/debugfs/file.c
@@ -468,6 +468,20 @@ ssize_t debugfs_attr_read(struct file *file, char __user *buf,
 }
 EXPORT_SYMBOL_GPL(debugfs_attr_read);
 
+ssize_t debugfs_attr_read_iter(struct kiocb *iocb, struct iov_iter *to)
+{
+	struct dentry *dentry = F_DENTRY(iocb->ki_filp);
+	ssize_t ret;
+
+	ret = debugfs_file_get(dentry);
+	if (unlikely(ret))
+		return ret;
+	ret = simple_attr_read_iter(iocb, to);
+	debugfs_file_put(dentry);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(debugfs_attr_read_iter);
+
 static ssize_t debugfs_attr_write_xsigned(struct file *file, const char __user *buf,
 			 size_t len, loff_t *ppos, bool is_signed)
 {
@@ -499,6 +513,36 @@ ssize_t debugfs_attr_write_signed(struct file *file, const char __user *buf,
 }
 EXPORT_SYMBOL_GPL(debugfs_attr_write_signed);
 
+static ssize_t debugfs_attr_write_iter_xsigned(struct kiocb *iocb,
+					       struct iov_iter *from,
+					       bool is_signed)
+{
+	struct dentry *dentry = F_DENTRY(iocb->ki_filp);
+	ssize_t ret;
+
+	ret = debugfs_file_get(dentry);
+	if (unlikely(ret))
+		return ret;
+	if (is_signed)
+		ret = simple_attr_write_iter_signed(iocb, from);
+	else
+		ret = simple_attr_write_iter(iocb, from);
+	debugfs_file_put(dentry);
+	return ret;
+}
+
+ssize_t debugfs_attr_write_iter(struct kiocb *iocb, struct iov_iter *from)
+{
+	return debugfs_attr_write_iter_xsigned(iocb, from, false);
+}
+EXPORT_SYMBOL_GPL(debugfs_attr_write_iter);
+
+ssize_t debugfs_attr_write_iter_signed(struct kiocb *iocb, struct iov_iter *from)
+{
+	return debugfs_attr_write_iter_xsigned(iocb, from, true);
+}
+EXPORT_SYMBOL_GPL(debugfs_attr_write_iter_signed);
+
 static struct dentry *debugfs_create_mode_unsafe(const char *name, umode_t mode,
 					struct dentry *parent, void *value,
 					const struct file_operations *fops,
diff --git a/fs/libfs.c b/fs/libfs.c
index 074cfacc377f..90f79113e48b 100644
--- a/fs/libfs.c
+++ b/fs/libfs.c
@@ -1365,6 +1365,93 @@ ssize_t simple_attr_read(struct file *file, char __user *buf,
 }
 EXPORT_SYMBOL_GPL(simple_attr_read);
 
+/* read from the buffer that is filled with the get function */
+ssize_t simple_attr_read_iter(struct kiocb *iocb, struct iov_iter *to)
+{
+	struct simple_attr *attr;
+	size_t size;
+	ssize_t ret;
+
+	attr = iocb->ki_filp->private_data;
+
+	if (!attr->get)
+		return -EACCES;
+
+	ret = mutex_lock_interruptible(&attr->mutex);
+	if (ret)
+		return ret;
+
+	if (iocb->ki_pos && attr->get_buf[0]) {
+		/* continued read */
+		size = strlen(attr->get_buf);
+	} else {
+		/* first read */
+		u64 val;
+		ret = attr->get(attr->data, &val);
+		if (ret)
+			goto out;
+
+		size = scnprintf(attr->get_buf, sizeof(attr->get_buf),
+				 attr->fmt, (unsigned long long)val);
+	}
+
+	ret = simple_copy_to_iter(attr->get_buf, &iocb->ki_pos, size, to);
+out:
+	mutex_unlock(&attr->mutex);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(simple_attr_read_iter);
+
+static ssize_t __simple_write_iter(struct kiocb *iocb, struct iov_iter *from,
+				   bool is_signed)
+{
+	struct simple_attr *attr;
+	unsigned long long val;
+	size_t len = iov_iter_count(from);
+	size_t size;
+	ssize_t ret;
+
+	attr = iocb->ki_filp->private_data;
+	if (!attr->set)
+		return -EACCES;
+
+	ret = mutex_lock_interruptible(&attr->mutex);
+	if (ret)
+		return ret;
+
+	ret = -EFAULT;
+	size = min(sizeof(attr->set_buf) - 1, len);
+	if (!copy_from_iter(attr->set_buf, size, from))
+		goto out;
+
+	attr->set_buf[size] = '\0';
+	if (is_signed)
+		ret = kstrtoll(attr->set_buf, 0, &val);
+	else
+		ret = kstrtoull(attr->set_buf, 0, &val);
+	if (ret)
+		goto out;
+	ret = attr->set(attr->data, val);
+	if (ret == 0)
+		ret = len; /* on success, claim we got the whole input */
+out:
+	mutex_unlock(&attr->mutex);
+	return ret;
+}
+
+ssize_t simple_attr_write_iter(struct kiocb *iocb, struct iov_iter *from)
+{
+	return __simple_write_iter(iocb, from, false);
+}
+EXPORT_SYMBOL_GPL(simple_attr_write_iter);
+
+ssize_t simple_attr_write_iter_signed(struct kiocb *iocb, struct iov_iter *from)
+
+{
+	return __simple_write_iter(iocb, from, true);
+}
+EXPORT_SYMBOL_GPL(simple_attr_write_iter_signed);
+
 /* interpret the buffer as a number to call the set function with */
 static ssize_t simple_attr_write_xsigned(struct file *file, const char __user *buf,
 			  size_t len, loff_t *ppos, bool is_signed)
diff --git a/include/linux/debugfs.h b/include/linux/debugfs.h
index ad417d079ec9..c6d189059d3d 100644
--- a/include/linux/debugfs.h
+++ b/include/linux/debugfs.h
@@ -55,8 +55,8 @@ static const struct file_operations __fops = {				\
 	.owner	 = THIS_MODULE,						\
 	.open	 = __fops ## _open,					\
 	.release = simple_attr_release,					\
-	.read	 = debugfs_attr_read,					\
-	.write	 = (__is_signed) ? debugfs_attr_write_signed : debugfs_attr_write,	\
+	.read_iter = debugfs_attr_read_iter,				\
+	.write_iter= (__is_signed) ? debugfs_attr_write_iter_signed : debugfs_attr_write_iter,	\
 	.llseek  = no_llseek,						\
 }
 
@@ -106,10 +106,13 @@ void debugfs_file_put(struct dentry *dentry);
 
 ssize_t debugfs_attr_read(struct file *file, char __user *buf,
 			size_t len, loff_t *ppos);
+ssize_t debugfs_attr_read_iter(struct kiocb *iocb, struct iov_iter *to);
 ssize_t debugfs_attr_write(struct file *file, const char __user *buf,
 			size_t len, loff_t *ppos);
+ssize_t debugfs_attr_write_iter(struct kiocb *iocb, struct iov_iter *from);
 ssize_t debugfs_attr_write_signed(struct file *file, const char __user *buf,
 			size_t len, loff_t *ppos);
+ssize_t debugfs_attr_write_iter_signed(struct kiocb *iocb, struct iov_iter *from);
 
 struct dentry *debugfs_rename(struct dentry *old_dir, struct dentry *old_dentry,
                 struct dentry *new_dir, const char *new_name);
@@ -271,6 +274,12 @@ static inline ssize_t debugfs_attr_read(struct file *file, char __user *buf,
 	return -ENODEV;
 }
 
+static inline ssize_t debugfs_attr_read_iter(struct kiocb *iocb,
+					     struct iov_iter *to)
+{
+	return -ENODEV;
+}
+
 static inline ssize_t debugfs_attr_write(struct file *file,
 					const char __user *buf,
 					size_t len, loff_t *ppos)
@@ -278,6 +287,12 @@ static inline ssize_t debugfs_attr_write(struct file *file,
 	return -ENODEV;
 }
 
+static inline ssize_t debugfs_attr_write_iter(struct kiocb *iocb,
+					      struct iov_iter *from)
+{
+	return -ENODEV;
+}
+
 static inline ssize_t debugfs_attr_write_signed(struct file *file,
 					const char __user *buf,
 					size_t len, loff_t *ppos)
@@ -285,6 +300,12 @@ static inline ssize_t debugfs_attr_write_signed(struct file *file,
 	return -ENODEV;
 }
 
+static inline ssize_t debugfs_attr_write_iter_signed(struct kiocb *iocb,
+						     struct iov_iter *from)
+{
+	return -ENODEV;
+}
+
 static inline struct dentry *debugfs_rename(struct dentry *old_dir, struct dentry *old_dentry,
                 struct dentry *new_dir, char *new_name)
 {
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 5806cea7a3ac..d15a79020efa 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -3528,8 +3528,8 @@ static const struct file_operations __fops = {				\
 	.owner	 = THIS_MODULE,						\
 	.open	 = __fops ## _open,					\
 	.release = simple_attr_release,					\
-	.read	 = simple_attr_read,					\
-	.write	 = (__is_signed) ? simple_attr_write_signed : simple_attr_write,	\
+	.read_iter = simple_attr_read_iter,				\
+	.write_iter = (__is_signed) ? simple_attr_write_iter_signed : simple_attr_write_iter,	\
 	.llseek	 = generic_file_llseek,					\
 }
 
@@ -3555,6 +3555,9 @@ ssize_t simple_attr_write(struct file *file, const char __user *buf,
 			  size_t len, loff_t *ppos);
 ssize_t simple_attr_write_signed(struct file *file, const char __user *buf,
 				 size_t len, loff_t *ppos);
+ssize_t simple_attr_read_iter(struct kiocb *iocb, struct iov_iter *to);
+ssize_t simple_attr_write_iter(struct kiocb *iocb, struct iov_iter *from);
+ssize_t simple_attr_write_iter_signed(struct kiocb *iocb, struct iov_iter *from);
 
 struct ctl_table;
 int __init list_bdev_fs_names(char *buf, size_t size);
-- 
2.43.0


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ