memory: don't allow unregistering a part of the registered region
Added sanity checks to prevent unregistering a memory range that wasn't registered as a one, complete region. Change-Id: I819b57560b2e48b0802113ffff9f72949d7a148a Signed-off-by: Darek Stojaczyk <dariusz.stojaczyk@intel.com> Reviewed-on: https://review.gerrithub.io/425556 Tested-by: SPDK CI Jenkins <sys_sgci@intel.com> Reviewed-by: Ben Walker <benjamin.walker@intel.com> Reviewed-by: Jim Harris <james.r.harris@intel.com>
This commit is contained in:
parent
a33e0943b0
commit
08039550d9
@ -377,7 +377,7 @@ spdk_mem_unregister(void *vaddr, size_t len)
|
||||
int rc;
|
||||
void *seg_vaddr;
|
||||
size_t seg_len;
|
||||
uint64_t reg;
|
||||
uint64_t reg, newreg;
|
||||
|
||||
if ((uintptr_t)vaddr & ~MASK_256TB) {
|
||||
DEBUG_PRINT("invalid usermode virtual address %p\n", vaddr);
|
||||
@ -392,6 +392,16 @@ spdk_mem_unregister(void *vaddr, size_t len)
|
||||
|
||||
pthread_mutex_lock(&g_spdk_mem_map_mutex);
|
||||
|
||||
/* The first page must be a start of a region. Also check if it's
|
||||
* registered to make sure we don't return -ERANGE for non-registered
|
||||
* regions.
|
||||
*/
|
||||
reg = spdk_mem_map_translate(g_mem_reg_map, (uint64_t)vaddr, NULL);
|
||||
if ((reg & REG_MAP_REGISTERED) && (reg & REG_MAP_NOTIFY_START) == 0) {
|
||||
pthread_mutex_unlock(&g_spdk_mem_map_mutex);
|
||||
return -ERANGE;
|
||||
}
|
||||
|
||||
seg_vaddr = vaddr;
|
||||
seg_len = len;
|
||||
while (seg_len > 0) {
|
||||
@ -404,8 +414,17 @@ spdk_mem_unregister(void *vaddr, size_t len)
|
||||
seg_len -= VALUE_2MB;
|
||||
}
|
||||
|
||||
newreg = spdk_mem_map_translate(g_mem_reg_map, (uint64_t)seg_vaddr, NULL);
|
||||
/* If the next page is registered, it must be a start of a region as well,
|
||||
* otherwise we'd be unregistering only a part of a region.
|
||||
*/
|
||||
if ((newreg & REG_MAP_NOTIFY_START) == 0 && (newreg & REG_MAP_REGISTERED)) {
|
||||
pthread_mutex_unlock(&g_spdk_mem_map_mutex);
|
||||
return -ERANGE;
|
||||
}
|
||||
seg_vaddr = vaddr;
|
||||
seg_len = 0;
|
||||
|
||||
while (len > 0) {
|
||||
reg = spdk_mem_map_translate(g_mem_reg_map, (uint64_t)vaddr, NULL);
|
||||
spdk_mem_map_set_translation(g_mem_reg_map, (uint64_t)vaddr, VALUE_2MB, 0);
|
||||
|
8
test/env/memory/memory_ut.c
vendored
8
test/env/memory/memory_ut.c
vendored
@ -385,14 +385,18 @@ test_mem_map_registration(void)
|
||||
|
||||
/* Unregister the middle page of the larger region. */
|
||||
rc = spdk_mem_unregister((void *)VALUE_2MB, VALUE_2MB);
|
||||
CU_ASSERT(rc == 0);
|
||||
CU_ASSERT(rc == -ERANGE);
|
||||
|
||||
/* Unregister the first page */
|
||||
rc = spdk_mem_unregister((void *)0, VALUE_2MB);
|
||||
CU_ASSERT(rc == 0);
|
||||
CU_ASSERT(rc == -ERANGE);
|
||||
|
||||
/* Unregister the third page */
|
||||
rc = spdk_mem_unregister((void *)(2 * VALUE_2MB), VALUE_2MB);
|
||||
CU_ASSERT(rc == -ERANGE);
|
||||
|
||||
/* Unregister the entire address range */
|
||||
rc = spdk_mem_unregister((void *)0, 3 * VALUE_2MB);
|
||||
CU_ASSERT(rc == 0);
|
||||
|
||||
spdk_mem_map_free(&map);
|
||||
|
Loading…
Reference in New Issue
Block a user