Blame SOURCES/0010-examples-vhost_scsi-move-to-safe-GPA-translation-API.patch

a6040a
From d34212ffb5e333a515f87b2f828606bc5690b8b3 Mon Sep 17 00:00:00 2001
a6040a
From: Maxime Coquelin <maxime.coquelin@redhat.com>
a6040a
Date: Mon, 23 Apr 2018 11:33:47 +0200
a6040a
Subject: [PATCH 10/11] examples/vhost_scsi: move to safe GPA translation API
a6040a
a6040a
This patch uses the new rte_vhost_va_from_guest_pa() API
a6040a
to ensure all the descriptor buffer is mapped contiguously
a6040a
in the application virtual address space.
a6040a
a6040a
As the application did not checked return of previous API,
a6040a
this patch just print an error if the buffer address isn't in
a6040a
the vhost memory regions or if it is scattered. Ideally, it
a6040a
should handle scattered buffers gracefully.
a6040a
a6040a
This issue has been assigned CVE-2018-1059.
a6040a
a6040a
Signed-off-by: Maxime Coquelin <maxime.coquelin@redhat.com>
a6040a
---
a6040a
 examples/vhost_scsi/vhost_scsi.c | 56 +++++++++++++++++++++++++++++++++-------
a6040a
 1 file changed, 47 insertions(+), 9 deletions(-)
a6040a
a6040a
diff --git a/examples/vhost_scsi/vhost_scsi.c b/examples/vhost_scsi/vhost_scsi.c
a6040a
index b4f1f8d..b40f993 100644
a6040a
--- a/examples/vhost_scsi/vhost_scsi.c
a6040a
+++ b/examples/vhost_scsi/vhost_scsi.c
a6040a
@@ -69,5 +69,5 @@
a6040a
 }
a6040a
 
a6040a
-static uint64_t gpa_to_vva(int vid, uint64_t gpa)
a6040a
+static uint64_t gpa_to_vva(int vid, uint64_t gpa, uint64_t *len)
a6040a
 {
a6040a
 	char path[PATH_MAX];
a6040a
@@ -89,5 +89,5 @@ static uint64_t gpa_to_vva(int vid, uint64_t gpa)
a6040a
 	assert(ctrlr->mem != NULL);
a6040a
 
a6040a
-	return rte_vhost_gpa_to_vva(ctrlr->mem, gpa);
a6040a
+	return rte_vhost_va_from_guest_pa(ctrlr->mem, gpa, len);
a6040a
 }
a6040a
 
a6040a
@@ -139,13 +139,27 @@ static uint64_t gpa_to_vva(int vid, uint64_t gpa)
a6040a
 {
a6040a
 	void *data;
a6040a
+	uint64_t chunck_len;
a6040a
 
a6040a
 	task->iovs_cnt = 0;
a6040a
+	chunck_len = task->desc->len;
a6040a
 	task->resp = (void *)(uintptr_t)gpa_to_vva(task->bdev->vid,
a6040a
-						   task->desc->addr);
a6040a
+						   task->desc->addr,
a6040a
+						   &chunck_len);
a6040a
+	if (!task->resp || chunck_len != task->desc->len) {
a6040a
+		fprintf(stderr, "failed to translate desc address.\n");
a6040a
+		return;
a6040a
+	}
a6040a
 
a6040a
 	while (descriptor_has_next(task->desc)) {
a6040a
 		task->desc = descriptor_get_next(task->vq->desc, task->desc);
a6040a
+		chunck_len = task->desc->len;
a6040a
 		data = (void *)(uintptr_t)gpa_to_vva(task->bdev->vid,
a6040a
-						     task->desc->addr);
a6040a
+						     task->desc->addr,
a6040a
+							 &chunck_len);
a6040a
+		if (!data || chunck_len != task->desc->len) {
a6040a
+			fprintf(stderr, "failed to translate desc address.\n");
a6040a
+			return;
a6040a
+		}
a6040a
+
a6040a
 		task->iovs[task->iovs_cnt].iov_base = data;
a6040a
 		task->iovs[task->iovs_cnt].iov_len = task->desc->len;
a6040a
@@ -159,10 +173,18 @@ static uint64_t gpa_to_vva(int vid, uint64_t gpa)
a6040a
 {
a6040a
 	void *data;
a6040a
+	uint64_t chunck_len;
a6040a
 
a6040a
 	task->iovs_cnt = 0;
a6040a
 
a6040a
 	do {
a6040a
+		chunck_len = task->desc->len;
a6040a
 		data = (void *)(uintptr_t)gpa_to_vva(task->bdev->vid,
a6040a
-						     task->desc->addr);
a6040a
+						     task->desc->addr,
a6040a
+							 &chunck_len);
a6040a
+		if (!data || chunck_len != task->desc->len) {
a6040a
+			fprintf(stderr, "failed to translate desc address.\n");
a6040a
+			return;
a6040a
+		}
a6040a
+
a6040a
 		task->iovs[task->iovs_cnt].iov_base = data;
a6040a
 		task->iovs[task->iovs_cnt].iov_len = task->desc->len;
a6040a
@@ -172,6 +194,10 @@ static uint64_t gpa_to_vva(int vid, uint64_t gpa)
a6040a
 	} while (descriptor_has_next(task->desc));
a6040a
 
a6040a
+	chunck_len = task->desc->len;
a6040a
 	task->resp = (void *)(uintptr_t)gpa_to_vva(task->bdev->vid,
a6040a
-						   task->desc->addr);
a6040a
+						   task->desc->addr,
a6040a
+						   &chunck_len);
a6040a
+	if (!task->resp || chunck_len != task->desc->len)
a6040a
+		fprintf(stderr, "failed to translate desc address.\n");
a6040a
 }
a6040a
 
a6040a
@@ -219,4 +245,5 @@ static uint64_t gpa_to_vva(int vid, uint64_t gpa)
a6040a
 		uint16_t last_idx;
a6040a
 		struct vhost_scsi_task *task;
a6040a
+		uint64_t chunck_len;
a6040a
 
a6040a
 		last_idx = scsi_vq->last_used_idx & (vq->size - 1);
a6040a
@@ -236,14 +263,25 @@ static uint64_t gpa_to_vva(int vid, uint64_t gpa)
a6040a
 		scsi_vq->last_used_idx++;
a6040a
 
a6040a
+		chunck_len = task->desc->len;
a6040a
 		task->req = (void *)(uintptr_t)gpa_to_vva(task->bdev->vid,
a6040a
-							  task->desc->addr);
a6040a
+							  task->desc->addr,
a6040a
+							  &chunck_len);
a6040a
+		if (!task->req || chunck_len != task->desc->len) {
a6040a
+			fprintf(stderr, "failed to translate desc address.\n");
a6040a
+			return;
a6040a
+		}
a6040a
 
a6040a
 		task->desc = descriptor_get_next(task->vq->desc, task->desc);
a6040a
 		if (!descriptor_has_next(task->desc)) {
a6040a
 			task->dxfer_dir = SCSI_DIR_NONE;
a6040a
+			chunck_len = task->desc->len;
a6040a
 			task->resp = (void *)(uintptr_t)
a6040a
 					      gpa_to_vva(task->bdev->vid,
a6040a
-							 task->desc->addr);
a6040a
-
a6040a
+							 task->desc->addr,
a6040a
+							 &chunck_len);
a6040a
+			if (!task->resp || chunck_len != task->desc->len) {
a6040a
+				fprintf(stderr, "failed to translate desc address.\n");
a6040a
+				return;
a6040a
+			}
a6040a
 		} else if (!descriptor_is_wr(task->desc)) {
a6040a
 			task->dxfer_dir = SCSI_DIR_TO_DEV;
a6040a
-- 
a6040a
1.8.3.1
a6040a