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 E7413A0500 for ; Tue, 17 Dec 2019 19:07:06 +0100 (CET) Received: from [92.243.14.124] (localhost [127.0.0.1]) by dpdk.org (Postfix) with ESMTP id DAF231BEC4; Tue, 17 Dec 2019 19:07:06 +0100 (CET) Received: from us-smtp-delivery-1.mimecast.com (us-smtp-2.mimecast.com [205.139.110.61]) by dpdk.org (Postfix) with ESMTP id 863B71BEC4 for ; Tue, 17 Dec 2019 19:07:05 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1576606025; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Z7dyaNaZ+fi70lhqu31Jwoztx2NAjxnJ/wICeQFAqlg=; b=fKjEerRICt+gsNOFXWb2b6fuEuKRceNmfc3U6PIupc41TBkpQyLOc+TepMjaSqLwJr2Qaj 6n1c74gDry/dm1jsuC4YJk2GQ1xSumrXE1DY98/E7l/Tj6PpOSQSx53tVvB7+ZtZ6P9Js8 s3hs31U5TQpz6V3Wcu3UQFPydh+t5xI= Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-284-bFjyQ2f5M7KRjGROQLP-1w-1; Tue, 17 Dec 2019 13:07:00 -0500 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id C662618C43C1; Tue, 17 Dec 2019 18:06:59 +0000 (UTC) Received: from amorenoz.users.ipa.redhat.com (ovpn-117-34.ams2.redhat.com [10.36.117.34]) by smtp.corp.redhat.com (Postfix) with ESMTP id BC4937C83B; Tue, 17 Dec 2019 18:06:58 +0000 (UTC) From: Adrian Moreno To: stable@dpdk.org Cc: ktraynor@redhat.com, maxime.coquelin@redhat.com, Tiwei Bie Date: Tue, 17 Dec 2019 19:06:37 +0100 Message-Id: <20191217180640.17993-5-amorenoz@redhat.com> In-Reply-To: <20191217180640.17993-1-amorenoz@redhat.com> References: <20191217180640.17993-1-amorenoz@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-MC-Unique: bFjyQ2f5M7KRjGROQLP-1w-1 X-Mimecast-Spam-Score: 0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: quoted-printable Subject: [dpdk-stable] [PATCH 18.11 4/7] vhost: do not inline unlikely fragmented buffers code 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" From: Maxime Coquelin [ upstream commit 084fac96ca0331f2646002c302f389415fef69e2 ] Handling of fragmented virtio-net header and indirect descriptors tables was implemented to fix CVE-2018-1059. It should never happen with healthy guests and so is already considered as unlikely code path. This patch moves these bits into non-inline dedicated functions to reduce the I-cache pressure. Signed-off-by: Maxime Coquelin Reviewed-by: Tiwei Bie Conflicts: =09lib/librte_vhost/vdpa.c: Due to not having [1]. Skiping changes on non existing function =09lib/librte_vhost/vhost.h: Due to not having [1]. alloc_copy_ind_table() is still in virtio_net.c =09lib/librte_vhost/virtio_net.c: Due to not having [1]. Remove alloc_copy_ind_table() [1] b13ad2dec vhost: provide helpers for virtio ring relay --- lib/librte_vhost/vhost.c | 33 +++++++++ lib/librte_vhost/vhost.h | 3 + lib/librte_vhost/virtio_net.c | 133 ++++++++++++++-------------------- 3 files changed, 92 insertions(+), 77 deletions(-) diff --git a/lib/librte_vhost/vhost.c b/lib/librte_vhost/vhost.c index fb21e1ddd..1b62fde68 100644 --- a/lib/librte_vhost/vhost.c +++ b/lib/librte_vhost/vhost.c @@ -200,6 +200,39 @@ __vhost_log_cache_write(struct virtio_net *dev, struct= vhost_virtqueue *vq, =09} } =20 +void * +vhost_alloc_copy_ind_table(struct virtio_net *dev, struct vhost_virtqueue = *vq, +=09=09uint64_t desc_addr, uint64_t desc_len) +{ +=09void *idesc; +=09uint64_t src, dst; +=09uint64_t len, remain =3D desc_len; + +=09idesc =3D rte_malloc(__func__, desc_len, 0); +=09if (unlikely(!idesc)) +=09=09return NULL; + +=09dst =3D (uint64_t)(uintptr_t)idesc; + +=09while (remain) { +=09=09len =3D remain; +=09=09src =3D vhost_iova_to_vva(dev, vq, desc_addr, &len, +=09=09=09=09VHOST_ACCESS_RO); +=09=09if (unlikely(!src || !len)) { +=09=09=09rte_free(idesc); +=09=09=09return NULL; +=09=09} + +=09=09rte_memcpy((void *)(uintptr_t)dst, (void *)(uintptr_t)src, len); + +=09=09remain -=3D len; +=09=09dst +=3D len; +=09=09desc_addr +=3D len; +=09} + +=09return idesc; +} + void cleanup_vq(struct vhost_virtqueue *vq, int destroy) { diff --git a/lib/librte_vhost/vhost.h b/lib/librte_vhost/vhost.h index a4f69f98a..5a857b155 100644 --- a/lib/librte_vhost/vhost.h +++ b/lib/librte_vhost/vhost.h @@ -558,6 +558,9 @@ void vhost_backend_cleanup(struct virtio_net *dev); =20 uint64_t __vhost_iova_to_vva(struct virtio_net *dev, struct vhost_virtqueu= e *vq, =09=09=09uint64_t iova, uint64_t *len, uint8_t perm); +void *vhost_alloc_copy_ind_table(struct virtio_net *dev, +=09=09=09struct vhost_virtqueue *vq, +=09=09=09uint64_t desc_addr, uint64_t desc_len); int vring_translate(struct virtio_net *dev, struct vhost_virtqueue *vq); void vring_invalidate(struct virtio_net *dev, struct vhost_virtqueue *vq); =20 diff --git a/lib/librte_vhost/virtio_net.c b/lib/librte_vhost/virtio_net.c index 26601c2d4..0a0b44c8b 100644 --- a/lib/librte_vhost/virtio_net.c +++ b/lib/librte_vhost/virtio_net.c @@ -37,39 +37,6 @@ is_valid_virt_queue_idx(uint32_t idx, int is_tx, uint32_= t nr_vring) =09return (is_tx ^ (idx & 1)) =3D=3D 0 && idx < nr_vring; } =20 -static __rte_always_inline void * -alloc_copy_ind_table(struct virtio_net *dev, struct vhost_virtqueue *vq, -=09=09uint64_t desc_addr, uint64_t desc_len) -{ -=09void *idesc; -=09uint64_t src, dst; -=09uint64_t len, remain =3D desc_len; - -=09idesc =3D rte_malloc(__func__, desc_len, 0); -=09if (unlikely(!idesc)) -=09=09return 0; - -=09dst =3D (uint64_t)(uintptr_t)idesc; - -=09while (remain) { -=09=09len =3D remain; -=09=09src =3D vhost_iova_to_vva(dev, vq, desc_addr, &len, -=09=09=09=09VHOST_ACCESS_RO); -=09=09if (unlikely(!src || !len)) { -=09=09=09rte_free(idesc); -=09=09=09return 0; -=09=09} - -=09=09rte_memcpy((void *)(uintptr_t)dst, (void *)(uintptr_t)src, len); - -=09=09remain -=3D len; -=09=09dst +=3D len; -=09=09desc_addr +=3D len; -=09} - -=09return idesc; -} - static __rte_always_inline void free_ind_table(void *idesc) { @@ -377,7 +344,7 @@ fill_vec_buf_split(struct virtio_net *dev, struct vhost= _virtqueue *vq, =09=09=09 * The indirect desc table is not contiguous =09=09=09 * in process VA space, we have to copy it. =09=09=09 */ -=09=09=09idesc =3D alloc_copy_ind_table(dev, vq, +=09=09=09idesc =3D vhost_alloc_copy_ind_table(dev, vq, =09=09=09=09=09vq->desc[idx].addr, vq->desc[idx].len); =09=09=09if (unlikely(!idesc)) =09=09=09=09return -1; @@ -494,7 +461,8 @@ fill_vec_buf_packed_indirect(struct virtio_net *dev, =09=09 * The indirect desc table is not contiguous =09=09 * in process VA space, we have to copy it. =09=09 */ -=09=09idescs =3D alloc_copy_ind_table(dev, vq, desc->addr, desc->len); +=09=09idescs =3D vhost_alloc_copy_ind_table(dev, +=09=09=09=09vq, desc->addr, desc->len); =09=09if (unlikely(!idescs)) =09=09=09return -1; =20 @@ -650,6 +618,36 @@ reserve_avail_buf_packed(struct virtio_net *dev, struc= t vhost_virtqueue *vq, =09return 0; } =20 +static __rte_noinline void +copy_vnet_hdr_to_desc(struct virtio_net *dev, struct vhost_virtqueue *vq, +=09=09struct buf_vector *buf_vec, +=09=09struct virtio_net_hdr_mrg_rxbuf *hdr) +{ +=09uint64_t len; +=09uint64_t remain =3D dev->vhost_hlen; +=09uint64_t src =3D (uint64_t)(uintptr_t)hdr, dst; +=09uint64_t iova =3D buf_vec->buf_iova; + +=09while (remain) { +=09=09len =3D RTE_MIN(remain, +=09=09=09=09buf_vec->buf_len); +=09=09dst =3D buf_vec->buf_addr; +=09=09rte_memcpy((void *)(uintptr_t)dst, +=09=09=09=09(void *)(uintptr_t)src, +=09=09=09=09len); + +=09=09PRINT_PACKET(dev, (uintptr_t)dst, +=09=09=09=09(uint32_t)len, 0); +=09=09vhost_log_cache_write(dev, vq, +=09=09=09=09iova, len); + +=09=09remain -=3D len; +=09=09iova +=3D len; +=09=09src +=3D len; +=09=09buf_vec++; +=09} +} + static __rte_always_inline int copy_mbuf_to_desc(struct virtio_net *dev, struct vhost_virtqueue *vq, =09=09=09 struct rte_mbuf *m, struct buf_vector *buf_vec, @@ -743,30 +741,7 @@ copy_mbuf_to_desc(struct virtio_net *dev, struct vhost= _virtqueue *vq, =09=09=09=09=09=09num_buffers); =20 =09=09=09if (unlikely(hdr =3D=3D &tmp_hdr)) { -=09=09=09=09uint64_t len; -=09=09=09=09uint64_t remain =3D dev->vhost_hlen; -=09=09=09=09uint64_t src =3D (uint64_t)(uintptr_t)hdr, dst; -=09=09=09=09uint64_t iova =3D buf_vec[0].buf_iova; -=09=09=09=09uint16_t hdr_vec_idx =3D 0; - -=09=09=09=09while (remain) { -=09=09=09=09=09len =3D RTE_MIN(remain, -=09=09=09=09=09=09buf_vec[hdr_vec_idx].buf_len); -=09=09=09=09=09dst =3D buf_vec[hdr_vec_idx].buf_addr; -=09=09=09=09=09rte_memcpy((void *)(uintptr_t)dst, -=09=09=09=09=09=09=09(void *)(uintptr_t)src, -=09=09=09=09=09=09=09len); - -=09=09=09=09=09PRINT_PACKET(dev, (uintptr_t)dst, -=09=09=09=09=09=09=09(uint32_t)len, 0); -=09=09=09=09=09vhost_log_cache_write(dev, vq, -=09=09=09=09=09=09=09iova, len); - -=09=09=09=09=09remain -=3D len; -=09=09=09=09=09iova +=3D len; -=09=09=09=09=09src +=3D len; -=09=09=09=09=09hdr_vec_idx++; -=09=09=09=09} +=09=09=09=09copy_vnet_hdr_to_desc(dev, vq, buf_vec, hdr); =09=09=09} else { =09=09=09=09PRINT_PACKET(dev, (uintptr_t)hdr_addr, =09=09=09=09=09=09dev->vhost_hlen, 0); @@ -1102,6 +1077,27 @@ vhost_dequeue_offload(struct virtio_net_hdr *hdr, st= ruct rte_mbuf *m) =09} } =20 +static __rte_noinline void +copy_vnet_hdr_from_desc(struct virtio_net_hdr *hdr, +=09=09struct buf_vector *buf_vec) +{ +=09uint64_t len; +=09uint64_t remain =3D sizeof(struct virtio_net_hdr); +=09uint64_t src; +=09uint64_t dst =3D (uint64_t)(uintptr_t)hdr; + +=09while (remain) { +=09=09len =3D RTE_MIN(remain, buf_vec->buf_len); +=09=09src =3D buf_vec->buf_addr; +=09=09rte_memcpy((void *)(uintptr_t)dst, +=09=09=09=09(void *)(uintptr_t)src, len); + +=09=09remain -=3D len; +=09=09dst +=3D len; +=09=09buf_vec++; +=09} +} + static __rte_always_inline int copy_desc_to_mbuf(struct virtio_net *dev, struct vhost_virtqueue *vq, =09=09 struct buf_vector *buf_vec, uint16_t nr_vec, @@ -1133,28 +1129,11 @@ copy_desc_to_mbuf(struct virtio_net *dev, struct vh= ost_virtqueue *vq, =20 =09if (virtio_net_with_host_offload(dev)) { =09=09if (unlikely(buf_len < sizeof(struct virtio_net_hdr))) { -=09=09=09uint64_t len; -=09=09=09uint64_t remain =3D sizeof(struct virtio_net_hdr); -=09=09=09uint64_t src; -=09=09=09uint64_t dst =3D (uint64_t)(uintptr_t)&tmp_hdr; -=09=09=09uint16_t hdr_vec_idx =3D 0; - =09=09=09/* =09=09=09 * No luck, the virtio-net header doesn't fit =09=09=09 * in a contiguous virtual area. =09=09=09 */ -=09=09=09while (remain) { -=09=09=09=09len =3D RTE_MIN(remain, -=09=09=09=09=09buf_vec[hdr_vec_idx].buf_len); -=09=09=09=09src =3D buf_vec[hdr_vec_idx].buf_addr; -=09=09=09=09rte_memcpy((void *)(uintptr_t)dst, -=09=09=09=09=09=09 (void *)(uintptr_t)src, len); - -=09=09=09=09remain -=3D len; -=09=09=09=09dst +=3D len; -=09=09=09=09hdr_vec_idx++; -=09=09=09} - +=09=09=09copy_vnet_hdr_from_desc(&tmp_hdr, buf_vec); =09=09=09hdr =3D &tmp_hdr; =09=09} else { =09=09=09hdr =3D (struct virtio_net_hdr *)((uintptr_t)buf_addr); --=20 2.21.0