Re: [PATCH 07/13] sysfs: add ->seq_show support to sysfs_ops

From: Christian Brauner
Date: Mon Sep 13 2021 - 09:47:36 EST


On Mon, Sep 13, 2021 at 07:41:15AM +0200, Christoph Hellwig wrote:
> Allow attributes to directly use the seq_file method instead of
> carving out a buffer that can easily lead to buffer overflows.
>
> Signed-off-by: Christoph Hellwig <hch@xxxxxx>
> ---

Acked-by: Christian Brauner <christian.brauner@xxxxxxxxxx>

> fs/sysfs/file.c | 19 ++++++++++++++-----
> include/linux/sysfs.h | 9 +++++++--
> 2 files changed, 21 insertions(+), 7 deletions(-)
>
> diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
> index 42dcf96881b68..12e0bfe40a2b4 100644
> --- a/fs/sysfs/file.c
> +++ b/fs/sysfs/file.c
> @@ -45,6 +45,9 @@ static int sysfs_kf_seq_show(struct seq_file *sf, void *v)
> ssize_t count;
> char *buf;
>
> + if (ops->seq_show)
> + return ops->seq_show(kobj, of->kn->priv, sf);
> +
> if (WARN_ON_ONCE(!ops->show))
> return -EINVAL;
>
> @@ -268,6 +271,10 @@ int sysfs_add_file_mode_ns(struct kernfs_node *parent,
> return -EINVAL;
>
> if (mode & SYSFS_PREALLOC) {
> + if (WARN(sysfs_ops->seq_show, KERN_ERR
> + "seq_show not supported on prealloc file: %s\n",
> + kobject_name(kobj)))
> + return -EINVAL;
> if (sysfs_ops->show && sysfs_ops->store)
> ops = &sysfs_prealloc_kfops_rw;
> else if (sysfs_ops->show)
> @@ -275,12 +282,14 @@ int sysfs_add_file_mode_ns(struct kernfs_node *parent,
> else if (sysfs_ops->store)
> ops = &sysfs_prealloc_kfops_wo;
> } else {
> - if (sysfs_ops->show && sysfs_ops->store)
> - ops = &sysfs_file_kfops_rw;
> - else if (sysfs_ops->show)
> - ops = &sysfs_file_kfops_ro;
> - else if (sysfs_ops->store)
> + if (sysfs_ops->seq_show || sysfs_ops->show) {
> + if (sysfs_ops->store)
> + ops = &sysfs_file_kfops_rw;
> + else
> + ops = &sysfs_file_kfops_ro;
> + } else if (sysfs_ops->store) {
> ops = &sysfs_file_kfops_wo;
> + }
> }
>
> if (!ops)
> diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h
> index e3f1e8ac1f85b..e1ab4da716730 100644
> --- a/include/linux/sysfs.h
> +++ b/include/linux/sysfs.h
> @@ -236,8 +236,13 @@ struct bin_attribute bin_attr_##_name = __BIN_ATTR_WO(_name, _size)
> struct bin_attribute bin_attr_##_name = __BIN_ATTR_RW(_name, _size)
>
> struct sysfs_ops {
> - ssize_t (*show)(struct kobject *, struct attribute *, char *);
> - ssize_t (*store)(struct kobject *, struct attribute *, const char *, size_t);
> + int (*seq_show)(struct kobject *kobj, struct attribute *attr,
> + struct seq_file *sf);
> + ssize_t (*store)(struct kobject *kobj, struct attribute *attr,
> + const char *buf, size_t size);
> +
> + /* deprecated except for preallocated attributes: */
> + ssize_t (*show)(struct kobject *kob, struct attribute *attr, char *buf);
> };
>
> #ifdef CONFIG_SYSFS
> --
> 2.30.2
>