[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH v16 1/3] mem_sharing: fix sharability check during fork reset
On Wed, Apr 22, 2020 at 06:42:42AM -0600, Tamas K Lengyel wrote: > On Wed, Apr 22, 2020 at 3:00 AM Roger Pau Monné <roger.pau@xxxxxxxxxx> wrote: > > > > On Tue, Apr 21, 2020 at 10:47:23AM -0700, Tamas K Lengyel wrote: > > > @@ -666,20 +670,31 @@ static int page_make_sharable(struct domain *d, > > > */ > > > if ( page->count_info != (PGC_allocated | (2 + expected_refcnt)) ) > > > { > > > - spin_unlock(&d->page_alloc_lock); > > > /* Return type count back to zero */ > > > put_page_and_type(page); > > > - return -E2BIG; > > > + rc = -E2BIG; > > > + goto out; > > > + } > > > + > > > + rc = 0; > > > + > > > + if ( validate_only ) > > > + { > > > + put_page_and_type(page); > > > > You seem to check some page attributes but then put the page again, > > which looks racy to me. Since you put the page, couldn't the checks > > that you have performed be stale by the point the data is consumed by > > the caller? > > During fork reset when this is called with validate_only = true the > domain is paused. Furthermore, fork reset is only for forks that have > no device model running, so nothing is interacting with its memory > that could acquire extra references. So no, this isn't racy since > there is nothing to race against that I'm aware of. Also, this check > is really to check for special pages, all of which are setup during > the initial fork process, not during runtime of the fork. Right, it would feel safer to me however if you just return from page_make_sharable while having a page reference, and drop it in mem_sharing_fork_reset if the page shouldn't be removed from the fork. This way you could also avoid having to take an extra reference just after returning from nominate_page in mem_sharing_fork_reset. page_make_sharable already returns while having taken an extra reference to the page in the non validate only case anyway. > > > > > + goto out; > > > } > > > > > > page_set_owner(page, dom_cow); > > > drop_dom_ref = !domain_adjust_tot_pages(d, -1); > > > page_list_del(page, &d->page_list); > > > - spin_unlock(&d->page_alloc_lock); > > > > > > +out: > > > + if ( !validate_only ) > > > + spin_unlock(&d->page_alloc_lock); > > > if ( drop_dom_ref ) > > > put_domain(d); > > > - return 0; > > > + > > > + return rc; > > > } > > > > > > static int page_make_private(struct domain *d, struct page_info *page) > > > @@ -809,8 +824,8 @@ static int debug_gref(struct domain *d, grant_ref_t > > > ref) > > > return debug_gfn(d, gfn); > > > } > > > > > > -static int nominate_page(struct domain *d, gfn_t gfn, > > > - int expected_refcnt, shr_handle_t *phandle) > > > +static int nominate_page(struct domain *d, gfn_t gfn, int > > > expected_refcnt, > > > > Is there any reason for expected_refcnt to be signed? All callers use > > unsigned values. > > No reason. It's just how the code was written by the original author > and we never changed it. Since you are already changing those lines, can I ask you to also change it to unsigned in the places that you touch? Thanks, Roger.
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |