qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH] raw: Fix image header protection


From: Kevin Wolf
Subject: Re: [Qemu-devel] [PATCH] raw: Fix image header protection
Date: Thu, 09 Sep 2010 14:44:19 +0200
User-agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.12) Gecko/20100907 Fedora/3.0.7-1.fc12 Thunderbird/3.0.7

Am 09.09.2010 14:30, schrieb Anthony Liguori:
> On 09/07/2010 07:08 AM, Kevin Wolf wrote:
>> Recenty a patch was committed to protect the first four bytes of an image to
>> avoid "converting" a probed raw image to a different format when a malicious
>> guest writes e.g. a qcow2 header to it.
>>
>> This check relies on the assumption that all qiov entries are multiples of 
>> 512,
>> which isn't true in practice. At least the installers of some Windows 
>> versions
>> are reported to fail the corresponding assertion.
>>
>> This patch removes the wrong assumption and fixes Win 2003 installation for 
>> me
>> (other Windows versions not tested, should be the same)
>>
>> Signed-off-by: Kevin Wolf<address@hidden>
>> ---
>>   block/raw.c   |   57 
>> ++++++++++++++++++++++++---------------------------------
>>   cutils.c      |   16 ++++++++++++----
>>   qemu-common.h |    1 +
>>   3 files changed, 37 insertions(+), 37 deletions(-)
>>
>> diff --git a/block/raw.c b/block/raw.c
>> index 61e6748..3286550 100644
>> --- a/block/raw.c
>> +++ b/block/raw.c
>> @@ -99,6 +99,7 @@ typedef struct RawScrubberBounce
>>   {
>>       BlockDriverCompletionFunc *cb;
>>       void *opaque;
>> +    uint8_t *buf;
>>       QEMUIOVector qiov;
>>   } RawScrubberBounce;
>>
>> @@ -113,6 +114,7 @@ static void raw_aio_writev_scrubbed(void *opaque, int 
>> ret)
>>       }
>>
>>       qemu_iovec_destroy(&b->qiov);
>> +    qemu_free(b->buf);
>>       qemu_free(b);
>>   }
>>
>> @@ -120,46 +122,35 @@ static BlockDriverAIOCB 
>> *raw_aio_writev(BlockDriverState *bs,
>>       int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
>>       BlockDriverCompletionFunc *cb, void *opaque)
>>   {
>> -    const uint8_t *first_buf;
>> -    int first_buf_index = 0, i;
>> -
>> -    /* This is probably being paranoid, but handle cases of zero size
>> -       vectors. */
>> -    for (i = 0; i<  qiov->niov; i++) {
>> -        if (qiov->iov[i].iov_len) {
>> -            assert(qiov->iov[i].iov_len>= 512);
>> -            first_buf_index = i;
>> -            break;
>> -        }
>> -    }
>> +    if (bs->probed) {
>> +        uint8_t first_buf[512];
>> +        qemu_iovec_part_to_buffer(qiov, first_buf, 512);
>>
>> -    first_buf = qiov->iov[first_buf_index].iov_base;
>> +        if (check_write_unsafe(bs, sector_num, first_buf, nb_sectors)) {
>> +            RawScrubberBounce *b;
>> +            int ret;
>>
>> -    if (check_write_unsafe(bs, sector_num, first_buf, nb_sectors)) {
>> -        RawScrubberBounce *b;
>> -        int ret;
>> +            /* write the first sector using sync I/O */
>> +            ret = raw_write_scrubbed_bootsect(bs, first_buf);
>> +            if (ret<  0) {
>> +                return NULL;
>> +            }
>>
>> -        /* write the first sector using sync I/O */
>> -        ret = raw_write_scrubbed_bootsect(bs, first_buf);
>> -        if (ret<  0) {
>> -            return NULL;
>> -        }
>> -
>> -        /* adjust request to be everything but first sector */
>> +            /* adjust request to be everything but first sector */
>>
>> -        b = qemu_malloc(sizeof(*b));
>> -        b->cb = cb;
>> -        b->opaque = opaque;
>> +            b = qemu_malloc(sizeof(*b));
>> +            b->cb = cb;
>> +            b->opaque = opaque;
>>
>> -        qemu_iovec_init(&b->qiov, qiov->nalloc);
>> -        qemu_iovec_concat(&b->qiov, qiov, qiov->size);
>> +            b->buf = qemu_malloc(qiov->size);
>> +            qemu_iovec_to_buffer(qiov, b->buf);
>>    
> 
> Isn't this an unbounded, guest controlled, malloc?  IOW, a guest could 
> do a request of 4GB and on a 32-bit system crash the qemu instance.

If you're concerned about that, we need to ban qemu_iovec_to_buffer()
completely. Currently we do the same thing for every write request for
every format but raw. Or instead of completely removing it, we could add
a size limit, though I suspect that would mean violating some specs.

If I was a guest though and wanted to crash qemu, I would just mess up
the virtio ring a bit so that qemu would exit() voluntarily. ;-)

Kevin



reply via email to

[Prev in Thread] Current Thread [Next in Thread]