mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
virtio_fs: read the vring size under virtio_fs_mutex in ->get_tree
The vring size was read after virtio_fs_find_instance() had dropped
virtio_fs_mutex, so a concurrent virtio_fs_remove() could free the
virtqueue first. The reference from the lookup keeps the virtio_fs
alive, but not its virtqueues.
Hold the mutex across the lookup and the read.
This issue was found by an in-house static analysis tool.
Fixes: a7f0d7aab0 ("virtiofs: split requests that exceed virtqueue size")
Cc: stable@vger.kernel.org
Assisted-by: Codex:gpt-5.6
Co-developed-by: Song Li <songl@zju.edu.cn>
Signed-off-by: Song Li <songl@zju.edu.cn>
Signed-off-by: Fan Wu <fanwu01@zju.edu.cn>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
This commit is contained in:
parent
15c20483d9
commit
e7ccc777a0
|
|
@ -455,26 +455,23 @@ static int virtio_fs_add_instance(struct virtio_device *vdev,
|
|||
return ret;
|
||||
}
|
||||
|
||||
/* Return the virtio_fs with a given tag, or NULL */
|
||||
/* Return the virtio_fs with a given tag, or NULL.
|
||||
* Callers hold virtio_fs_mutex, which also keeps the virtqueues alive.
|
||||
*/
|
||||
static struct virtio_fs *virtio_fs_find_instance(const char *tag)
|
||||
{
|
||||
struct virtio_fs *fs;
|
||||
|
||||
mutex_lock(&virtio_fs_mutex);
|
||||
lockdep_assert_held(&virtio_fs_mutex);
|
||||
|
||||
list_for_each_entry(fs, &virtio_fs_instances, list) {
|
||||
if (strcmp(fs->tag, tag) == 0) {
|
||||
kobject_get(&fs->kobj);
|
||||
goto found;
|
||||
return fs;
|
||||
}
|
||||
}
|
||||
|
||||
fs = NULL; /* not found */
|
||||
|
||||
found:
|
||||
mutex_unlock(&virtio_fs_mutex);
|
||||
|
||||
return fs;
|
||||
return NULL; /* not found */
|
||||
}
|
||||
|
||||
static void virtio_fs_free_devs(struct virtio_fs *fs)
|
||||
|
|
@ -1700,13 +1697,17 @@ static int virtio_fs_get_tree(struct fs_context *fsc)
|
|||
* in chan->iq->priv. Once fuse_conn is going away, it calls ->put()
|
||||
* to drop the reference to this object.
|
||||
*/
|
||||
mutex_lock(&virtio_fs_mutex);
|
||||
fs = virtio_fs_find_instance(fsc->source);
|
||||
if (fs)
|
||||
virtqueue_size = virtqueue_get_vring_size(fs->vqs[VQ_REQUEST].vq);
|
||||
mutex_unlock(&virtio_fs_mutex);
|
||||
|
||||
if (!fs) {
|
||||
pr_info("virtio-fs: tag <%s> not found\n", fsc->source);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
virtqueue_size = virtqueue_get_vring_size(fs->vqs[VQ_REQUEST].vq);
|
||||
if (WARN_ON(virtqueue_size <= FUSE_HEADER_OVERHEAD))
|
||||
goto out_err;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user