]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
virtio_ring: Check used descriptors are chain heads
authorAndrew Scull <ascull@google.com>
Mon, 16 May 2022 10:41:32 +0000 (10:41 +0000)
committerTom Rini <trini@konsulko.com>
Wed, 8 Jun 2022 13:24:03 +0000 (09:24 -0400)
When the device returns used buffers, it should refer to the descriptor
that is the head of the descriptor chain for that buffer. Confirm this
to be the case by tracking the head of descriptor chains that have been
made available to the device.

Signed-off-by: Andrew Scull <ascull@google.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
drivers/virtio/virtio_ring.c
include/virtio_ring.h

index 73671d79daffb2f1a5504f11f347f9e0970e8433..f71bab784773b46ba1fee10cdfecdacc484e16f9 100644 (file)
@@ -82,6 +82,9 @@ int virtqueue_add(struct virtqueue *vq, struct virtio_sg *sgs[],
        /* Update free pointer */
        vq->free_head = i;
 
+       /* Mark the descriptor as the head of a chain. */
+       vq->vring_desc_shadow[head].chain_head = true;
+
        /*
         * Put entry in available array (but don't update avail->idx
         * until they do sync).
@@ -144,6 +147,9 @@ static void detach_buf(struct virtqueue *vq, unsigned int head)
 {
        unsigned int i;
 
+       /* Unmark the descriptor as the head of a chain. */
+       vq->vring_desc_shadow[head].chain_head = false;
+
        /* Put back on free list: unmap first-level descriptors and find end */
        i = head;
 
@@ -194,6 +200,12 @@ void *virtqueue_get_buf(struct virtqueue *vq, unsigned int *len)
                return NULL;
        }
 
+       if (unlikely(!vq->vring_desc_shadow[i].chain_head)) {
+               printf("(%s.%d): id %u is not a head\n",
+                      vq->vdev->name, vq->index, i);
+               return NULL;
+       }
+
        detach_buf(vq, i);
        vq->last_used_idx++;
        /*
index 52cbe77c0a27c9ce88757b175427f1eee59697a2..c77c212cffd3d5e2d2cc9a3a689a528c10a0aed3 100644 (file)
@@ -61,6 +61,8 @@ struct vring_desc_shadow {
        u32 len;
        u16 flags;
        u16 next;
+       /* Metadata about the descriptor. */
+       bool chain_head;
 };
 
 struct vring_avail {