qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: "Philippe Mathieu-Daudé" <philmd@redhat.com>
To: Peter Lieven <pl@kamp.de>, Felipe Franciosi <felipe@nutanix.com>
Cc: "Kevin Wolf" <kwolf@redhat.com>,
	"Peter Turschmid" <peter.turschm@nutanix.com>,
	"Stefan Hajnoczi" <stefanha@redhat.com>,
	"qemu-block@nongnu.org" <qemu-block@nongnu.org>,
	"qemu-devel@nongnu.org" <qemu-devel@nongnu.org>,
	"qemu-stable@nongnu.org" <qemu-stable@nongnu.org>,
	"P J P" <ppandit@redhat.com>, "Max Reitz" <mreitz@redhat.com>,
	"Ronnie Sahlberg" <ronniesahlberg@gmail.com>,
	"Marc-André Lureau" <marcandre.lureau@redhat.com>,
	"Paolo Bonzini" <pbonzini@redhat.com>,
	"Raphael Norwitz" <raphael.norwitz@nutanix.com>
Subject: Re: [PATCH] iscsi: Cap block count from GET LBA STATUS (CVE-2020-1711)
Date: Fri, 24 Jan 2020 11:04:29 +0100	[thread overview]
Message-ID: <c00fc076-3a46-7a52-a539-66751fb2943a@redhat.com> (raw)
In-Reply-To: <9F93582E-139B-45B2-8630-FDD331F09DEF@kamp.de>

On 1/23/20 11:58 PM, Peter Lieven wrote:
>> Am 23.01.2020 um 22:29 schrieb Felipe Franciosi <felipe@nutanix.com>:
>>> On Jan 23, 2020, at 5:46 PM, Philippe Mathieu-Daudé <philmd@redhat.com> wrote:
>>>> On 1/23/20 1:44 PM, Felipe Franciosi wrote:
>>>> When querying an iSCSI server for the provisioning status of blocks (via
>>>> GET LBA STATUS), Qemu only validates that the response descriptor zero's
>>>> LBA matches the one requested. Given the SCSI spec allows servers to
>>>> respond with the status of blocks beyond the end of the LUN, Qemu may
>>>> have its heap corrupted by clearing/setting too many bits at the end of
>>>> its allocmap for the LUN.
>>>> A malicious guest in control of the iSCSI server could carefully program
>>>> Qemu's heap (by selectively setting the bitmap) and then smash it.
>>>> This limits the number of bits that iscsi_co_block_status() will try to
>>>> update in the allocmap so it can't overflow the bitmap.
>>>
>>> Please add:
>>>
>>> Fixes: CVE-2020-1711 (title of CVE if possible)
>>
>> I wasn't sure we had one yet. Kevin: can you do the needful in your branch?
>>
>>> Cc: qemu-stable@nongnu.org
>>
>> Yeah, that's there.
>>
>>>
>>>> Signed-off-by: Felipe Franciosi <felipe@nutanix.com>
>>>> Signed-off-by: Peter Turschmid <peter.turschm@nutanix.com>
>>>> Signed-off-by: Raphael Norwitz <raphael.norwitz@nutanix.com>
>>>> ---
>>>> block/iscsi.c | 5 +++--
>>>> 1 file changed, 3 insertions(+), 2 deletions(-)
>>>> diff --git a/block/iscsi.c b/block/iscsi.c
>>>> index 2aea7e3f13..cbd57294ab 100644
>>>> --- a/block/iscsi.c
>>>> +++ b/block/iscsi.c
>>>> @@ -701,7 +701,7 @@ static int coroutine_fn iscsi_co_block_status(BlockDriverState *bs,
>>>>      struct scsi_get_lba_status *lbas = NULL;
>>>>      struct scsi_lba_status_descriptor *lbasd = NULL;
>>>>      struct IscsiTask iTask;
>>>> -    uint64_t lba;
>>>> +    uint64_t lba, max_bytes;
>>>>      int ret;
>>>>        iscsi_co_init_iscsitask(iscsilun, &iTask);
>>>> @@ -721,6 +721,7 @@ static int coroutine_fn iscsi_co_block_status(BlockDriverState *bs,
>>>>      }
>>>>        lba = offset / iscsilun->block_size;
>>>> +    max_bytes = (iscsilun->num_blocks - lba) * iscsilun->block_size;
>>>>        qemu_mutex_lock(&iscsilun->mutex);
>>>> retry:
>>>> @@ -764,7 +765,7 @@ retry:
>>>>          goto out_unlock;
>>>>      }
>>>> -    *pnum = (int64_t) lbasd->num_blocks * iscsilun->block_size;
>>>> +    *pnum = MIN((int64_t) lbasd->num_blocks * iscsilun->block_size, max_bytes);
>>>>        if (lbasd->provisioning == SCSI_PROVISIONING_TYPE_DEALLOCATED ||
>>>>          lbasd->provisioning == SCSI_PROVISIONING_TYPE_ANCHORED) {
>>>
>>> What about this?
>>>
>>> -- >8 --
>>> diff --git a/block/iscsi.c b/block/iscsi.c
>>> index 2aea7e3f13..25598accbb 100644
>>> --- a/block/iscsi.c
>>> +++ b/block/iscsi.c
>>> @@ -506,6 +506,11 @@ iscsi_allocmap_update(IscsiLun *iscsilun, int64_t offset,
>>>     /* shrink to touch only completely contained clusters */
>>>     cl_num_shrunk = DIV_ROUND_UP(offset, iscsilun->cluster_size);
>>>     nb_cls_shrunk = (offset + bytes) / iscsilun->cluster_size - cl_num_shrunk;
>>> +    if (nb_cls_expanded >= iscsilun->allocmap_size
>>> +        || nb_cls_shrunk >= iscsilun->allocmap_size) {
>>> +        error_report("iSCSI invalid request: ..." /* TODO */);
>>> +        return;
>>> +    }
>>>     if (allocated) {
>>>         bitmap_set(iscsilun->allocmap, cl_num_expanded, nb_cls_expanded);
>>>     } else {
>>> ---
>>
>> I'm not sure the above is correct because (if I read this right)
>> nb_cls_* represents the number of clusters, not the last cluster.
>>
>> Personally, I would have the checks (or "trim"s) closer to where they
>> were issued (to fail sooner) and assert()s closer to bitmap (as no oob
>> accesses should be happening at this point). There were also
>> discussions about using safer (higher level) bitmaps for this. I'm
>> always in favour of adding all reasonable checks. :)
> 
> I would add assertions that cl_num + nb_cls <= allocmap_size before every set and clear.

The description starts with "A malicious guest in control of the iSCSI 
server ..." so asserting (and killing the VM) doesn't seem correct... I 
suppose the iSCSI protocol has some error to return for invalid requests.

Also shouldn't we report some warning in case of such invalid request? 
So the management side can look at the 'malicious iSCSI server'?



  reply	other threads:[~2020-01-24 10:05 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-01-23 12:44 [PATCH] iscsi: Cap block count from GET LBA STATUS (CVE-2020-1711) Felipe Franciosi
2020-01-23 16:59 ` Kevin Wolf
2020-01-28 12:30   ` Philippe Mathieu-Daudé
2020-01-28 12:42     ` Kevin Wolf
2020-02-05 14:22       ` Felipe Franciosi
2020-01-23 17:46 ` Philippe Mathieu-Daudé
2020-01-23 21:29   ` Felipe Franciosi
2020-01-23 22:58     ` Peter Lieven
2020-01-24 10:04       ` Philippe Mathieu-Daudé [this message]
2020-01-24 10:48         ` Felipe Franciosi
2020-01-24 13:39           ` Kevin Wolf
2020-01-24 13:42             ` Philippe Mathieu-Daudé
2020-01-24 13:52               ` Kevin Wolf
2020-01-24 14:24                 ` Philippe Mathieu-Daudé

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=c00fc076-3a46-7a52-a539-66751fb2943a@redhat.com \
    --to=philmd@redhat.com \
    --cc=felipe@nutanix.com \
    --cc=kwolf@redhat.com \
    --cc=marcandre.lureau@redhat.com \
    --cc=mreitz@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=peter.turschm@nutanix.com \
    --cc=pl@kamp.de \
    --cc=ppandit@redhat.com \
    --cc=qemu-block@nongnu.org \
    --cc=qemu-devel@nongnu.org \
    --cc=qemu-stable@nongnu.org \
    --cc=raphael.norwitz@nutanix.com \
    --cc=ronniesahlberg@gmail.com \
    --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).