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

Commit b57c1869 authored by Daniel De Graaf's avatar Daniel De Graaf Committed by Konrad Rzeszutek Wilk
Browse files

xen-gntdev: Avoid unmapping ranges twice



In paravirtualized domains, mn_invl_page or mn_invl_range_start can
unmap a segment of a mapped region without unmapping all pages. When
the region is later released, the pages will be unmapped twice, leading
to an incorrect -EINVAL return.

Signed-off-by: default avatarDaniel De Graaf <dgdegra@tycho.nsa.gov>
Signed-off-by: default avatarKonrad Rzeszutek Wilk <konrad.wilk@oracle.com>
parent 84e4075d
Loading
Loading
Loading
Loading
+31 −2
Original line number Diff line number Diff line
@@ -282,7 +282,7 @@ static int map_grant_pages(struct grant_map *map)
	return err;
}

static int unmap_grant_pages(struct grant_map *map, int offset, int pages)
static int __unmap_grant_pages(struct grant_map *map, int offset, int pages)
{
	int i, err = 0;

@@ -301,7 +301,6 @@ static int unmap_grant_pages(struct grant_map *map, int offset, int pages)
		}
	}

	pr_debug("map %d+%d [%d+%d]\n", map->index, map->count, offset, pages);
	err = gnttab_unmap_refs(map->unmap_ops + offset, map->pages + offset, pages);
	if (err)
		return err;
@@ -314,6 +313,36 @@ static int unmap_grant_pages(struct grant_map *map, int offset, int pages)
	return err;
}

static int unmap_grant_pages(struct grant_map *map, int offset, int pages)
{
	int range, err = 0;

	pr_debug("unmap %d+%d [%d+%d]\n", map->index, map->count, offset, pages);

	/* It is possible the requested range will have a "hole" where we
	 * already unmapped some of the grants. Only unmap valid ranges.
	 */
	while (pages && !err) {
		while (pages && !map->unmap_ops[offset].handle) {
			offset++;
			pages--;
		}
		range = 0;
		while (range < pages) {
			if (!map->unmap_ops[offset+range].handle) {
				range--;
				break;
			}
			range++;
		}
		err = __unmap_grant_pages(map, offset, range);
		offset += range;
		pages -= range;
	}

	return err;
}

/* ------------------------------------------------------------------ */

static void gntdev_vma_close(struct vm_area_struct *vma)