From 53fc1d8afd78213d572f46d6f7277132387b5239 Mon Sep 17 00:00:00 2001 From: "Daniel P. Berrange" Date: Thu, 3 Jun 2010 14:36:34 +0100 Subject: [PATCH] Ensure UNIX domain sockets are removed on daemon shutdown 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 | 132 +++++++++++++++++++++++++--------------------- daemon/libvirtd.h | 1 + 2 files changed, 72 insertions(+), 61 deletions(-) diff --git a/daemon/libvirtd.c b/daemon/libvirtd.c index e86f78d2fa..711360b63b 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 (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 (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 (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(&server->logDir, "%s/log/libvirt", + base_dir_prefix) < 0) + goto no_memory; } else { - if (snprintf(sockname, maxlen, "@%s/libvirt-sock", - sock_dir_prefix) >= maxlen) - goto snprintf_error; + if (virAsprintf(&server->logDir, "%s/.libvirt/log", + base_dir_prefix) < 0) + goto no_memory; } - if (server->privileged) { - if (!(server->logDir = strdup (LOCAL_STATE_DIR "/log/libvirt"))) - virReportOOMError(); - } else { - if (virAsprintf(&server->logDir, "%s/.libvirt/log", dir_prefix) < 0) - virReportOOMError(); - } - - 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,14 @@ 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->path); + VIR_FREE(sock); sock = next; } diff --git a/daemon/libvirtd.h b/daemon/libvirtd.h index d292681001..4d8e7e2955 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;