Commit 08039550 authored by Darek Stojaczyk's avatar Darek Stojaczyk Committed by Jim Harris
Browse files

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: default avatarDarek Stojaczyk <dariusz.stojaczyk@intel.com>
Reviewed-on: https://review.gerrithub.io/425556


Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: default avatarBen Walker <benjamin.walker@intel.com>
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
parent a33e0943
Loading
Loading
Loading
Loading
+20 −1
Original line number Diff line number Diff line
@@ -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);
+6 −2
Original line number Diff line number Diff line
@@ -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);