This patch uses the new rte_vhost_va_from_guest_pa() API
to ensure all the descriptor buffer is mapped contiguously
in the application virtual address space.
As the application did not checked return of previous API,
this patch just print an error if the buffer address isn't in
the vhost memory regions or if it is scattered. Ideally, it
should handle scattered buffers gracefully.
This issue has been assigned CVE-2018-1059.
Signed-off-by: Maxime Coquelin <maxime.coquelin@redhat.com>
-static uint64_t gpa_to_vva(int vid, uint64_t gpa)
+static uint64_t gpa_to_vva(int vid, uint64_t gpa, uint64_t *len)
{
char path[PATH_MAX];
struct vhost_scsi_ctrlr *ctrlr;
{
char path[PATH_MAX];
struct vhost_scsi_ctrlr *ctrlr;
assert(ctrlr->mem != NULL);
assert(ctrlr->mem != NULL);
- return rte_vhost_gpa_to_vva(ctrlr->mem, gpa);
+ return rte_vhost_va_from_guest_pa(ctrlr->mem, gpa, len);
}
static struct vring_desc *
}
static struct vring_desc *
vhost_process_read_payload_chain(struct vhost_scsi_task *task)
{
void *data;
vhost_process_read_payload_chain(struct vhost_scsi_task *task)
{
void *data;
+ chunck_len = task->desc->len;
task->resp = (void *)(uintptr_t)gpa_to_vva(task->bdev->vid,
task->resp = (void *)(uintptr_t)gpa_to_vva(task->bdev->vid,
+ task->desc->addr,
+ &chunck_len);
+ if (!task->resp || chunck_len != task->desc->len) {
+ fprintf(stderr, "failed to translate desc address.\n");
+ return;
+ }
while (descriptor_has_next(task->desc)) {
task->desc = descriptor_get_next(task->vq->desc, task->desc);
while (descriptor_has_next(task->desc)) {
task->desc = descriptor_get_next(task->vq->desc, task->desc);
+ chunck_len = task->desc->len;
data = (void *)(uintptr_t)gpa_to_vva(task->bdev->vid,
data = (void *)(uintptr_t)gpa_to_vva(task->bdev->vid,
+ task->desc->addr,
+ &chunck_len);
+ if (!data || chunck_len != task->desc->len) {
+ fprintf(stderr, "failed to translate desc address.\n");
+ return;
+ }
+
task->iovs[task->iovs_cnt].iov_base = data;
task->iovs[task->iovs_cnt].iov_len = task->desc->len;
task->data_len += task->desc->len;
task->iovs[task->iovs_cnt].iov_base = data;
task->iovs[task->iovs_cnt].iov_len = task->desc->len;
task->data_len += task->desc->len;
vhost_process_write_payload_chain(struct vhost_scsi_task *task)
{
void *data;
vhost_process_write_payload_chain(struct vhost_scsi_task *task)
{
void *data;
+ chunck_len = task->desc->len;
data = (void *)(uintptr_t)gpa_to_vva(task->bdev->vid,
data = (void *)(uintptr_t)gpa_to_vva(task->bdev->vid,
+ task->desc->addr,
+ &chunck_len);
+ if (!data || chunck_len != task->desc->len) {
+ fprintf(stderr, "failed to translate desc address.\n");
+ return;
+ }
+
task->iovs[task->iovs_cnt].iov_base = data;
task->iovs[task->iovs_cnt].iov_len = task->desc->len;
task->data_len += task->desc->len;
task->iovs[task->iovs_cnt].iov_base = data;
task->iovs[task->iovs_cnt].iov_len = task->desc->len;
task->data_len += task->desc->len;
task->desc = descriptor_get_next(task->vq->desc, task->desc);
} while (descriptor_has_next(task->desc));
task->desc = descriptor_get_next(task->vq->desc, task->desc);
} while (descriptor_has_next(task->desc));
+ chunck_len = task->desc->len;
task->resp = (void *)(uintptr_t)gpa_to_vva(task->bdev->vid,
task->resp = (void *)(uintptr_t)gpa_to_vva(task->bdev->vid,
+ task->desc->addr,
+ &chunck_len);
+ if (!task->resp || chunck_len != task->desc->len)
+ fprintf(stderr, "failed to translate desc address.\n");
}
static struct vhost_block_dev *
}
static struct vhost_block_dev *
int req_idx;
uint16_t last_idx;
struct vhost_scsi_task *task;
int req_idx;
uint16_t last_idx;
struct vhost_scsi_task *task;
last_idx = scsi_vq->last_used_idx & (vq->size - 1);
req_idx = vq->avail->ring[last_idx];
last_idx = scsi_vq->last_used_idx & (vq->size - 1);
req_idx = vq->avail->ring[last_idx];
assert((task->desc->flags & VRING_DESC_F_INDIRECT) == 0);
scsi_vq->last_used_idx++;
assert((task->desc->flags & VRING_DESC_F_INDIRECT) == 0);
scsi_vq->last_used_idx++;
+ chunck_len = task->desc->len;
task->req = (void *)(uintptr_t)gpa_to_vva(task->bdev->vid,
task->req = (void *)(uintptr_t)gpa_to_vva(task->bdev->vid,
+ task->desc->addr,
+ &chunck_len);
+ if (!task->req || chunck_len != task->desc->len) {
+ fprintf(stderr, "failed to translate desc address.\n");
+ return;
+ }
task->desc = descriptor_get_next(task->vq->desc, task->desc);
if (!descriptor_has_next(task->desc)) {
task->dxfer_dir = SCSI_DIR_NONE;
task->desc = descriptor_get_next(task->vq->desc, task->desc);
if (!descriptor_has_next(task->desc)) {
task->dxfer_dir = SCSI_DIR_NONE;
+ chunck_len = task->desc->len;
task->resp = (void *)(uintptr_t)
gpa_to_vva(task->bdev->vid,
task->resp = (void *)(uintptr_t)
gpa_to_vva(task->bdev->vid,
+ task->desc->addr,
+ &chunck_len);
+ if (!task->resp || chunck_len != task->desc->len) {
+ fprintf(stderr, "failed to translate desc address.\n");
+ return;
+ }
} else if (!descriptor_is_wr(task->desc)) {
task->dxfer_dir = SCSI_DIR_TO_DEV;
vhost_process_write_payload_chain(task);
} else if (!descriptor_is_wr(task->desc)) {
task->dxfer_dir = SCSI_DIR_TO_DEV;
vhost_process_write_payload_chain(task);