From mboxrd@z Thu Jan 1 00:00:00 1970 From: Vasileios Almpanis Date: Thu, 20 Aug 2026 14:11:04 +0000 Subject: Re: [Devel] [PATCH VZ10 5/5] drivers/vhost/blk: rework queue/backend setup In-Reply-To: <20260818150920.13123-6-andrey.zhadchenko@virtuozzo.com> References: <20260818150920.13123-1-andrey.zhadchenko@virtuozzo.com> <20260818150920.13123-6-andrey.zhadchenko@virtuozzo.com> Message-ID: <178723506422.906560.7120237971816041698.b4-review@b4> List-Id: > vhost_blk_setup() is pretty bad: silently refusing changed vq->num > if requests are already allocated, fetching user input second time > (double-fetch vulnerability). > To handle this, tie request allocation to backend existence. After > all, if there is no backend, there is no point in having requests. > Also expand it to get rid of boilerplate drop_backend, flush, > fput sequence in a few places. > > https://virtuozzo.atlassian.net/browse/VSTOR-138640 Fixes: 40a5928ec730 ("drivers/vhost: vhost-blk accelerator for virtio-blk guests") > Signed-off-by: Andrey Zhadchenko > > diff --git a/drivers/vhost/blk.c b/drivers/vhost/blk.c > index 070e5ce30a16..17ca135867e6 100644 > --- a/drivers/vhost/blk.c > +++ b/drivers/vhost/blk.c > @@ -647,11 +647,14 @@ static void vhost_blk_flush(struct vhost_blk *blk) > spin_unlock(&blk->flush_lock); > } > > -static inline void vhost_blk_drop_backends(struct vhost_blk *blk) > +static void vhost_blk_drop_backend(struct vhost_blk *blk) > { > struct vhost_virtqueue *vq; > int i; > > + if (!blk->backend) > + return; > + > for (i = 0; i < VHOST_BLK_VQ_MAX; i++) { > vq = &blk->vqs[i].vq; > > @@ -659,6 +662,45 @@ static inline void vhost_blk_drop_backends(struct vhost_blk *blk) > vhost_vq_set_backend(vq, NULL); > mutex_unlock(&vq->mutex); > } > + > + vhost_blk_flush(blk); > + > + for (i = 0; i < VHOST_BLK_VQ_MAX; i++) { > + kvfree(blk->vqs[i].req); > + blk->vqs[i].req = NULL; > + } > + > + fput(blk->backend); > + blk->backend = NULL; > +} > + > +static int vhost_blk_setup_vqs(struct vhost_blk *blk) > +{ > + struct vhost_virtqueue *vq; > + int i; > + > + for (i = 0; i < VHOST_BLK_VQ_MAX; i++) { > + vq = &blk->vqs[i].vq; > + > + if (!vhost_vq_is_setup(vq)) > + continue; > + > + blk->vqs[i].req = kvmalloc_array(vq->num, sizeof(struct vhost_blk_req), > + GFP_KERNEL); > + if (!blk->vqs[i].req) > + return -ENOMEM; > + > + mutex_lock(&vq->mutex); > + vhost_vq_set_backend(vq, blk->backend); > + if (vhost_vq_init_access(vq)) { > + mutex_unlock(&vq->mutex); > + return -EFAULT; > + } > + mutex_unlock(&vq->mutex); NIT: extra blank line > + > + } > + > + return 0; > } > > static int vhost_blk_open(struct inode *inode, struct file *file) > @@ -711,16 +753,10 @@ static int vhost_blk_open(struct inode *inode, struct file *file) > static int vhost_blk_release(struct inode *inode, struct file *f) > { > struct vhost_blk *blk = f->private_data; > - int i; > > - vhost_blk_drop_backends(blk); > - vhost_blk_flush(blk); > + vhost_blk_drop_backend(blk); > vhost_dev_stop(&blk->dev); > - if (blk->backend) > - fput(blk->backend); > vhost_dev_cleanup(&blk->dev); > - for (i = 0; i < VHOST_BLK_VQ_MAX; i++) > - kvfree(blk->vqs[i].req); > kfree(blk->dev.vqs); > kvfree(blk); > > @@ -754,32 +790,19 @@ static int vhost_blk_set_features(struct vhost_blk *blk, u64 features) > > static long vhost_blk_set_backend(struct vhost_blk *blk, int fd) > { > - struct vhost_virtqueue *vq; > struct file *file; > struct inode *inode; > - int ret, i; > + int ret; > > mutex_lock(&blk->dev.mutex); > ret = vhost_dev_check_owner(&blk->dev); > if (ret) > goto out_dev; > > - /* > - * fd < 0 means "stop the device". Detach the backend from every vq so > - * vhost_blk_handle_guest_kick() stops fetching descriptors, drain the > - * in-flight requests, and release the backing file. > - */ > + /* fd < 0 means "stop the device" */ > if (fd < 0) { > - if (!blk->backend) { > - ret = 0; /* already stopped */ > - goto out_dev; > - } > - vhost_blk_drop_backends(blk); > - vhost_blk_flush(blk); > - fput(blk->backend); > - blk->backend = NULL; > ret = 0; > - goto out_dev; > + goto out_drop; > } > > if (blk->backend) { > @@ -796,31 +819,21 @@ static long vhost_blk_set_backend(struct vhost_blk *blk, int fd) > inode = file->f_mapping->host; > if (!S_ISBLK(inode->i_mode)) { > ret = -EFAULT; > - goto out_file; > + fput(file); > + goto out_dev; > } > > - for (i = 0; i < VHOST_BLK_VQ_MAX; i++) { > - vq = &blk->vqs[i].vq; > - if (!vhost_vq_access_ok(vq)) { > - ret = -EFAULT; > - goto out_drop; > - } > - > - mutex_lock(&vq->mutex); > - vhost_vq_set_backend(vq, file); > - ret = vhost_vq_init_access(vq); > - mutex_unlock(&vq->mutex); > - } NIT: extra blank line -- Vasileios Almpanis