From: Laurent Vivier <lvivier@redhat.com>
To: Alexander Bulekov <alxndr@bu.edu>, qemu-devel@nongnu.org
Cc: Paolo Bonzini <pbonzini@redhat.com>,
Stefan Hajnoczi <stefanha@redhat.com>,
"Michael S. Tsirkin" <mst@redhat.com>
Subject: Re: Assertion failure through vring_split_desc_read
Date: Tue, 12 May 2020 17:14:07 +0200 [thread overview]
Message-ID: <008dc437-4719-0271-7647-b04f1253049c@redhat.com> (raw)
In-Reply-To: <b67bd42d-b832-20ff-411e-dd3f4a40da1a@redhat.com>
On 12/05/2020 15:49, Laurent Vivier wrote:
> On 11/05/2020 05:51, Alexander Bulekov wrote:
>> Hello,
>> While fuzzing, I found an input that triggers an assertion failure
>> through virtio-rng -> vring_split_desc_read. Maybe this is related to:
>> Message-ID: <20200511033001.dzvtbdhl3oz5pgiy@mozz.bu.edu>
>> Assertion failure through virtio_lduw_phys_cached
>>
>> #8 0x7fe6a9acf091 in __assert_fail /build/glibc-GwnBeO/glibc-2.30/assert/assert.c:101:3
>> #9 0x564cbe7d96fd in address_space_read_cached include/exec/memory.h:2423:5
>> #10 0x564cbe7e79c5 in vring_split_desc_read hw/virtio/virtio.c:236:5
>> #11 0x564cbe7e84ce in virtqueue_split_read_next_desc hw/virtio/virtio.c:929:5
>> #12 0x564cbe78f86b in virtqueue_split_get_avail_bytes hw/virtio/virtio.c:1009:18
>> #13 0x564cbe78ab22 in virtqueue_get_avail_bytes hw/virtio/virtio.c:1208:9
>> #14 0x564cc08aade1 in get_request_size hw/virtio/virtio-rng.c:40:5
>> #15 0x564cc08aa20b in virtio_rng_process hw/virtio/virtio-rng.c:115:12
>> #16 0x564cc08a8c48 in virtio_rng_set_status hw/virtio/virtio-rng.c:172:5
>> #17 0x564cbe7a50be in virtio_set_status hw/virtio/virtio.c:1876:9
>> #18 0x564cc08d1b8f in virtio_pci_common_write hw/virtio/virtio-pci.c:1245:9
>>
>> I can reproduce it in a qemu 5.0 build using these qtest commands:
>> https://paste.debian.net/plain/1146089
>> (not including them here, as some are quite long)
>>
>> wget https://paste.debian.net/plain/1146089 -O qtest-trace; ~/Development/qemu/build/i386-softmmu/qemu-system-i386 -M pc-q35-5.0 -device virtio-rng-pci,addr=04.0 -display none -nodefaults -nographic -qtest stdio < qtest-trace
>
> Nice work.
>
> If I use directly "curl https://paste.debian.net/plain/1146089 |
> qemu-system-i386 ..." I have only a warning:
>
> qemu-system-i386: Guest moved used index from 0 to 496
>
> I've added some traces.
>
> The assert is triggered because addr (0xffff0) >= cache->len (0x11d0).
>
> addr is 2nd argument of:
>
> address_space_read_cached(cache, i * sizeof(VRingDesc),
> desc, sizeof(VRingDesc));
>
> and "i" appears to be "65535".
>
> In virtqueue_split_read_next_desc(), the value is checked not to be
> greater than max.
>
> But max is 268345360...
>
> "max" is provided by virtqueue_split_get_avail_bytes(), it's originally
> vq->vring.num (255), but in the case of VRING_DESC_F_INDIRECT max is
> updated to "desc.len / sizeof(VRingDesc)". desc.len is 4293525760.
>
> It is set from max to cache->len by address_space_cache_init() but this
> value seems to be truncated in the next iteration of the loop (where we
> have the assert()).
>
> I'm investigating why we have that.
The problem is in virtqueue_split_get_avail_bytes().
On start, max is set to vq->vring.num (255), then in the
virtqueue_get_head() loop we read an indirect descriptor and max is set
to desc.len / sizeof(VRingDesc) (268345360). cache->len is
indirect_desc_cache.len, initialized from desc_len. So it is fine.
But after that desc is consumed by virtqueue_split_read_next_desc() and
then indirect_desc_cache is destroyed by address_space_cache_destroy(),
but max is not reset and used to check the next access with a new desc
that has a different size.
I think max should be reset when the cache is destroyed or set at the
begining of the loop.
Something like:
diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index b6c8ef5bc025..f6d90a99e5e4 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -1001,7 +1001,6 @@ static void
virtqueue_split_get_avail_bytes(VirtQueue *vq,
idx = vq->last_avail_idx;
total_bufs = in_total = out_total = 0;
- max = vq->vring.num;
caches = vring_get_region_caches(vq);
if (!caches) {
goto err;
@@ -1013,6 +1012,7 @@ static void
virtqueue_split_get_avail_bytes(VirtQueue *vq,
VRingDesc desc;
unsigned int i;
+ max = vq->vring.num;
num_bufs = total_bufs;
if (!virtqueue_get_head(vq, idx++, &i)) {
Thanks,
Laurent
next prev parent reply other threads:[~2020-05-12 15:18 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-05-11 3:51 Assertion failure through vring_split_desc_read Alexander Bulekov
2020-05-12 13:49 ` Laurent Vivier
2020-05-12 15:14 ` Laurent Vivier [this message]
2020-05-13 23:24 ` John Snow
2020-05-14 8:12 ` Philippe Mathieu-Daudé
2020-05-14 13:50 ` Alexander Bulekov
2020-05-14 17:22 ` John Snow
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=008dc437-4719-0271-7647-b04f1253049c@redhat.com \
--to=lvivier@redhat.com \
--cc=alxndr@bu.edu \
--cc=mst@redhat.com \
--cc=pbonzini@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=stefanha@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).