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 <daniel.verkamp@intel.com>
This commit is contained in:
Daniel Verkamp 2016-06-22 14:57:53 -07:00
parent bb125a6f55
commit 4db1b420f4
2 changed files with 15 additions and 8 deletions

View File

@ -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) {

View File

@ -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