virtio-fs.lists.linux.dev archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 0/3] virtiofs: export filesystem tags through sysfs
@ 2024-02-08 19:32 Stefan Hajnoczi
  2024-02-08 19:32 ` [PATCH v2 1/3] virtiofs: forbid newlines in tags Stefan Hajnoczi
                   ` (2 more replies)
  0 siblings, 3 replies; 10+ messages in thread
From: Stefan Hajnoczi @ 2024-02-08 19:32 UTC (permalink / raw)
  To: linux-fsdevel
  Cc: Alyssa Ross, gmaglione, virtio-fs, vgoyal, mzxreary, Greg KH,
	miklos, Stefan Hajnoczi

v2:
- Vivek mentioned that he didn't have time to work on this patch series
  recently so I gave it a shot.
- Information is now exposed in /sys/fs/virtiofs/ whereas before it was part of
  the generic virtio device kobject, which didn't really fit.

Userspace needs a way to enumerate available virtiofs filesystems and detect
when they are hotplugged or unplugged. This would allow systemd to wait for a
virtiofs filesystem during boot, for example.

This patch series adds the following in sysfs:

  /sys/fs/virtiofs/<n>/tag    - unique identifier for mount(8)
  /sys/fs/virtiofs/<n>/device - symlink to virtio device

A uevent is emitted when virtiofs devices are hotplugged or unplugged:

  KERNEL[111.113221] add      /fs/virtiofs/2 (virtiofs)
  ACTION=add
  DEVPATH=/fs/virtiofs/2
  SUBSYSTEM=virtiofs
  TAG=test

  KERNEL[165.527167] remove   /fs/virtiofs/2 (virtiofs)
  ACTION=remove
  DEVPATH=/fs/virtiofs/2
  SUBSYSTEM=virtiofs
  TAG=test

Stefan Hajnoczi (3):
  virtiofs: forbid newlines in tags
  virtiofs: export filesystem tags through sysfs
  virtiofs: emit uevents on filesystem events

 fs/fuse/virtio_fs.c                         | 138 +++++++++++++++++---
 Documentation/ABI/testing/sysfs-fs-virtiofs |  11 ++
 2 files changed, 128 insertions(+), 21 deletions(-)
 create mode 100644 Documentation/ABI/testing/sysfs-fs-virtiofs

-- 
2.43.0


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH v2 1/3] virtiofs: forbid newlines in tags
  2024-02-08 19:32 [PATCH v2 0/3] virtiofs: export filesystem tags through sysfs Stefan Hajnoczi
@ 2024-02-08 19:32 ` Stefan Hajnoczi
  2024-02-09 10:33   ` Greg KH
  2024-02-08 19:32 ` [PATCH v2 2/3] virtiofs: export filesystem tags through sysfs Stefan Hajnoczi
  2024-02-08 19:32 ` [PATCH v2 3/3] virtiofs: emit uevents on filesystem events Stefan Hajnoczi
  2 siblings, 1 reply; 10+ messages in thread
From: Stefan Hajnoczi @ 2024-02-08 19:32 UTC (permalink / raw)
  To: linux-fsdevel
  Cc: Alyssa Ross, gmaglione, virtio-fs, vgoyal, mzxreary, Greg KH,
	miklos, Stefan Hajnoczi

Newlines in virtiofs tags are awkward for users and potential vectors
for string injection attacks.

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
 fs/fuse/virtio_fs.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/fs/fuse/virtio_fs.c b/fs/fuse/virtio_fs.c
index 5f1be1da92ce..de9a38efdf1e 100644
--- a/fs/fuse/virtio_fs.c
+++ b/fs/fuse/virtio_fs.c
@@ -323,6 +323,16 @@ static int virtio_fs_read_tag(struct virtio_device *vdev, struct virtio_fs *fs)
 		return -ENOMEM;
 	memcpy(fs->tag, tag_buf, len);
 	fs->tag[len] = '\0';
+
+	/* While the VIRTIO specification allows any character, newlines are
+	 * awkward on mount(8) command-lines and cause problems in the sysfs
+	 * "tag" attr and uevent TAG= properties. Forbid them.
+	 */
+	if (strchr(fs->tag, '\n')) {
+		dev_err(&vdev->dev, "refusing virtiofs tag with newline character\n");
+		return -EINVAL;
+	}
+
 	return 0;
 }
 
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v2 2/3] virtiofs: export filesystem tags through sysfs
  2024-02-08 19:32 [PATCH v2 0/3] virtiofs: export filesystem tags through sysfs Stefan Hajnoczi
  2024-02-08 19:32 ` [PATCH v2 1/3] virtiofs: forbid newlines in tags Stefan Hajnoczi
@ 2024-02-08 19:32 ` Stefan Hajnoczi
  2024-02-09 10:36   ` Greg KH
  2024-02-08 19:32 ` [PATCH v2 3/3] virtiofs: emit uevents on filesystem events Stefan Hajnoczi
  2 siblings, 1 reply; 10+ messages in thread
From: Stefan Hajnoczi @ 2024-02-08 19:32 UTC (permalink / raw)
  To: linux-fsdevel
  Cc: Alyssa Ross, gmaglione, virtio-fs, vgoyal, mzxreary, Greg KH,
	miklos, Stefan Hajnoczi

The virtiofs filesystem is mounted using a "tag" which is exported by
the virtiofs device:

  # mount -t virtiofs <tag> /mnt

The virtiofs driver knows about all the available tags but these are
currently not exported to user space.

People have asked for these tags to be exported to user space. Most
recently Lennart Poettering has asked for it as he wants to scan the
tags and mount virtiofs automatically in certain cases.

https://gitlab.com/virtio-fs/virtiofsd/-/issues/128

This patch exports tags at /sys/fs/virtiofs/<N>/tag where N is the id of
the virtiofs device. The filesystem tag can be obtained by reading this
"tag" file.

There is also a symlink at /sys/fs/virtiofs/<N>/device that points to
the virtiofs device that exports this tag.

This patch converts the existing struct virtio_fs into a full kobject.
It already had a refcount so it's an easy change. The virtio_fs objects
can then be exposed in a kset at /sys/fs/virtiofs/. Note that virtio_fs
objects may live slightly longer than we wish for them to be exposed to
userspace, so kobject_del() is called explicitly when the underlying
virtio_device is removed. The virtio_fs object is freed when all
references are dropped (e.g. active mounts) but disappears as soon as
the virtiofs device is gone.

Originally-by: Vivek Goyal <vgoyal@redhat.com>
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
 fs/fuse/virtio_fs.c                         | 113 ++++++++++++++++----
 Documentation/ABI/testing/sysfs-fs-virtiofs |  11 ++
 2 files changed, 103 insertions(+), 21 deletions(-)
 create mode 100644 Documentation/ABI/testing/sysfs-fs-virtiofs

diff --git a/fs/fuse/virtio_fs.c b/fs/fuse/virtio_fs.c
index de9a38efdf1e..28e96b7cde00 100644
--- a/fs/fuse/virtio_fs.c
+++ b/fs/fuse/virtio_fs.c
@@ -31,6 +31,9 @@
 static DEFINE_MUTEX(virtio_fs_mutex);
 static LIST_HEAD(virtio_fs_instances);
 
+/* The /sys/fs/virtio_fs/ kset */
+static struct kset *virtio_fs_kset;
+
 enum {
 	VQ_HIPRIO,
 	VQ_REQUEST
@@ -55,7 +58,7 @@ struct virtio_fs_vq {
 
 /* A virtio-fs device instance */
 struct virtio_fs {
-	struct kref refcount;
+	struct kobject kobj;
 	struct list_head list;    /* on virtio_fs_instances */
 	char *tag;
 	struct virtio_fs_vq *vqs;
@@ -161,18 +164,43 @@ static inline void dec_in_flight_req(struct virtio_fs_vq *fsvq)
 		complete(&fsvq->in_flight_zero);
 }
 
-static void release_virtio_fs_obj(struct kref *ref)
+static ssize_t virtio_fs_tag_attr_show(struct kobject *kobj,
+		struct kobj_attribute *attr, char *buf)
 {
-	struct virtio_fs *vfs = container_of(ref, struct virtio_fs, refcount);
+	struct virtio_fs *fs = container_of(kobj, struct virtio_fs, kobj);
+
+	return sysfs_emit(buf, fs->tag);
+}
+
+static struct kobj_attribute virtio_fs_tag_attr = {
+	.attr = { .name = "tag", .mode= 0644 },
+	.show = virtio_fs_tag_attr_show,
+};
+
+static struct attribute *virtio_fs_attrs[] = {
+	&virtio_fs_tag_attr.attr,
+	NULL
+};
+ATTRIBUTE_GROUPS(virtio_fs);
+
+static void virtio_fs_ktype_release(struct kobject *kobj)
+{
+	struct virtio_fs *vfs = container_of(kobj, struct virtio_fs, kobj);
 
 	kfree(vfs->vqs);
 	kfree(vfs);
 }
 
+static const struct kobj_type virtio_fs_ktype = {
+	.release = virtio_fs_ktype_release,
+	.sysfs_ops = &kobj_sysfs_ops,
+	.default_groups = virtio_fs_groups,
+};
+
 /* Make sure virtiofs_mutex is held */
 static void virtio_fs_put(struct virtio_fs *fs)
 {
-	kref_put(&fs->refcount, release_virtio_fs_obj);
+	kobject_put(&fs->kobj);
 }
 
 static void virtio_fs_fiq_release(struct fuse_iqueue *fiq)
@@ -243,25 +271,44 @@ static void virtio_fs_start_all_queues(struct virtio_fs *fs)
 }
 
 /* Add a new instance to the list or return -EEXIST if tag name exists*/
-static int virtio_fs_add_instance(struct virtio_fs *fs)
+static int virtio_fs_add_instance(struct virtio_device *vdev,
+				  struct virtio_fs *fs)
 {
 	struct virtio_fs *fs2;
-	bool duplicate = false;
+	int ret;
 
 	mutex_lock(&virtio_fs_mutex);
 
 	list_for_each_entry(fs2, &virtio_fs_instances, list) {
-		if (strcmp(fs->tag, fs2->tag) == 0)
-			duplicate = true;
+		if (strcmp(fs->tag, fs2->tag) == 0) {
+			mutex_unlock(&virtio_fs_mutex);
+			return -EEXIST;
+		}
 	}
 
-	if (!duplicate)
-		list_add_tail(&fs->list, &virtio_fs_instances);
+	/* Use the virtio_device's index as a unique identifier, there is no
+	 * need to allocate our own identifiers because the virtio_fs instance
+	 * is only visible to userspace as long as the underlying virtio_device
+	 * exists.
+	 */
+	fs->kobj.kset = virtio_fs_kset;
+	ret = kobject_add(&fs->kobj, NULL, "%d", vdev->index);
+	if (ret < 0) {
+		mutex_unlock(&virtio_fs_mutex);
+		return ret;
+	}
+
+	ret = sysfs_create_link(&fs->kobj, &vdev->dev.kobj, "device");
+	if (ret < 0) {
+		kobject_del(&fs->kobj);
+		mutex_unlock(&virtio_fs_mutex);
+		return ret;
+	}
+
+	list_add_tail(&fs->list, &virtio_fs_instances);
 
 	mutex_unlock(&virtio_fs_mutex);
 
-	if (duplicate)
-		return -EEXIST;
 	return 0;
 }
 
@@ -274,7 +321,7 @@ static struct virtio_fs *virtio_fs_find_instance(const char *tag)
 
 	list_for_each_entry(fs, &virtio_fs_instances, list) {
 		if (strcmp(fs->tag, tag) == 0) {
-			kref_get(&fs->refcount);
+			kobject_get(&fs->kobj);
 			goto found;
 		}
 	}
@@ -875,7 +922,7 @@ static int virtio_fs_probe(struct virtio_device *vdev)
 	fs = kzalloc(sizeof(*fs), GFP_KERNEL);
 	if (!fs)
 		return -ENOMEM;
-	kref_init(&fs->refcount);
+	kobject_init(&fs->kobj, &virtio_fs_ktype);
 	vdev->priv = fs;
 
 	ret = virtio_fs_read_tag(vdev, fs);
@@ -897,7 +944,7 @@ static int virtio_fs_probe(struct virtio_device *vdev)
 	 */
 	virtio_device_ready(vdev);
 
-	ret = virtio_fs_add_instance(fs);
+	ret = virtio_fs_add_instance(vdev, fs);
 	if (ret < 0)
 		goto out_vqs;
 
@@ -906,11 +953,10 @@ static int virtio_fs_probe(struct virtio_device *vdev)
 out_vqs:
 	virtio_reset_device(vdev);
 	virtio_fs_cleanup_vqs(vdev);
-	kfree(fs->vqs);
 
 out:
 	vdev->priv = NULL;
-	kfree(fs);
+	kobject_put(&fs->kobj);
 	return ret;
 }
 
@@ -934,6 +980,8 @@ static void virtio_fs_remove(struct virtio_device *vdev)
 	mutex_lock(&virtio_fs_mutex);
 	/* This device is going away. No one should get new reference */
 	list_del_init(&fs->list);
+	sysfs_remove_link(&fs->kobj, "device");
+	kobject_del(&fs->kobj);
 	virtio_fs_stop_all_queues(fs);
 	virtio_fs_drain_all_queues_locked(fs);
 	virtio_reset_device(vdev);
@@ -1520,6 +1568,20 @@ static struct file_system_type virtio_fs_type = {
 	.kill_sb	= virtio_kill_sb,
 };
 
+static int __init virtio_fs_sysfs_init(void)
+{
+	virtio_fs_kset = kset_create_and_add("virtiofs", NULL, fs_kobj);
+	if (!virtio_fs_kset)
+		return -ENOMEM;
+	return 0;
+}
+
+static void __exit virtio_fs_sysfs_exit(void)
+{
+	kset_unregister(virtio_fs_kset);
+	virtio_fs_kset = NULL;
+}
+
 static int __init virtio_fs_init(void)
 {
 	int ret;
@@ -1528,19 +1590,28 @@ static int __init virtio_fs_init(void)
 	if (ret < 0)
 		return ret;
 
+	ret = virtio_fs_sysfs_init();
+	if (ret < 0)
+		goto unregister_virtio_driver;
+
 	ret = register_filesystem(&virtio_fs_type);
-	if (ret < 0) {
-		unregister_virtio_driver(&virtio_fs_driver);
-		return ret;
-	}
+	if (ret < 0)
+		goto sysfs_exit;
 
 	return 0;
+
+sysfs_exit:
+	virtio_fs_sysfs_exit();
+unregister_virtio_driver:
+	unregister_virtio_driver(&virtio_fs_driver);
+	return ret;
 }
 module_init(virtio_fs_init);
 
 static void __exit virtio_fs_exit(void)
 {
 	unregister_filesystem(&virtio_fs_type);
+	virtio_fs_sysfs_exit();
 	unregister_virtio_driver(&virtio_fs_driver);
 }
 module_exit(virtio_fs_exit);
diff --git a/Documentation/ABI/testing/sysfs-fs-virtiofs b/Documentation/ABI/testing/sysfs-fs-virtiofs
new file mode 100644
index 000000000000..4839dbce997e
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-fs-virtiofs
@@ -0,0 +1,11 @@
+What:		/sys/fs/virtiofs/<n>/tag
+Date:		Feb 2024
+Contact:	virtio-fs@lists.linux.dev
+Description:
+		[RO] The mount "tag" that can be used to mount this filesystem.
+
+What:		/sys/fs/virtiofs/<n>/device
+Date:		Feb 2024
+Contact:	virtio-fs@lists.linux.dev
+Description:
+		Symlink to the virtio device that exports this filesystem.
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v2 3/3] virtiofs: emit uevents on filesystem events
  2024-02-08 19:32 [PATCH v2 0/3] virtiofs: export filesystem tags through sysfs Stefan Hajnoczi
  2024-02-08 19:32 ` [PATCH v2 1/3] virtiofs: forbid newlines in tags Stefan Hajnoczi
  2024-02-08 19:32 ` [PATCH v2 2/3] virtiofs: export filesystem tags through sysfs Stefan Hajnoczi
@ 2024-02-08 19:32 ` Stefan Hajnoczi
  2024-02-09 10:39   ` Greg KH
  2 siblings, 1 reply; 10+ messages in thread
From: Stefan Hajnoczi @ 2024-02-08 19:32 UTC (permalink / raw)
  To: linux-fsdevel
  Cc: Alyssa Ross, gmaglione, virtio-fs, vgoyal, mzxreary, Greg KH,
	miklos, Stefan Hajnoczi

Alyssa Ross <hi@alyssa.is> requested that virtiofs notifies userspace
when filesytems become available. This can be used to detect when a
filesystem with a given tag is hotplugged, for example. uevents allow
userspace to detect changes without resorting to polling.

The tag is included as a uevent property so it's easy for userspace to
identify the filesystem in question even when the sysfs directory goes
away during removal.

Here are example uevents:

  # udevadm monitor -k -p

  KERNEL[111.113221] add      /fs/virtiofs/2 (virtiofs)
  ACTION=add
  DEVPATH=/fs/virtiofs/2
  SUBSYSTEM=virtiofs
  TAG=test

  KERNEL[165.527167] remove   /fs/virtiofs/2 (virtiofs)
  ACTION=remove
  DEVPATH=/fs/virtiofs/2
  SUBSYSTEM=virtiofs
  TAG=test

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
 fs/fuse/virtio_fs.c | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/fs/fuse/virtio_fs.c b/fs/fuse/virtio_fs.c
index 28e96b7cde00..18a8f531e5d4 100644
--- a/fs/fuse/virtio_fs.c
+++ b/fs/fuse/virtio_fs.c
@@ -270,6 +270,17 @@ static void virtio_fs_start_all_queues(struct virtio_fs *fs)
 	}
 }
 
+static void virtio_fs_uevent(struct virtio_fs *fs, enum kobject_action action)
+{
+	char tag_str[sizeof("TAG=") +
+		     sizeof_field(struct virtio_fs_config, tag) + 1];
+	char *envp[] = {tag_str, NULL};
+
+	snprintf(tag_str, sizeof(tag_str), "TAG=%s", fs->tag);
+
+	kobject_uevent_env(&fs->kobj, action, envp);
+}
+
 /* Add a new instance to the list or return -EEXIST if tag name exists*/
 static int virtio_fs_add_instance(struct virtio_device *vdev,
 				  struct virtio_fs *fs)
@@ -309,6 +320,8 @@ static int virtio_fs_add_instance(struct virtio_device *vdev,
 
 	mutex_unlock(&virtio_fs_mutex);
 
+	virtio_fs_uevent(fs, KOBJ_ADD);
+
 	return 0;
 }
 
@@ -977,6 +990,8 @@ static void virtio_fs_remove(struct virtio_device *vdev)
 {
 	struct virtio_fs *fs = vdev->priv;
 
+	virtio_fs_uevent(fs, KOBJ_REMOVE);
+
 	mutex_lock(&virtio_fs_mutex);
 	/* This device is going away. No one should get new reference */
 	list_del_init(&fs->list);
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH v2 1/3] virtiofs: forbid newlines in tags
  2024-02-08 19:32 ` [PATCH v2 1/3] virtiofs: forbid newlines in tags Stefan Hajnoczi
@ 2024-02-09 10:33   ` Greg KH
  2024-02-09 11:30     ` Stefan Hajnoczi
  0 siblings, 1 reply; 10+ messages in thread
From: Greg KH @ 2024-02-09 10:33 UTC (permalink / raw)
  To: Stefan Hajnoczi
  Cc: linux-fsdevel, Alyssa Ross, gmaglione, virtio-fs, vgoyal,
	mzxreary, miklos

On Thu, Feb 08, 2024 at 02:32:09PM -0500, Stefan Hajnoczi wrote:
> Newlines in virtiofs tags are awkward for users and potential vectors
> for string injection attacks.
> 
> Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
> ---
>  fs/fuse/virtio_fs.c | 10 ++++++++++
>  1 file changed, 10 insertions(+)
> 
> diff --git a/fs/fuse/virtio_fs.c b/fs/fuse/virtio_fs.c
> index 5f1be1da92ce..de9a38efdf1e 100644
> --- a/fs/fuse/virtio_fs.c
> +++ b/fs/fuse/virtio_fs.c
> @@ -323,6 +323,16 @@ static int virtio_fs_read_tag(struct virtio_device *vdev, struct virtio_fs *fs)
>  		return -ENOMEM;
>  	memcpy(fs->tag, tag_buf, len);
>  	fs->tag[len] = '\0';
> +
> +	/* While the VIRTIO specification allows any character, newlines are
> +	 * awkward on mount(8) command-lines and cause problems in the sysfs
> +	 * "tag" attr and uevent TAG= properties. Forbid them.
> +	 */
> +	if (strchr(fs->tag, '\n')) {
> +		dev_err(&vdev->dev, "refusing virtiofs tag with newline character\n");

Please don't let userspace spam mthe kernel log if they are the ones
that are setting the tags.  Just make this a debug message instead.

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v2 2/3] virtiofs: export filesystem tags through sysfs
  2024-02-08 19:32 ` [PATCH v2 2/3] virtiofs: export filesystem tags through sysfs Stefan Hajnoczi
@ 2024-02-09 10:36   ` Greg KH
  2024-02-09 11:33     ` Stefan Hajnoczi
  0 siblings, 1 reply; 10+ messages in thread
From: Greg KH @ 2024-02-09 10:36 UTC (permalink / raw)
  To: Stefan Hajnoczi
  Cc: linux-fsdevel, Alyssa Ross, gmaglione, virtio-fs, vgoyal,
	mzxreary, miklos

On Thu, Feb 08, 2024 at 02:32:10PM -0500, Stefan Hajnoczi wrote:
> The virtiofs filesystem is mounted using a "tag" which is exported by
> the virtiofs device:
> 
>   # mount -t virtiofs <tag> /mnt
> 
> The virtiofs driver knows about all the available tags but these are
> currently not exported to user space.
> 
> People have asked for these tags to be exported to user space. Most
> recently Lennart Poettering has asked for it as he wants to scan the
> tags and mount virtiofs automatically in certain cases.
> 
> https://gitlab.com/virtio-fs/virtiofsd/-/issues/128
> 
> This patch exports tags at /sys/fs/virtiofs/<N>/tag where N is the id of
> the virtiofs device. The filesystem tag can be obtained by reading this
> "tag" file.
> 
> There is also a symlink at /sys/fs/virtiofs/<N>/device that points to
> the virtiofs device that exports this tag.
> 
> This patch converts the existing struct virtio_fs into a full kobject.
> It already had a refcount so it's an easy change. The virtio_fs objects
> can then be exposed in a kset at /sys/fs/virtiofs/. Note that virtio_fs
> objects may live slightly longer than we wish for them to be exposed to
> userspace, so kobject_del() is called explicitly when the underlying
> virtio_device is removed. The virtio_fs object is freed when all
> references are dropped (e.g. active mounts) but disappears as soon as
> the virtiofs device is gone.
> 
> Originally-by: Vivek Goyal <vgoyal@redhat.com>
> Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
> ---
>  fs/fuse/virtio_fs.c                         | 113 ++++++++++++++++----
>  Documentation/ABI/testing/sysfs-fs-virtiofs |  11 ++
>  2 files changed, 103 insertions(+), 21 deletions(-)
>  create mode 100644 Documentation/ABI/testing/sysfs-fs-virtiofs
> 
> diff --git a/fs/fuse/virtio_fs.c b/fs/fuse/virtio_fs.c
> index de9a38efdf1e..28e96b7cde00 100644
> --- a/fs/fuse/virtio_fs.c
> +++ b/fs/fuse/virtio_fs.c
> @@ -31,6 +31,9 @@
>  static DEFINE_MUTEX(virtio_fs_mutex);
>  static LIST_HEAD(virtio_fs_instances);
>  
> +/* The /sys/fs/virtio_fs/ kset */
> +static struct kset *virtio_fs_kset;
> +
>  enum {
>  	VQ_HIPRIO,
>  	VQ_REQUEST
> @@ -55,7 +58,7 @@ struct virtio_fs_vq {
>  
>  /* A virtio-fs device instance */
>  struct virtio_fs {
> -	struct kref refcount;
> +	struct kobject kobj;
>  	struct list_head list;    /* on virtio_fs_instances */
>  	char *tag;
>  	struct virtio_fs_vq *vqs;
> @@ -161,18 +164,43 @@ static inline void dec_in_flight_req(struct virtio_fs_vq *fsvq)
>  		complete(&fsvq->in_flight_zero);
>  }
>  
> -static void release_virtio_fs_obj(struct kref *ref)
> +static ssize_t virtio_fs_tag_attr_show(struct kobject *kobj,
> +		struct kobj_attribute *attr, char *buf)
>  {
> -	struct virtio_fs *vfs = container_of(ref, struct virtio_fs, refcount);
> +	struct virtio_fs *fs = container_of(kobj, struct virtio_fs, kobj);
> +
> +	return sysfs_emit(buf, fs->tag);
> +}
> +
> +static struct kobj_attribute virtio_fs_tag_attr = {
> +	.attr = { .name = "tag", .mode= 0644 },
> +	.show = virtio_fs_tag_attr_show,
> +};

__ATTR_RO()?
That way we all know you got the mode setting correct :)

Other than that minor thing, looks good, nice job!

greg k-h

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v2 3/3] virtiofs: emit uevents on filesystem events
  2024-02-08 19:32 ` [PATCH v2 3/3] virtiofs: emit uevents on filesystem events Stefan Hajnoczi
@ 2024-02-09 10:39   ` Greg KH
  2024-02-09 12:15     ` Stefan Hajnoczi
  0 siblings, 1 reply; 10+ messages in thread
From: Greg KH @ 2024-02-09 10:39 UTC (permalink / raw)
  To: Stefan Hajnoczi
  Cc: linux-fsdevel, Alyssa Ross, gmaglione, virtio-fs, vgoyal,
	mzxreary, miklos

On Thu, Feb 08, 2024 at 02:32:11PM -0500, Stefan Hajnoczi wrote:
> Alyssa Ross <hi@alyssa.is> requested that virtiofs notifies userspace
> when filesytems become available. This can be used to detect when a
> filesystem with a given tag is hotplugged, for example. uevents allow
> userspace to detect changes without resorting to polling.
> 
> The tag is included as a uevent property so it's easy for userspace to
> identify the filesystem in question even when the sysfs directory goes
> away during removal.
> 
> Here are example uevents:
> 
>   # udevadm monitor -k -p
> 
>   KERNEL[111.113221] add      /fs/virtiofs/2 (virtiofs)
>   ACTION=add
>   DEVPATH=/fs/virtiofs/2
>   SUBSYSTEM=virtiofs
>   TAG=test
> 
>   KERNEL[165.527167] remove   /fs/virtiofs/2 (virtiofs)
>   ACTION=remove
>   DEVPATH=/fs/virtiofs/2
>   SUBSYSTEM=virtiofs
>   TAG=test
> 
> Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
> ---
>  fs/fuse/virtio_fs.c | 15 +++++++++++++++
>  1 file changed, 15 insertions(+)
> 
> diff --git a/fs/fuse/virtio_fs.c b/fs/fuse/virtio_fs.c
> index 28e96b7cde00..18a8f531e5d4 100644
> --- a/fs/fuse/virtio_fs.c
> +++ b/fs/fuse/virtio_fs.c
> @@ -270,6 +270,17 @@ static void virtio_fs_start_all_queues(struct virtio_fs *fs)
>  	}
>  }
>  
> +static void virtio_fs_uevent(struct virtio_fs *fs, enum kobject_action action)
> +{
> +	char tag_str[sizeof("TAG=") +
> +		     sizeof_field(struct virtio_fs_config, tag) + 1];
> +	char *envp[] = {tag_str, NULL};
> +
> +	snprintf(tag_str, sizeof(tag_str), "TAG=%s", fs->tag);
> +
> +	kobject_uevent_env(&fs->kobj, action, envp);
> +}
> +
>  /* Add a new instance to the list or return -EEXIST if tag name exists*/
>  static int virtio_fs_add_instance(struct virtio_device *vdev,
>  				  struct virtio_fs *fs)
> @@ -309,6 +320,8 @@ static int virtio_fs_add_instance(struct virtio_device *vdev,
>  
>  	mutex_unlock(&virtio_fs_mutex);
>  
> +	virtio_fs_uevent(fs, KOBJ_ADD);

Why do you have to explicitly ask for the event?  Doesn't sysfs trigger
this for you automatically?  Set the kset uevent callback for this,
right?

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v2 1/3] virtiofs: forbid newlines in tags
  2024-02-09 10:33   ` Greg KH
@ 2024-02-09 11:30     ` Stefan Hajnoczi
  0 siblings, 0 replies; 10+ messages in thread
From: Stefan Hajnoczi @ 2024-02-09 11:30 UTC (permalink / raw)
  To: Greg KH
  Cc: linux-fsdevel, Alyssa Ross, gmaglione, virtio-fs, vgoyal,
	mzxreary, miklos

[-- Attachment #1: Type: text/plain, Size: 1383 bytes --]

On Fri, Feb 09, 2024 at 10:33:20AM +0000, Greg KH wrote:
> On Thu, Feb 08, 2024 at 02:32:09PM -0500, Stefan Hajnoczi wrote:
> > Newlines in virtiofs tags are awkward for users and potential vectors
> > for string injection attacks.
> > 
> > Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
> > ---
> >  fs/fuse/virtio_fs.c | 10 ++++++++++
> >  1 file changed, 10 insertions(+)
> > 
> > diff --git a/fs/fuse/virtio_fs.c b/fs/fuse/virtio_fs.c
> > index 5f1be1da92ce..de9a38efdf1e 100644
> > --- a/fs/fuse/virtio_fs.c
> > +++ b/fs/fuse/virtio_fs.c
> > @@ -323,6 +323,16 @@ static int virtio_fs_read_tag(struct virtio_device *vdev, struct virtio_fs *fs)
> >  		return -ENOMEM;
> >  	memcpy(fs->tag, tag_buf, len);
> >  	fs->tag[len] = '\0';
> > +
> > +	/* While the VIRTIO specification allows any character, newlines are
> > +	 * awkward on mount(8) command-lines and cause problems in the sysfs
> > +	 * "tag" attr and uevent TAG= properties. Forbid them.
> > +	 */
> > +	if (strchr(fs->tag, '\n')) {
> > +		dev_err(&vdev->dev, "refusing virtiofs tag with newline character\n");
> 
> Please don't let userspace spam mthe kernel log if they are the ones
> that are setting the tags.  Just make this a debug message instead.

This check is performed while probing the device. Userspace is not
involved but I'll change it to dev_dbg() anyway.

Stefan

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v2 2/3] virtiofs: export filesystem tags through sysfs
  2024-02-09 10:36   ` Greg KH
@ 2024-02-09 11:33     ` Stefan Hajnoczi
  0 siblings, 0 replies; 10+ messages in thread
From: Stefan Hajnoczi @ 2024-02-09 11:33 UTC (permalink / raw)
  To: Greg KH
  Cc: linux-fsdevel, Alyssa Ross, gmaglione, virtio-fs, vgoyal,
	mzxreary, miklos

[-- Attachment #1: Type: text/plain, Size: 3514 bytes --]

On Fri, Feb 09, 2024 at 10:36:47AM +0000, Greg KH wrote:
> On Thu, Feb 08, 2024 at 02:32:10PM -0500, Stefan Hajnoczi wrote:
> > The virtiofs filesystem is mounted using a "tag" which is exported by
> > the virtiofs device:
> > 
> >   # mount -t virtiofs <tag> /mnt
> > 
> > The virtiofs driver knows about all the available tags but these are
> > currently not exported to user space.
> > 
> > People have asked for these tags to be exported to user space. Most
> > recently Lennart Poettering has asked for it as he wants to scan the
> > tags and mount virtiofs automatically in certain cases.
> > 
> > https://gitlab.com/virtio-fs/virtiofsd/-/issues/128
> > 
> > This patch exports tags at /sys/fs/virtiofs/<N>/tag where N is the id of
> > the virtiofs device. The filesystem tag can be obtained by reading this
> > "tag" file.
> > 
> > There is also a symlink at /sys/fs/virtiofs/<N>/device that points to
> > the virtiofs device that exports this tag.
> > 
> > This patch converts the existing struct virtio_fs into a full kobject.
> > It already had a refcount so it's an easy change. The virtio_fs objects
> > can then be exposed in a kset at /sys/fs/virtiofs/. Note that virtio_fs
> > objects may live slightly longer than we wish for them to be exposed to
> > userspace, so kobject_del() is called explicitly when the underlying
> > virtio_device is removed. The virtio_fs object is freed when all
> > references are dropped (e.g. active mounts) but disappears as soon as
> > the virtiofs device is gone.
> > 
> > Originally-by: Vivek Goyal <vgoyal@redhat.com>
> > Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
> > ---
> >  fs/fuse/virtio_fs.c                         | 113 ++++++++++++++++----
> >  Documentation/ABI/testing/sysfs-fs-virtiofs |  11 ++
> >  2 files changed, 103 insertions(+), 21 deletions(-)
> >  create mode 100644 Documentation/ABI/testing/sysfs-fs-virtiofs
> > 
> > diff --git a/fs/fuse/virtio_fs.c b/fs/fuse/virtio_fs.c
> > index de9a38efdf1e..28e96b7cde00 100644
> > --- a/fs/fuse/virtio_fs.c
> > +++ b/fs/fuse/virtio_fs.c
> > @@ -31,6 +31,9 @@
> >  static DEFINE_MUTEX(virtio_fs_mutex);
> >  static LIST_HEAD(virtio_fs_instances);
> >  
> > +/* The /sys/fs/virtio_fs/ kset */
> > +static struct kset *virtio_fs_kset;
> > +
> >  enum {
> >  	VQ_HIPRIO,
> >  	VQ_REQUEST
> > @@ -55,7 +58,7 @@ struct virtio_fs_vq {
> >  
> >  /* A virtio-fs device instance */
> >  struct virtio_fs {
> > -	struct kref refcount;
> > +	struct kobject kobj;
> >  	struct list_head list;    /* on virtio_fs_instances */
> >  	char *tag;
> >  	struct virtio_fs_vq *vqs;
> > @@ -161,18 +164,43 @@ static inline void dec_in_flight_req(struct virtio_fs_vq *fsvq)
> >  		complete(&fsvq->in_flight_zero);
> >  }
> >  
> > -static void release_virtio_fs_obj(struct kref *ref)
> > +static ssize_t virtio_fs_tag_attr_show(struct kobject *kobj,
> > +		struct kobj_attribute *attr, char *buf)
> >  {
> > -	struct virtio_fs *vfs = container_of(ref, struct virtio_fs, refcount);
> > +	struct virtio_fs *fs = container_of(kobj, struct virtio_fs, kobj);
> > +
> > +	return sysfs_emit(buf, fs->tag);
> > +}
> > +
> > +static struct kobj_attribute virtio_fs_tag_attr = {
> > +	.attr = { .name = "tag", .mode= 0644 },
> > +	.show = virtio_fs_tag_attr_show,
> > +};
> 
> __ATTR_RO()?
> That way we all know you got the mode setting correct :)
> 
> Other than that minor thing, looks good, nice job!

Will fix, thanks!

Stefan

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v2 3/3] virtiofs: emit uevents on filesystem events
  2024-02-09 10:39   ` Greg KH
@ 2024-02-09 12:15     ` Stefan Hajnoczi
  0 siblings, 0 replies; 10+ messages in thread
From: Stefan Hajnoczi @ 2024-02-09 12:15 UTC (permalink / raw)
  To: Greg KH
  Cc: linux-fsdevel, Alyssa Ross, gmaglione, virtio-fs, vgoyal,
	mzxreary, miklos

[-- Attachment #1: Type: text/plain, Size: 2729 bytes --]

On Fri, Feb 09, 2024 at 10:39:04AM +0000, Greg KH wrote:
> On Thu, Feb 08, 2024 at 02:32:11PM -0500, Stefan Hajnoczi wrote:
> > Alyssa Ross <hi@alyssa.is> requested that virtiofs notifies userspace
> > when filesytems become available. This can be used to detect when a
> > filesystem with a given tag is hotplugged, for example. uevents allow
> > userspace to detect changes without resorting to polling.
> > 
> > The tag is included as a uevent property so it's easy for userspace to
> > identify the filesystem in question even when the sysfs directory goes
> > away during removal.
> > 
> > Here are example uevents:
> > 
> >   # udevadm monitor -k -p
> > 
> >   KERNEL[111.113221] add      /fs/virtiofs/2 (virtiofs)
> >   ACTION=add
> >   DEVPATH=/fs/virtiofs/2
> >   SUBSYSTEM=virtiofs
> >   TAG=test
> > 
> >   KERNEL[165.527167] remove   /fs/virtiofs/2 (virtiofs)
> >   ACTION=remove
> >   DEVPATH=/fs/virtiofs/2
> >   SUBSYSTEM=virtiofs
> >   TAG=test
> > 
> > Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
> > ---
> >  fs/fuse/virtio_fs.c | 15 +++++++++++++++
> >  1 file changed, 15 insertions(+)
> > 
> > diff --git a/fs/fuse/virtio_fs.c b/fs/fuse/virtio_fs.c
> > index 28e96b7cde00..18a8f531e5d4 100644
> > --- a/fs/fuse/virtio_fs.c
> > +++ b/fs/fuse/virtio_fs.c
> > @@ -270,6 +270,17 @@ static void virtio_fs_start_all_queues(struct virtio_fs *fs)
> >  	}
> >  }
> >  
> > +static void virtio_fs_uevent(struct virtio_fs *fs, enum kobject_action action)
> > +{
> > +	char tag_str[sizeof("TAG=") +
> > +		     sizeof_field(struct virtio_fs_config, tag) + 1];
> > +	char *envp[] = {tag_str, NULL};
> > +
> > +	snprintf(tag_str, sizeof(tag_str), "TAG=%s", fs->tag);
> > +
> > +	kobject_uevent_env(&fs->kobj, action, envp);
> > +}
> > +
> >  /* Add a new instance to the list or return -EEXIST if tag name exists*/
> >  static int virtio_fs_add_instance(struct virtio_device *vdev,
> >  				  struct virtio_fs *fs)
> > @@ -309,6 +320,8 @@ static int virtio_fs_add_instance(struct virtio_device *vdev,
> >  
> >  	mutex_unlock(&virtio_fs_mutex);
> >  
> > +	virtio_fs_uevent(fs, KOBJ_ADD);
> 
> Why do you have to explicitly ask for the event?  Doesn't sysfs trigger
> this for you automatically?  Set the kset uevent callback for this,
> right?

I haven't found a way to get an implicit KOBJ_ADD uevent. device_add()
and other kset_uevent_ops users emit KOBJ_ADD manually too. Grepping for
KOBJ_ADD in fs/sysfs/ and lib/ doesn't produce any useful results
either.

It is possible to eliminate the explicit KOBJ_REMOVE though because
kobject_del() already calls it. I will fix that and switch to
kset_uevent_ops->uevent().

Thanks,
Stefan

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2024-02-09 12:15 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-02-08 19:32 [PATCH v2 0/3] virtiofs: export filesystem tags through sysfs Stefan Hajnoczi
2024-02-08 19:32 ` [PATCH v2 1/3] virtiofs: forbid newlines in tags Stefan Hajnoczi
2024-02-09 10:33   ` Greg KH
2024-02-09 11:30     ` Stefan Hajnoczi
2024-02-08 19:32 ` [PATCH v2 2/3] virtiofs: export filesystem tags through sysfs Stefan Hajnoczi
2024-02-09 10:36   ` Greg KH
2024-02-09 11:33     ` Stefan Hajnoczi
2024-02-08 19:32 ` [PATCH v2 3/3] virtiofs: emit uevents on filesystem events Stefan Hajnoczi
2024-02-09 10:39   ` Greg KH
2024-02-09 12:15     ` Stefan Hajnoczi

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).