qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Kevin Wolf <kwolf@redhat.com>
To: Anthony Liguori <anthony@codemonkey.ws>
Cc: qemu-devel@nongnu.org
Subject: Re: [Qemu-devel] [PATCH] raw: Fix image header protection
Date: Thu, 09 Sep 2010 14:44:19 +0200	[thread overview]
Message-ID: <4C88D6A3.6050001@redhat.com> (raw)
In-Reply-To: <4C88D381.5030306@codemonkey.ws>

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<kwolf@redhat.com>
>> ---
>>   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	other threads:[~2010-09-09 12:44 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-09-07 12:08 [Qemu-devel] [PATCH] raw: Fix image header protection Kevin Wolf
2010-09-09 12:30 ` Anthony Liguori
2010-09-09 12:44   ` Kevin Wolf [this message]
2010-09-09 12:52     ` Anthony Liguori
2010-09-09 13:02       ` Kevin Wolf
2010-09-09 13:16         ` Anthony Liguori

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=4C88D6A3.6050001@redhat.com \
    --to=kwolf@redhat.com \
    --cc=anthony@codemonkey.ws \
    --cc=qemu-devel@nongnu.org \
    /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).