[libvirt] [PATCH] Ensure UNIX domain sockets are removed on daemon shutdown

Daniel P. Berrange berrange at redhat.com
Thu Jun 3 13:40:10 UTC 2010


When libvirtd exits it is leaving UNIX domain sockets on
the filesystem. These need to be removed.

The qemudInitPaths() method has signficant code churn to
switch from using a pre-allocated buffer on the stack, to
dynamically allocating on the heap.

* daemon/libvirtd.c, daemon/libvirtd.h: Store a reference
  to the UNIX domain socket path and unlink it on shutdown
---
 daemon/libvirtd.c |  127 ++++++++++++++++++++++++++++------------------------
 daemon/libvirtd.h |    1 +
 2 files changed, 69 insertions(+), 59 deletions(-)

diff --git a/daemon/libvirtd.c b/daemon/libvirtd.c
index e86f78d..381b2df 100644
--- a/daemon/libvirtd.c
+++ b/daemon/libvirtd.c
@@ -533,7 +533,7 @@ static int qemudWritePidFile(const char *pidFile) {
 }
 
 static int qemudListenUnix(struct qemud_server *server,
-                           const char *path, int readonly, int auth) {
+                           char *path, int readonly, int auth) {
     struct qemud_socket *sock;
     struct sockaddr_un addr;
     mode_t oldmask;
@@ -549,6 +549,7 @@ static int qemudListenUnix(struct qemud_server *server,
     sock->port = -1;
     sock->type = QEMUD_SOCK_TYPE_UNIX;
     sock->auth = auth;
+    sock->path = path;
 
     if ((sock->fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
         VIR_ERROR(_("Failed to create socket: %s"),
@@ -743,17 +744,30 @@ cleanup:
 }
 
 static int qemudInitPaths(struct qemud_server *server,
-                          char *sockname,
-                          char *roSockname,
-                          int maxlen)
+                          char **sockname,
+                          char **roSockname)
 {
-    char *sock_dir;
-    char *dir_prefix = NULL;
-    int ret = -1;
+    char *base_dir_prefix = NULL;
     char *sock_dir_prefix = NULL;
+    int ret = -1;
+
+    /* The base_dir_prefix is the base under which all libvirtd
+     * files live */
+    if (server->privileged) {
+        if (!(base_dir_prefix = strdup (LOCAL_STATE_DIR)))
+            goto no_memory;
+    } else {
+        uid_t uid = geteuid();
+        if (!(base_dir_prefix = virGetUserDirectory(uid)))
+            goto cleanup;
+    }
 
+    /* The unix_sock_dir is the location under which all
+     * unix domain sockets live */
     if (unix_sock_dir) {
-        sock_dir = unix_sock_dir;
+        if (!(sock_dir_prefix = strdup(unix_sock_dir)))
+            goto no_memory;
+
         /* Change the group ownership of /var/run/libvirt to unix_sock_gid */
         if (server->privileged) {
             if (chown(unix_sock_dir, -1, unix_sock_gid) < 0)
@@ -761,68 +775,53 @@ static int qemudInitPaths(struct qemud_server *server,
                           unix_sock_dir);
         }
     } else {
-        sock_dir = sockname;
         if (server->privileged) {
-            dir_prefix = strdup (LOCAL_STATE_DIR);
-            if (dir_prefix == NULL) {
-                virReportOOMError();
-                goto cleanup;
-            }
-            if (snprintf (sock_dir, maxlen, "%s/run/libvirt",
-                          dir_prefix) >= maxlen)
-                goto snprintf_error;
+            if (virAsprintf(&sock_dir_prefix, "%s/run/libvirt",
+                            base_dir_prefix) < 0)
+                goto no_memory;
         } else {
-            uid_t uid = geteuid();
-            dir_prefix = virGetUserDirectory(uid);
-            if (dir_prefix == NULL) {
-                /* Do not diagnose here; virGetUserDirectory does that.  */
-                goto snprintf_error;
-            }
-
-            if (snprintf(sock_dir, maxlen, "%s/.libvirt", dir_prefix) >= maxlen)
-                goto snprintf_error;
+            if (virAsprintf(&sock_dir_prefix, "%s/.libvirt",
+                            base_dir_prefix) < 0)
+                goto no_memory;
         }
     }
 
-    sock_dir_prefix = strdup (sock_dir);
-    if (!sock_dir_prefix) {
-        virReportOOMError();
-        goto cleanup;
-    }
-
     if (server->privileged) {
-        if (snprintf (sockname, maxlen, "%s/libvirt-sock",
-                      sock_dir_prefix) >= maxlen
-            || (snprintf (roSockname, maxlen, "%s/libvirt-sock-ro",
-                          sock_dir_prefix) >= maxlen))
-            goto snprintf_error;
-        unlink(sockname);
-        unlink(roSockname);
+        if (virAsprintf(sockname, "%s/libvirt-sock",
+                        sock_dir_prefix) < 0)
+            goto no_memory;
+        if (virAsprintf(roSockname, "%s/libvirt-sock-ro",
+                        sock_dir_prefix) < 0)
+            goto no_memory;
+        unlink(*sockname);
+        unlink(*roSockname);
     } else {
-        if (snprintf(sockname, maxlen, "@%s/libvirt-sock",
-                     sock_dir_prefix) >= maxlen)
-            goto snprintf_error;
+        if (virAsprintf(sockname, "@%s/libvirt-sock",
+                        sock_dir_prefix) < 0)
+            goto no_memory;
+        /* There is no RO socket in unprivileged mode,
+         * since the user always has full RW access
+         * to their private instance */
     }
 
     if (server->privileged) {
-        if (!(server->logDir = strdup (LOCAL_STATE_DIR "/log/libvirt")))
-            virReportOOMError();
+        if (virAsprintf(&server->logDir, "%s/log/libvirt",
+                        base_dir_prefix) < 0)
+            goto no_memory;
     } else {
-        if (virAsprintf(&server->logDir, "%s/.libvirt/log", dir_prefix) < 0)
-            virReportOOMError();
+        if (virAsprintf(&server->logDir, "%s/.libvirt/log",
+                        base_dir_prefix) < 0)
+            goto no_memory;
     }
 
-    if (server->logDir == NULL)
-        goto cleanup;
-
     ret = 0;
 
- snprintf_error:
-    if (ret)
-        VIR_ERROR0(_("Resulting path too long for buffer in qemudInitPaths()"));
+no_memory:
+    if (ret != 0)
+        virReportOOMError();
 
  cleanup:
-    VIR_FREE(dir_prefix);
+    VIR_FREE(base_dir_prefix);
     VIR_FREE(sock_dir_prefix);
     return ret;
 }
@@ -931,22 +930,22 @@ static struct qemud_server *qemudInitialize(void) {
 }
 
 static int qemudNetworkInit(struct qemud_server *server) {
-    char sockname[PATH_MAX];
-    char roSockname[PATH_MAX];
+    char *sockname = NULL;
+    char *roSockname = NULL;
 #if HAVE_SASL
     int err;
 #endif /* HAVE_SASL */
 
-    roSockname[0] = '\0';
-
-    if (qemudInitPaths(server, sockname, roSockname, PATH_MAX) < 0)
+    if (qemudInitPaths(server, &sockname, &roSockname) < 0)
         goto cleanup;
 
     if (qemudListenUnix(server, sockname, 0, auth_unix_rw) < 0)
         goto cleanup;
+    sockname = NULL;
 
-    if (roSockname[0] != '\0' && qemudListenUnix(server, roSockname, 1, auth_unix_ro) < 0)
+    if (roSockname != NULL && qemudListenUnix(server, roSockname, 1, auth_unix_ro) < 0)
         goto cleanup;
+    roSockname = NULL;
 
 #if HAVE_SASL
     if (auth_unix_rw == REMOTE_AUTH_SASL ||
@@ -1057,6 +1056,8 @@ static int qemudNetworkInit(struct qemud_server *server) {
     return 0;
 
  cleanup:
+    VIR_FREE(sockname);
+    VIR_FREE(roSockname);
     return -1;
 }
 
@@ -1080,6 +1081,7 @@ static int qemudNetworkEnable(struct qemud_server *server) {
     return 0;
 }
 
+
 static gnutls_session_t
 remoteInitializeTLSSession (void)
 {
@@ -2422,6 +2424,13 @@ static void qemudCleanup(struct qemud_server *server) {
         if (sock->watch)
             virEventRemoveHandleImpl(sock->watch);
         close(sock->fd);
+
+        /* Unlink unix domain sockets which are not in
+         * the abstract namespace */
+        if (sock->path &&
+            sock->path[0] != '@')
+            unlink(sock->path);
+
         VIR_FREE(sock);
         sock = next;
     }
diff --git a/daemon/libvirtd.h b/daemon/libvirtd.h
index d292681..4d8e7e2 100644
--- a/daemon/libvirtd.h
+++ b/daemon/libvirtd.h
@@ -233,6 +233,7 @@ struct qemud_client {
 
 
 struct qemud_socket {
+    char *path;
     int fd;
     int watch;
     int readonly;
-- 
1.6.6.1




More information about the libvir-list mailing list