Skip to content

Commit 3d81e85

Browse files
jgross1gregkh
authored andcommitted
xen/grant-table: add gnttab_try_end_foreign_access()
Commit 6b1775f 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: Demi Marie Obenour <demi@invisiblethingslab.com> Signed-off-by: Juergen Gross <jgross@suse.com> Reviewed-by: Jan Beulich <jbeulich@suse.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 5c60037 commit 3d81e85

2 files changed

Lines changed: 24 additions & 2 deletions

File tree

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
@@ -97,10 +97,22 @@ int gnttab_end_foreign_access_ref(grant_ref_t ref, int readonly);
9797
* access has been ended, free the given page too. Access will be ended
9898
* immediately iff the grant entry is not in use, otherwise it will happen
9999
* some time later. page may be 0, in which case no freeing will occur.
100+
* Note that the granted page might still be accessed (read or write) by the
101+
* other side after gnttab_end_foreign_access() returns, so even if page was
102+
* specified as 0 it is not allowed to just reuse the page for other
103+
* purposes immediately.
100104
*/
101105
void gnttab_end_foreign_access(grant_ref_t ref, int readonly,
102106
unsigned long page);
103107

108+
/*
109+
* End access through the given grant reference, iff the grant entry is
110+
* no longer in use. In case of success ending foreign access, the
111+
* grant reference is deallocated.
112+
* Return 1 if the grant entry was freed, 0 if it is still in use.
113+
*/
114+
int gnttab_try_end_foreign_access(grant_ref_t ref);
115+
104116
int gnttab_grant_foreign_transfer(domid_t domid, unsigned long pfn);
105117

106118
unsigned long gnttab_end_foreign_transfer_ref(grant_ref_t ref);

0 commit comments

Comments
 (0)