All of lore.kernel.org
 help / color / mirror / Atom feed
From: Don Slutz <dslutz@verizon.com>
To: Andrew Cooper <andrew.cooper3@citrix.com>,
	Jan Beulich <JBeulich@suse.com>
Cc: Keir Fraser <keir@xen.org>,
	"xen-devel@lists.xen.org" <xen-devel@lists.xen.org>
Subject: Re: [PATCH 1/1] x86/hvm: prevent hvm_free_ioreq_gmfn() clobber of arbitrary memory
Date: Tue, 14 Apr 2015 18:54:28 -0400	[thread overview]
Message-ID: <552D9AA4.8070806@one.verizon.com> (raw)
In-Reply-To: <552D1375.8050204@citrix.com>

On 04/14/15 09:17, Andrew Cooper wrote:
> On 14/04/15 12:47, Jan Beulich wrote:
>>>>> On 13.04.15 at 18:01, <dslutz@verizon.com> wrote:
>>> --- a/xen/arch/x86/hvm/hvm.c
>>> +++ b/xen/arch/x86/hvm/hvm.c
>>> @@ -536,8 +536,9 @@ static int hvm_alloc_ioreq_gmfn(struct domain *d, 
>>> unsigned long *gmfn)
>>>  
>>>  static void hvm_free_ioreq_gmfn(struct domain *d, unsigned long gmfn)
>>>  {
>>> -    unsigned int i = gmfn - d->arch.hvm_domain.ioreq_gmfn.base;
>>> +    unsigned long i = gmfn - d->arch.hvm_domain.ioreq_gmfn.base;
>>>  
>>> +    BUG_ON(i >= sizeof(d->arch.hvm_domain.ioreq_gmfn.mask) * 8);
>>>      clear_bit(i, &d->arch.hvm_domain.ioreq_gmfn.mask);
>>>  }
>> I'd be happier with an ASSERT() - Andrew?
> 
> If I recall, this is a follow on from the compiler error, where gmfn now
> gets initialised to ~0 to avoid a build failure.
> 
> If gcc is correct and there is a way for gmfn to be used, then the
> clear_bit() here clobber memory.  The BUG_ON() serves as a protection
> against the clobbering.
> 
> If however gcc was actually wrong, then the code here is actually fine,
> and a BUG_ON() or ASSERT() will never actually trigger.
> 
> In addition, not a hotpath in the slightest, so performance isn't a concern.
> 
> 
> I have still not managed to conclusively work out whether gcc is correct
> or wrong.  As a result, I would lean in the direction of BUG_ON() rather
> than ASSERT(), out of paranoia.  However, I would prefer even more a
> solution where we were certain that gmfn isn't bogus.
> 

The best I can do is to write out the code paths that I can see.  This
is all taken from RELEASE-4.5.0


There are 4 calls to hvm_free_ioreq_gmfn:

1 x86/hvm/hvm.c hvm_ioreq_server_map_pages   764 hvm_free_ioreq_gmfn(d,
bufioreq_pfn);
2 x86/hvm/hvm.c hvm_ioreq_server_map_pages   768 hvm_free_ioreq_gmfn(d,
ioreq_pfn);
3 x86/hvm/hvm.c hvm_ioreq_server_unmap_pages 788 hvm_free_ioreq_gmfn(d,
s->bufioreq.gmfn);
4 x86/hvm/hvm.c hvm_ioreq_server_unmap_pages 790 hvm_free_ioreq_gmfn(d,
s->ioreq.gmfn);



GCC only reported about bufioreq_pfn:

hvm.c: In function ‘hvm_create_ioreq_server’:
hvm.c:487:18: error: ‘bufioreq_pfn’ may be used uninitialised in this
function


Which is the line:

    unsigned int i = gmfn - d->arch.hvm_domain.ioreq_gmfn.base;

And gcc has changed the arg 'gmfn' into 'bufioreq_pfn' so this should
only apply to #1.

Now for #1, the args to hvm_ioreq_server_map_pages() 'is_default' and
'handle_bufioreq' are important.  The call that GCC is reporting on
(with context):

--------------------------------------------------------------------------
    return 0;

fail4:
    hvm_unmap_ioreq_page(s, 0);

fail3:
    if ( !is_default && handle_bufioreq )
        hvm_free_ioreq_gmfn(d, bufioreq_pfn);
--------------------------------------------------------------------------


So only the case:

'is_default' === 0, 'handle_bufioreq' === 1 needs to be checked for
all goto's of fail4 or fail3.

Now the call to hvm_alloc_ioreq_gmfn(d, &bufioreq_pfn) does have a
path where bufioreq_pfn is not set, however it will return -ENOMEM
for this case.  And so should always goto fail2:

---------------------------------------------------------------------
        if ( handle_bufioreq )
        {
            rc = hvm_alloc_ioreq_gmfn(d, &bufioreq_pfn);
            if ( rc )
                goto fail2;
        }
    }

    rc = hvm_map_ioreq_page(s, 0, ioreq_pfn);
    if ( rc )
        goto fail3;
---------------------------------------------------------------------

Since both share 'handle_bufioreq', the only time I can see
'handle_bufioreq' not uninitialised is when we goto fail2.

The ways to fail3 & fail4:
---------------------------------------------------------------------
    rc = hvm_map_ioreq_page(s, 0, ioreq_pfn);
    if ( rc )
        goto fail3;

    if ( handle_bufioreq )
    {
        rc = hvm_map_ioreq_page(s, 1, bufioreq_pfn);
        if ( rc )
            goto fail4;
    }

    return 0;
--------------------------------------------------------------------

are all after the goto for fail2.  So I see hvm_alloc_ioreq_gmfn()
setting 'bufioreq_pfn' in all cases where it is possible to get to
fail3.


Hope this helps.

    -Don Slutz


> ~Andrew
> 

  reply	other threads:[~2015-04-14 22:54 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-04-13 16:01 [PATCH 1/1] x86/hvm: prevent hvm_free_ioreq_gmfn() clobber of arbitrary memory Don Slutz
2015-04-14 11:47 ` Jan Beulich
2015-04-14 13:17   ` Andrew Cooper
2015-04-14 22:54     ` Don Slutz [this message]
2015-04-16 10:53     ` Tim Deegan
2015-04-16 11:32       ` Jan Beulich
2015-04-16 16:37         ` Tim Deegan
2015-04-16 18:44           ` Andrew Cooper
2015-04-17  7:45           ` Jan Beulich
2015-04-23 13:25 Paul Durrant

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=552D9AA4.8070806@one.verizon.com \
    --to=dslutz@verizon.com \
    --cc=JBeulich@suse.com \
    --cc=andrew.cooper3@citrix.com \
    --cc=keir@xen.org \
    --cc=xen-devel@lists.xen.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.