Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
openSUSE:Step:FrontRunner
xen.23271
6138ae99-gnttab-status-frame-mapping-race.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 6138ae99-gnttab-status-frame-mapping-race.patch of Package xen.23271
# Commit eb6bbf7b30da5bae87932514d54d0e3c68b23757 # Date 2021-09-08 14:37:45 +0200 # Author Jan Beulich <jbeulich@suse.com> # Committer Jan Beulich <jbeulich@suse.com> gnttab: deal with status frame mapping race Once gnttab_map_frame() drops the grant table lock, the MFN it reports back to its caller is free to other manipulation. In particular gnttab_unpopulate_status_frames() might free it, by a racing request on another CPU, thus resulting in a reference to a deallocated page getting added to a domain's P2M. Obtain a page reference in gnttab_map_frame() to prevent freeing of the page until xenmem_add_to_physmap_one() has actually completed its acting on the page. Do so uniformly, even if only strictly required for v2 status pages, to avoid extra conditionals (which then would all need to be kept in sync going forward). This is CVE-2021-28701 / XSA-384. Reported-by: Julien Grall <jgrall@amazon.com> Signed-off-by: Jan Beulich <jbeulich@suse.com> Reviewed-by: Julien Grall <jgrall@amazon.com> --- a/xen/arch/arm/mm.c +++ b/xen/arch/arm/mm.c @@ -1227,6 +1227,8 @@ int xenmem_add_to_physmap_one( if ( rc ) return rc; + /* Need to take care of the reference obtained in gnttab_map_frame(). */ + page = mfn_to_page(mfn); t = p2m_ram_rw; break; @@ -1294,9 +1296,12 @@ int xenmem_add_to_physmap_one( /* Map at new location. */ rc = guest_physmap_add_entry(d, gfn, mfn, 0, t); - /* If we fail to add the mapping, we need to drop the reference we - * took earlier on foreign pages */ - if ( rc && space == XENMAPSPACE_gmfn_foreign ) + /* + * For XENMAPSPACE_gmfn_foreign if we failed to add the mapping, we need + * to drop the reference we took earlier. In all other cases we need to + * drop any reference we took earlier (perhaps indirectly). + */ + if ( space == XENMAPSPACE_gmfn_foreign ? rc : page != NULL ) { ASSERT(page != NULL); put_page(page); --- a/xen/arch/x86/mm.c +++ b/xen/arch/x86/mm.c @@ -4777,6 +4777,8 @@ int xenmem_add_to_physmap_one( rc = gnttab_map_frame(d, idx, gpfn, &mfn); if ( rc ) return rc; + /* Need to take care of the ref obtained in gnttab_map_frame(). */ + page = mfn_to_page(mfn); break; case XENMAPSPACE_gmfn: { --- a/xen/common/grant_table.c +++ b/xen/common/grant_table.c @@ -3997,7 +3997,16 @@ int gnttab_map_frame(struct domain *d, u } if ( !rc ) - gnttab_set_frame_gfn(gt, status, idx, gfn); + { + /* + * Make sure gnttab_unpopulate_status_frames() won't (successfully) + * free the page until our caller has completed its operation. + */ + if ( get_page(mfn_to_page(*mfn), d) ) + gnttab_set_frame_gfn(gt, status, idx, gfn); + else + rc = -EBUSY; + } grant_write_unlock(gt);
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor