From 4db1b420f478e81c2f646c94f964a2943fc90852 Mon Sep 17 00:00:00 2001 From: Daniel Verkamp Date: Wed, 22 Jun 2016 14:57:53 -0700 Subject: [PATCH] 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: Daniel Verkamp --- lib/memory/vtophys.c | 16 ++++++++-------- test/lib/memory/vtophys.c | 7 +++++++ 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/lib/memory/vtophys.c b/lib/memory/vtophys.c index 5abab3c9b..4b10a073c 100644 --- a/lib/memory/vtophys.c +++ b/lib/memory/vtophys.c @@ -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; - vfn_2mb = (uint64_t)buf; - vfn_2mb >>= SHIFT_2MB; + vaddr = (uint64_t)buf; + if (vaddr & ~MASK_128TB) { + printf("invalid usermode virtual address %p\n", buf); + return SPDK_VTOPHYS_ERROR; + } + + vfn_2mb = vaddr >> SHIFT_2MB; map_2mb = vtophys_get_map(vfn_2mb); if (!map_2mb) { diff --git a/test/lib/memory/vtophys.c b/test/lib/memory/vtophys.c index ed2890c01..3eff06ad4 100644 --- a/test/lib/memory/vtophys.c +++ b/test/lib/memory/vtophys.c @@ -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