xen/page_alloc: Harden assign_pages()

domain_tot_pages() and d->max_pages are 32-bit values. While the order
should always be quite small, it would still be possible to overflow
if domain_tot_pages() is near to (2^32 - 1).

As this code may be called by a guest via XENMEM_increase_reservation
and XENMEM_populate_physmap, we want to make sure the guest is not going
to be able to allocate more than it is allowed.

Rework the allocation check to avoid any possible overflow. While the
check domain_tot_pages() < d->max_pages should technically not be
necessary, it is probably best to have it to catch any possible
inconsistencies in the future.

This is CVE-2021-28706 / part of XSA-385.

Signed-off-by: Julien Grall <jgrall@amazon.com>
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Roger Pau Monné <roger.pau@citrix.com>
master commit: 143501861d
master date: 2021-11-22 11:11:05 +0000
This commit is contained in:
Julien Grall authored and Jan Beulich committed 2021-11-23 13:35:03 +01:00
1 parent 95172a6347
commit 8e657cfe0a
2 files changed
+18 -8

No files matched your search

+4 -3
View File
@@ -2239,7 +2239,8 @@ gnttab_transfer(
* pages when it is dying.
*/
if ( unlikely(e->is_dying) ||
unlikely(e->tot_pages >= e->max_pages) )
unlikely(e->tot_pages >= e->max_pages) ||
unlikely(!(e->tot_pages + 1)) )
{
spin_unlock(&e->page_alloc_lock);
@@ -2248,8 +2249,8 @@ gnttab_transfer(
e->domain_id);
else
gdprintk(XENLOG_INFO,
"Transferee d%d has no headroom (tot %u, max %u)\n",
e->domain_id, e->tot_pages, e->max_pages);
"Transferee %pd has no headroom (tot %u, max %u)\n",
e, e->tot_pages, e->max_pages);
gop.status = GNTST_general_error;
goto unlock_and_copyback;
+14 -5
View File
@@ -2278,17 +2278,26 @@ int assign_pages(
if ( !(memflags & MEMF_no_refcount) )
{
if ( unlikely((d->tot_pages + (1 << order)) > d->max_pages) )
unsigned int nr = 1u << order;
if ( unlikely(d->tot_pages > d->max_pages) )
{
gprintk(XENLOG_INFO, "Inconsistent allocation for %pd: %u > %u\n",
d, d->tot_pages, d->max_pages);
rc = -EPERM;
goto out;
}
if ( unlikely(nr > d->max_pages - d->tot_pages) )
{
if ( !tmem_enabled() || order != 0 || d->tot_pages != d->max_pages )
gprintk(XENLOG_INFO, "Over-allocation for domain %u: "
"%u > %u\n", d->domain_id,
d->tot_pages + (1 << order), d->max_pages);
gprintk(XENLOG_INFO, "Over-allocation for %pd: %Lu > %u\n",
d, d->tot_pages + 0ull + nr, d->max_pages);
rc = -E2BIG;
goto out;
}
if ( unlikely(domain_adjust_tot_pages(d, 1 << order) == (1 << order)) )
if ( unlikely(domain_adjust_tot_pages(d, nr) == nr) )
get_knownalive_domain(d);
}
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.