Commit 168e4af3 authored by Jason Wang's avatar Jason Wang Committed by Michael S. Tsirkin
Browse files

virtio: guard against NULL pfn



To avoid access stale memory region cache after reset, this patch
check the existence of virtqueue pfn for all exported virtqueue access
helpers before trying to use them.

Cc: Cornelia Huck <cornelia.huck@de.ibm.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Reviewed-by: default avatarCornelia Huck <cornelia.huck@de.ibm.com>
Signed-off-by: default avatarJason Wang <jasowang@redhat.com>
Reviewed-by: default avatarMichael S. Tsirkin <mst@redhat.com>
Signed-off-by: default avatarMichael S. Tsirkin <mst@redhat.com>
parent 72d9196f
Loading
Loading
Loading
Loading
+26 −0
Original line number Diff line number Diff line
@@ -318,6 +318,10 @@ int virtio_queue_ready(VirtQueue *vq)
 * Called within rcu_read_lock().  */
static int virtio_queue_empty_rcu(VirtQueue *vq)
{
    if (unlikely(!vq->vring.avail)) {
        return 1;
    }

    if (vq->shadow_avail_idx != vq->last_avail_idx) {
        return 0;
    }
@@ -329,6 +333,10 @@ int virtio_queue_empty(VirtQueue *vq)
{
    bool empty;

    if (unlikely(!vq->vring.avail)) {
        return 1;
    }

    if (vq->shadow_avail_idx != vq->last_avail_idx) {
        return 0;
    }
@@ -431,6 +439,10 @@ void virtqueue_fill(VirtQueue *vq, const VirtQueueElement *elem,
        return;
    }

    if (unlikely(!vq->vring.used)) {
        return;
    }

    idx = (idx + vq->used_idx) % vq->vring.num;

    uelem.id = elem->index;
@@ -448,6 +460,10 @@ void virtqueue_flush(VirtQueue *vq, unsigned int count)
        return;
    }

    if (unlikely(!vq->vring.used)) {
        return;
    }

    /* Make sure buffer is written before we update index. */
    smp_wmb();
    trace_virtqueue_flush(vq, count);
@@ -546,6 +562,16 @@ void virtqueue_get_avail_bytes(VirtQueue *vq, unsigned int *in_bytes,
    int64_t len = 0;
    int rc;

    if (unlikely(!vq->vring.desc)) {
        if (in_bytes) {
            *in_bytes = 0;
        }
        if (out_bytes) {
            *out_bytes = 0;
        }
        return;
    }

    rcu_read_lock();
    idx = vq->last_avail_idx;
    total_bufs = in_total = out_total = 0;