]> git.droids-corp.org - dpdk.git/commitdiff
vhost: introduce safe API for GPA translation
authorMaxime Coquelin <maxime.coquelin@redhat.com>
Tue, 23 Jan 2018 13:37:50 +0000 (14:37 +0100)
committerMaxime Coquelin <maxime.coquelin@redhat.com>
Mon, 23 Apr 2018 14:04:30 +0000 (16:04 +0200)
This new rte_vhost_va_from_guest_pa API takes an extra len
parameter, used to specify the size of the range to be mapped.
Effective mapped range is returned via len parameter.

This issue has been assigned CVE-2018-1059.

Reported-by: Yongji Xie <xieyongji@baidu.com>
Signed-off-by: Maxime Coquelin <maxime.coquelin@redhat.com>
lib/librte_vhost/rte_vhost.h
lib/librte_vhost/rte_vhost_version.map
lib/librte_vhost/vhost.h

index e4e8824c98b04a15721a8c27a9a07698c0247ee4..7d065137a456f6ac9842fce4ceda9558b50fb80b 100644 (file)
@@ -149,6 +149,46 @@ rte_vhost_gpa_to_vva(struct rte_vhost_memory *mem, uint64_t gpa)
        return 0;
 }
 
+/**
+ * Convert guest physical address to host virtual address safely
+ *
+ * This variant of rte_vhost_gpa_to_vva() takes care all the
+ * requested length is mapped and contiguous in process address
+ * space.
+ *
+ * @param mem
+ *  the guest memory regions
+ * @param gpa
+ *  the guest physical address for querying
+ * @param len
+ *  the size of the requested area to map, updated with actual size mapped
+ * @return
+ *  the host virtual address on success, 0 on failure
+ */
+static __rte_always_inline uint64_t
+rte_vhost_va_from_guest_pa(struct rte_vhost_memory *mem,
+                                                  uint64_t gpa, uint64_t *len)
+{
+       struct rte_vhost_mem_region *r;
+       uint32_t i;
+
+       for (i = 0; i < mem->nregions; i++) {
+               r = &mem->regions[i];
+               if (gpa >= r->guest_phys_addr &&
+                   gpa <  r->guest_phys_addr + r->size) {
+
+                       if (unlikely(*len > r->guest_phys_addr + r->size - gpa))
+                               *len = r->guest_phys_addr + r->size - gpa;
+
+                       return gpa - r->guest_phys_addr +
+                              r->host_user_addr;
+               }
+       }
+       *len = 0;
+
+       return 0;
+}
+
 #define RTE_VHOST_NEED_LOG(features)   ((features) & (1ULL << VHOST_F_LOG_ALL))
 
 /**
index b9d338077dfeee7d59c3435f599389fc90361a27..8243bcabfc185ebcf9ff594702f7e08f30b41525 100644 (file)
@@ -61,6 +61,8 @@ DPDK_18.02 {
 } DPDK_17.08;
 
 EXPERIMENTAL {
+       global:
+
        rte_vdpa_register_device;
        rte_vdpa_unregister_device;
        rte_vdpa_find_device_id;
@@ -79,5 +81,5 @@ EXPERIMENTAL {
        rte_vhost_crypto_fetch_requests;
        rte_vhost_crypto_finalize_requests;
        rte_vhost_crypto_set_zero_copy;
-
+       rte_vhost_va_from_guest_pa;
 } DPDK_18.02;
index f7dbd2c94377246e8d3716ef85ca79a221e4765a..ba2fc74048710981f2ffcba889f9840fecacf965 100644 (file)
@@ -446,7 +446,7 @@ vhost_iova_to_vva(struct virtio_net *dev, struct vhost_virtqueue *vq,
                        uint64_t iova, uint64_t *len, uint8_t perm)
 {
        if (!(dev->features & (1ULL << VIRTIO_F_IOMMU_PLATFORM)))
-               return rte_vhost_gpa_to_vva(dev->mem, iova);
+               return rte_vhost_va_from_guest_pa(dev->mem, iova, len);
 
        return __vhost_iova_to_vva(dev, vq, iova, len, perm);
 }