Michael S. Tsirkin
2022-Jun-10 14:50 UTC
[PATCH] virtio_ring : fix vring_packed_desc memory out of bounds bug
On Fri, Jun 10, 2022 at 06:33:14PM +0800, huangjie.albert wrote:> ksoftirqd may consume the packet and it will call: > virtnet_poll > -->virtnet_receive > -->virtqueue_get_buf_ctx > -->virtqueue_get_buf_ctx_packed > and in virtqueue_get_buf_ctx_packed: > > vq->last_used_idx += vq->packed.desc_state[id].num; > if (unlikely(vq->last_used_idx >= vq->packed.vring.num)) { > vq->last_used_idx -= vq->packed.vring.num; > vq->packed.used_wrap_counter ^= 1; > } > > if at the same time, there comes a vring interrupt?in vring_interrupt: > we will call: > vring_interrupt > -->more_used > -->more_used_packed > -->is_used_desc_packed > in is_used_desc_packed, the last_used_idx maybe >= vq->packed.vring.num. > so this could case a memory out of bounds bug. > > this patch is to fix this. > > Signed-off-by: huangjie.albert <huangjie.albert at bytedance.com>This pattern was always iffy, but I don't think the patch improves the situation much. last_used_idx and vq->packed.used_wrap_counter can still get out of sync. Maybe refactor code to keep everything in vq->last_used_idx? Jason what is your take?> --- > drivers/virtio/virtio_ring.c | 3 +++ > 1 file changed, 3 insertions(+) > > diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c > index 13a7348cedff..d2abbb3a8187 100644 > --- a/drivers/virtio/virtio_ring.c > +++ b/drivers/virtio/virtio_ring.c > @@ -1397,6 +1397,9 @@ static inline bool is_used_desc_packed(const struct vring_virtqueue *vq, > bool avail, used; > u16 flags; > > + if (idx >= vq->packed.vring.num) > + return false; > + > flags = le16_to_cpu(vq->packed.vring.desc[idx].flags); > avail = !!(flags & (1 << VRING_PACKED_DESC_F_AVAIL)); > used = !!(flags & (1 << VRING_PACKED_DESC_F_USED)); > -- > 2.27.0
Jason Wang
2022-Jun-13 06:56 UTC
[PATCH] virtio_ring : fix vring_packed_desc memory out of bounds bug
On Fri, Jun 10, 2022 at 10:51 PM Michael S. Tsirkin <mst at redhat.com> wrote:> > On Fri, Jun 10, 2022 at 06:33:14PM +0800, huangjie.albert wrote: > > ksoftirqd may consume the packet and it will call: > > virtnet_poll > > -->virtnet_receive > > -->virtqueue_get_buf_ctx > > -->virtqueue_get_buf_ctx_packed > > and in virtqueue_get_buf_ctx_packed: > > > > vq->last_used_idx += vq->packed.desc_state[id].num; > > if (unlikely(vq->last_used_idx >= vq->packed.vring.num)) { > > vq->last_used_idx -= vq->packed.vring.num; > > vq->packed.used_wrap_counter ^= 1; > > } > > > > if at the same time, there comes a vring interrupt?in vring_interrupt: > > we will call: > > vring_interrupt > > -->more_used > > -->more_used_packed > > -->is_used_desc_packed > > in is_used_desc_packed, the last_used_idx maybe >= vq->packed.vring.num. > > so this could case a memory out of bounds bug. > > > > this patch is to fix this. > > > > Signed-off-by: huangjie.albert <huangjie.albert at bytedance.com> > > > This pattern was always iffy, but I don't think the patch > improves the situation much. last_used_idx and vq->packed.used_wrap_counter > can still get out of sync. > > Maybe refactor code to keep everything in vq->last_used_idx? > > Jason what is your take?I think we can do this since 16bit/32bit operations are guaranteed to be atomic. Thanks> > > > > > > --- > > drivers/virtio/virtio_ring.c | 3 +++ > > 1 file changed, 3 insertions(+) > > > > diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c > > index 13a7348cedff..d2abbb3a8187 100644 > > --- a/drivers/virtio/virtio_ring.c > > +++ b/drivers/virtio/virtio_ring.c > > @@ -1397,6 +1397,9 @@ static inline bool is_used_desc_packed(const struct vring_virtqueue *vq, > > bool avail, used; > > u16 flags; > > > > + if (idx >= vq->packed.vring.num) > > + return false; > > + > > flags = le16_to_cpu(vq->packed.vring.desc[idx].flags); > > avail = !!(flags & (1 << VRING_PACKED_DESC_F_AVAIL)); > > used = !!(flags & (1 << VRING_PACKED_DESC_F_USED)); > > -- > > 2.27.0 >