c401cc
From 67b99a7fa2aea64c6125fbd501df4e76402415a5 Mon Sep 17 00:00:00 2001
c401cc
Message-Id: <67b99a7fa2aea64c6125fbd501df4e76402415a5.1390394206.git.jdenemar@redhat.com>
c401cc
From: Jiri Denemark <jdenemar@redhat.com>
c401cc
Date: Thu, 9 Jan 2014 22:26:40 +0100
c401cc
Subject: [PATCH] Don't crash if a connection closes early
c401cc
c401cc
CVE-2014-1447
c401cc
c401cc
When a client closes its connection to libvirtd early during
c401cc
virConnectOpen, more specifically just after making
c401cc
REMOTE_PROC_CONNECT_SUPPORTS_FEATURE call to check if
c401cc
VIR_DRV_FEATURE_PROGRAM_KEEPALIVE is supported without even waiting for
c401cc
the result, libvirtd may crash due to a race in keep-alive
c401cc
initialization. Once receiving the REMOTE_PROC_CONNECT_SUPPORTS_FEATURE
c401cc
call, the daemon's event loop delegates it to a worker thread. In case
c401cc
the event loop detects EOF on the connection and calls
c401cc
virNetServerClientClose before the worker thread starts to handle
c401cc
REMOTE_PROC_CONNECT_SUPPORTS_FEATURE call, client->keepalive will be
c401cc
disposed by the time virNetServerClientStartKeepAlive gets called from
c401cc
remoteDispatchConnectSupportsFeature. Because the flow is common for
c401cc
both authenticated and read-only connections, even unprivileged clients
c401cc
may cause the daemon to crash.
c401cc
c401cc
To avoid the crash, virNetServerClientStartKeepAlive needs to check if
c401cc
the connection is still open before starting keep-alive protocol.
c401cc
c401cc
Every libvirt release since 0.9.8 is affected by this bug.
c401cc
c401cc
(cherry picked from commit 173c2914734eb5c32df6d35a82bf503e12261bcf)
c401cc
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
c401cc
---
c401cc
 src/rpc/virnetserverclient.c | 15 ++++++++++++++-
c401cc
 1 file changed, 14 insertions(+), 1 deletion(-)
c401cc
c401cc
diff --git a/src/rpc/virnetserverclient.c b/src/rpc/virnetserverclient.c
c401cc
index 0b9ab52..64e91d3 100644
c401cc
--- a/src/rpc/virnetserverclient.c
c401cc
+++ b/src/rpc/virnetserverclient.c
c401cc
@@ -1533,9 +1533,22 @@ cleanup:
c401cc
 int
c401cc
 virNetServerClientStartKeepAlive(virNetServerClientPtr client)
c401cc
 {
c401cc
-    int ret;
c401cc
+    int ret = -1;
c401cc
+
c401cc
     virObjectLock(client);
c401cc
+
c401cc
+    /* The connection might have been closed before we got here and thus the
c401cc
+     * keepalive object could have been removed too.
c401cc
+     */
c401cc
+    if (!client->sock) {
c401cc
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
c401cc
+                       _("connection not open"));
c401cc
+        goto cleanup;
c401cc
+    }
c401cc
+
c401cc
     ret = virKeepAliveStart(client->keepalive, 0, 0);
c401cc
+
c401cc
+cleanup:
c401cc
     virObjectUnlock(client);
c401cc
     return ret;
c401cc
 }
c401cc
-- 
c401cc
1.8.5.3
c401cc