Received: by 2002:a25:8b12:0:0:0:0:0 with SMTP id i18csp236195ybl; Thu, 22 Aug 2019 23:34:40 -0700 (PDT) X-Google-Smtp-Source: APXvYqy8Yp2pgNk8z6tPv8aOkY6ITO57WNtVYo2OXqe2F0tTnd9uO5CGDo3LLSN6FO+h0kIsk16J X-Received: by 2002:a62:e109:: with SMTP id q9mr3413965pfh.71.1566542080047; Thu, 22 Aug 2019 23:34:40 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1566542080; cv=none; d=google.com; s=arc-20160816; b=MGtwIOzE7ZCVitl4LjuPGonHjXcE35UqSmOynVp9Rz4bmTw2rmnxfDtzfQni5hFB3G o/dFagVUFWvXXweArUALJbfv6SIK9EeC3ARo4db0dWgNeGL2JlrFav3gjX7f3O2d6FsR sIXL6Og5kTyoR1hI+E9Cm/jplf+VpdJxfr/6j9RKNCIFV5v8lD75AoRSPuSCrJpgwayU mPRTU2WqjHsam4XBT0FhWwayFJ8qqNzWX8wwytgev3s2wfk+RswK+mzhO3pahh2hp0en +2/XP3KiIhdlQ0Q5lguSH4s0NAs8x8vRVD03whvk1I+FoJfN4drsEM77A83rk8SxXtxG VVmw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=FiUaVsNBosw44Fn33CogW96HoeCLDJuvHTbLIaURI7s=; b=dmtq6N3dVhSrmJ7c3WegTKFiaHE7ypZuJlwBfmRzN2CYQHpFbDu/8vAsolSfZ62UkF aM+T6fd+1dLu0Nn25d9DlBFHjRf+B7yWZB0F3cpGzHNPvCfPUJyxZPJfb+ow7LL/RgXI SxeMlIrNOfAjSyGH27K0zR4M1ChHJUBToccGT2D99xJhAavC23T1kfw3EJEG6wV1Xpe0 Sm5nB8AkVK36GmZmPmNQK1P8SVDtc7eCn++ypJS4v1Kwno5b5ecWXO/KimDnBPExzziR ZB6gzXgrR6zqQAve0vYRK4a1ztV500K1ph13/2SYyeIMQrK9l9fVyAQ54ylPlHgkR8e3 nTAA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=dDSx5+Pg; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id o31si1212537pgb.579.2019.08.22.23.34.24; Thu, 22 Aug 2019 23:34:40 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=dDSx5+Pg; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2405457AbfHVRnA (ORCPT + 99 others); Thu, 22 Aug 2019 13:43:00 -0400 Received: from mail.kernel.org ([198.145.29.99]:44100 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2403996AbfHVRXn (ORCPT ); Thu, 22 Aug 2019 13:23:43 -0400 Received: from localhost (wsip-184-188-36-2.sd.sd.cox.net [184.188.36.2]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 4BD2023427; Thu, 22 Aug 2019 17:23:42 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1566494622; bh=gYalicMEIuy46kAjTuIZB5boLoqYysoGmjEG9YvgiJU=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=dDSx5+PgeifCDvDoaKcQ0wc/pYwpB11i9AgkwnFZSinPjNtB3IihKWzg0VWZEbC8n EotmrXR+Ne0ZJgObi8tu+GkR0g6B1Opi47CeYZeVKV16VGbT1KhhZBVd5Fek6hgQpc Z7J7XNIEGxhN5py7tGsGyH37rsERKivauJpYzd84= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Jason Wang , Stefan Hajnoczi , "Michael S. Tsirkin" , Ben Hutchings Subject: [PATCH 4.9 052/103] vhost_net: fix possible infinite loop Date: Thu, 22 Aug 2019 10:18:40 -0700 Message-Id: <20190822171730.905236089@linuxfoundation.org> X-Mailer: git-send-email 2.23.0 In-Reply-To: <20190822171728.445189830@linuxfoundation.org> References: <20190822171728.445189830@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Jason Wang commit e2412c07f8f3040593dfb88207865a3cd58680c0 upstream. When the rx buffer is too small for a packet, we will discard the vq descriptor and retry it for the next packet: while ((sock_len = vhost_net_rx_peek_head_len(net, sock->sk, &busyloop_intr))) { ... /* On overrun, truncate and discard */ if (unlikely(headcount > UIO_MAXIOV)) { iov_iter_init(&msg.msg_iter, READ, vq->iov, 1, 1); err = sock->ops->recvmsg(sock, &msg, 1, MSG_DONTWAIT | MSG_TRUNC); pr_debug("Discarded rx packet: len %zd\n", sock_len); continue; } ... } This makes it possible to trigger a infinite while..continue loop through the co-opreation of two VMs like: 1) Malicious VM1 allocate 1 byte rx buffer and try to slow down the vhost process as much as possible e.g using indirect descriptors or other. 2) Malicious VM2 generate packets to VM1 as fast as possible Fixing this by checking against weight at the end of RX and TX loop. This also eliminate other similar cases when: - userspace is consuming the packets in the meanwhile - theoretical TOCTOU attack if guest moving avail index back and forth to hit the continue after vhost find guest just add new buffers This addresses CVE-2019-3900. Fixes: d8316f3991d20 ("vhost: fix total length when packets are too short") Fixes: 3a4d5c94e9593 ("vhost_net: a kernel-level virtio server") Signed-off-by: Jason Wang Reviewed-by: Stefan Hajnoczi Signed-off-by: Michael S. Tsirkin [bwh: Backported to 4.9: - Both Tx modes are handled in one loop in handle_tx() - Adjust context] Signed-off-by: Ben Hutchings Signed-off-by: Greg Kroah-Hartman --- drivers/vhost/net.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) --- a/drivers/vhost/net.c +++ b/drivers/vhost/net.c @@ -393,7 +393,7 @@ static void handle_tx(struct vhost_net * hdr_size = nvq->vhost_hlen; zcopy = nvq->ubufs; - for (;;) { + do { /* Release DMAs done buffers first */ if (zcopy) vhost_zerocopy_signal_used(net, vq); @@ -481,10 +481,7 @@ static void handle_tx(struct vhost_net * vhost_zerocopy_signal_used(net, vq); total_len += len; vhost_net_tx_packet(net); - if (unlikely(vhost_exceeds_weight(vq, ++sent_pkts, - total_len))) - break; - } + } while (likely(!vhost_exceeds_weight(vq, ++sent_pkts, total_len))); out: mutex_unlock(&vq->mutex); } @@ -682,7 +679,10 @@ static void handle_rx(struct vhost_net * vq->log : NULL; mergeable = vhost_has_feature(vq, VIRTIO_NET_F_MRG_RXBUF); - while ((sock_len = vhost_net_rx_peek_head_len(net, sock->sk))) { + do { + sock_len = vhost_net_rx_peek_head_len(net, sock->sk); + if (!sock_len) + break; sock_len += sock_hlen; vhost_len = sock_len + vhost_hlen; headcount = get_rx_bufs(vq, vq->heads, vhost_len, @@ -761,10 +761,10 @@ static void handle_rx(struct vhost_net * vhost_log_write(vq, vq_log, log, vhost_len, vq->iov, in); total_len += vhost_len; - if (unlikely(vhost_exceeds_weight(vq, ++recv_pkts, total_len))) - goto out; - } - vhost_net_enable_vq(net, vq); + } while (likely(!vhost_exceeds_weight(vq, ++recv_pkts, total_len))); + + if (!sock_len) + vhost_net_enable_vq(net, vq); out: mutex_unlock(&vq->mutex); } @@ -834,7 +834,7 @@ static int vhost_net_open(struct inode * n->vqs[i].sock_hlen = 0; } vhost_dev_init(dev, vqs, VHOST_NET_VQ_MAX, - VHOST_NET_WEIGHT, VHOST_NET_PKT_WEIGHT); + VHOST_NET_PKT_WEIGHT, VHOST_NET_WEIGHT); vhost_poll_init(n->poll + VHOST_NET_VQ_TX, handle_tx_net, POLLOUT, dev); vhost_poll_init(n->poll + VHOST_NET_VQ_RX, handle_rx_net, POLLIN, dev);