From 1407b0752eee2353160701d0182c7e911ccb538a Mon Sep 17 00:00:00 2001 From: Zhike Wang Date: Wed, 13 Nov 2019 19:03:28 +0800 Subject: [PATCH] vhost: fix vring requests validation broken if no FD When VHOST_USER_VRING_NOFD_MASK is set, the fd_num is 0, so validate_msg_fds() will return error. In this case, the negotiation of vring message between vhost user front end and back end would fail, and as a result, vhost user link could NOT be up. How to reproduce: 1.Run dpdk testpmd insides VM, which locates at host with ovs+dpdk. 2.Notice that inside ovs there are endless logs regarding failure to handle VHOST_USER_SET_VRING_CALL, and link of vm could NOT be up. Fixes: bf472259dde6 ("vhost: fix possible denial of service by leaking FDs") Cc: stable@dpdk.org Signed-off-by: Zhike Wang Reviewed-by: Maxime Coquelin Reviewed-by: Tiwei Bie --- lib/librte_vhost/vhost_user.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/lib/librte_vhost/vhost_user.c b/lib/librte_vhost/vhost_user.c index 90ecee1977..0cfb8b792b 100644 --- a/lib/librte_vhost/vhost_user.c +++ b/lib/librte_vhost/vhost_user.c @@ -1563,8 +1563,10 @@ vhost_user_set_vring_call(struct virtio_net **pdev, struct VhostUserMsg *msg, struct virtio_net *dev = *pdev; struct vhost_vring_file file; struct vhost_virtqueue *vq; + int expected_fds; - if (validate_msg_fds(msg, 1) != 0) + expected_fds = (msg->payload.u64 & VHOST_USER_VRING_NOFD_MASK) ? 0 : 1; + if (validate_msg_fds(msg, expected_fds) != 0) return RTE_VHOST_MSG_RESULT_ERR; file.index = msg->payload.u64 & VHOST_USER_VRING_IDX_MASK; @@ -1588,7 +1590,10 @@ 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) + int expected_fds; + + expected_fds = (msg->payload.u64 & VHOST_USER_VRING_NOFD_MASK) ? 0 : 1; + if (validate_msg_fds(msg, expected_fds) != 0) return RTE_VHOST_MSG_RESULT_ERR; if (!(msg->payload.u64 & VHOST_USER_VRING_NOFD_MASK)) @@ -1790,8 +1795,10 @@ vhost_user_set_vring_kick(struct virtio_net **pdev, struct VhostUserMsg *msg, struct virtio_net *dev = *pdev; struct vhost_vring_file file; struct vhost_virtqueue *vq; + int expected_fds; - if (validate_msg_fds(msg, 1) != 0) + expected_fds = (msg->payload.u64 & VHOST_USER_VRING_NOFD_MASK) ? 0 : 1; + if (validate_msg_fds(msg, expected_fds) != 0) return RTE_VHOST_MSG_RESULT_ERR; file.index = msg->payload.u64 & VHOST_USER_VRING_IDX_MASK; -- 2.20.1