Hello community, here is the log from the commit of package dpdk for openSUSE:Factory checked in at 2019-11-20 10:29:50 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/dpdk (Old) and /work/SRC/openSUSE:Factory/.dpdk.new.26869 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "dpdk" Wed Nov 20 10:29:50 2019 rev:41 rq:749810 version:18.11.3 Changes: -------- --- /work/SRC/openSUSE:Factory/dpdk/dpdk.changes 2019-10-03 14:09:35.836079039 +0200 +++ /work/SRC/openSUSE:Factory/.dpdk.new.26869/dpdk.changes 2019-11-20 10:29:55.742594467 +0100 @@ -1,0 +2,14 @@ +Tue Nov 19 15:45:29 UTC 2019 - Jaime CaamaƱo Ruiz <[email protected]> + +- Add version to the PMD driver directory to avoid loading previous + version drivers (bsc#1157179). +- Update to 18.11.3 (bsc#1156146). For a list of fixes check: + * https://doc.dpdk.org/guides-18.11/rel_notes/release_18_11.html#fixes +- Add patches to fix vulnerability where malicious container can trigger + a denial of service (CVE-2019-14818, bsc#1156146) + * 0001-vhost-fix-possible-denial-of-service-on-SET_VRING_NU.patch + * 0002-vhost-fix-possible-denial-of-service-by-leaking-FDs.patch +- Removed patrches already included upstream: + * dpdk-fix-implicit-fallthrough-warning.patch + +------------------------------------------------------------------- Old: ---- dpdk-18.11.2.tar.xz dpdk-fix-implicit-fallthrough-warning.patch New: ---- 0001-vhost-fix-possible-denial-of-service-on-SET_VRING_NU.patch 0002-vhost-fix-possible-denial-of-service-by-leaking-FDs.patch dpdk-18.11.3.tar.xz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ dpdk.spec ++++++ --- /var/tmp/diff_new_pack.i9KbJJ/_old 2019-11-20 10:29:58.018594921 +0100 +++ /var/tmp/diff_new_pack.i9KbJJ/_new 2019-11-20 10:29:58.018594921 +0100 @@ -26,7 +26,7 @@ %if "%flavor" == "thunderx" %define name_tag -thunderx -%define summary_tag thunderx +%define summary_tag (thunderx) %define aarch64_machine2 thunderx %define exclusive_arch aarch64 %endif @@ -58,7 +58,7 @@ %define lname libdpdk-%{maj}_%{min} Name: dpdk%{name_tag} -Version: 18.11.2 +Version: 18.11.3 Release: 0 Summary: Set of libraries and drivers for fast packet processing License: BSD-3-Clause AND GPL-2.0-only AND LGPL-2.1-only @@ -66,8 +66,9 @@ Url: http://dpdk.org Source: http://fast.dpdk.org/rel/dpdk-%{version}.tar.xz Source1: preamble -Patch: dpdk-fix-implicit-fallthrough-warning.patch Patch1: 0002-fix-cpu-compatibility.patch +Patch2: 0001-vhost-fix-possible-denial-of-service-on-SET_VRING_NU.patch +Patch3: 0002-vhost-fix-possible-denial-of-service-by-leaking-FDs.patch BuildRequires: doxygen BuildRequires: fdupes BuildRequires: libelf-devel @@ -159,13 +160,14 @@ %define sdkdir %{_datadir}/dpdk %define docdir %{_docdir}/dpdk %define incdir %{_includedir}/dpdk -%define pmddir %{_libdir}/dpdk-pmds +%define pmddir %{_libdir}/dpdk-pmds-%{maj}.%{min} %prep # can't use %{name} because of dpdk-thunderx %setup -q -n dpdk-stable-%{version} -%patch -p1 %patch1 -p1 -z .init +%patch2 -p1 -z .init +%patch3 -p1 -z .init # This fixes CROSS compilation (broken) in the mk file for ThunderX sed -i '/^CROSS /s/^/#/' mk/machine/thunderx/rte.vars.mk @@ -355,10 +357,8 @@ %files -n %{lname} %defattr(-,root,root) %if %{with shared} -%dir %{_libdir}/dpdk-pmds - %{_libdir}/*.so.* -%{pmddir}/ +%{pmddir} %endif %files doc ++++++ 0001-vhost-fix-possible-denial-of-service-on-SET_VRING_NU.patch ++++++ >From f110daae0d7d033db151d2791f6555546d5144ac Mon Sep 17 00:00:00 2001 From: Maxime Coquelin <[email protected]> Date: Fri, 23 Aug 2019 15:17:05 +0200 Subject: [v18.11 PATCH v2 1/2] vhost: fix possible denial of service on SET_VRING_NUM vhost_user_set_vring_num() performs multiple allocations without checking whether data were previously allocated. It may cause a denial of service because of the memory leaks that happen if a malicious vhost-user master keeps sending VHOST_USER_SET_VRING_NUM request until the slave runs out of memory. This issue has been assigned CVE-2019-14818 Reported-by: Jason Wang <[email protected]> Signed-off-by: Maxime Coquelin <[email protected]> --- lib/librte_vhost/vhost_user.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/librte_vhost/vhost_user.c b/lib/librte_vhost/vhost_user.c index 5552f8bbfb..457e62d97e 100644 --- a/lib/librte_vhost/vhost_user.c +++ b/lib/librte_vhost/vhost_user.c @@ -346,6 +346,8 @@ vhost_user_set_vring_num(struct virtio_net **pdev, vq->nr_zmbuf = 0; vq->last_zmbuf_idx = 0; vq->zmbuf_size = vq->size; + if (vq->zmbufs) + rte_free(vq->zmbufs); vq->zmbufs = rte_zmalloc(NULL, vq->zmbuf_size * sizeof(struct zcopy_mbuf), 0); if (vq->zmbufs == NULL) { @@ -358,6 +360,8 @@ vhost_user_set_vring_num(struct virtio_net **pdev, } if (vq_is_packed(dev)) { + if (vq->shadow_used_packed) + rte_free(vq->shadow_used_packed); vq->shadow_used_packed = rte_malloc(NULL, vq->size * sizeof(struct vring_used_elem_packed), @@ -369,6 +373,8 @@ vhost_user_set_vring_num(struct virtio_net **pdev, } } else { + if (vq->shadow_used_split) + rte_free(vq->shadow_used_split); vq->shadow_used_split = rte_malloc(NULL, vq->size * sizeof(struct vring_used_elem), RTE_CACHE_LINE_SIZE); @@ -379,6 +385,8 @@ vhost_user_set_vring_num(struct virtio_net **pdev, } } + if (vq->batch_copy_elems) + rte_free(vq->batch_copy_elems); vq->batch_copy_elems = rte_malloc(NULL, vq->size * sizeof(struct batch_copy_elem), RTE_CACHE_LINE_SIZE); -- 2.21.0 ++++++ 0002-vhost-fix-possible-denial-of-service-by-leaking-FDs.patch ++++++ >From 8accec7a78708ee8ece4550e370d32ccdff4dee8 Mon Sep 17 00:00:00 2001 From: Maxime Coquelin <[email protected]> Date: Tue, 3 Sep 2019 17:34:22 +0200 Subject: [v18.11 PATCH v2 2/2] vhost: fix possible denial of service by leaking FDs A malicious Vhost-user master could send in loop hand-crafted vhost-user messages containing more file descriptors the vhost-user slave expects. Doing so causes the application using the vhost-user library to run out of FDs. This issue has been assigned CVE-2019-14818 Fixes: 8f972312b8f4 ("vhost: support vhost-user") Signed-off-by: Maxime Coquelin <[email protected]> --- lib/librte_vhost/vhost_user.c | 118 ++++++++++++++++++++++++++++++++-- 1 file changed, 114 insertions(+), 4 deletions(-) diff --git a/lib/librte_vhost/vhost_user.c b/lib/librte_vhost/vhost_user.c index 457e62d97e..98cd670e03 100644 --- a/lib/librte_vhost/vhost_user.c +++ b/lib/librte_vhost/vhost_user.c @@ -83,6 +83,36 @@ static const char *vhost_message_str[VHOST_USER_MAX] = { static int send_vhost_reply(int sockfd, struct VhostUserMsg *msg); static int read_vhost_message(int sockfd, struct VhostUserMsg *msg); +static void +close_msg_fds(struct VhostUserMsg *msg) +{ + int i; + + for (i = 0; i < msg->fd_num; i++) + close(msg->fds[i]); +} + +/* + * Ensure the expected number of FDs is received, + * close all FDs and return an error if this is not the case. + */ +static int +validate_msg_fds(struct VhostUserMsg *msg, int expected_fds) +{ + if (msg->fd_num == expected_fds) + return 0; + + RTE_LOG(ERR, VHOST_CONFIG, + " Expect %d FDs for request %s, received %d\n", + expected_fds, + vhost_message_str[msg->request.master], + msg->fd_num); + + close_msg_fds(msg); + + return -1; +} + static uint64_t get_blk_size(int fd) { @@ -179,18 +209,25 @@ vhost_backend_cleanup(struct virtio_net *dev) */ static int vhost_user_set_owner(struct virtio_net **pdev __rte_unused, - struct VhostUserMsg *msg __rte_unused, + struct VhostUserMsg *msg, int main_fd __rte_unused) { + if (validate_msg_fds(msg, 0) != 0) + return VH_RESULT_ERR; + return VH_RESULT_OK; } static int vhost_user_reset_owner(struct virtio_net **pdev, - struct VhostUserMsg *msg __rte_unused, + struct VhostUserMsg *msg, int main_fd __rte_unused) { struct virtio_net *dev = *pdev; + + if (validate_msg_fds(msg, 0) != 0) + return VH_RESULT_ERR; + vhost_destroy_device_notify(dev); cleanup_device(dev, 0); @@ -208,6 +245,9 @@ vhost_user_get_features(struct virtio_net **pdev, struct VhostUserMsg *msg, struct virtio_net *dev = *pdev; uint64_t features = 0; + if (validate_msg_fds(msg, 0) != 0) + return VH_RESULT_ERR; + rte_vhost_driver_get_features(dev->ifname, &features); msg->payload.u64 = features; @@ -227,6 +267,9 @@ vhost_user_get_queue_num(struct virtio_net **pdev, struct VhostUserMsg *msg, struct virtio_net *dev = *pdev; uint32_t queue_num = 0; + if (validate_msg_fds(msg, 0) != 0) + return VH_RESULT_ERR; + rte_vhost_driver_get_queue_num(dev->ifname, &queue_num); msg->payload.u64 = (uint64_t)queue_num; @@ -249,6 +292,9 @@ vhost_user_set_features(struct virtio_net **pdev, struct VhostUserMsg *msg, struct rte_vdpa_device *vdpa_dev; int did = -1; + if (validate_msg_fds(msg, 0) != 0) + return VH_RESULT_ERR; + rte_vhost_driver_get_features(dev->ifname, &vhost_features); if (features & ~vhost_features) { RTE_LOG(ERR, VHOST_CONFIG, @@ -329,6 +375,9 @@ vhost_user_set_vring_num(struct virtio_net **pdev, struct virtio_net *dev = *pdev; struct vhost_virtqueue *vq = dev->virtqueue[msg->payload.state.index]; + if (validate_msg_fds(msg, 0) != 0) + return VH_RESULT_ERR; + vq->size = msg->payload.state.num; /* VIRTIO 1.0, 2.4 Virtqueues says: @@ -708,6 +757,9 @@ vhost_user_set_vring_addr(struct virtio_net **pdev, struct VhostUserMsg *msg, struct vhost_virtqueue *vq; struct vhost_vring_addr *addr = &msg->payload.addr; + if (validate_msg_fds(msg, 0) != 0) + return VH_RESULT_ERR; + if (dev->mem == NULL) return VH_RESULT_ERR; @@ -746,6 +798,9 @@ vhost_user_set_vring_base(struct virtio_net **pdev, struct vhost_virtqueue *vq = dev->virtqueue[msg->payload.state.index]; uint64_t val = msg->payload.state.num; + if (validate_msg_fds(msg, 0) != 0) + return VH_RESULT_ERR; + if (vq_is_packed(dev)) { /* * Bit[0:14]: avail index @@ -907,6 +962,9 @@ vhost_user_set_mem_table(struct virtio_net **pdev, struct VhostUserMsg *msg, int populate; int fd; + if (validate_msg_fds(msg, memory->nregions) != 0) + return VH_RESULT_ERR; + if (memory->nregions > VHOST_MEMORY_MAX_NREGIONS) { RTE_LOG(ERR, VHOST_CONFIG, "too many memory regions (%u)\n", memory->nregions); @@ -917,8 +975,7 @@ vhost_user_set_mem_table(struct virtio_net **pdev, struct VhostUserMsg *msg, RTE_LOG(INFO, VHOST_CONFIG, "(%d) memory regions not changed\n", dev->vid); - for (i = 0; i < memory->nregions; i++) - close(msg->fds[i]); + close_msg_fds(msg); return VH_RESULT_OK; } @@ -1061,6 +1118,10 @@ vhost_user_set_mem_table(struct virtio_net **pdev, struct VhostUserMsg *msg, "Failed to read qemu ack on postcopy set-mem-table\n"); goto err_mmap; } + + if (validate_msg_fds(&ack_msg, 0) != 0) + goto err_mmap; + if (ack_msg.request.master != VHOST_USER_SET_MEM_TABLE) { RTE_LOG(ERR, VHOST_CONFIG, "Bad qemu ack on postcopy set-mem-table (%d)\n", @@ -1181,6 +1242,9 @@ vhost_user_set_vring_call(struct virtio_net **pdev, struct VhostUserMsg *msg, struct vhost_vring_file file; struct vhost_virtqueue *vq; + if (validate_msg_fds(msg, 1) != 0) + return VH_RESULT_ERR; + file.index = msg->payload.u64 & VHOST_USER_VRING_IDX_MASK; if (msg->payload.u64 & VHOST_USER_VRING_NOFD_MASK) file.fd = VIRTIO_INVALID_EVENTFD; @@ -1202,6 +1266,9 @@ static int vhost_user_set_vring_err(struct virtio_net **pdev __rte_unused, struct VhostUserMsg *msg, int main_fd __rte_unused) { + if (validate_msg_fds(msg, 1) != 0) + return VH_RESULT_ERR; + if (!(msg->payload.u64 & VHOST_USER_VRING_NOFD_MASK)) close(msg->fds[0]); RTE_LOG(INFO, VHOST_CONFIG, "not implemented\n"); @@ -1217,6 +1284,9 @@ vhost_user_set_vring_kick(struct virtio_net **pdev, struct VhostUserMsg *msg, struct vhost_vring_file file; struct vhost_virtqueue *vq; + if (validate_msg_fds(msg, 1) != 0) + return VH_RESULT_ERR; + file.index = msg->payload.u64 & VHOST_USER_VRING_IDX_MASK; if (msg->payload.u64 & VHOST_USER_VRING_NOFD_MASK) file.fd = VIRTIO_INVALID_EVENTFD; @@ -1273,6 +1343,9 @@ vhost_user_get_vring_base(struct virtio_net **pdev, struct vhost_virtqueue *vq = dev->virtqueue[msg->payload.state.index]; uint64_t val; + if (validate_msg_fds(msg, 0) != 0) + return VH_RESULT_ERR; + /* We have to stop the queue (virtio) if it is running. */ vhost_destroy_device_notify(dev); @@ -1346,6 +1419,9 @@ vhost_user_set_vring_enable(struct virtio_net **pdev, struct rte_vdpa_device *vdpa_dev; int did = -1; + if (validate_msg_fds(msg, 0) != 0) + return VH_RESULT_ERR; + RTE_LOG(INFO, VHOST_CONFIG, "set queue enable: %d to qp idx: %d\n", enable, index); @@ -1376,6 +1452,9 @@ vhost_user_get_protocol_features(struct virtio_net **pdev, struct virtio_net *dev = *pdev; uint64_t features, protocol_features; + if (validate_msg_fds(msg, 0) != 0) + return VH_RESULT_ERR; + rte_vhost_driver_get_features(dev->ifname, &features); rte_vhost_driver_get_protocol_features(dev->ifname, &protocol_features); @@ -1404,6 +1483,9 @@ vhost_user_set_protocol_features(struct virtio_net **pdev, uint64_t protocol_features = msg->payload.u64; uint64_t slave_protocol_features = 0; + if (validate_msg_fds(msg, 0) != 0) + return VH_RESULT_ERR; + rte_vhost_driver_get_protocol_features(dev->ifname, &slave_protocol_features); if (protocol_features & ~slave_protocol_features) { @@ -1427,6 +1509,9 @@ vhost_user_set_log_base(struct virtio_net **pdev, struct VhostUserMsg *msg, uint64_t size, off; void *addr; + if (validate_msg_fds(msg, 1) != 0) + return VH_RESULT_ERR; + if (fd < 0) { RTE_LOG(ERR, VHOST_CONFIG, "invalid log fd: %d\n", fd); return VH_RESULT_ERR; @@ -1490,6 +1575,9 @@ static int vhost_user_set_log_fd(struct virtio_net **pdev __rte_unused, struct VhostUserMsg *msg, int main_fd __rte_unused) { + if (validate_msg_fds(msg, 1) != 0) + return VH_RESULT_ERR; + close(msg->fds[0]); RTE_LOG(INFO, VHOST_CONFIG, "not implemented.\n"); @@ -1513,6 +1601,9 @@ vhost_user_send_rarp(struct virtio_net **pdev, struct VhostUserMsg *msg, struct rte_vdpa_device *vdpa_dev; int did = -1; + if (validate_msg_fds(msg, 0) != 0) + return VH_RESULT_ERR; + RTE_LOG(DEBUG, VHOST_CONFIG, ":: mac: %02x:%02x:%02x:%02x:%02x:%02x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); @@ -1540,6 +1631,10 @@ vhost_user_net_set_mtu(struct virtio_net **pdev, struct VhostUserMsg *msg, int main_fd __rte_unused) { struct virtio_net *dev = *pdev; + + if (validate_msg_fds(msg, 0) != 0) + return VH_RESULT_ERR; + if (msg->payload.u64 < VIRTIO_MIN_MTU || msg->payload.u64 > VIRTIO_MAX_MTU) { RTE_LOG(ERR, VHOST_CONFIG, "Invalid MTU size (%"PRIu64")\n", @@ -1560,6 +1655,9 @@ vhost_user_set_req_fd(struct virtio_net **pdev, struct VhostUserMsg *msg, struct virtio_net *dev = *pdev; int fd = msg->fds[0]; + if (validate_msg_fds(msg, 1) != 0) + return VH_RESULT_ERR; + if (fd < 0) { RTE_LOG(ERR, VHOST_CONFIG, "Invalid file descriptor for slave channel (%d)\n", @@ -1630,6 +1728,9 @@ vhost_user_iotlb_msg(struct virtio_net **pdev, struct VhostUserMsg *msg, uint16_t i; uint64_t vva, len; + if (validate_msg_fds(msg, 0) != 0) + return VH_RESULT_ERR; + switch (imsg->type) { case VHOST_IOTLB_UPDATE: len = imsg->size; @@ -1676,6 +1777,9 @@ vhost_user_set_postcopy_advise(struct virtio_net **pdev, #ifdef RTE_LIBRTE_VHOST_POSTCOPY struct uffdio_api api_struct; + if (validate_msg_fds(msg, 0) != 0) + return VH_RESULT_ERR; + dev->postcopy_ufd = syscall(__NR_userfaultfd, O_CLOEXEC | O_NONBLOCK); if (dev->postcopy_ufd == -1) { @@ -1711,6 +1815,9 @@ vhost_user_set_postcopy_listen(struct virtio_net **pdev, { struct virtio_net *dev = *pdev; + if (validate_msg_fds(msg, 0) != 0) + return VH_RESULT_ERR; + if (dev->mem && dev->mem->nregions) { RTE_LOG(ERR, VHOST_CONFIG, "Regions already registered at postcopy-listen\n"); @@ -1727,6 +1834,9 @@ vhost_user_postcopy_end(struct virtio_net **pdev, struct VhostUserMsg *msg, { struct virtio_net *dev = *pdev; + if (validate_msg_fds(msg, 0) != 0) + return VH_RESULT_ERR; + dev->postcopy_listening = 0; if (dev->postcopy_ufd >= 0) { close(dev->postcopy_ufd); -- 2.21.0 ++++++ dpdk-18.11.2.tar.xz -> dpdk-18.11.3.tar.xz ++++++ /work/SRC/openSUSE:Factory/dpdk/dpdk-18.11.2.tar.xz /work/SRC/openSUSE:Factory/.dpdk.new.26869/dpdk-18.11.3.tar.xz differ: char 26, line 1
