mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 18:50:05 +01:00
The original rules for `struct page` required the following invariants at all times: - refcount > 0 implies owner != NULL - PGC_allocated implies refcount > 0 steal_page, in a misguided attempt to protect against unknown races, violates both of these rules, thus introducing other races: - Temporarily, the count_info has the refcount go to 0 while PGC_allocated is set - It explicitly returns the page PGC_allocated set, but owner == NULL and page not on the page_list. The second one meant that page_get_owner_and_reference() could return NULL even after having successfully grabbed a reference on the page, leading the caller to leak the reference (since "couldn't get ref" and "got ref but no owner" look the same). Furthermore, rather than grabbing a page reference to ensure that the owner doesn't change under its feet, it appears to rely on holding d->page_alloc lock to prevent this. Unfortunately, this is ineffective: page->owner remains non-NULL for some time after the count has been set to 0; meaning that it would be entirely possible for the page to be freed and re-allocated to a different domain between the page_get_owner() check and the count_info check. Modify steal_page to instead follow the appropriate access discipline, taking the page through series of states similar to being freed and then re-allocated with MEMF_no_owner: - Grab an extra reference to make sure we don't race with anyone else freeing the page - Drop both references and PGC_allocated atomically, so that (if successful), anyone else trying to grab a reference will fail - Attempt to reset Xen's mappings - Reset the rest of the state. Then, modify the two callers appropriately: - Leave count_info alone (it's already been cleared) - Call free_domheap_page() directly if appropriate - Call assign_pages() rather than open-coding a partial assign With all callers to assign_pages() now passing in pages with the type_info field clear, tighten the respective assertion there. This is XSA-287. Signed-off-by: George Dunlap <george.dunlap@citrix.com> Signed-off-by: Jan Beulich <jbeulich@suse.com>