Skip to content

Commit 3777ea7

Browse files
committed
xen/xenbus: don't let xenbus_grant_ring() remove grants in error case
Letting xenbus_grant_ring() tear down grants in the error case is problematic, as the other side could already have used these grants. Calling gnttab_end_foreign_access_ref() without checking success is resulting in an unclear situation for any caller of xenbus_grant_ring() as in the error case the memory pages of the ring page might be partially mapped. Freeing them would risk unwanted foreign access to them, while not freeing them would leak memory. In order to remove the need to undo any gnttab_grant_foreign_access() calls, use gnttab_alloc_grant_references() to make sure no further error can occur in the loop granting access to the ring pages. It should be noted that this way of handling removes leaking of grant entries in the error case, too. This is CVE-2022-23040 / part of XSA-396. Reported-by: Demi Marie Obenour <[email protected]> Signed-off-by: Juergen Gross <[email protected]> Reviewed-by: Jan Beulich <[email protected]>
1 parent ffb217a commit 3777ea7

File tree

1 file changed

+11
-13
lines changed

1 file changed

+11
-13
lines changed

drivers/xen/xenbus/xenbus_client.c

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -379,7 +379,14 @@ int xenbus_grant_ring(struct xenbus_device *dev, void *vaddr,
379379
unsigned int nr_pages, grant_ref_t *grefs)
380380
{
381381
int err;
382-
int i, j;
382+
unsigned int i;
383+
grant_ref_t gref_head;
384+
385+
err = gnttab_alloc_grant_references(nr_pages, &gref_head);
386+
if (err) {
387+
xenbus_dev_fatal(dev, err, "granting access to ring page");
388+
return err;
389+
}
383390

384391
for (i = 0; i < nr_pages; i++) {
385392
unsigned long gfn;
@@ -389,23 +396,14 @@ int xenbus_grant_ring(struct xenbus_device *dev, void *vaddr,
389396
else
390397
gfn = virt_to_gfn(vaddr);
391398

392-
err = gnttab_grant_foreign_access(dev->otherend_id, gfn, 0);
393-
if (err < 0) {
394-
xenbus_dev_fatal(dev, err,
395-
"granting access to ring page");
396-
goto fail;
397-
}
398-
grefs[i] = err;
399+
grefs[i] = gnttab_claim_grant_reference(&gref_head);
400+
gnttab_grant_foreign_access_ref(grefs[i], dev->otherend_id,
401+
gfn, 0);
399402

400403
vaddr = vaddr + XEN_PAGE_SIZE;
401404
}
402405

403406
return 0;
404-
405-
fail:
406-
for (j = 0; j < i; j++)
407-
gnttab_end_foreign_access_ref(grefs[j], 0);
408-
return err;
409407
}
410408
EXPORT_SYMBOL_GPL(xenbus_grant_ring);
411409

0 commit comments

Comments
 (0)