Yuchen Lin 2020-05-23 15:26:53 +00:00 committed by Git OBS Bridge
commit c055aa2abd
14 changed files with 505 additions and 502 deletions

View File

@ -0,0 +1,73 @@
From e2950fec9cd9c235a7847ed97b6914174857bf93 Mon Sep 17 00:00:00 2001
From: "mvarlese@suse.de" <mvarlese@suse.de>
Date: Wed, 29 Apr 2020 12:24:16 +0200
Subject: [PATCH] fix cpu compatibility
---
drivers/bus/vdev/vdev.c | 4 ++++
lib/librte_eal/common/eal_common_bus.c | 5 ++++-
lib/librte_eal/common/include/rte_common.h | 14 +++++++++++++-
3 files changed, 21 insertions(+), 2 deletions(-)
diff --git a/drivers/bus/vdev/vdev.c b/drivers/bus/vdev/vdev.c
index a89ea2353..cf8e8dca6 100644
--- a/drivers/bus/vdev/vdev.c
+++ b/drivers/bus/vdev/vdev.c
@@ -55,7 +55,11 @@ static struct vdev_custom_scans vdev_custom_scans =
static rte_spinlock_t vdev_custom_scan_lock = RTE_SPINLOCK_INITIALIZER;
/* register a driver */
+#if defined(__x86_64__) || defined(__i386__)
+void __attribute__((target ("sse2")))
+#else
void
+#endif
rte_vdev_register(struct rte_vdev_driver *driver)
{
TAILQ_INSERT_TAIL(&vdev_driver_list, driver, next);
diff --git a/lib/librte_eal/common/eal_common_bus.c b/lib/librte_eal/common/eal_common_bus.c
index baa5b532a..58f3fdbaa 100644
--- a/lib/librte_eal/common/eal_common_bus.c
+++ b/lib/librte_eal/common/eal_common_bus.c
@@ -15,8 +15,11 @@
static struct rte_bus_list rte_bus_list =
TAILQ_HEAD_INITIALIZER(rte_bus_list);
-
+#if defined(__x86_64__) || defined(__i386__)
+void __attribute__((target ("sse2")))
+#else
void
+#endif
rte_bus_register(struct rte_bus *bus)
{
RTE_VERIFY(bus);
diff --git a/lib/librte_eal/common/include/rte_common.h b/lib/librte_eal/common/include/rte_common.h
index c35283807..8f4f98ed4 100644
--- a/lib/librte_eal/common/include/rte_common.h
+++ b/lib/librte_eal/common/include/rte_common.h
@@ -107,8 +107,20 @@ typedef uint16_t unaligned_uint16_t;
* Lowest number is the first to run.
*/
#ifndef RTE_INIT_PRIO /* Allow to override from EAL */
+#if defined(__x86_64__) || defined(__i386__)
#define RTE_INIT_PRIO(func, prio) \
-static void __attribute__((constructor(RTE_PRIO(prio)), used)) func(void)
+static void \
+ __attribute__((constructor(RTE_PRIO(prio)), used)) \
+ __attribute__((target ("sse2"))) \
+ __attribute__((target ("no-sse3"))) \
+ __attribute__((target ("no-sse4"))) \
+ func(void)
+#else
+#define RTE_INIT_PRIO(func, prio) \
+static void \
+ __attribute__((constructor(RTE_PRIO(prio)), used)) \
+ func(void)
+#endif
#endif
/**
--
2.16.4

View File

@ -0,0 +1,49 @@
From 342f6d57f417303b12f86d040b87f27448e4a0ae Mon Sep 17 00:00:00 2001
From: Maxime Coquelin <maxime.coquelin@redhat.com>
Date: Tue, 21 Apr 2020 11:16:56 +0200
Subject: [PATCH 1/6] vhost: check log mmap offset and size overflow
vhost_user_set_log_base() is a message handler that is
called to handle the VHOST_USER_SET_LOG_BASE message.
Its payload contains a 64 bit size and offset. Both are
added up and used as a size when calling mmap().
There is no integer overflow check. If an integer overflow
occurs a smaller memory map would be created than
requested. Since the returned mapping is mapped as writable
and used for logging, a memory corruption could occur.
Fixes: fbc4d248b198 ("vhost: fix offset while mmaping log base address")
Cc: stable@dpdk.org
This issue has been assigned CVE-2020-10722
Reported-by: Ilja Van Sprundel <ivansprundel@ioactive.com>
Signed-off-by: Maxime Coquelin <maxime.coquelin@redhat.com>
Reviewed-by: Xiaolong Ye <xiaolong.ye@intel.com>
Reviewed-by: Ilja Van Sprundel <ivansprundel@ioactive.com>
---
lib/librte_vhost/vhost_user.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/lib/librte_vhost/vhost_user.c b/lib/librte_vhost/vhost_user.c
index 40c4520c08..02962fcdbc 100644
--- a/lib/librte_vhost/vhost_user.c
+++ b/lib/librte_vhost/vhost_user.c
@@ -2059,10 +2059,10 @@ vhost_user_set_log_base(struct virtio_net **pdev, struct VhostUserMsg *msg,
size = msg->payload.log.mmap_size;
off = msg->payload.log.mmap_offset;
- /* Don't allow mmap_offset to point outside the mmap region */
- if (off > size) {
+ /* Check for mmap size and offset overflow. */
+ if (off >= -size) {
RTE_LOG(ERR, VHOST_CONFIG,
- "log offset %#"PRIx64" exceeds log size %#"PRIx64"\n",
+ "log offset %#"PRIx64" and log size %#"PRIx64" overflow\n",
off, size);
return RTE_VHOST_MSG_RESULT_ERR;
}
--
2.25.2

View File

@ -1,65 +0,0 @@
From f110daae0d7d033db151d2791f6555546d5144ac Mon Sep 17 00:00:00 2001
From: Maxime Coquelin <maxime.coquelin@redhat.com>
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 <jasowang@redhat.com>
Signed-off-by: Maxime Coquelin <maxime.coquelin@redhat.com>
---
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

View File

@ -1,60 +0,0 @@
From: mvarlese@suse.de
diff -Nuar dpdk-18.11.old/drivers/bus/vdev/vdev.c dpdk-18.11/drivers/bus/vdev/vdev.c
--- dpdk-18.11.old/drivers/bus/vdev/vdev.c 2019-02-20 14:26:48.849061397 +0100
+++ dpdk-18.11/drivers/bus/vdev/vdev.c 2019-02-20 14:33:12.638554838 +0100
@@ -55,7 +55,11 @@
static rte_spinlock_t vdev_custom_scan_lock = RTE_SPINLOCK_INITIALIZER;
/* register a driver */
+#if defined(__x86_64__) || defined(__i386__)
+void __attribute__((target ("sse2")))
+#else
void
+#endif
rte_vdev_register(struct rte_vdev_driver *driver)
{
TAILQ_INSERT_TAIL(&vdev_driver_list, driver, next);
diff -Nuar dpdk-18.11.old/lib/librte_eal/common/eal_common_bus.c dpdk-18.11/lib/librte_eal/common/eal_common_bus.c
--- dpdk-18.11.old/lib/librte_eal/common/eal_common_bus.c 2019-02-20 14:26:48.801061210 +0100
+++ dpdk-18.11/lib/librte_eal/common/eal_common_bus.c 2019-02-20 14:28:52.933544223 +0100
@@ -43,8 +43,11 @@
static struct rte_bus_list rte_bus_list =
TAILQ_HEAD_INITIALIZER(rte_bus_list);
-
+#if defined(__x86_64__) || defined(__i386__)
+void __attribute__((target ("sse2")))
+#else
void
+#endif
rte_bus_register(struct rte_bus *bus)
{
RTE_VERIFY(bus);
diff -Nuar dpdk-18.11.old/lib/librte_eal/common/include/rte_common.h dpdk-18.11/lib/librte_eal/common/include/rte_common.h
--- dpdk-18.11.old/lib/librte_eal/common/include/rte_common.h 2019-02-20 14:26:48.809061243 +0100
+++ dpdk-18.11/lib/librte_eal/common/include/rte_common.h 2019-02-20 14:51:56.275496936 +0100
@@ -103,8 +103,21 @@
* Priority number must be above 100.
* Lowest number is the first to run.
*/
+#if defined(__x86_64__) || defined(__i386__)
#define RTE_INIT_PRIO(func, prio) \
-static void __attribute__((constructor(RTE_PRIO(prio)), used)) func(void)
+static void \
+ __attribute__((constructor(RTE_PRIO(prio)), used)) \
+ __attribute__((target ("sse2"))) \
+ __attribute__((target ("no-sse3"))) \
+ __attribute__((target ("no-sse4"))) \
+ func(void)
+#else
+#define RTE_INIT_PRIO(func, prio) \
+static void \
+ __attribute__((constructor(RTE_PRIO(prio)), used)) \
+ func(void)
+#endif
+
/**
* Run function before main() with low priority.

View File

@ -1,344 +0,0 @@
From 8accec7a78708ee8ece4550e370d32ccdff4dee8 Mon Sep 17 00:00:00 2001
From: Maxime Coquelin <maxime.coquelin@redhat.com>
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 <maxime.coquelin@redhat.com>
---
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

View File

@ -0,0 +1,58 @@
From 7e74c33644452051cc4193fd2516d97e1e4009e0 Mon Sep 17 00:00:00 2001
From: Maxime Coquelin <maxime.coquelin@redhat.com>
Date: Tue, 21 Apr 2020 18:17:43 +0200
Subject: [PATCH 2/6] vhost: fix vring index check
vhost_user_check_and_alloc_queue_pair() is used to extract
a vring index from a payload. This function validates the
index and is called early on in when performing message
handling. Most message handlers depend on it correctly
validating the vring index.
Depending on the message type the vring index is in
different parts of the payload. The function contains a
switch/case for each type and copies the index. This is
stored in a uint16. This index is then validated. Depending
on the message, the source index is an unsigned int. If
integer truncation occurs (uint->uint16) the top 16 bits
of the index are never validated.
When they are used later on (e.g. in
vhost_user_set_vring_num() or vhost_user_set_vring_addr())
it can lead to out of bound indexing. The out of bound
indexed data gets written to, and hence this can cause
memory corruption.
This patch fixes this vulnerability by declaring vring
index as an unsigned int in
vhost_user_check_and_alloc_queue_pair().
Fixes: 160cbc815b41 ("vhost: remove a hack on queue allocation")
Cc: stable@dpdk.org
This issue has been assigned CVE-2020-10723
Reported-by: Ilja Van Sprundel <ivansprundel@ioactive.com>
Signed-off-by: Maxime Coquelin <maxime.coquelin@redhat.com>
Reviewed-by: Xiaolong Ye <xiaolong.ye@intel.com>
Reviewed-by: Ilja Van Sprundel <ivansprundel@ioactive.com>
---
lib/librte_vhost/vhost_user.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/librte_vhost/vhost_user.c b/lib/librte_vhost/vhost_user.c
index 02962fcdbc..d19614265b 100644
--- a/lib/librte_vhost/vhost_user.c
+++ b/lib/librte_vhost/vhost_user.c
@@ -2526,7 +2526,7 @@ static int
vhost_user_check_and_alloc_queue_pair(struct virtio_net *dev,
struct VhostUserMsg *msg)
{
- uint16_t vring_idx;
+ uint32_t vring_idx;
switch (msg->request.master) {
case VHOST_USER_SET_VRING_KICK:
--
2.25.2

View File

@ -0,0 +1,77 @@
From 5216718e4837d4dcc6020cd5f6d5d629222bad8c Mon Sep 17 00:00:00 2001
From: Maxime Coquelin <maxime.coquelin@redhat.com>
Date: Tue, 21 Apr 2020 19:10:09 +0200
Subject: [PATCH 3/6] vhost/crypto: validate keys lengths
transform_cipher_param() and transform_chain_param() handle
the payload data for the VHOST_USER_CRYPTO_CREATE_SESS
message. These payloads have to be validated, since it
could come from untrusted sources.
Two buffers and their lenghts are defined in this payload,
one the the auth key and one for the cipher key. But above
functions do not validate the key length inputs, which could
lead to read out of bounds, as buffers have static sizes of
64 bytes for the cipher key and 512 bytes for the auth key.
This patch adds necessary checks on the key length field
before being used.
Fixes: e80a98708166 ("vhost/crypto: add session message handler")
Cc: stable@dpdk.org
This issue has been assigned CVE-2020-10724
Reported-by: Ilja Van Sprundel <ivansprundel@ioactive.com>
Signed-off-by: Maxime Coquelin <maxime.coquelin@redhat.com>
Reviewed-by: Xiaolong Ye <xiaolong.ye@intel.com>
Reviewed-by: Ilja Van Sprundel <ivansprundel@ioactive.com>
---
lib/librte_vhost/vhost_crypto.c | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/lib/librte_vhost/vhost_crypto.c b/lib/librte_vhost/vhost_crypto.c
index 68911972b6..07a4115482 100644
--- a/lib/librte_vhost/vhost_crypto.c
+++ b/lib/librte_vhost/vhost_crypto.c
@@ -237,6 +237,11 @@ transform_cipher_param(struct rte_crypto_sym_xform *xform,
if (unlikely(ret < 0))
return ret;
+ if (param->cipher_key_len > VHOST_USER_CRYPTO_MAX_CIPHER_KEY_LENGTH) {
+ VC_LOG_DBG("Invalid cipher key length\n");
+ return -VIRTIO_CRYPTO_BADMSG;
+ }
+
xform->type = RTE_CRYPTO_SYM_XFORM_CIPHER;
xform->cipher.key.length = param->cipher_key_len;
if (xform->cipher.key.length > 0)
@@ -287,6 +292,12 @@ transform_chain_param(struct rte_crypto_sym_xform *xforms,
&xform_cipher->cipher.algo);
if (unlikely(ret < 0))
return ret;
+
+ if (param->cipher_key_len > VHOST_USER_CRYPTO_MAX_CIPHER_KEY_LENGTH) {
+ VC_LOG_DBG("Invalid cipher key length\n");
+ return -VIRTIO_CRYPTO_BADMSG;
+ }
+
xform_cipher->type = RTE_CRYPTO_SYM_XFORM_CIPHER;
xform_cipher->cipher.key.length = param->cipher_key_len;
xform_cipher->cipher.key.data = param->cipher_key_buf;
@@ -301,6 +312,12 @@ transform_chain_param(struct rte_crypto_sym_xform *xforms,
ret = auth_algo_transform(param->hash_algo, &xform_auth->auth.algo);
if (unlikely(ret < 0))
return ret;
+
+ if (param->auth_key_len > VHOST_USER_CRYPTO_MAX_HMAC_KEY_LENGTH) {
+ VC_LOG_DBG("Invalid auth key length\n");
+ return -VIRTIO_CRYPTO_BADMSG;
+ }
+
xform_auth->auth.digest_length = param->digest_len;
xform_auth->auth.key.length = param->auth_key_len;
xform_auth->auth.key.data = param->auth_key_buf;
--
2.25.2

View File

@ -0,0 +1,46 @@
From c74f5a29dbb505bb31bec932a9bd77325e2ceea6 Mon Sep 17 00:00:00 2001
From: Marvin Liu <yong.liu@intel.com>
Date: Wed, 8 Apr 2020 17:13:55 +0800
Subject: [PATCH 4/6] vhost: fix translated address not checked
Malicious guest can construct desc with invalid address and zero buffer
length. That will request vhost to check both translated address and
translated data length. This patch will add missed address check.
Fixes: 75ed51697820 ("vhost: add packed ring batch dequeue")
Fixes: ef861692c398 ("vhost: add packed ring batch enqueue")
Cc: stable@dpdk.org
This issue has been assigned CVE-2020-10725
Signed-off-by: Marvin Liu <yong.liu@intel.com>
Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>
---
lib/librte_vhost/virtio_net.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/lib/librte_vhost/virtio_net.c b/lib/librte_vhost/virtio_net.c
index ac2842b2d2..33f10258cf 100644
--- a/lib/librte_vhost/virtio_net.c
+++ b/lib/librte_vhost/virtio_net.c
@@ -1086,6 +1086,8 @@ virtio_dev_rx_batch_packed(struct virtio_net *dev,
VHOST_ACCESS_RW);
vhost_for_each_try_unroll(i, 0, PACKED_BATCH_SIZE) {
+ if (unlikely(!desc_addrs[i]))
+ return -1;
if (unlikely(lens[i] != descs[avail_idx + i].len))
return -1;
}
@@ -1841,6 +1843,8 @@ vhost_reserve_avail_batch_packed(struct virtio_net *dev,
}
vhost_for_each_try_unroll(i, 0, PACKED_BATCH_SIZE) {
+ if (unlikely(!desc_addrs[i]))
+ return -1;
if (unlikely((lens[i] != descs[avail_idx + i].len)))
return -1;
}
--
2.25.2

View File

@ -0,0 +1,52 @@
From 9566391031723e854e818bb7d965e9e677784dc4 Mon Sep 17 00:00:00 2001
From: Xiaolong Ye <xiaolong.ye@intel.com>
Date: Wed, 8 Apr 2020 15:31:35 +0800
Subject: [PATCH 5/6] vhost: fix potential memory space leak
A malicious container which has direct access to the vhost-user socket
can keep sending VHOST_USER_GET_INFLIGHT_FD messages which may cause
leaking resources until resulting a DOS. Fix it by unmapping the
dev->inflight_info->addr before assigning new mapped addr to it.
Fixes: d87f1a1cb7b6 ("vhost: support inflight info sharing")
Cc: stable@dpdk.org
This issue has been assigned CVE-2020-10726
Signed-off-by: Xiaolong Ye <xiaolong.ye@intel.com>
Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>
---
lib/librte_vhost/vhost_user.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/lib/librte_vhost/vhost_user.c b/lib/librte_vhost/vhost_user.c
index d19614265b..2a4ba205cf 100644
--- a/lib/librte_vhost/vhost_user.c
+++ b/lib/librte_vhost/vhost_user.c
@@ -1433,6 +1433,11 @@ vhost_user_get_inflight_fd(struct virtio_net **pdev,
}
memset(addr, 0, mmap_size);
+ if (dev->inflight_info->addr) {
+ munmap(dev->inflight_info->addr, dev->inflight_info->size);
+ dev->inflight_info->addr = NULL;
+ }
+
dev->inflight_info->addr = addr;
dev->inflight_info->size = msg->payload.inflight.mmap_size = mmap_size;
dev->inflight_info->fd = msg->fds[0] = fd;
@@ -1517,8 +1522,10 @@ vhost_user_set_inflight_fd(struct virtio_net **pdev, VhostUserMsg *msg,
}
}
- if (dev->inflight_info->addr)
+ if (dev->inflight_info->addr) {
munmap(dev->inflight_info->addr, dev->inflight_info->size);
+ dev->inflight_info->addr = NULL;
+ }
addr = mmap(0, mmap_size, PROT_READ | PROT_WRITE, MAP_SHARED,
fd, mmap_offset);
--
2.25.2

View File

@ -0,0 +1,80 @@
From 1cb6dbef9c15e739da9b253c53b558e93906c6c5 Mon Sep 17 00:00:00 2001
From: Xuan Ding <xuan.ding@intel.com>
Date: Wed, 8 Apr 2020 10:19:51 +0000
Subject: [PATCH 6/6] vhost: fix potential fd leak
Vhost will create temporary file when receiving VHOST_USER_GET_INFLIGHT_FD
message. Malicious guest can send endless this message to drain out the
resource of host.
When receiving VHOST_USER_GET_INFLIGHT_FD message repeatedly, closing the
file created during the last handling of this message.
Fixes: d87f1a1cb7b666550 ("vhost: support inflight info sharing")
Cc: stable@dpdk.org
This issue has been assigned CVE-2020-10726
Signed-off-by: Xuan Ding <xuan.ding@intel.com>
Signed-off-by: Xiaolong Ye <xiaolong.ye@intel.com>
Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>
---
lib/librte_vhost/vhost_user.c | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/lib/librte_vhost/vhost_user.c b/lib/librte_vhost/vhost_user.c
index 2a4ba205cf..8954f7930e 100644
--- a/lib/librte_vhost/vhost_user.c
+++ b/lib/librte_vhost/vhost_user.c
@@ -206,7 +206,7 @@ vhost_backend_cleanup(struct virtio_net *dev)
dev->inflight_info->addr = NULL;
}
- if (dev->inflight_info->fd > 0) {
+ if (dev->inflight_info->fd >= 0) {
close(dev->inflight_info->fd);
dev->inflight_info->fd = -1;
}
@@ -1408,6 +1408,7 @@ vhost_user_get_inflight_fd(struct virtio_net **pdev,
"failed to alloc dev inflight area\n");
return RTE_VHOST_MSG_RESULT_ERR;
}
+ dev->inflight_info->fd = -1;
}
num_queues = msg->payload.inflight.num_queues;
@@ -1438,6 +1439,11 @@ vhost_user_get_inflight_fd(struct virtio_net **pdev,
dev->inflight_info->addr = NULL;
}
+ if (dev->inflight_info->fd >= 0) {
+ close(dev->inflight_info->fd);
+ dev->inflight_info->fd = -1;
+ }
+
dev->inflight_info->addr = addr;
dev->inflight_info->size = msg->payload.inflight.mmap_size = mmap_size;
dev->inflight_info->fd = msg->fds[0] = fd;
@@ -1520,6 +1526,7 @@ vhost_user_set_inflight_fd(struct virtio_net **pdev, VhostUserMsg *msg,
"failed to alloc dev inflight area\n");
return RTE_VHOST_MSG_RESULT_ERR;
}
+ dev->inflight_info->fd = -1;
}
if (dev->inflight_info->addr) {
@@ -1534,8 +1541,10 @@ vhost_user_set_inflight_fd(struct virtio_net **pdev, VhostUserMsg *msg,
return RTE_VHOST_MSG_RESULT_ERR;
}
- if (dev->inflight_info->fd)
+ if (dev->inflight_info->fd >= 0) {
close(dev->inflight_info->fd);
+ dev->inflight_info->fd = -1;
+ }
dev->inflight_info->fd = fd;
dev->inflight_info->addr = addr;
--
2.25.2

View File

@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:e525d094379c0f9d29de82b9c611412f69d88b42829967e3201b4236d4edb6b1
size 11377388

3
dpdk-19.11.1.tar.xz Normal file
View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:4d7f8e854d00f67297e8d22ae358d64528e9ad4b7c9a9b886453026b07f52e6e
size 12396260

View File

@ -1,3 +1,31 @@
-------------------------------------------------------------------
Tue May 19 11:41:34 UTC 2020 - Jaime Caamaño Ruiz <jcaamano@suse.com>
- Add patches to fix vulnerability where malicious guest/container can
cause resource leak resulting a Denial-of-Service, or memory corruption
and crash, or information leak in vhost-user backend application
(bsc#1171477, CVE-2020-10722, CVE-2020-10723, CVE-2020-10724,
CVE-2020-10725, CVE-2020-10726).
* 0001-vhost-check-log-mmap-offset-and-size-overflow.patch
* 0002-vhost-fix-vring-index-check.patch
* 0003-vhost-crypto-validate-keys-lengths.patch
* 0004-vhost-fix-translated-address-not-checked.patch
* 0005-vhost-fix-potential-memory-space-leak.patch
* 0006-vhost-fix-potential-fd-leak.patch
-------------------------------------------------------------------
Wed Apr 29 11:45:24 UTC 2020 - Jaime Caamaño Ruiz <jcaamano@suse.com>
- Update to v19.11.1. For a list of changes, check:
* https://doc.dpdk.org/guides/rel_notes/release_19_11.html#new-features
- Removed patches no longer applying to the code base:
* 0001-vhost-fix-possible-denial-of-service-on-SET_VRING_NU.patch
* 0002-vhost-fix-possible-denial-of-service-by-leaking-FDs.patch
* 0002-fix-cpu-compatibility.patch
- Rebased patches:
* 0001-fix-cpu-compatibility.patch
-------------------------------------------------------------------
Mon Mar 2 10:25:12 UTC 2020 - Stefan Weiberg <sweiberg@suse.com>

View File

@ -1,7 +1,7 @@
#
# spec file for package dpdk
#
# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany.
# Copyright (c) 2020 SUSE LLC
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
@ -18,19 +18,16 @@
%define flavor @BUILD_FLAVOR@%{nil}
%define aarch64_machine2 armv8a
%define exclusive_arch aarch64 x86_64 ppc64le
%define name_tag %{nil}
%define summary_tag %{nil}
%if "%flavor" == "thunderx"
%define name_tag -thunderx
%define summary_tag (thunderx)
%define aarch64_machine2 thunderx
%define exclusive_arch aarch64
%endif
%define machine native
%define machine2 default
%ifarch x86_64
@ -45,30 +42,32 @@
%define machine2 power8
%define target ppc_64-%{machine2}-linuxapp-gcc
%endif
# This is in sync with <src>/ABI_VERSION
# TODO: automate this sync
%define maj 20
%define min 0
%define lname libdpdk-%{maj}_%{min}
%bcond_without shared
# Add option to build without examples
%bcond_without examples
# Add option to build without tools
%bcond_without tools
# The lname versioning is based solely on the MAJOR and MINOR
# as per DPDK CONFIG_RTE_MAJOR_ABI.
%define maj 18
%define min 11
%define lname libdpdk-%{maj}_%{min}
Name: dpdk%{name_tag}
Version: 18.11.3
Version: 19.11.1
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
Group: System/Libraries
Url: http://dpdk.org
URL: http://dpdk.org
Source: http://fast.dpdk.org/rel/dpdk-%{version}.tar.xz
Source1: preamble
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
Patch1: 0001-fix-cpu-compatibility.patch
Patch2: 0001-vhost-check-log-mmap-offset-and-size-overflow.patch
Patch3: 0002-vhost-fix-vring-index-check.patch
Patch4: 0003-vhost-crypto-validate-keys-lengths.patch
Patch5: 0004-vhost-fix-translated-address-not-checked.patch
Patch6: 0005-vhost-fix-potential-memory-space-leak.patch
Patch7: 0006-vhost-fix-potential-fd-leak.patch
BuildRequires: doxygen
BuildRequires: fdupes
BuildRequires: libelf-devel
@ -76,13 +75,13 @@ BuildRequires: libmnl-devel
BuildRequires: libnuma-devel
BuildRequires: libpcap-devel
BuildRequires: pesign-obs-integration
BuildRequires: zlib-devel
Conflicts: dpdk-any
Provides: dpdk-any = %{version}
ExclusiveArch: %exclusive_arch
%if 0%{?sle_version} >= 120400
BuildRequires: rdma-core-devel
%endif
BuildRequires: zlib-devel
ExclusiveArch: %exclusive_arch
Provides: dpdk-any = %{version}
Conflicts: otherproviders(dpdk-any)
%description
The Data Plane Development Kit is a set of libraries and drivers for
@ -92,8 +91,8 @@ fast packet processing in the user space.
Summary: Data Plane Development Kit development files %{summary_tag}
Group: Development/Libraries/C and C++
Requires: %{lname} = %{version}
Conflicts: dpdk-any-devel
Provides: dpdk-any-devel = %{version}
Conflicts: otherproviders(dpdk-any-devel)
%description devel
This package contains the headers and other files needed for developing
@ -111,9 +110,9 @@ to use the Data Plane Development Kit.
%package doc
Summary: Data Plane Development Kit API documentation %{summary_tag}
Group: System/Libraries
BuildArch: noarch
Conflicts: dpdk-any-doc
Provides: dpdk-any-doc = %{version}
Conflicts: otherproviders(dpdk-any-doc)
BuildArch: noarch
%description doc
API programming documentation for the Data Plane Development Kit.
@ -127,8 +126,8 @@ Requires: findutils
Requires: iproute
Requires: kmod
Requires: pciutils
Conflicts: dpdk-any-tools
Provides: dpdk-any-tools = %{version}
Conflicts: otherproviders(dpdk-any-tools)
%description tools
This package contains tools for setting up Data Plane Development Kit environment
@ -139,8 +138,8 @@ This package contains tools for setting up Data Plane Development Kit environmen
Summary: Data Plane Development Kit example applications %{summary_tag}
Group: System/Libraries
BuildRequires: libvirt-devel
Conflicts: dpdk-any-examples
Provides: dpdk-any-examples = %{version}
Conflicts: otherproviders(dpdk-any-examples)
%description examples
Example applications utilizing the Data Plane Development Kit, such
@ -151,7 +150,7 @@ as L2 and L3 forwarding.
Summary: DPDK KNI kernel module %{summary_tag}
Group: System/Kernel
BuildRequires: %{kernel_module_package_buildreqs}
Conflicts: otherproviders(dpdk-any-kmp)
Conflicts: dpdk-any-kmp
%suse_kernel_module_package -p %{_sourcedir}/preamble pae 64kb
%description kmp
@ -168,10 +167,17 @@ The DPDK Kernel NIC Interface (KNI) allows userspace applications access to the
%patch1 -p1 -z .init
%patch2 -p1 -z .init
%patch3 -p1 -z .init
%patch4 -p1 -z .init
%patch5 -p1 -z .init
%patch6 -p1 -z .init
%patch7 -p1 -z .init
# This fixes CROSS compilation (broken) in the mk file for ThunderX
sed -i '/^CROSS /s/^/#/' mk/machine/thunderx/rte.vars.mk
# Verify ABI
[ "$(cat ABI_VERSION)" = "%{maj}.%{min}" ] || exit 1
%build
# set up a method for modifying the resulting .config file
function setconf() {
@ -188,16 +194,17 @@ function setdefaultconf()
setconf CONFIG_RTE_LIBRTE_DPAA_BUS n $1
setconf CONFIG_RTE_LIBRTE_DPAA_MEMPOOL n $1
setconf CONFIG_RTE_LIBRTE_DPAA_PMD n $1
setconf CONFIG_RTE_LIBRTE_PMD_CAAM_JR n $1
setconf CONFIG_RTE_LIBRTE_PMD_DPAA_SEC n $1
setconf CONFIG_RTE_LIBRTE_PMD_DPAA_EVENTDEV n $1
%ifarch aarch64
setconf CONFIG_RTE_LIBRTE_PFE_PMD n $1
%endif
setconf CONFIG_RTE_MACHINE '"%{machine2}"' $1
# Disable experimental features
setconf CONFIG_RTE_NEXT_ABI n $1
# SONAME equals to DPDK release version
setconf CONFIG_RTE_MAJOR_ABI %{maj}.%{min} $1
# Enable automatic driver loading from this path
setconf CONFIG_RTE_EAL_PMD_PATH '"%{pmddir}"' $1
@ -268,7 +275,7 @@ export BRP_PESIGN_FILES="*.ko"
for flavor in %{flavors_to_build}; do
cd %{target}-$flavor
export RTE_KERNELDIR=%{_prefix}/src/linux-obj/%{_target_cpu}/$flavor
dir=/usr/src/linux-obj/%{_target_cpu}/$flavor
dir=%{_prefix}/src/linux-obj/%{_target_cpu}/$flavor
krel=$(make -s -C "$dir" kernelrelease)
mkdir -p %{buildroot}/lib/modules/$krel/extra/dpdk/
#make install expects same kernel for build and target, lets copy it manually
@ -350,6 +357,7 @@ ln -s %{_sbindir}/dpdk-devbind %{buildroot}%{_sbindir}/dpdk_nic_bind
# BSD
%{_bindir}/testpmd
%{_bindir}/testbbdev
%{_bindir}/testsad
%{_bindir}/dpdk-procinfo
%{_bindir}/dpdk_proc_info
%{_bindir}/dpdk-pdump
@ -392,6 +400,7 @@ ln -s %{_sbindir}/dpdk-devbind %{buildroot}%{_sbindir}/dpdk_nic_bind
%{_sbindir}/dpdk-devbind
%{_sbindir}/dpdk_nic_bind
%{_bindir}/dpdk-test-eventdev
%{_bindir}/dpdk-test-compress-perf
%{_bindir}/dpdk-test-crypto-perf
%endif