[PATCH 3/6] admin: Introduce virAdmServerUpdateTlsFiles
by Zhangbo (Oscar)
The server needs to use CA certificate, CRL, server certificate/key to
complete the TLS handshake. If these files change, we need to restart
libvirtd for them to take effect. This API can update the TLS context
without restarting libvirtd.
---
include/libvirt/libvirt-admin.h | 4 ++++
src/admin/admin_protocol.x | 13 ++++++++++-
src/admin/admin_server.c | 13 +++++++++++
src/admin/admin_server.h | 4 ++++
src/admin/libvirt-admin.c | 34 ++++++++++++++++++++++++++++
src/admin/libvirt_admin_private.syms | 1 +
src/admin/libvirt_admin_public.syms | 1 +
7 files changed, 69 insertions(+), 1 deletion(-)
diff --git a/include/libvirt/libvirt-admin.h b/include/libvirt/libvirt-admin.h
index 3edc044490..6e38261129 100644
--- a/include/libvirt/libvirt-admin.h
+++ b/include/libvirt/libvirt-admin.h
@@ -410,6 +410,10 @@ int virAdmServerSetClientLimits(virAdmServerPtr srv,
int nparams,
unsigned int flags);
+int virAdmServerUpdateTlsFiles(virAdmServerPtr srv,
+ unsigned int filetypes,
+ unsigned int flags);
+
int virAdmConnectGetLoggingOutputs(virAdmConnectPtr conn,
char **outputs,
unsigned int flags);
diff --git a/src/admin/admin_protocol.x b/src/admin/admin_protocol.x
index 42e215d23a..0fc8c54c80 100644
--- a/src/admin/admin_protocol.x
+++ b/src/admin/admin_protocol.x
@@ -181,6 +181,12 @@ struct admin_server_set_client_limits_args {
unsigned int flags;
};
+struct admin_server_update_tls_files_args {
+ admin_nonnull_server srv;
+ unsigned int filetypes;
+ unsigned int flags;
+};
+
struct admin_connect_get_logging_outputs_args {
unsigned int flags;
};
@@ -314,5 +320,10 @@ enum admin_procedure {
/**
* @generate: both
*/
- ADMIN_PROC_CONNECT_SET_LOGGING_FILTERS = 17
+ ADMIN_PROC_CONNECT_SET_LOGGING_FILTERS = 17,
+
+ /**
+ * @generate: both
+ */
+ ADMIN_PROC_SERVER_UPDATE_TLS_FILES = 18
};
diff --git a/src/admin/admin_server.c b/src/admin/admin_server.c
index ba87f701c3..558913367b 100644
--- a/src/admin/admin_server.c
+++ b/src/admin/admin_server.c
@@ -367,3 +367,16 @@ adminServerSetClientLimits(virNetServerPtr srv,
return 0;
}
+
+int
+adminServerUpdateTlsFiles(virNetServerPtr srv,
+ unsigned int filetypes,
+ unsigned int flags)
+{
+ virCheckFlags(0, -1);
+
+ if (virNetServerUpdateTlsFiles(srv, filetypes) < 0)
+ return -1;
+
+ return 0;
+}
diff --git a/src/admin/admin_server.h b/src/admin/admin_server.h
index 1d5cbec55f..bd355017f2 100644
--- a/src/admin/admin_server.h
+++ b/src/admin/admin_server.h
@@ -67,3 +67,7 @@ int adminServerSetClientLimits(virNetServerPtr srv,
virTypedParameterPtr params,
int nparams,
unsigned int flags);
+
+int adminServerUpdateTlsFiles(virNetServerPtr srv,
+ unsigned int filetypes,
+ unsigned int flags);
diff --git a/src/admin/libvirt-admin.c b/src/admin/libvirt-admin.c
index 4099a54854..f3f92ed91c 100644
--- a/src/admin/libvirt-admin.c
+++ b/src/admin/libvirt-admin.c
@@ -1082,6 +1082,40 @@ virAdmServerSetClientLimits(virAdmServerPtr srv,
return ret;
}
+/**
+ * virAdmServerUpdateTlsFiles:
+ * @srv: a valid server object reference
+ * @filetypes: bitwise-OR of virServerTlsFiletype
+ * @flags: extra flags; not used yet, so callers should always pass 0
+ *
+ * Notify server to update tls file, such as cacert, cacrl, server cert / key.
+ * Mark the files that need to be updated by the @filetypes parameter.
+ * See virServerTlsFiletype for detailed description of accepted filetypes.
+ *
+ * Returns 0 if the TLS files have been updated successfully or -1 in case of an
+ * error.
+ */
+int
+virAdmServerUpdateTlsFiles(virAdmServerPtr srv,
+ unsigned int filetypes,
+ unsigned int flags)
+{
+ int ret = -1;
+
+ VIR_DEBUG("srv=%p, filetypes=%u, flags=0x%x", srv, filetypes, flags);
+ virResetLastError();
+
+ virCheckAdmServerGoto(srv, error);
+
+ if ((ret = remoteAdminServerUpdateTlsFiles(srv, filetypes, flags)) < 0)
+ goto error;
+
+ return ret;
+ error:
+ virDispatchError(NULL);
+ return ret;
+}
+
/**
* virAdmConnectGetLoggingOutputs:
* @conn: pointer to an active admin connection
diff --git a/src/admin/libvirt_admin_private.syms b/src/admin/libvirt_admin_private.syms
index 9526412de8..157a45341e 100644
--- a/src/admin/libvirt_admin_private.syms
+++ b/src/admin/libvirt_admin_private.syms
@@ -31,6 +31,7 @@ xdr_admin_server_lookup_client_args;
xdr_admin_server_lookup_client_ret;
xdr_admin_server_set_client_limits_args;
xdr_admin_server_set_threadpool_parameters_args;
+xdr_admin_server_update_tls_files_args;
# datatypes.h
virAdmClientClass;
diff --git a/src/admin/libvirt_admin_public.syms b/src/admin/libvirt_admin_public.syms
index 9a3f843780..8126973e5b 100644
--- a/src/admin/libvirt_admin_public.syms
+++ b/src/admin/libvirt_admin_public.syms
@@ -38,6 +38,7 @@ LIBVIRT_ADMIN_2.0.0 {
virAdmClientClose;
virAdmServerGetClientLimits;
virAdmServerSetClientLimits;
+ virAdmServerUpdateTlsFiles;
};
LIBVIRT_ADMIN_3.0.0 {
--
2.23.0.windows.1
4 years, 10 months
[PATCH 2/6] virnetserver: Introduce virNetServerUpdateTlsFiles
by Zhangbo (Oscar)
Add an API to update server's tls context before admin method can be
introduced.
---
include/libvirt/libvirt-admin.h | 8 ++++
src/libvirt_remote.syms | 1 +
src/rpc/virnetserver.c | 72 +++++++++++++++++++++++++++++++++
src/rpc/virnetserver.h | 3 ++
src/rpc/virnetserverclient.c | 4 ++
src/rpc/virnettlscontext.c | 41 +++++++++++++++++++
src/rpc/virnettlscontext.h | 2 +
7 files changed, 131 insertions(+)
diff --git a/include/libvirt/libvirt-admin.h b/include/libvirt/libvirt-admin.h
index abf2792926..3edc044490 100644
--- a/include/libvirt/libvirt-admin.h
+++ b/include/libvirt/libvirt-admin.h
@@ -392,6 +392,14 @@ int virAdmClientClose(virAdmClientPtr client, unsigned int flags);
# define VIR_SERVER_CLIENTS_UNAUTH_CURRENT "nclients_unauth"
+/* tls related filetype flags. */
+typedef enum {
+ VIR_TLS_FILE_TYPE_CA_CERT = (1U << 0),
+ VIR_TLS_FILE_TYPE_CA_CRL = (1U << 1),
+ VIR_TLS_FILE_TYPE_SERVER_CERT = (1U << 2),
+ VIR_TLS_FILE_TYPE_SERVER_KEY = (1U << 3),
+} virServerTlsFiletype;
+
int virAdmServerGetClientLimits(virAdmServerPtr srv,
virTypedParameterPtr *params,
int *nparams,
diff --git a/src/libvirt_remote.syms b/src/libvirt_remote.syms
index 0493467f46..0018a0c41d 100644
--- a/src/libvirt_remote.syms
+++ b/src/libvirt_remote.syms
@@ -137,6 +137,7 @@ virNetServerSetClientLimits;
virNetServerSetThreadPoolParameters;
virNetServerSetTLSContext;
virNetServerUpdateServices;
+virNetServerUpdateTlsFiles;
# rpc/virnetserverclient.h
diff --git a/src/rpc/virnetserver.c b/src/rpc/virnetserver.c
index c87dade1a8..65ec677d0a 100644
--- a/src/rpc/virnetserver.c
+++ b/src/rpc/virnetserver.c
@@ -1207,3 +1207,75 @@ virNetServerSetClientLimits(virNetServerPtr srv,
virObjectUnlock(srv);
return ret;
}
+
+static virNetTLSContextPtr
+virNetServerGetTLSContext(virNetServerPtr srv)
+{
+ size_t i;
+ virNetTLSContextPtr ctxt = NULL;
+ virNetServerServicePtr svc = NULL;
+
+ /* find svcTLS from srv, get svcTLS->tls */
+ for (i = 0; i < srv->nservices; i++) {
+ svc = srv->services[i];
+ ctxt = virNetServerServiceGetTLSContext(svc);
+ if (ctxt != NULL)
+ break;
+ }
+
+ return ctxt;
+}
+
+static int virNetServerUpdateTlsFilesCheckParams(unsigned int filetypes)
+{
+ bool haveSrvCert = filetypes & VIR_TLS_FILE_TYPE_SERVER_CERT;
+ bool haveSrvKey = filetypes & VIR_TLS_FILE_TYPE_SERVER_KEY;
+
+ if ((haveSrvCert && !haveSrvKey) ||
+ (!haveSrvCert && haveSrvKey)) {
+ virReportError(VIR_ERR_SYSTEM_ERROR,
+ _("server cert/key must be updated together. "
+ "filetypes: %d"), filetypes);
+ return -1;
+ }
+
+ return 0;
+}
+
+int
+virNetServerUpdateTlsFiles(virNetServerPtr srv,
+ unsigned int filetypes)
+{
+ int ret = -1;
+#ifndef WITH_GNUTLS
+ virReportError(VIR_ERR_SYSTEM_ERROR,
+ _("Don't support GNUTLS, can't to update filetypes: %d"),
+ filetypes);
+#else
+ virNetTLSContextPtr ctxt = NULL;
+
+ if (virNetServerUpdateTlsFilesCheckParams(filetypes))
+ return -1;
+
+ virObjectLock(srv);
+
+ ctxt = virNetServerGetTLSContext(srv);
+ if (!ctxt) {
+ VIR_ERROR(_("no tls svc found, can't to update filetypes: %d"),
+ filetypes);
+ goto cleanup;
+ }
+
+ if (virNetTLSContextReload(ctxt, filetypes)) {
+ VIR_ERROR(_("reload server's tls context fail"));
+ goto cleanup;
+ }
+
+ VIR_INFO("update all tls files complete, filetypes: %d", filetypes);
+ ret = 0;
+
+ cleanup:
+ virObjectUnlock(srv);
+#endif
+ return ret;
+}
diff --git a/src/rpc/virnetserver.h b/src/rpc/virnetserver.h
index 260c99b22d..99466dd041 100644
--- a/src/rpc/virnetserver.h
+++ b/src/rpc/virnetserver.h
@@ -133,3 +133,6 @@ size_t virNetServerGetCurrentUnauthClients(virNetServerPtr srv);
int virNetServerSetClientLimits(virNetServerPtr srv,
long long int maxClients,
long long int maxClientsUnauth);
+
+int virNetServerUpdateTlsFiles(virNetServerPtr srv,
+ unsigned int filetypes);
diff --git a/src/rpc/virnetserverclient.c b/src/rpc/virnetserverclient.c
index 67b3bf9531..f0952cadde 100644
--- a/src/rpc/virnetserverclient.c
+++ b/src/rpc/virnetserverclient.c
@@ -1117,7 +1117,9 @@ int virNetServerClientInit(virNetServerClientPtr client)
client->tls);
/* Begin the TLS handshake. */
+ virObjectLock(client->tlsCtxt);
ret = virNetTLSSessionHandshake(client->tls);
+ virObjectUnlock(client->tlsCtxt);
if (ret == 0) {
/* Unlikely, but ... Next step is to check the certificate. */
if (virNetServerClientCheckAccess(client) < 0)
@@ -1438,7 +1440,9 @@ virNetServerClientDispatchHandshake(virNetServerClientPtr client)
{
int ret;
/* Continue the handshake. */
+ virObjectLock(client->tlsCtxt);
ret = virNetTLSSessionHandshake(client->tls);
+ virObjectUnlock(client->tlsCtxt);
if (ret == 0) {
/* Finished. Next step is to check the certificate. */
if (virNetServerClientCheckAccess(client) < 0)
diff --git a/src/rpc/virnettlscontext.c b/src/rpc/virnettlscontext.c
index 12811bed78..8baa6a15b2 100644
--- a/src/rpc/virnettlscontext.c
+++ b/src/rpc/virnettlscontext.c
@@ -1139,6 +1139,47 @@ void virNetTLSContextDispose(void *obj)
gnutls_certificate_free_credentials(ctxt->x509cred);
}
+int virNetTLSContextReload(virNetTLSContextPtr ctxt,
+ unsigned int filetypes)
+{
+ int ret = -1;
+ char *cacert = NULL;
+ char *cacrl = NULL;
+ char *cert = NULL;
+ char *key = NULL;
+
+ virObjectLock(ctxt);
+
+ if (virNetTLSContextLocateCredentials(NULL, false, true,
+ &cacert, &cacrl, &cert, &key) < 0)
+ goto cleanup;
+
+ if (filetypes & VIR_TLS_FILE_TYPE_CA_CERT) {
+ if (virNetTLSContextSetCACert(ctxt, cacert, false))
+ goto cleanup;
+ }
+
+ if (filetypes & VIR_TLS_FILE_TYPE_CA_CRL) {
+ if (virNetTLSContextSetCACRL(ctxt, cacrl, false))
+ goto cleanup;
+ }
+
+ if (filetypes & VIR_TLS_FILE_TYPE_SERVER_CERT) {
+ gnutls_certificate_free_keys(ctxt->x509cred);
+ if (virNetTLSContextSetCertAndKey(ctxt, cert, key, false))
+ goto cleanup;
+ }
+
+ ret = 0;
+
+ cleanup:
+ virObjectUnlock(ctxt);
+ VIR_FREE(cacert);
+ VIR_FREE(cacrl);
+ VIR_FREE(key);
+ VIR_FREE(cert);
+ return ret;
+}
static ssize_t
virNetTLSSessionPush(void *opaque, const void *buf, size_t len)
diff --git a/src/rpc/virnettlscontext.h b/src/rpc/virnettlscontext.h
index f3273bc26a..9e83caf255 100644
--- a/src/rpc/virnettlscontext.h
+++ b/src/rpc/virnettlscontext.h
@@ -65,6 +65,8 @@ virNetTLSContextPtr virNetTLSContextNewClient(const char *cacert,
int virNetTLSContextCheckCertificate(virNetTLSContextPtr ctxt,
virNetTLSSessionPtr sess);
+int virNetTLSContextReload(virNetTLSContextPtr ctxt,
+ unsigned int filetypes);
typedef ssize_t (*virNetTLSSessionWriteFunc)(const char *buf, size_t len,
void *opaque);
--
2.23.0.windows.1
4 years, 10 months
[PATCH 1/6] virnettlscontext: refactoring virNetTLSContextLoadCredentials
by Zhangbo (Oscar)
Encapsulate the code for setting TLS-related files into functions,
which is convenient for other modules to call.
---
src/rpc/virnettlscontext.c | 135 ++++++++++++++++++++++---------------
1 file changed, 82 insertions(+), 53 deletions(-)
diff --git a/src/rpc/virnettlscontext.c b/src/rpc/virnettlscontext.c
index 44f0dfce77..12811bed78 100644
--- a/src/rpc/virnettlscontext.c
+++ b/src/rpc/virnettlscontext.c
@@ -594,6 +594,85 @@ static int virNetTLSContextSanityCheckCredentials(bool isServer,
return ret;
}
+static int virNetTLSContextSetCACert(virNetTLSContextPtr ctxt,
+ const char *cacert,
+ bool allowMissing)
+{
+ int err;
+ if (virNetTLSContextCheckCertFile("CA certificate", cacert, allowMissing) < 0)
+ return -1;
+
+ VIR_DEBUG("loading CA cert from %s", cacert);
+ err = gnutls_certificate_set_x509_trust_file(ctxt->x509cred,
+ cacert,
+ GNUTLS_X509_FMT_PEM);
+ if (err < 0) {
+ virReportError(VIR_ERR_SYSTEM_ERROR,
+ _("Unable to set x509 CA certificate: %s: %s"),
+ cacert, gnutls_strerror(err));
+ return -1;
+ }
+
+ return 0;
+}
+
+static int virNetTLSContextSetCACRL(virNetTLSContextPtr ctxt,
+ const char *cacrl,
+ bool allowMissing)
+{
+ int rv, err;
+ if ((rv = virNetTLSContextCheckCertFile("CA revocation list", cacrl, allowMissing)) < 0)
+ return -1;
+
+ if (rv == 0) {
+ VIR_DEBUG("loading CRL from %s", cacrl);
+ err = gnutls_certificate_set_x509_crl_file(ctxt->x509cred,
+ cacrl,
+ GNUTLS_X509_FMT_PEM);
+ if (err < 0) {
+ virReportError(VIR_ERR_SYSTEM_ERROR,
+ _("Unable to set x509 certificate revocation list: %s: %s"),
+ cacrl, gnutls_strerror(err));
+ return -1;
+ }
+ } else {
+ VIR_DEBUG("Skipping non-existent CA CRL %s", cacrl);
+ }
+
+ return 0;
+}
+
+static int virNetTLSContextSetCertAndKey(virNetTLSContextPtr ctxt,
+ const char *cert,
+ const char *key,
+ bool allowMissing)
+{
+ int rv, err;
+ if ((rv = virNetTLSContextCheckCertFile("certificate", cert, allowMissing)) < 0)
+ return -1;
+ if (rv == 0 &&
+ (rv = virNetTLSContextCheckCertFile("private key", key, allowMissing)) < 0)
+ return -1;
+
+ if (rv == 0) {
+ VIR_DEBUG("loading cert and key from %s and %s", cert, key);
+ err =
+ gnutls_certificate_set_x509_key_file(ctxt->x509cred,
+ cert, key,
+ GNUTLS_X509_FMT_PEM);
+ if (err < 0) {
+ virReportError(VIR_ERR_SYSTEM_ERROR,
+ _("Unable to set x509 key and certificate: %s, %s: %s"),
+ key, cert, gnutls_strerror(err));
+ return -1;
+ }
+ } else {
+ VIR_DEBUG("Skipping non-existent cert %s key %s on client",
+ cert, key);
+ }
+
+ return 0;
+}
static int virNetTLSContextLoadCredentials(virNetTLSContextPtr ctxt,
bool isServer,
@@ -602,69 +681,19 @@ static int virNetTLSContextLoadCredentials(virNetTLSContextPtr ctxt,
const char *cert,
const char *key)
{
- int err;
-
if (cacert && cacert[0] != '\0') {
- if (virNetTLSContextCheckCertFile("CA certificate", cacert, false) < 0)
- return -1;
-
- VIR_DEBUG("loading CA cert from %s", cacert);
- err = gnutls_certificate_set_x509_trust_file(ctxt->x509cred,
- cacert,
- GNUTLS_X509_FMT_PEM);
- if (err < 0) {
- virReportError(VIR_ERR_SYSTEM_ERROR,
- _("Unable to set x509 CA certificate: %s: %s"),
- cacert, gnutls_strerror(err));
+ if (virNetTLSContextSetCACert(ctxt, cacert, false))
return -1;
- }
}
if (cacrl && cacrl[0] != '\0') {
- int rv;
- if ((rv = virNetTLSContextCheckCertFile("CA revocation list", cacrl, true)) < 0)
+ if (virNetTLSContextSetCACRL(ctxt, cacrl, true))
return -1;
-
- if (rv == 0) {
- VIR_DEBUG("loading CRL from %s", cacrl);
- err = gnutls_certificate_set_x509_crl_file(ctxt->x509cred,
- cacrl,
- GNUTLS_X509_FMT_PEM);
- if (err < 0) {
- virReportError(VIR_ERR_SYSTEM_ERROR,
- _("Unable to set x509 certificate revocation list: %s: %s"),
- cacrl, gnutls_strerror(err));
- return -1;
- }
- } else {
- VIR_DEBUG("Skipping non-existent CA CRL %s", cacrl);
- }
}
if (cert && cert[0] != '\0' && key && key[0] != '\0') {
- int rv;
- if ((rv = virNetTLSContextCheckCertFile("certificate", cert, !isServer)) < 0)
+ if (virNetTLSContextSetCertAndKey(ctxt, cert, key, !isServer))
return -1;
- if (rv == 0 &&
- (rv = virNetTLSContextCheckCertFile("private key", key, !isServer)) < 0)
- return -1;
-
- if (rv == 0) {
- VIR_DEBUG("loading cert and key from %s and %s", cert, key);
- err =
- gnutls_certificate_set_x509_key_file(ctxt->x509cred,
- cert, key,
- GNUTLS_X509_FMT_PEM);
- if (err < 0) {
- virReportError(VIR_ERR_SYSTEM_ERROR,
- _("Unable to set x509 key and certificate: %s, %s: %s"),
- key, cert, gnutls_strerror(err));
- return -1;
- }
- } else {
- VIR_DEBUG("Skipping non-existent cert %s key %s on client",
- cert, key);
- }
}
return 0;
--
2.23.0.windows.1
4 years, 10 months
[PATCH 0/6] update tls files without restarting libvirtd
by Zhangbo (Oscar)
When a client wants to establish a TLS connection with libvirtd, a CRL
file, CA cert and server cert/key are used. Right
now, if these files are changed, you must restart libvirtd to make them
take effect. The restart behavior of libvirtd will cause clients
connecting with libvirtd to fail.
In a server cluster, these files, mostly the CRL, may be updated
quite frequently dueto the large amount of certificates. If the new
file does not take effect in time, there are security risks. So you
may need to restart libvirtd frequently to make the CRL etc. take
effect in time. However, frequent restarts will affect the reliability
of cluster virtual machine management(such as openstack) services.
These patches add a virt-admin command to update the tls related files
*online*.
Zhang Bo (6):
virnettlscontext: refactoring virNetTLSContextLoadCredentials
virnetserver: Introduce virNetServerUpdateTlsFiles
admin: Introduce virAdmServerUpdateTlsFiles
admin: support server cert update mode
virt-admin: Introduce command srv-update-tls
docs: update virt-admin.rst for server-update-tls
docs/manpages/virt-admin.rst | 21 ++++
include/libvirt/libvirt-admin.h | 26 ++++
src/admin/admin_protocol.x | 13 +-
src/admin/admin_server.c | 8 ++
src/admin/admin_server.h | 4 +
src/admin/libvirt-admin.c | 39 ++++++
src/admin/libvirt_admin_private.syms | 1 +
src/admin/libvirt_admin_public.syms | 1 +
src/libvirt_remote.syms | 1 +
src/rpc/virnetserver.c | 81 ++++++++++++
src/rpc/virnetserver.h | 4 +
src/rpc/virnetserverclient.c | 4 +
src/rpc/virnettlscontext.c | 179 +++++++++++++++++++--------
src/rpc/virnettlscontext.h | 3 +
tools/virt-admin.c | 88 +++++++++++++
15 files changed, 419 insertions(+), 54 deletions(-)
--
2.23.0.windows.1
4 years, 10 months
[libvirt PATCH] src: use closefrom() for mass closing of FDs
by Daniel P. Berrangé
On FreeBSD 12 the default ulimit settings allow for 100,000
open file descriptors. As a result spawning processes in
libvirt is abominably slow. Fortunately FreeBSD has long
since provided a good solution in the form of closefrom(),
which closes all FDs equal to or larger than the specified
parameter.
Signed-off-by: Daniel P. Berrangé <berrange(a)redhat.com>
---
src/util/vircommand.c | 60 ++++++++++++++++++++++++++++++++++++++++---
tests/testutils.c | 9 +++++++
2 files changed, 66 insertions(+), 3 deletions(-)
diff --git a/src/util/vircommand.c b/src/util/vircommand.c
index 904a3023c5..764fb2fe43 100644
--- a/src/util/vircommand.c
+++ b/src/util/vircommand.c
@@ -494,6 +494,59 @@ virCommandMassCloseGetFDsGeneric(virCommandPtr cmd G_GNUC_UNUSED,
}
# endif /* !__linux__ */
+# ifdef __FreeBSD__
+
+static int
+virCommandMassClose(virCommandPtr cmd,
+ int childin,
+ int childout,
+ int childerr)
+{
+ int lastfd = -1;
+ int fd = -1;
+
+ /*
+ * Two phases of closing.
+ *
+ * The first (inefficient) phase iterates over FDs,
+ * preserving certain FDs we need to pass down, and
+ * closing others. The number of iterations is bounded
+ * to the number of the biggest FD we need to preserve.
+ *
+ * The second (speedy) phase uses closefrom() to cull
+ * all remaining FDs in the process.
+ *
+ * Usually the first phase will be fairly quick only
+ * processing a handful of low FD numbers, and thus using
+ * closefrom() is a massive win for high ulimit() NFILES
+ * values.
+ */
+ lastfd = MAX(lastfd, childin);
+ lastfd = MAX(lastfd, childout);
+ lastfd = MAX(lastfd, childerr);
+
+ while (fd < cmd->npassfd)
+ lastfd = MAX(lastfd, cmd->passfd[fd].fd);
+
+ for (fd = 0; fd <= lastfd; fd++) {
+ if (fd == childin || fd == childout || fd == childerr)
+ continue;
+ if (!virCommandFDIsSet(cmd, fd)) {
+ int tmpfd = fd;
+ VIR_MASS_CLOSE(tmpfd);
+ } else if (virSetInherit(fd, true) < 0) {
+ virReportSystemError(errno, _("failed to preserve fd %d"), fd);
+ return -1;
+ }
+ }
+
+ closefrom(lastfd + 1);
+
+ return 0;
+}
+
+# else /* ! __FreeBSD__ */
+
static int
virCommandMassClose(virCommandPtr cmd,
int childin,
@@ -520,13 +573,13 @@ virCommandMassClose(virCommandPtr cmd,
if (!(fds = virBitmapNew(openmax)))
return -1;
-# ifdef __linux__
+# ifdef __linux__
if (virCommandMassCloseGetFDsLinux(cmd, fds) < 0)
return -1;
-# else
+# else
if (virCommandMassCloseGetFDsGeneric(cmd, fds) < 0)
return -1;
-# endif
+# endif
fd = virBitmapNextSetBit(fds, 2);
for (; fd >= 0; fd = virBitmapNextSetBit(fds, fd)) {
@@ -544,6 +597,7 @@ virCommandMassClose(virCommandPtr cmd,
return 0;
}
+# endif /* ! __FreeBSD__ */
/*
* virExec:
diff --git a/tests/testutils.c b/tests/testutils.c
index 7b9a5ea05b..662203d707 100644
--- a/tests/testutils.c
+++ b/tests/testutils.c
@@ -333,8 +333,10 @@ static
void virTestCaptureProgramExecChild(const char *const argv[],
int pipefd)
{
+# ifndef __FreeBSD__
size_t i;
int open_max;
+# endif /* ! __FreeBSD__ */
int stdinfd = -1;
const char *const env[] = {
"LANG=C",
@@ -344,6 +346,7 @@ void virTestCaptureProgramExecChild(const char *const argv[],
if ((stdinfd = open("/dev/null", O_RDONLY)) < 0)
goto cleanup;
+# ifndef __FreeBSD__
open_max = sysconf(_SC_OPEN_MAX);
if (open_max < 0)
goto cleanup;
@@ -356,6 +359,7 @@ void virTestCaptureProgramExecChild(const char *const argv[],
VIR_FORCE_CLOSE(tmpfd);
}
}
+# endif /* __FreeBSD__ */
if (dup2(stdinfd, STDIN_FILENO) != STDIN_FILENO)
goto cleanup;
@@ -364,6 +368,11 @@ void virTestCaptureProgramExecChild(const char *const argv[],
if (dup2(pipefd, STDERR_FILENO) != STDERR_FILENO)
goto cleanup;
+# ifdef __FreeBSD__
+ closefrom(STDERR_FILENO);
+ stdinfd = pipefd = -1;
+# endif
+
/* SUS is crazy here, hence the cast */
execve(argv[0], (char *const*)argv, (char *const*)env);
--
2.24.1
4 years, 10 months
New release of libvirt-php?
by Neal Gompa
Hey,
It's been a couple of years (!!!) since the last libvirt-php release.
Since then, the code has been pretty dramatically restructured to more
closely mimic how libvirt and other bindings are structured. With that
and the new API add just pushed, could we get a new release of
libvirt-php?
IMO, it's a bad sign when the Fedora package has gone through 10
builds with a version bump with basically no interaction on my part
(automated rebuilds or mass change builds!).
--
真実はいつも一つ!/ Always, there's only one truth!
4 years, 10 months
[PATCH 0/2] virsh: qemu-monitor-command: Improve docs and retrun value handling
by Peter Krempa
2/2 was already reviewed, but it depends on the docs patch.
Peter Krempa (2):
docs: virsh: Modernize docs for qemu-monitor-command
virsh: Allow extracting 'return' section of QMP command in
'qemu-monitor-command'
docs/manpages/virsh.rst | 24 ++++++++++++++--------
tools/virsh-domain.c | 44 ++++++++++++++++++++++++++++++++---------
2 files changed, 51 insertions(+), 17 deletions(-)
--
2.24.1
4 years, 10 months
[libvirt PATCH] tests: avoid referencing stale readdir pointer
by Daniel P. Berrangé
The contents of 'struct dirent' are only valid until the next call to
readdir() or closedir(). It is thus invalid to save a pointer to the
'd_name' field. Somehow this hasn't affected the test suite until
recently when FreeBSD 12 started showing use of uninitialized memory
resulting in test failures.
Signed-off-by: Daniel P. Berrangé <berrange(a)redhat.com>
---
Pushed as a build fix
tests/testutilsqemu.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/tests/testutilsqemu.c b/tests/testutilsqemu.c
index c17e284930..0cb9a7456d 100644
--- a/tests/testutilsqemu.c
+++ b/tests/testutilsqemu.c
@@ -497,7 +497,7 @@ testQemuGetLatestCapsForArch(const char *arch,
char *tmp = NULL;
unsigned long maxver = 0;
unsigned long ver;
- const char *maxname = NULL;
+ g_autofree char *maxname = NULL;
char *ret = NULL;
fullsuffix = g_strdup_printf("%s.%s", arch, suffix);
@@ -522,7 +522,8 @@ testQemuGetLatestCapsForArch(const char *arch,
}
if (ver > maxver) {
- maxname = ent->d_name;
+ g_free(maxname);
+ maxname = g_strdup(ent->d_name);
maxver = ver;
}
}
--
2.24.1
4 years, 10 months