From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from dpdk.org (dpdk.org [92.243.14.124]) by inbox.dpdk.org (Postfix) with ESMTP id 0BE10A0553 for ; Mon, 17 Feb 2020 18:47:05 +0100 (CET) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id 01A951DA12; Mon, 17 Feb 2020 18:47:05 +0100 (CET) Received: from mail-wr1-f67.google.com (mail-wr1-f67.google.com [209.85.221.67]) by dpdk.org (Postfix) with ESMTP id CE85D1DA12 for ; Mon, 17 Feb 2020 18:47:03 +0100 (CET) Received: by mail-wr1-f67.google.com with SMTP id k11so20774067wrd.9 for ; Mon, 17 Feb 2020 09:47:03 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=7wBaDV/9Jkyk+DmtbIY+zDur8LkWQ4BOlv76AJnm9d4=; b=ans1T+8QVs76mC4F34pq128FcrUVlp5nYiJCSdJAkuj+y06Fbssl0DM8rYQ9kNLY/4 UTLc4YcE4lA5ff1aVrOxfZJDouK14/Fq41iYU4V8rNDWsi60+JU0Rxva5dhvBVyG7LLc gbET9hBoY+tD35DIgFbM6VBCDFOoGxt5oUbKruDJzRlzbpOTJkhPm604eT26KeNbIV8n dM2/B8rY1/n7UszAY8YTLHcvqO74ztTyNGWrxuAUgnORusagjYA5gC3a0boo2Vjt6B6i sEXk2bhUElFsnJG+5Ue8OmRPyFy91nZg51i9oP952cKSzOwkMOtiIzq/mAbQ/hsx/br+ ACLw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=7wBaDV/9Jkyk+DmtbIY+zDur8LkWQ4BOlv76AJnm9d4=; b=hbvyelHPRsgXtaX9xnr+DLRTxBUwU+NkPaC7rgfR8nqLQYxlYApSeDiU8Lq2tYRW0I u88lYJRZEvIaNRYu8lVYoTRscKdg7Yn+0jlGY1h0oWITVQ0foTwO36XEb+xgHZ8C7KYy AAg/3AR5XoqksM+e7+A9KxNtNtRrA8fJVKgNKKeZOXLYtB6vPgoZQv5TPUxN8CUyeosX MfFvrs1gqT7Ray2XrDTtx4Qxyf7rrgHw8sSbfrSjCYx1zTslYsOScMA3H1YbrSvMeP96 R1EeeZgZhvWOPrFUcitECaI/0yuh6ZRdFu0i6h61GhC//UMNlIUeHm3+Be1IPlc5yWc8 BQlQ== X-Gm-Message-State: APjAAAUUf5MqAwsXaoAoFy04k4qdxFm8nms37KkD6rvE9ElPEalWiTMg j2EWUIpstDD7Q1xnNxcmNWXM9RntkfoMag== X-Google-Smtp-Source: APXvYqx8pukKWfgg28phlT4WIdh9D+6Smh03YCIL3icwWqk5KJcUM4FUEbm+hgobXK2qXvPccDRFGA== X-Received: by 2002:adf:dd51:: with SMTP id u17mr22692020wrm.290.1581961623557; Mon, 17 Feb 2020 09:47:03 -0800 (PST) Received: from localhost (userh634.uk.uudial.com. [194.69.103.7]) by smtp.gmail.com with ESMTPSA id z21sm225015wml.5.2020.02.17.09.47.02 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 17 Feb 2020 09:47:02 -0800 (PST) From: luca.boccassi@gmail.com To: Adrian Moreno Cc: Maxime Coquelin , dpdk stable Date: Mon, 17 Feb 2020 17:45:35 +0000 Message-Id: <20200217174546.25334-43-luca.boccassi@gmail.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200217174546.25334-1-luca.boccassi@gmail.com> References: <20200211112216.3929-190-luca.boccassi@gmail.com> <20200217174546.25334-1-luca.boccassi@gmail.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Subject: [dpdk-stable] patch 'vhost: protect log address translation in IOTLB update' has been queued to stable release 19.11.1 X-BeenThere: stable@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: patches for DPDK stable branches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: stable-bounces@dpdk.org Sender: "stable" Hi, FYI, your patch has been queued to stable release 19.11.1 Note it hasn't been pushed to http://dpdk.org/browse/dpdk-stable yet. It will be pushed if I get no objections before 02/19/20. So please shout if anyone has objections. Also note that after the patch there's a diff of the upstream commit vs the patch applied to the branch. This will indicate if there was any rebasing needed to apply to the stable branch. If there were code changes for rebasing (ie: not only metadata diffs), please double check that the rebase was correctly done. Thanks. Luca Boccassi --- >From 37d6a69f880b9c9292f7adbc72c4aba008e03115 Mon Sep 17 00:00:00 2001 From: Adrian Moreno Date: Thu, 13 Feb 2020 11:04:58 +0100 Subject: [PATCH] vhost: protect log address translation in IOTLB update [ upstream commit 4f37df14c405b754b5e971c75f4f67f4bb5bfdde ] Currently, the log address translation only happens in the vhost-user's translate_ring_addresses(). However, the IOTLB update handler is not checking if it was mapped to re-trigger that translation. Since the log address mapping could fail, check it on iotlb updates. Also, check it on vring_translate() so we do not dirty pages if the logging address is not yet ready. Additionally, properly protect the accesses to the iotlb structures. Fixes: fbda9f145927 ("vhost: translate incoming log address to GPA") Signed-off-by: Adrian Moreno Reviewed-by: Maxime Coquelin --- lib/librte_vhost/vhost.c | 56 ++++++++++++++++++++++++++++++++++ lib/librte_vhost/vhost.h | 15 +++++++-- lib/librte_vhost/vhost_user.c | 57 +++++++++++++++-------------------- 3 files changed, 93 insertions(+), 35 deletions(-) diff --git a/lib/librte_vhost/vhost.c b/lib/librte_vhost/vhost.c index 1cbe948f74..20fda61518 100644 --- a/lib/librte_vhost/vhost.c +++ b/lib/librte_vhost/vhost.c @@ -350,6 +350,57 @@ free_device(struct virtio_net *dev) rte_free(dev); } +static __rte_always_inline int +log_translate(struct virtio_net *dev, struct vhost_virtqueue *vq) +{ + if (likely(!(vq->ring_addrs.flags & (1 << VHOST_VRING_F_LOG)))) + return 0; + + vq->log_guest_addr = translate_log_addr(dev, vq, + vq->ring_addrs.log_guest_addr); + if (vq->log_guest_addr == 0) + return -1; + + return 0; +} + +/* + * Converts vring log address to GPA + * If IOMMU is enabled, the log address is IOVA + * If IOMMU not enabled, the log address is already GPA + * + * Caller should have iotlb_lock read-locked + */ +uint64_t +translate_log_addr(struct virtio_net *dev, struct vhost_virtqueue *vq, + uint64_t log_addr) +{ + if (dev->features & (1ULL << VIRTIO_F_IOMMU_PLATFORM)) { + const uint64_t exp_size = sizeof(uint64_t); + uint64_t hva, gpa; + uint64_t size = exp_size; + + hva = vhost_iova_to_vva(dev, vq, log_addr, + &size, VHOST_ACCESS_RW); + + if (size != exp_size) + return 0; + + gpa = hva_to_gpa(dev, hva, exp_size); + if (!gpa) { + RTE_LOG(ERR, VHOST_CONFIG, + "VQ: Failed to find GPA for log_addr: 0x%" + PRIx64 " hva: 0x%" PRIx64 "\n", + log_addr, hva); + return 0; + } + return gpa; + + } else + return log_addr; +} + +/* Caller should have iotlb_lock read-locked */ static int vring_translate_split(struct virtio_net *dev, struct vhost_virtqueue *vq) { @@ -388,6 +439,7 @@ vring_translate_split(struct virtio_net *dev, struct vhost_virtqueue *vq) return 0; } +/* Caller should have iotlb_lock read-locked */ static int vring_translate_packed(struct virtio_net *dev, struct vhost_virtqueue *vq) { @@ -434,6 +486,10 @@ vring_translate(struct virtio_net *dev, struct vhost_virtqueue *vq) if (vring_translate_split(dev, vq) < 0) return -1; } + + if (log_translate(dev, vq) < 0) + return -1; + vq->access_ok = 1; return 0; diff --git a/lib/librte_vhost/vhost.h b/lib/librte_vhost/vhost.h index 9f11b28a31..9ec5934566 100644 --- a/lib/librte_vhost/vhost.h +++ b/lib/librte_vhost/vhost.h @@ -462,14 +462,23 @@ static __rte_always_inline void vhost_log_cache_used_vring(struct virtio_net *dev, struct vhost_virtqueue *vq, uint64_t offset, uint64_t len) { - vhost_log_cache_write(dev, vq, vq->log_guest_addr + offset, len); + if (unlikely(dev->features & (1ULL << VHOST_F_LOG_ALL))) { + if (unlikely(vq->log_guest_addr == 0)) + return; + __vhost_log_cache_write(dev, vq, vq->log_guest_addr + offset, + len); + } } static __rte_always_inline void vhost_log_used_vring(struct virtio_net *dev, struct vhost_virtqueue *vq, uint64_t offset, uint64_t len) { - vhost_log_write(dev, vq->log_guest_addr + offset, len); + if (unlikely(dev->features & (1ULL << VHOST_F_LOG_ALL))) { + if (unlikely(vq->log_guest_addr == 0)) + return; + __vhost_log_write(dev, vq->log_guest_addr + offset, len); + } } static __rte_always_inline void @@ -620,6 +629,8 @@ void *vhost_alloc_copy_ind_table(struct virtio_net *dev, struct vhost_virtqueue *vq, uint64_t desc_addr, uint64_t desc_len); int vring_translate(struct virtio_net *dev, struct vhost_virtqueue *vq); +uint64_t translate_log_addr(struct virtio_net *dev, struct vhost_virtqueue *vq, + uint64_t log_addr); void vring_invalidate(struct virtio_net *dev, struct vhost_virtqueue *vq); static __rte_always_inline uint64_t diff --git a/lib/librte_vhost/vhost_user.c b/lib/librte_vhost/vhost_user.c index 8a33510a47..40c4520c08 100644 --- a/lib/librte_vhost/vhost_user.c +++ b/lib/librte_vhost/vhost_user.c @@ -656,13 +656,11 @@ ring_addr_to_vva(struct virtio_net *dev, struct vhost_virtqueue *vq, { if (dev->features & (1ULL << VIRTIO_F_IOMMU_PLATFORM)) { uint64_t vva; - uint64_t req_size = *size; - vva = vhost_user_iotlb_cache_find(vq, ra, + vhost_user_iotlb_rd_lock(vq); + vva = vhost_iova_to_vva(dev, vq, ra, size, VHOST_ACCESS_RW); - if (req_size != *size) - vhost_user_iotlb_miss(dev, (ra + *size), - VHOST_ACCESS_RW); + vhost_user_iotlb_rd_unlock(vq); return vva; } @@ -670,37 +668,16 @@ ring_addr_to_vva(struct virtio_net *dev, struct vhost_virtqueue *vq, return qva_to_vva(dev, ra, size); } -/* - * Converts vring log address to GPA - * If IOMMU is enabled, the log address is IOVA - * If IOMMU not enabled, the log address is already GPA - */ static uint64_t -translate_log_addr(struct virtio_net *dev, struct vhost_virtqueue *vq, - uint64_t log_addr) +log_addr_to_gpa(struct virtio_net *dev, struct vhost_virtqueue *vq) { - if (dev->features & (1ULL << VIRTIO_F_IOMMU_PLATFORM)) { - const uint64_t exp_size = sizeof(struct vring_used) + - sizeof(struct vring_used_elem) * vq->size; - uint64_t hva, gpa; - uint64_t size = exp_size; + uint64_t log_gpa; - hva = vhost_iova_to_vva(dev, vq, log_addr, - &size, VHOST_ACCESS_RW); - if (size != exp_size) - return 0; + vhost_user_iotlb_rd_lock(vq); + log_gpa = translate_log_addr(dev, vq, vq->ring_addrs.log_guest_addr); + vhost_user_iotlb_rd_unlock(vq); - gpa = hva_to_gpa(dev, hva, exp_size); - if (!gpa) { - RTE_LOG(ERR, VHOST_CONFIG, - "VQ: Failed to find GPA for log_addr: 0x%" PRIx64 " hva: 0x%" PRIx64 "\n", - log_addr, hva); - return 0; - } - return gpa; - - } else - return log_addr; + return log_gpa; } static struct virtio_net * @@ -712,7 +689,7 @@ translate_ring_addresses(struct virtio_net *dev, int vq_index) if (addr->flags & (1 << VHOST_VRING_F_LOG)) { vq->log_guest_addr = - translate_log_addr(dev, vq, addr->log_guest_addr); + log_addr_to_gpa(dev, vq); if (vq->log_guest_addr == 0) { RTE_LOG(DEBUG, VHOST_CONFIG, "(%d) failed to map log_guest_addr.\n", @@ -2251,6 +2228,13 @@ is_vring_iotlb_split(struct vhost_virtqueue *vq, struct vhost_iotlb_msg *imsg) if (ra->used_user_addr < end && (ra->used_user_addr + len) > start) return 1; + if (ra->flags & (1 << VHOST_VRING_F_LOG)) { + len = sizeof(uint64_t); + if (ra->log_guest_addr < end && + (ra->log_guest_addr + len) > start) + return 1; + } + return 0; } @@ -2276,6 +2260,13 @@ is_vring_iotlb_packed(struct vhost_virtqueue *vq, struct vhost_iotlb_msg *imsg) if (ra->used_user_addr < end && (ra->used_user_addr + len) > start) return 1; + if (ra->flags & (1 << VHOST_VRING_F_LOG)) { + len = sizeof(uint64_t); + if (ra->log_guest_addr < end && + (ra->log_guest_addr + len) > start) + return 1; + } + return 0; } -- 2.20.1 --- Diff of the applied patch vs upstream commit (please double-check if non-empty: --- --- - 2020-02-17 17:00:16.509727070 +0000 +++ 0043-vhost-protect-log-address-translation-in-IOTLB-updat.patch 2020-02-17 17:00:15.367951305 +0000 @@ -1,8 +1,10 @@ -From 4f37df14c405b754b5e971c75f4f67f4bb5bfdde Mon Sep 17 00:00:00 2001 +From 37d6a69f880b9c9292f7adbc72c4aba008e03115 Mon Sep 17 00:00:00 2001 From: Adrian Moreno Date: Thu, 13 Feb 2020 11:04:58 +0100 Subject: [PATCH] vhost: protect log address translation in IOTLB update +[ upstream commit 4f37df14c405b754b5e971c75f4f67f4bb5bfdde ] + Currently, the log address translation only happens in the vhost-user's translate_ring_addresses(). However, the IOTLB update handler is not checking if it was mapped to re-trigger that translation. @@ -14,7 +16,6 @@ Additionally, properly protect the accesses to the iotlb structures. Fixes: fbda9f145927 ("vhost: translate incoming log address to GPA") -Cc: stable@dpdk.org Signed-off-by: Adrian Moreno Reviewed-by: Maxime Coquelin @@ -25,10 +26,10 @@ 3 files changed, 93 insertions(+), 35 deletions(-) diff --git a/lib/librte_vhost/vhost.c b/lib/librte_vhost/vhost.c -index c819a84774..0266318440 100644 +index 1cbe948f74..20fda61518 100644 --- a/lib/librte_vhost/vhost.c +++ b/lib/librte_vhost/vhost.c -@@ -353,6 +353,57 @@ free_device(struct virtio_net *dev) +@@ -350,6 +350,57 @@ free_device(struct virtio_net *dev) rte_free(dev); } @@ -70,7 +71,7 @@ + + gpa = hva_to_gpa(dev, hva, exp_size); + if (!gpa) { -+ VHOST_LOG_CONFIG(ERR, ++ RTE_LOG(ERR, VHOST_CONFIG, + "VQ: Failed to find GPA for log_addr: 0x%" + PRIx64 " hva: 0x%" PRIx64 "\n", + log_addr, hva); @@ -86,7 +87,7 @@ static int vring_translate_split(struct virtio_net *dev, struct vhost_virtqueue *vq) { -@@ -391,6 +442,7 @@ vring_translate_split(struct virtio_net *dev, struct vhost_virtqueue *vq) +@@ -388,6 +439,7 @@ vring_translate_split(struct virtio_net *dev, struct vhost_virtqueue *vq) return 0; } @@ -94,7 +95,7 @@ static int vring_translate_packed(struct virtio_net *dev, struct vhost_virtqueue *vq) { -@@ -437,6 +489,10 @@ vring_translate(struct virtio_net *dev, struct vhost_virtqueue *vq) +@@ -434,6 +486,10 @@ vring_translate(struct virtio_net *dev, struct vhost_virtqueue *vq) if (vring_translate_split(dev, vq) < 0) return -1; } @@ -106,7 +107,7 @@ return 0; diff --git a/lib/librte_vhost/vhost.h b/lib/librte_vhost/vhost.h -index 686ce42a20..2087d1400e 100644 +index 9f11b28a31..9ec5934566 100644 --- a/lib/librte_vhost/vhost.h +++ b/lib/librte_vhost/vhost.h @@ -462,14 +462,23 @@ static __rte_always_inline void @@ -135,7 +136,7 @@ } static __rte_always_inline void -@@ -626,6 +635,8 @@ void *vhost_alloc_copy_ind_table(struct virtio_net *dev, +@@ -620,6 +629,8 @@ void *vhost_alloc_copy_ind_table(struct virtio_net *dev, struct vhost_virtqueue *vq, uint64_t desc_addr, uint64_t desc_len); int vring_translate(struct virtio_net *dev, struct vhost_virtqueue *vq); @@ -145,7 +146,7 @@ static __rte_always_inline uint64_t diff --git a/lib/librte_vhost/vhost_user.c b/lib/librte_vhost/vhost_user.c -index 9a7b8b3088..bd1be01040 100644 +index 8a33510a47..40c4520c08 100644 --- a/lib/librte_vhost/vhost_user.c +++ b/lib/librte_vhost/vhost_user.c @@ -656,13 +656,11 @@ ring_addr_to_vva(struct virtio_net *dev, struct vhost_virtqueue *vq, @@ -196,7 +197,7 @@ - gpa = hva_to_gpa(dev, hva, exp_size); - if (!gpa) { -- VHOST_LOG_CONFIG(ERR, +- RTE_LOG(ERR, VHOST_CONFIG, - "VQ: Failed to find GPA for log_addr: 0x%" PRIx64 " hva: 0x%" PRIx64 "\n", - log_addr, hva); - return 0; @@ -216,7 +217,7 @@ - translate_log_addr(dev, vq, addr->log_guest_addr); + log_addr_to_gpa(dev, vq); if (vq->log_guest_addr == 0) { - VHOST_LOG_CONFIG(DEBUG, + RTE_LOG(DEBUG, VHOST_CONFIG, "(%d) failed to map log_guest_addr.\n", @@ -2251,6 +2228,13 @@ is_vring_iotlb_split(struct vhost_virtqueue *vq, struct vhost_iotlb_msg *imsg) if (ra->used_user_addr < end && (ra->used_user_addr + len) > start)