From mboxrd@z Thu Jan  1 00:00:00 1970
Return-Path: <dev-bounces@dpdk.org>
Received: from dpdk.org (dpdk.org [92.243.14.124])
	by inbox.dpdk.org (Postfix) with ESMTP id C39DDA2E1B
	for <public@inbox.dpdk.org>; Wed,  4 Sep 2019 14:05:40 +0200 (CEST)
Received: from [92.243.14.124] (localhost [127.0.0.1])
	by dpdk.org (Postfix) with ESMTP id DACDB1EDB9;
	Wed,  4 Sep 2019 14:05:35 +0200 (CEST)
Received: from mga01.intel.com (mga01.intel.com [192.55.52.88])
 by dpdk.org (Postfix) with ESMTP id 8FAF51EDB4;
 Wed,  4 Sep 2019 14:05:34 +0200 (CEST)
X-Amp-Result: SKIPPED(no attachment in message)
X-Amp-File-Uploaded: False
Received: from orsmga005.jf.intel.com ([10.7.209.41])
 by fmsmga101.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384;
 04 Sep 2019 05:05:33 -0700
X-ExtLoop1: 1
X-IronPort-AV: E=Sophos;i="5.64,465,1559545200"; d="scan'208";a="358079838"
Received: from irvmail001.ir.intel.com ([163.33.26.43])
 by orsmga005.jf.intel.com with ESMTP; 04 Sep 2019 05:05:31 -0700
Received: from wgcvswdev001.ir.intel.com (wgcvswdev001.ir.intel.com
 [10.102.246.100])
 by irvmail001.ir.intel.com (8.14.3/8.13.6/MailSET/Hub) with ESMTP id
 x84C5UMP023721; Wed, 4 Sep 2019 13:05:30 +0100
Received: from wgcvswdev001.ir.intel.com (localhost [127.0.0.1])
 by wgcvswdev001.ir.intel.com with ESMTP id x84C4s0a002403;
 Wed, 4 Sep 2019 13:04:54 +0100
Received: (from tchaitax@localhost)
	by wgcvswdev001.ir.intel.com with œ id x84C4soI002399;
	Wed, 4 Sep 2019 13:04:54 +0100
From: Chaitanya Babu Talluri <tallurix.chaitanya.babu@intel.com>
To: dev@dpdk.org
Cc: reshma.pattan@intel.com, jananeex.m.parthasarathy@intel.com,
 anatoly.burakov@intel.com,
 Chaitanya Babu Talluri <tallurix.chaitanya.babu@intel.com>, stable@dpdk.org
Date: Wed,  4 Sep 2019 13:04:39 +0100
Message-Id: <1567598682-2225-2-git-send-email-tallurix.chaitanya.babu@intel.com>
X-Mailer: git-send-email 1.7.0.7
In-Reply-To: <1566907031-2105-1-git-send-email-tallurix.chaitanya.babu@intel.com>
References: <1566907031-2105-1-git-send-email-tallurix.chaitanya.babu@intel.com>
Subject: [dpdk-dev] [PATCH v4 1/4] lib/eal: fix vfio unmap that fails
	unexpectedly
X-BeenThere: dev@dpdk.org
X-Mailman-Version: 2.1.15
Precedence: list
List-Id: DPDK patches and discussions <dev.dpdk.org>
List-Unsubscribe: <https://mails.dpdk.org/options/dev>,
 <mailto:dev-request@dpdk.org?subject=unsubscribe>
List-Archive: <http://mails.dpdk.org/archives/dev/>
List-Post: <mailto:dev@dpdk.org>
List-Help: <mailto:dev-request@dpdk.org?subject=help>
List-Subscribe: <https://mails.dpdk.org/listinfo/dev>,
 <mailto:dev-request@dpdk.org?subject=subscribe>
Errors-To: dev-bounces@dpdk.org
Sender: "dev" <dev-bounces@dpdk.org>

Unmap fails when there are duplicate entries in user_mem_maps.

The fix is to validate if the input VA, IOVA exists or
overlaps in user_mem_maps before creating map.

Fixes: 73a63908 ("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 | 46 +++++++++++++++++++++++++++++
 1 file changed, 46 insertions(+)

diff --git a/lib/librte_eal/linux/eal/eal_vfio.c b/lib/librte_eal/linux/eal/eal_vfio.c
index 501c74f23..104912077 100644
--- a/lib/librte_eal/linux/eal/eal_vfio.c
+++ b/lib/librte_eal/linux/eal/eal_vfio.c
@@ -212,6 +212,41 @@ find_user_mem_map(struct user_mem_maps *user_mem_maps, uint64_t addr,
 	return NULL;
 }
 
+static int
+find_user_mem_map_overlap(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;
+
+		bool no_lo_va_overlap = addr < map->addr && va_end <= map->addr;
+		bool no_hi_va_overlap = addr >= map_va_end &&
+			va_end > map_va_end;
+		bool no_lo_iova_overlap = iova < map->iova &&
+			iova_end <= map->iova;
+		bool no_hi_iova_overlap = iova >= map_iova_end &&
+			iova_end > map_iova_end;
+
+		/* check input VA and iova is not within the
+		 * existing map's range
+		 */
+		if ((no_lo_va_overlap || no_hi_va_overlap) &&
+				(no_lo_iova_overlap || no_hi_iova_overlap))
+			continue;
+		else
+			/* map overlaps */
+			return 1;
+	}
+	/* map doesn't overlap */
+	return 0;
+}
+
 /* this will sort all user maps, and merge/compact any adjacent maps */
 static void
 compact_user_maps(struct user_mem_maps *user_mem_maps)
@@ -1732,6 +1767,17 @@ container_dma_map(struct vfio_config *vfio_cfg, uint64_t vaddr, uint64_t iova,
 		ret = -1;
 		goto out;
 	}
+
+	/* check whether vaddr and iova exists in user_mem_maps */
+	ret = find_user_mem_map_overlap(user_mem_maps, vaddr, iova, len);
+	if (ret) {
+		RTE_LOG(ERR, EAL, "Mapping overlaps with a previously "
+				"existing mapping\n");
+		rte_errno = EEXIST;
+		ret = -1;
+		goto out;
+	}
+
 	/* map the entry */
 	if (vfio_dma_mem_map(vfio_cfg, vaddr, iova, len, 1)) {
 		/* technically, this will fail if there are currently no devices
-- 
2.17.2