Jason Wang
2022-Jul-01 09:27 UTC
[PATCH v11 21/40] virtio_ring: packed: introduce virtqueue_resize_packed()
? 2022/6/29 14:56, Xuan Zhuo ??:> virtio ring packed supports resize. > > Only after the new vring is successfully allocated based on the new num, > we will release the old vring. In any case, an error is returned, > indicating that the vring still points to the old vring. > > In the case of an error, re-initialize(by virtqueue_reinit_packed()) the > virtqueue to ensure that the vring can be used. > > Signed-off-by: Xuan Zhuo <xuanzhuo at linux.alibaba.com> > --- > drivers/virtio/virtio_ring.c | 29 +++++++++++++++++++++++++++++ > 1 file changed, 29 insertions(+) > > diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c > index 650f701a5480..4860787286db 100644 > --- a/drivers/virtio/virtio_ring.c > +++ b/drivers/virtio/virtio_ring.c > @@ -2042,6 +2042,35 @@ static struct virtqueue *vring_create_virtqueue_packed( > return NULL; > } > > +static int virtqueue_resize_packed(struct virtqueue *_vq, u32 num) > +{ > + struct vring_virtqueue_packed vring = {}; > + struct vring_virtqueue *vq = to_vvq(_vq); > + struct virtio_device *vdev = _vq->vdev; > + int err; > + > + if (vring_alloc_queue_packed(&vring, vdev, num)) > + goto err_ring; > + > + err = vring_alloc_state_extra_packed(&vring); > + if (err) > + goto err_state_extra; > + > + vring_free(&vq->vq); > + > + virtqueue_init(vq, vring.vring.num); > + virtqueue_vring_attach_packed(vq, &vring); > + virtqueue_vring_init_packed(vq); > + > + return 0; > + > +err_state_extra: > + vring_free_packed(&vring, vdev); > +err_ring: > + virtqueue_reinit_packed(vq);So desc_state and desc_extra has been freed vring_free_packed() when vring_alloc_state_extra_packed() fails. We might get use-after-free here? Actually, I think for resize we need 1) detach old 2) allocate new 3) if 2) succeed, attach new otherwise attach old This seems more clearer than the current logic? Thanks> + return -ENOMEM; > +} > + > > /* > * Generic functions and exported symbols.
Xuan Zhuo
2022-Jul-04 02:13 UTC
[PATCH v11 21/40] virtio_ring: packed: introduce virtqueue_resize_packed()
On Fri, 1 Jul 2022 17:27:48 +0800, Jason Wang <jasowang at redhat.com> wrote:> > ? 2022/6/29 14:56, Xuan Zhuo ??: > > virtio ring packed supports resize. > > > > Only after the new vring is successfully allocated based on the new num, > > we will release the old vring. In any case, an error is returned, > > indicating that the vring still points to the old vring. > > > > In the case of an error, re-initialize(by virtqueue_reinit_packed()) the > > virtqueue to ensure that the vring can be used. > > > > Signed-off-by: Xuan Zhuo <xuanzhuo at linux.alibaba.com> > > --- > > drivers/virtio/virtio_ring.c | 29 +++++++++++++++++++++++++++++ > > 1 file changed, 29 insertions(+) > > > > diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c > > index 650f701a5480..4860787286db 100644 > > --- a/drivers/virtio/virtio_ring.c > > +++ b/drivers/virtio/virtio_ring.c > > @@ -2042,6 +2042,35 @@ static struct virtqueue *vring_create_virtqueue_packed( > > return NULL; > > } > > > > +static int virtqueue_resize_packed(struct virtqueue *_vq, u32 num) > > +{ > > + struct vring_virtqueue_packed vring = {}; > > + struct vring_virtqueue *vq = to_vvq(_vq); > > + struct virtio_device *vdev = _vq->vdev; > > + int err; > > + > > + if (vring_alloc_queue_packed(&vring, vdev, num)) > > + goto err_ring; > > + > > + err = vring_alloc_state_extra_packed(&vring); > > + if (err) > > + goto err_state_extra; > > + > > + vring_free(&vq->vq); > > + > > + virtqueue_init(vq, vring.vring.num); > > + virtqueue_vring_attach_packed(vq, &vring); > > + virtqueue_vring_init_packed(vq); > > + > > + return 0; > > + > > +err_state_extra: > > + vring_free_packed(&vring, vdev); > > +err_ring: > > + virtqueue_reinit_packed(vq); > > > So desc_state and desc_extra has been freed vring_free_packed() when > vring_alloc_state_extra_packed() fails. We might get use-after-free here?vring_free_packed() frees the temporary structure vring. It does not affect desc_state and desc_extra of vq. So it is safe.> > Actually, I think for resize we need > > 1) detach old > 2) allocate new > 3) if 2) succeed, attach new otherwise attach oldThe implementation is now: 1. allocate new 2. free old (detach old) 3. attach new error: 1. free temporary 2. reinit old Do you think this is ok? We need to add a new variable to save the old vring in the process you mentioned, there is not much difference in other. Thanks.> > This seems more clearer than the current logic? > > Thanks > > > > + return -ENOMEM; > > +} > > + > > > > /* > > * Generic functions and exported symbols. >