Skip to content

Commit 6b1775f

Browse files
committed
xen/grant-table: add gnttab_try_end_foreign_access()
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: Demi Marie Obenour <[email protected]> Signed-off-by: Juergen Gross <[email protected]> Reviewed-by: Jan Beulich <[email protected]> --- V2: - new patch V4: - add comments to header (Jan Beulich)
1 parent 3777ea7 commit 6b1775f

File tree

2 files changed

+24
-2
lines changed

2 files changed

+24
-2
lines changed

drivers/xen/grant-table.c

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -435,11 +435,21 @@ static void gnttab_add_deferred(grant_ref_t ref, bool readonly,
435435
what, ref, page ? page_to_pfn(page) : -1);
436436
}
437437

438+
int gnttab_try_end_foreign_access(grant_ref_t ref)
439+
{
440+
int ret = _gnttab_end_foreign_access_ref(ref, 0);
441+
442+
if (ret)
443+
put_free_entry(ref);
444+
445+
return ret;
446+
}
447+
EXPORT_SYMBOL_GPL(gnttab_try_end_foreign_access);
448+
438449
void gnttab_end_foreign_access(grant_ref_t ref, int readonly,
439450
unsigned long page)
440451
{
441-
if (gnttab_end_foreign_access_ref(ref, readonly)) {
442-
put_free_entry(ref);
452+
if (gnttab_try_end_foreign_access(ref)) {
443453
if (page != 0)
444454
put_page(virt_to_page(page));
445455
} else

include/xen/grant_table.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,10 +104,22 @@ int gnttab_end_foreign_access_ref(grant_ref_t ref, int readonly);
104104
* access has been ended, free the given page too. Access will be ended
105105
* immediately iff the grant entry is not in use, otherwise it will happen
106106
* some time later. page may be 0, in which case no freeing will occur.
107+
* Note that the granted page might still be accessed (read or write) by the
108+
* other side after gnttab_end_foreign_access() returns, so even if page was
109+
* specified as 0 it is not allowed to just reuse the page for other
110+
* purposes immediately.
107111
*/
108112
void gnttab_end_foreign_access(grant_ref_t ref, int readonly,
109113
unsigned long page);
110114

115+
/*
116+
* End access through the given grant reference, iff the grant entry is
117+
* no longer in use. In case of success ending foreign access, the
118+
* grant reference is deallocated.
119+
* Return 1 if the grant entry was freed, 0 if it is still in use.
120+
*/
121+
int gnttab_try_end_foreign_access(grant_ref_t ref);
122+
111123
int gnttab_grant_foreign_transfer(domid_t domid, unsigned long pfn);
112124

113125
unsigned long gnttab_end_foreign_transfer_ref(grant_ref_t ref);

0 commit comments

Comments
 (0)