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> --- 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