All of lore.kernel.org
 help / color / mirror / Atom feed
From: Alex Williamson <alex.williamson@redhat.com>
To: Pierre Morel <pmorel@linux.vnet.ibm.com>
Cc: pbonzini@redhat.com, qemu-devel@nongnu.org, peter.maydell@linaro.org
Subject: Re: [Qemu-devel] [PATCH v2] vfio/common: Check iova with limit not with size
Date: Wed, 06 Jan 2016 12:08:05 -0700	[thread overview]
Message-ID: <1452107285.29599.127.camel@redhat.com> (raw)
In-Reply-To: <1452009820-24968-1-git-send-email-pmorel@linux.vnet.ibm.com>

On Tue, 2016-01-05 at 17:03 +0100, Pierre Morel wrote:
> In vfio_listener_region_add(), the code makes sure
> that the offset in the section is lower than the size
> of the section.
> But the calculation uses size of the region instead of
> the region's limit (size - 1).

We're really just trying to validate that the region is not zero sized
and hasn't overflowed the addresses space.

> This leads to Int128 overflow when the region has
> been initialized to UINT64_MAX because in this case
> memory_region_init() transform the size from UINT64_MAX
> to int128_2_64().
> 
> Let's really use the limit by sustracting one to the size
> and take care to use the limit for functions using limit
> and size to call functions which need size.
> 
> Signed-off-by: Pierre Morel <pmorel@linux.vnet.ibm.com>
> ---
>  hw/vfio/common.c |   15 ++++++++++-----
>  1 files changed, 10 insertions(+), 5 deletions(-)
> 
> diff --git a/hw/vfio/common.c b/hw/vfio/common.c
> index 6797208..fe4962a 100644
> --- a/hw/vfio/common.c
> +++ b/hw/vfio/common.c
> @@ -342,18 +342,23 @@ static void vfio_listener_region_add(MemoryListener *listener,
>  
>      iova = TARGET_PAGE_ALIGN(section->offset_within_address_space);
>      llend = int128_make64(section->offset_within_address_space);
> -    llend = int128_add(llend, section->size);
> +
> +    if (int128_ge(llend, int128_2_64())) {

We've just set llend using int128_make64, so this is guaranteed false.

> +        llend = int128_add(llend, int128_sub(section->size, int128_one()));
> +    } else {
> +        llend = int128_add(llend, section->size);
> +    }

So the above changed nothing.

>      llend = int128_and(llend, int128_exts64(TARGET_PAGE_MASK));
>  
> -    if (int128_ge(int128_make64(iova), llend)) {
> +    if (int128_gt(int128_make64(iova), llend)) {

And this allows zero sized regions through.

>          return;
>      }
>      end = int128_get64(llend);
>  
> -    if ((iova < container->min_iova) || ((end - 1) > container->max_iova)) {
> +    if ((iova < container->min_iova) || (end > container->max_iova)) {
>          error_report("vfio: IOMMU container %p can't map guest IOVA region"
>                       " 0x%"HWADDR_PRIx"..0x%"HWADDR_PRIx,
> -                     container, iova, end - 1);
> +                     container, iova, end);

This looks wrong too, max_iova is set to the last valid iova, for
instance if the iommu only supported a 4k address space, max_iova would
be 0xfff.  A mapping of size 4k at offset 0 should work, but this
change would cause it to fail.

>          ret = -EFAULT;
>          goto fail;
>      }
> @@ -363,7 +368,7 @@ static void vfio_listener_region_add(MemoryListener *listener,
>      if (memory_region_is_iommu(section->mr)) {
>          VFIOGuestIOMMU *giommu;
>  
> -        trace_vfio_listener_region_add_iommu(iova, end - 1);
> +        trace_vfio_listener_region_add_iommu(iova, end);
>          /*
>           * FIXME: We should do some checking to see if the
>           * capabilities of the host VFIO IOMMU are adequate to model

I think maybe you want to set end using:

end = int128_get64(int128_sub(llend, int128_one()));

Then removing the -1 in other places becomes correct, BUT we need to
add 1 where we're passing the size, end - iova - > end - iova + 1.
 Thanks,

Alex

  reply	other threads:[~2016-01-06 19:08 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-01-05 16:03 [Qemu-devel] [PATCH v2] vfio/common: Check iova with limit not with size Pierre Morel
2016-01-06 19:08 ` Alex Williamson [this message]
2016-01-12 14:39   ` Pierre Morel

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=1452107285.29599.127.camel@redhat.com \
    --to=alex.williamson@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=peter.maydell@linaro.org \
    --cc=pmorel@linux.vnet.ibm.com \
    --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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.