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

Re: [Xen-devel] [PATCH 13/25] argo: implement the register op



On Fri, Dec 21, 2018 at 03:05:03PM -0800, Christopher Clark wrote:
> On Thu, Dec 20, 2018 at 4:52 AM Roger Pau Monné <roger.pau@xxxxxxxxxx> wrote:
> >
> > On Wed, Dec 19, 2018 at 09:41:59PM -0800, Christopher Clark wrote:
> > > On Wed, Dec 12, 2018 at 8:48 AM Roger Pau Monné <roger.pau@xxxxxxxxxx> 
> > > wrote:
> > > >
> > > > On Fri, Nov 30, 2018 at 05:32:52PM -0800, Christopher Clark wrote:
> > Then I wonder why you need such check in any case if the code can
> > handle such cases, the more than the check itself is racy.
> 
> OK, so at the root of the question here is: does it matter what the p2m
> type of the memory is at these points:
> 
> 1) when the gfn is translated to mfn, at the time of ring registration

This is the important check, because that's where you should take a
reference to the page. In this case you should check that the page is
of ram_rw type.

> 2) when the hypervisor writes into guest memory:
>     - where the tx_ptr index is initialized in the register op
>     - where ringbuf data is written in sendv
>     - where ring description data is written in notify

As long as you keep a reference to the pages that are part of the ring
you don't need to do any checks when writing/reading from them. If the
guest messes up it's p2m and does change the gfn -> mfn mappings for
pages that are part of the ring that's the guest problem, the
hypervisor still has a reference to those pages so they won't be
reused.

> or is having PGT_writable_page type and ownership by the domain
> sufficient?
> 
> For 1), I think there's some use in saying no to a guest that has
> supplied a region that appears misconfigured.

Sure, when you setup the ring in Xen you should execute all the checks
and make sure the ring pages are of type ram_rw and take a reference
to each page.

> For 2), input would be appreciated. It currently works under the
> assumption that a p2m type check is unnecessary, which is why the
> put_gfn is where it is.

Right, and this should go away since it's confusing and unnecessary
AFAICT.

> For further background context, here's my understanding of this section:
> 
> When the guest invokes the hypercall operation to register a ring, it
> identifies the memory that it owns and wants the hypervisor to use by
> supplying an array of gfns (or in v2, addresses which are shifted to
> extract their gfns).
> 
> The hypervisor translates from gfns to mfns, using the translation that
> exists at that time, and then refers to that memory internally by mfn
> from there on out. This find_ring_mfn function is where the gfn->mfn
> translation happens.  (The variable name does needs renaming from pfn,
> as you noted - thanks.)
> 
> To do the translation from gfn to mfn, (on x86) it's using
> get_gfn_unshare. That's doing three things:
> * returns the mfn, if there is one.
> * returns the p2m type of that memory.
> * acquires a reference to that gfn, which needs to be dropped at some
>   point.
> 
> The p2m type type check on the gfn in find_ring_mfn at that time is
> possibly conservative, rejecting more types than perhaps it needs to,
> but the type that it accepts (p2m_ram_rw) is sane. It is a validation of
> the p2m type at that instant, intended to detect if the guest has
> supplied memory to the ring register op that does not make sense for it
> to use as a ring, as indicated by the current p2m type, and if so, fail
> early, or indicate that a retry later is needed.
> 
> Then the get_page_and_type call is where the memory identified by the
> mfn that was just obtained, gets locked to PGT_writable_page type, and
> ownership fixed to its current owner domain, by adding to its reference
> count.

Here you should make sure the get_page is performed while the gfn is
still locked, and once you have a reference to the page you can unlock
the gfn. As said above, if the guest then wants to mess up with the
gfn -> mfn mapping that's fine, the hypervisor already has a
reference to the underlying original memory page.

> Then the gfn reference count is dropped with the put_gfn call. This
> means that the guest can elect to change the p2m type afterwards, if it
> wants; (any change needs to be consistent with its domain ownership and
> PGT_writable_page type though -- not sure if that constrains possible types).

Hm, not really get_gfn / put_gfn doesn't actually take references, but
rather pick the p2m lock. What takes references is get_page.

> That memory can have guest-supplied data written into it, either by the
> domain owning the page itself, or in response to argo sendv operations
> by other domains that are authorized to transmit into the ring.
> 
> Your note that the "check itself is racy": ie. that a change of p2m type
> could occur immediately afterwards is true.
> 
> So: Do you think that a check on the current p2m type of the pages in
> the ring is needed at the points where the hypervisor issues writes into
> that ring memory?

No, as long as you have a reference to the page (note: not the gfn)
that you are writing to it should be fine.

Roger.

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.