[2/3] lib/eal: fix vfio unmap that succeeds unexpectedly

Message ID 1566392575-7965-3-git-send-email-tallurix.chaitanya.babu@intel.com (mailing list archive)
State Superseded, archived
Headers
Series add unit tests for eal vfio library |

Checks

Context Check Description
ci/checkpatch success coding style OK
ci/Intel-compilation fail Compilation issues

Commit Message

Chaitanya Babu, TalluriX Aug. 21, 2019, 1:02 p.m. UTC
  Un-map of page with valid virtual address and
another page's IOVA succeeds unexpectedly.
An entry in user_mem_maps can refer multiple pages.
Currently in such case to unmap single page, VA
and IOVA related to entry in user_mem_maps is
checked but not based on page (based on the
page size), this is the cause.

The solution is that in find_user_mem_maps,
check whether user input iova is in relation with
input virtual address of the page which is to be
unmapped.

Fixes: 73a6390859 ("vfio: allow to map other memory regions")
Cc: stable@dpdk.org

Signed-off-by: Chaitanya Babu Talluri <tallurix.chaitanya.babu@intel.com>
---
 lib/librte_eal/linux/eal/eal_vfio.c | 13 ++++++-------
 1 file changed, 6 insertions(+), 7 deletions(-)
  

Comments

Burakov, Anatoly Aug. 21, 2019, 1:24 p.m. UTC | #1
On 21-Aug-19 2:02 PM, Chaitanya Babu Talluri wrote:
> Un-map of page with valid virtual address and
> another page's IOVA succeeds unexpectedly.
> An entry in user_mem_maps can refer multiple pages.
> Currently in such case to unmap single page, VA
> and IOVA related to entry in user_mem_maps is
> checked but not based on page (based on the
> page size), this is the cause.
> 
> The solution is that in find_user_mem_maps,
> check whether user input iova is in relation with
> input virtual address of the page which is to be
> unmapped.

The description could be clearer. Suggested rewording:

Unmapping page with a VA that is found in the list of current mappings 
will succeed even if the IOVA for the chunk that is being unmapped, is 
mismatched. Fix it by checking if IOVA address matches the expected IOVA 
address exactly.
  

Patch

diff --git a/lib/librte_eal/linux/eal/eal_vfio.c b/lib/librte_eal/linux/eal/eal_vfio.c
index 104912077..04c284cb2 100644
--- a/lib/librte_eal/linux/eal/eal_vfio.c
+++ b/lib/librte_eal/linux/eal/eal_vfio.c
@@ -184,13 +184,13 @@  find_user_mem_map(struct user_mem_maps *user_mem_maps, uint64_t addr,
 		uint64_t iova, uint64_t len)
 {
 	uint64_t va_end = addr + len;
-	uint64_t iova_end = iova + len;
 	int i;
 
 	for (i = 0; i < user_mem_maps->n_maps; i++) {
 		struct user_mem_map *map = &user_mem_maps->maps[i];
 		uint64_t map_va_end = map->addr + map->len;
-		uint64_t map_iova_end = map->iova + map->len;
+		uint64_t diff_addr_len = addr - map->addr;
+		uint64_t expected_iova = map->iova + diff_addr_len;
 
 		/* check start VA */
 		if (addr < map->addr || addr >= map_va_end)
@@ -199,11 +199,10 @@  find_user_mem_map(struct user_mem_maps *user_mem_maps, uint64_t addr,
 		if (va_end <= map->addr || va_end > map_va_end)
 			continue;
 
-		/* check start IOVA */
-		if (iova < map->iova || iova >= map_iova_end)
-			continue;
-		/* check if IOVA end is within boundaries */
-		if (iova_end <= map->iova || iova_end > map_iova_end)
+		/* check whether user input iova is in sync with
+		 * user_mem_map entry's iova
+		 */
+		if (expected_iova != iova)
 			continue;
 
 		/* we've found our map */