Commit 4db1b420 authored by Daniel Verkamp's avatar Daniel Verkamp
Browse files

vtophys: fix usermode address range check



vtophys() was checking for out-of-range addresses incorrectly: vfn_2mb
is already shifted to account for 2 MB hugepages, but it was being
compared with a mask that did not account for the shift.  This would
allow out-of-bounds access to the 128tb map array for certain invalid
addresses (it had no effect on addresses within the valid userspace
range).

Change-Id: Ida7455595e586494c9025f9ba65d050abb16b1b9
Signed-off-by: default avatarDaniel Verkamp <daniel.verkamp@intel.com>
parent bb125a6f
Loading
Loading
Loading
Loading
+8 −8
Original line number Diff line number Diff line
@@ -94,11 +94,6 @@ vtophys_get_map(uint64_t vfn_2mb)
	uint64_t idx_128tb = MAP_128TB_IDX(vfn_2mb);
	uint64_t idx_1gb = MAP_1GB_IDX(vfn_2mb);

	if (vfn_2mb & ~MASK_128TB) {
		printf("invalid usermode virtual address\n");
		return NULL;
	}

	map_1gb = vtophys_map_128tb.map[idx_128tb];

	if (!map_1gb) {
@@ -160,10 +155,15 @@ uint64_t
spdk_vtophys(void *buf)
{
	struct map_2mb *map_2mb;
	uint64_t vfn_2mb, pfn_2mb;
	uint64_t vaddr, vfn_2mb, pfn_2mb;

	vaddr = (uint64_t)buf;
	if (vaddr & ~MASK_128TB) {
		printf("invalid usermode virtual address %p\n", buf);
		return SPDK_VTOPHYS_ERROR;
	}

	vfn_2mb = (uint64_t)buf;
	vfn_2mb >>= SHIFT_2MB;
	vfn_2mb = vaddr >> SHIFT_2MB;

	map_2mb = vtophys_get_map(vfn_2mb);
	if (!map_2mb) {
+7 −0
Original line number Diff line number Diff line
@@ -73,6 +73,13 @@ vtophys_negative_test(void)
		size = size << 1;
	}

	/* Test addresses that are not in the valid x86-64 usermode range */

	if (spdk_vtophys((void *)0x0000800000000000ULL) != SPDK_VTOPHYS_ERROR) {
		rc = -1;
		printf("Err: kernel-mode address incorrectly allowed\n");
	}

	if (!rc)
		printf("vtophys_negative_test passed\n");
	else