Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 73e1d9b3 authored by Juergen Gross's avatar Juergen Gross Committed by Greg Kroah-Hartman
Browse files

xen/grant-table: add gnttab_try_end_foreign_access()



Commit 6b1775f26a2da2b05a6dc8ec2b5d14e9a4701a1a upstream.

Add a new grant table function gnttab_try_end_foreign_access(), which
will remove and free a grant if it is not in use.

Its main use case is to either free a grant if it is no longer in use,
or to take some other action if it is still in use. This other action
can be an error exit, or (e.g. in the case of blkfront persistent grant
feature) some special handling.

This is CVE-2022-23036, CVE-2022-23038 / part of XSA-396.

Reported-by: default avatarDemi Marie Obenour <demi@invisiblethingslab.com>
Signed-off-by: default avatarJuergen Gross <jgross@suse.com>
Reviewed-by: default avatarJan Beulich <jbeulich@suse.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 8f80d12f
Loading
Loading
Loading
Loading
+12 −2
Original line number Original line Diff line number Diff line
@@ -377,11 +377,21 @@ static void gnttab_add_deferred(grant_ref_t ref, bool readonly,
	       what, ref, page ? page_to_pfn(page) : -1);
	       what, ref, page ? page_to_pfn(page) : -1);
}
}


int gnttab_try_end_foreign_access(grant_ref_t ref)
{
	int ret = _gnttab_end_foreign_access_ref(ref, 0);

	if (ret)
		put_free_entry(ref);

	return ret;
}
EXPORT_SYMBOL_GPL(gnttab_try_end_foreign_access);

void gnttab_end_foreign_access(grant_ref_t ref, int readonly,
void gnttab_end_foreign_access(grant_ref_t ref, int readonly,
			       unsigned long page)
			       unsigned long page)
{
{
	if (gnttab_end_foreign_access_ref(ref, readonly)) {
	if (gnttab_try_end_foreign_access(ref)) {
		put_free_entry(ref);
		if (page != 0)
		if (page != 0)
			put_page(virt_to_page(page));
			put_page(virt_to_page(page));
	} else
	} else
+12 −0
Original line number Original line Diff line number Diff line
@@ -97,10 +97,22 @@ int gnttab_end_foreign_access_ref(grant_ref_t ref, int readonly);
 * access has been ended, free the given page too.  Access will be ended
 * access has been ended, free the given page too.  Access will be ended
 * immediately iff the grant entry is not in use, otherwise it will happen
 * immediately iff the grant entry is not in use, otherwise it will happen
 * some time later.  page may be 0, in which case no freeing will occur.
 * some time later.  page may be 0, in which case no freeing will occur.
 * Note that the granted page might still be accessed (read or write) by the
 * other side after gnttab_end_foreign_access() returns, so even if page was
 * specified as 0 it is not allowed to just reuse the page for other
 * purposes immediately.
 */
 */
void gnttab_end_foreign_access(grant_ref_t ref, int readonly,
void gnttab_end_foreign_access(grant_ref_t ref, int readonly,
			       unsigned long page);
			       unsigned long page);


/*
 * End access through the given grant reference, iff the grant entry is
 * no longer in use.  In case of success ending foreign access, the
 * grant reference is deallocated.
 * Return 1 if the grant entry was freed, 0 if it is still in use.
 */
int gnttab_try_end_foreign_access(grant_ref_t ref);

int gnttab_grant_foreign_transfer(domid_t domid, unsigned long pfn);
int gnttab_grant_foreign_transfer(domid_t domid, unsigned long pfn);


unsigned long gnttab_end_foreign_transfer_ref(grant_ref_t ref);
unsigned long gnttab_end_foreign_transfer_ref(grant_ref_t ref);