All of lore.kernel.org
 help / color / mirror / Atom feed
From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
To: linux-kernel@vger.kernel.org
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	stable@vger.kernel.org,
	syzbot+e3e074963495f92a89ed@syzkaller.appspotmail.com,
	syzbot+d5a0a170c5069658b141@syzkaller.appspotmail.com,
	Stefan Hajnoczi <stefanha@redhat.com>,
	"Michael S. Tsirkin" <mst@redhat.com>,
	Jason Wang <jasowang@redhat.com>, Sasha Levin <sashal@kernel.org>,
	syzbot+bd391451452fb0b93039@syzkaller.appspotmail.com
Subject: [PATCH 4.9 38/51] vhost/vsock: fix use-after-free in network stack callers
Date: Tue, 11 Dec 2018 16:41:46 +0100	[thread overview]
Message-ID: <20181211151617.160217603@linuxfoundation.org> (raw)
In-Reply-To: <20181211151612.328911565@linuxfoundation.org>

4.9-stable review patch.  If anyone has any objections, please let me know.

------------------

[ Upstream commit 834e772c8db0c6a275d75315d90aba4ebbb1e249 ]

If the network stack calls .send_pkt()/.cancel_pkt() during .release(),
a struct vhost_vsock use-after-free is possible.  This occurs because
.release() does not wait for other CPUs to stop using struct
vhost_vsock.

Switch to an RCU-enabled hashtable (indexed by guest CID) so that
.release() can wait for other CPUs by calling synchronize_rcu().  This
also eliminates vhost_vsock_lock acquisition in the data path so it
could have a positive effect on performance.

This is CVE-2018-14625 "kernel: use-after-free Read in vhost_transport_send_pkt".

Cc: stable@vger.kernel.org
Reported-and-tested-by: syzbot+bd391451452fb0b93039@syzkaller.appspotmail.com
Reported-by: syzbot+e3e074963495f92a89ed@syzkaller.appspotmail.com
Reported-by: syzbot+d5a0a170c5069658b141@syzkaller.appspotmail.com
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Acked-by: Jason Wang <jasowang@redhat.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 drivers/vhost/vsock.c | 57 +++++++++++++++++++++++++------------------
 1 file changed, 33 insertions(+), 24 deletions(-)

diff --git a/drivers/vhost/vsock.c b/drivers/vhost/vsock.c
index 6bca57896915..f800f89068db 100644
--- a/drivers/vhost/vsock.c
+++ b/drivers/vhost/vsock.c
@@ -15,6 +15,7 @@
 #include <net/sock.h>
 #include <linux/virtio_vsock.h>
 #include <linux/vhost.h>
+#include <linux/hashtable.h>
 
 #include <net/af_vsock.h>
 #include "vhost.h"
@@ -27,14 +28,14 @@ enum {
 
 /* Used to track all the vhost_vsock instances on the system. */
 static DEFINE_SPINLOCK(vhost_vsock_lock);
-static LIST_HEAD(vhost_vsock_list);
+static DEFINE_READ_MOSTLY_HASHTABLE(vhost_vsock_hash, 8);
 
 struct vhost_vsock {
 	struct vhost_dev dev;
 	struct vhost_virtqueue vqs[2];
 
-	/* Link to global vhost_vsock_list, protected by vhost_vsock_lock */
-	struct list_head list;
+	/* Link to global vhost_vsock_hash, writes use vhost_vsock_lock */
+	struct hlist_node hash;
 
 	struct vhost_work send_pkt_work;
 	spinlock_t send_pkt_list_lock;
@@ -50,11 +51,14 @@ static u32 vhost_transport_get_local_cid(void)
 	return VHOST_VSOCK_DEFAULT_HOST_CID;
 }
 
-static struct vhost_vsock *__vhost_vsock_get(u32 guest_cid)
+/* Callers that dereference the return value must hold vhost_vsock_lock or the
+ * RCU read lock.
+ */
+static struct vhost_vsock *vhost_vsock_get(u32 guest_cid)
 {
 	struct vhost_vsock *vsock;
 
-	list_for_each_entry(vsock, &vhost_vsock_list, list) {
+	hash_for_each_possible_rcu(vhost_vsock_hash, vsock, hash, guest_cid) {
 		u32 other_cid = vsock->guest_cid;
 
 		/* Skip instances that have no CID yet */
@@ -69,17 +73,6 @@ static struct vhost_vsock *__vhost_vsock_get(u32 guest_cid)
 	return NULL;
 }
 
-static struct vhost_vsock *vhost_vsock_get(u32 guest_cid)
-{
-	struct vhost_vsock *vsock;
-
-	spin_lock_bh(&vhost_vsock_lock);
-	vsock = __vhost_vsock_get(guest_cid);
-	spin_unlock_bh(&vhost_vsock_lock);
-
-	return vsock;
-}
-
 static void
 vhost_transport_do_send_pkt(struct vhost_vsock *vsock,
 			    struct vhost_virtqueue *vq)
@@ -206,9 +199,12 @@ vhost_transport_send_pkt(struct virtio_vsock_pkt *pkt)
 	struct vhost_virtqueue *vq;
 	int len = pkt->len;
 
+	rcu_read_lock();
+
 	/* Find the vhost_vsock according to guest context id  */
 	vsock = vhost_vsock_get(le64_to_cpu(pkt->hdr.dst_cid));
 	if (!vsock) {
+		rcu_read_unlock();
 		virtio_transport_free_pkt(pkt);
 		return -ENODEV;
 	}
@@ -223,6 +219,8 @@ vhost_transport_send_pkt(struct virtio_vsock_pkt *pkt)
 	spin_unlock_bh(&vsock->send_pkt_list_lock);
 
 	vhost_work_queue(&vsock->dev, &vsock->send_pkt_work);
+
+	rcu_read_unlock();
 	return len;
 }
 
@@ -232,12 +230,15 @@ vhost_transport_cancel_pkt(struct vsock_sock *vsk)
 	struct vhost_vsock *vsock;
 	struct virtio_vsock_pkt *pkt, *n;
 	int cnt = 0;
+	int ret = -ENODEV;
 	LIST_HEAD(freeme);
 
+	rcu_read_lock();
+
 	/* Find the vhost_vsock according to guest context id  */
 	vsock = vhost_vsock_get(vsk->remote_addr.svm_cid);
 	if (!vsock)
-		return -ENODEV;
+		goto out;
 
 	spin_lock_bh(&vsock->send_pkt_list_lock);
 	list_for_each_entry_safe(pkt, n, &vsock->send_pkt_list, list) {
@@ -263,7 +264,10 @@ vhost_transport_cancel_pkt(struct vsock_sock *vsk)
 			vhost_poll_queue(&tx_vq->poll);
 	}
 
-	return 0;
+	ret = 0;
+out:
+	rcu_read_unlock();
+	return ret;
 }
 
 static struct virtio_vsock_pkt *
@@ -529,10 +533,6 @@ static int vhost_vsock_dev_open(struct inode *inode, struct file *file)
 	spin_lock_init(&vsock->send_pkt_list_lock);
 	INIT_LIST_HEAD(&vsock->send_pkt_list);
 	vhost_work_init(&vsock->send_pkt_work, vhost_transport_send_pkt_work);
-
-	spin_lock_bh(&vhost_vsock_lock);
-	list_add_tail(&vsock->list, &vhost_vsock_list);
-	spin_unlock_bh(&vhost_vsock_lock);
 	return 0;
 
 out:
@@ -573,9 +573,13 @@ static int vhost_vsock_dev_release(struct inode *inode, struct file *file)
 	struct vhost_vsock *vsock = file->private_data;
 
 	spin_lock_bh(&vhost_vsock_lock);
-	list_del(&vsock->list);
+	if (vsock->guest_cid)
+		hash_del_rcu(&vsock->hash);
 	spin_unlock_bh(&vhost_vsock_lock);
 
+	/* Wait for other CPUs to finish using vsock */
+	synchronize_rcu();
+
 	/* Iterating over all connections for all CIDs to find orphans is
 	 * inefficient.  Room for improvement here. */
 	vsock_for_each_connected_socket(vhost_vsock_reset_orphans);
@@ -616,12 +620,17 @@ static int vhost_vsock_set_cid(struct vhost_vsock *vsock, u64 guest_cid)
 
 	/* Refuse if CID is already in use */
 	spin_lock_bh(&vhost_vsock_lock);
-	other = __vhost_vsock_get(guest_cid);
+	other = vhost_vsock_get(guest_cid);
 	if (other && other != vsock) {
 		spin_unlock_bh(&vhost_vsock_lock);
 		return -EADDRINUSE;
 	}
+
+	if (vsock->guest_cid)
+		hash_del_rcu(&vsock->hash);
+
 	vsock->guest_cid = guest_cid;
+	hash_add_rcu(vhost_vsock_hash, &vsock->hash, guest_cid);
 	spin_unlock_bh(&vhost_vsock_lock);
 
 	return 0;
-- 
2.19.1




  parent reply	other threads:[~2018-12-11 16:13 UTC|newest]

Thread overview: 56+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-12-11 15:41 [PATCH 4.9 00/51] 4.9.145-stable review Greg Kroah-Hartman
2018-12-11 15:41 ` [PATCH 4.9 01/51] media: omap3isp: Unregister media device as first Greg Kroah-Hartman
2018-12-11 15:41 ` [PATCH 4.9 02/51] iommu/vt-d: Fix NULL pointer dereference in prq_event_thread() Greg Kroah-Hartman
2018-12-11 15:41 ` [PATCH 4.9 03/51] brcmutil: really fix decoding channel info for 160 MHz bandwidth Greg Kroah-Hartman
2018-12-11 15:41 ` [PATCH 4.9 04/51] iommu/ipmmu-vmsa: Fix crash on early domain free Greg Kroah-Hartman
2018-12-11 15:41 ` [PATCH 4.9 05/51] can: rcar_can: Fix erroneous registration Greg Kroah-Hartman
2018-12-11 15:41 ` [PATCH 4.9 06/51] HID: input: Ignore battery reported by Symbol DS4308 Greg Kroah-Hartman
2018-12-11 15:41 ` [PATCH 4.9 07/51] batman-adv: Expand merged fragment buffer for full packet Greg Kroah-Hartman
2018-12-11 15:41 ` [PATCH 4.9 08/51] bnx2x: Assign unique DMAE channel number for FW DMAE transactions Greg Kroah-Hartman
2018-12-11 15:41 ` [PATCH 4.9 09/51] qed: Fix PTT leak in qed_drain() Greg Kroah-Hartman
2018-12-11 15:41 ` [PATCH 4.9 10/51] qed: Fix reading wrong value in loop condition Greg Kroah-Hartman
2018-12-11 15:41 ` [PATCH 4.9 11/51] net/mlx4_core: Zero out lkey field in SW2HW_MPT fw command Greg Kroah-Hartman
2018-12-11 15:41 ` [PATCH 4.9 12/51] net/mlx4_core: Fix uninitialized variable compilation warning Greg Kroah-Hartman
2018-12-11 15:41 ` [PATCH 4.9 13/51] net/mlx4: Fix UBSAN warning of signed integer overflow Greg Kroah-Hartman
2018-12-11 15:41 ` [PATCH 4.9 14/51] mtd: rawnand: qcom: Namespace prefix some commands Greg Kroah-Hartman
2018-12-11 15:41 ` [PATCH 4.9 15/51] net: faraday: ftmac100: remove netif_running(netdev) check before disabling interrupts Greg Kroah-Hartman
2018-12-11 15:41 ` [PATCH 4.9 16/51] iommu/vt-d: Use memunmap to free memremap Greg Kroah-Hartman
2018-12-11 15:41 ` [PATCH 4.9 17/51] team: no need to do team_notify_peers or team_mcast_rejoin when disabling port Greg Kroah-Hartman
2018-12-11 15:41 ` [PATCH 4.9 18/51] net: amd: add missing of_node_put() Greg Kroah-Hartman
2018-12-11 15:41 ` [PATCH 4.9 19/51] mm: dont warn about allocations which stall for too long Greg Kroah-Hartman
2018-12-11 15:41 ` [PATCH 4.9 20/51] ARC: [zebu] Remove CONFIG_INITRAMFS_SOURCE from defconfigs Greg Kroah-Hartman
2018-12-11 15:41 ` [PATCH 4.9 21/51] usb: quirk: add no-LPM quirk on SanDisk Ultra Flair device Greg Kroah-Hartman
2018-12-11 15:41 ` [PATCH 4.9 22/51] usb: appledisplay: Add 27" Apple Cinema Display Greg Kroah-Hartman
2018-12-11 15:41 ` [PATCH 4.9 23/51] USB: check usb_get_extra_descriptor for proper size Greg Kroah-Hartman
2018-12-11 15:41 ` [PATCH 4.9 24/51] ALSA: usb-audio: Fix UAF decrement if card has no live interfaces in card.c Greg Kroah-Hartman
2018-12-11 15:41 ` [PATCH 4.9 25/51] ALSA: hda: Add support for AMD Stoney Ridge Greg Kroah-Hartman
2018-12-11 15:41 ` [PATCH 4.9 26/51] ALSA: pcm: Fix starvation on down_write_nonblock() Greg Kroah-Hartman
2018-12-11 15:41 ` [PATCH 4.9 27/51] ALSA: pcm: Call snd_pcm_unlink() conditionally at closing Greg Kroah-Hartman
2018-12-11 15:41 ` [PATCH 4.9 28/51] ALSA: pcm: Fix interval evaluation with openmin/max Greg Kroah-Hartman
2018-12-11 15:41 ` [PATCH 4.9 29/51] ALSA: hda/realtek - Fix speaker output regression on Thinkpad T570 Greg Kroah-Hartman
2018-12-11 15:41 ` [PATCH 4.9 30/51] virtio/s390: avoid race on vcdev->config Greg Kroah-Hartman
2018-12-11 15:41 ` [PATCH 4.9 31/51] virtio/s390: fix race in ccw_io_helper() Greg Kroah-Hartman
2018-12-11 15:41 ` [PATCH 4.9 32/51] SUNRPC: Fix leak of krb5p encode pages Greg Kroah-Hartman
2018-12-11 15:41 ` [PATCH 4.9 33/51] dmaengine: cppi41: delete channel from pending list when stop channel Greg Kroah-Hartman
2018-12-11 15:41 ` [PATCH 4.9 34/51] xhci: Prevent U1/U2 link pm states if exit latency is too long Greg Kroah-Hartman
2018-12-11 15:41 ` [PATCH 4.9 35/51] sr: pass down correctly sized SCSI sense buffer Greg Kroah-Hartman
2018-12-11 15:41 ` [PATCH 4.9 36/51] swiotlb: clean up reporting Greg Kroah-Hartman
2018-12-11 15:41 ` [PATCH 4.9 37/51] vsock: lookup and setup guest_cid inside vhost_vsock_lock Greg Kroah-Hartman
2018-12-11 15:41 ` Greg Kroah-Hartman [this message]
2018-12-11 15:41 ` [PATCH 4.9 39/51] Staging: lustre: remove two build warnings Greg Kroah-Hartman
2018-12-11 15:41 ` [PATCH 4.9 40/51] cifs: Fix separator when building path from dentry Greg Kroah-Hartman
2018-12-11 15:41 ` [PATCH 4.9 41/51] staging: rtl8712: Fix possible buffer overrun Greg Kroah-Hartman
2018-12-11 15:41 ` [PATCH 4.9 42/51] tty: serial: 8250_mtk: always resume the device in probe Greg Kroah-Hartman
2018-12-11 15:41 ` [PATCH 4.9 43/51] tty: do not set TTY_IO_ERROR flag if console port Greg Kroah-Hartman
2018-12-11 15:41 ` [PATCH 4.9 44/51] kgdboc: fix KASAN global-out-of-bounds bug in param_set_kgdboc_var() Greg Kroah-Hartman
2018-12-11 15:41 ` [PATCH 4.9 45/51] mac80211_hwsim: Timer should be initialized before device registered Greg Kroah-Hartman
2018-12-11 15:41 ` [PATCH 4.9 46/51] mac80211: Clear beacon_int in ieee80211_do_stop Greg Kroah-Hartman
2018-12-11 15:41 ` [PATCH 4.9 47/51] mac80211: ignore tx status for PS stations in ieee80211_tx_status_ext Greg Kroah-Hartman
2018-12-11 15:41 ` [PATCH 4.9 48/51] mac80211: fix reordering of buffered broadcast packets Greg Kroah-Hartman
2018-12-11 15:41 ` [PATCH 4.9 49/51] mac80211: ignore NullFunc frames in the duplicate detection Greg Kroah-Hartman
2018-12-11 15:41 ` [PATCH 4.9 50/51] kbuild: fix linker feature test macros when cross compiling with Clang Greg Kroah-Hartman
2018-12-11 15:41 ` [PATCH 4.9 51/51] kbuild: allow to use GCC toolchain not in Clang search path Greg Kroah-Hartman
2018-12-11 20:33 ` [PATCH 4.9 00/51] 4.9.145-stable review kernelci.org bot
2018-12-11 23:57 ` shuah
2018-12-12  6:45 ` Naresh Kamboju
2018-12-12 18:49 ` Guenter Roeck

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20181211151617.160217603@linuxfoundation.org \
    --to=gregkh@linuxfoundation.org \
    --cc=jasowang@redhat.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mst@redhat.com \
    --cc=sashal@kernel.org \
    --cc=stable@vger.kernel.org \
    --cc=stefanha@redhat.com \
    --cc=syzbot+bd391451452fb0b93039@syzkaller.appspotmail.com \
    --cc=syzbot+d5a0a170c5069658b141@syzkaller.appspotmail.com \
    --cc=syzbot+e3e074963495f92a89ed@syzkaller.appspotmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.