aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoger Pau Monné <royger@FreeBSD.org>2021-01-20 18:40:51 +0000
committerMark Johnston <markj@FreeBSD.org>2021-02-24 01:42:01 +0000
commit602f1da04217967e7627be3fe19a56098ad29b6f (patch)
tree5d65fea4f512f163e9e3cc3157e1685ba62524cd
parentefc9549ba0c2caffd45e1f7f88fdd75a0225e568 (diff)
downloadsrc-602f1da04217967e7627be3fe19a56098ad29b6f.tar.gz
src-602f1da04217967e7627be3fe19a56098ad29b6f.zip
xen-blkback: fix leak of grant maps on ring setup failure
Multi page rings are mapped using a single hypercall that gets passed an array of grants to map. One of the grants in the array failing to map would lead to the failure of the whole ring setup operation, but there was no cleanup of the rest of the grant maps in the array that could have likely been created as a result of the hypercall. Add proper cleanup on the failure path during ring setup to unmap any grants that could have been created. This is part of XSA-361. Approved by: so Security: CVE-2021-26932 Security: FreeBSD-SA-21:06.xen Security: XSA-361 Sponsored by: Citrix Systems R&D (cherry picked from commit 808d4aad1022a2a33d222663b0c9badde30b9d45) (cherry picked from commit dfb372f5d38c302953a6a4e2838179cd0a1a6438)
-rw-r--r--sys/dev/xen/blkback/blkback.c21
1 files changed, 21 insertions, 0 deletions
diff --git a/sys/dev/xen/blkback/blkback.c b/sys/dev/xen/blkback/blkback.c
index d935ba965b00..b98ccb6e2595 100644
--- a/sys/dev/xen/blkback/blkback.c
+++ b/sys/dev/xen/blkback/blkback.c
@@ -2912,10 +2912,31 @@ xbb_connect_ring(struct xbb_softc *xbb)
ring_idx < xbb->ring_config.ring_pages;
ring_idx++, gnt++) {
if (gnt->status != 0) {
+ struct gnttab_unmap_grant_ref unmap[XBB_MAX_RING_PAGES];
+ unsigned int i, j;
+
xbb->ring_config.va = 0;
xenbus_dev_fatal(xbb->dev, EACCES,
"Ring shared page mapping failed. "
"Status %d.", gnt->status);
+
+ /* Unmap everything to avoid leaking grant table maps */
+ for (i = 0, j = 0; i < xbb->ring_config.ring_pages;
+ i++) {
+ if (gnts[i].status != GNTST_okay)
+ continue;
+
+ unmap[j].host_addr = gnts[i].host_addr;
+ unmap[j].dev_bus_addr = gnts[i].dev_bus_addr;
+ unmap[j++].handle = gnts[i].handle;
+ }
+ if (j != 0) {
+ error = HYPERVISOR_grant_table_op(
+ GNTTABOP_unmap_grant_ref, unmap, j);
+ if (error != 0)
+ panic("Unable to unmap grants (%d)",
+ error);
+ }
return (EACCES);
}
xbb->ring_config.handle[ring_idx] = gnt->handle;