mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-07-31 14:07:16 +00:00
remote: fix handling of systemd activation wrt socket ordering
The current libvirtd code for systemd socket activation assumes socket FDs are passed in the order unix-rw, unix-ro, unix-admin. There is in fact no ordering guarantee made by systemd. Applications are expected to check the address or name associated with each FD to figure out its identity. This rewrites libvirtd to make use of the new systemd activation APIs to make it robust wrt socket ordering changes. Reviewed-by: Michal Privoznik <mprivozn@redhat.com> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
This commit is contained in:
parent
e9095c328a
commit
e2f012b8f0
@ -56,6 +56,7 @@
|
|||||||
#include "virutil.h"
|
#include "virutil.h"
|
||||||
#include "virgettext.h"
|
#include "virgettext.h"
|
||||||
#include "util/virnetdevopenvswitch.h"
|
#include "util/virnetdevopenvswitch.h"
|
||||||
|
#include "virsystemd.h"
|
||||||
|
|
||||||
#include "driver.h"
|
#include "driver.h"
|
||||||
|
|
||||||
@ -367,30 +368,34 @@ daemonSetupNetworking(virNetServerPtr srv,
|
|||||||
bool ipsock,
|
bool ipsock,
|
||||||
bool privileged)
|
bool privileged)
|
||||||
{
|
{
|
||||||
virNetServerServicePtr svc = NULL;
|
|
||||||
virNetServerServicePtr svcAdm = NULL;
|
|
||||||
virNetServerServicePtr svcRO = NULL;
|
|
||||||
virNetServerServicePtr svcTCP = NULL;
|
|
||||||
virNetServerServicePtr svcTLS = NULL;
|
|
||||||
gid_t unix_sock_gid = 0;
|
gid_t unix_sock_gid = 0;
|
||||||
int unix_sock_ro_mask = 0;
|
int unix_sock_ro_mask = 0;
|
||||||
int unix_sock_rw_mask = 0;
|
int unix_sock_rw_mask = 0;
|
||||||
int unix_sock_adm_mask = 0;
|
int unix_sock_adm_mask = 0;
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
|
VIR_AUTOPTR(virSystemdActivation) act = NULL;
|
||||||
|
virSystemdActivationMap actmap[] = {
|
||||||
|
{ .name = "libvirtd.socket", .family = AF_UNIX, .path = sock_path },
|
||||||
|
{ .name = "libvirtd-ro.socket", .family = AF_UNIX, .path = sock_path_ro },
|
||||||
|
{ .name = "libvirtd-admin.socket", .family = AF_UNIX, .path = sock_path_adm },
|
||||||
|
{ .name = "libvirtd-tcp.socket", .family = AF_INET },
|
||||||
|
{ .name = "libvirtd-tls.socket", .family = AF_INET },
|
||||||
|
};
|
||||||
|
|
||||||
unsigned int cur_fd = STDERR_FILENO + 1;
|
if ((actmap[3].port = virSocketAddrResolveService(config->tcp_port)) < 0)
|
||||||
unsigned int nfds = virGetListenFDs();
|
return -1;
|
||||||
|
|
||||||
|
if ((actmap[4].port = virSocketAddrResolveService(config->tls_port)) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (virSystemdGetActivation(actmap, ARRAY_CARDINALITY(actmap), &act) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
if (config->unix_sock_group) {
|
if (config->unix_sock_group) {
|
||||||
if (virGetGroupID(config->unix_sock_group, &unix_sock_gid) < 0)
|
if (virGetGroupID(config->unix_sock_group, &unix_sock_gid) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nfds > (sock_path_ro ? 2 : 1)) {
|
|
||||||
VIR_ERROR(_("Too many (%u) FDs passed from caller"), nfds);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (virStrToLong_i(config->unix_sock_ro_perms, NULL, 8, &unix_sock_ro_mask) != 0) {
|
if (virStrToLong_i(config->unix_sock_ro_perms, NULL, 8, &unix_sock_ro_mask) != 0) {
|
||||||
VIR_ERROR(_("Failed to parse mode '%s'"), config->unix_sock_ro_perms);
|
VIR_ERROR(_("Failed to parse mode '%s'"), config->unix_sock_ro_perms);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
@ -406,148 +411,135 @@ daemonSetupNetworking(virNetServerPtr srv,
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(svc = virNetServerServiceNewFDOrUNIX(sock_path,
|
if (virNetServerAddServiceUNIX(srv,
|
||||||
unix_sock_rw_mask,
|
act,
|
||||||
unix_sock_gid,
|
"libvirtd.socket",
|
||||||
config->auth_unix_rw,
|
sock_path,
|
||||||
NULL,
|
unix_sock_rw_mask,
|
||||||
false,
|
unix_sock_gid,
|
||||||
config->max_queued_clients,
|
config->auth_unix_rw,
|
||||||
config->max_client_requests,
|
NULL,
|
||||||
nfds, &cur_fd)))
|
false,
|
||||||
|
config->max_queued_clients,
|
||||||
|
config->max_client_requests) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
if (sock_path_ro) {
|
if (sock_path_ro &&
|
||||||
if (!(svcRO = virNetServerServiceNewFDOrUNIX(sock_path_ro,
|
virNetServerAddServiceUNIX(srv,
|
||||||
unix_sock_ro_mask,
|
act,
|
||||||
unix_sock_gid,
|
"libvirtd-ro.socket",
|
||||||
config->auth_unix_ro,
|
sock_path_ro,
|
||||||
NULL,
|
unix_sock_ro_mask,
|
||||||
true,
|
unix_sock_gid,
|
||||||
config->max_queued_clients,
|
config->auth_unix_ro,
|
||||||
config->max_client_requests,
|
NULL,
|
||||||
nfds, &cur_fd)))
|
true,
|
||||||
goto cleanup;
|
config->max_queued_clients,
|
||||||
}
|
config->max_client_requests) < 0)
|
||||||
|
|
||||||
if (virNetServerAddService(srv, svc) < 0)
|
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
if (svcRO &&
|
if (sock_path_adm &&
|
||||||
virNetServerAddService(srv, svcRO) < 0)
|
virNetServerAddServiceUNIX(srvAdm,
|
||||||
|
act,
|
||||||
|
"libvirtd-admin.socket",
|
||||||
|
sock_path_adm,
|
||||||
|
unix_sock_adm_mask,
|
||||||
|
unix_sock_gid,
|
||||||
|
REMOTE_AUTH_NONE,
|
||||||
|
NULL,
|
||||||
|
false,
|
||||||
|
config->admin_max_queued_clients,
|
||||||
|
config->admin_max_client_requests) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
if (sock_path_adm) {
|
if (((ipsock && config->listen_tcp) || act) &&
|
||||||
VIR_DEBUG("Registering unix socket %s", sock_path_adm);
|
virNetServerAddServiceTCP(srv,
|
||||||
if (!(svcAdm = virNetServerServiceNewUNIX(sock_path_adm,
|
act,
|
||||||
unix_sock_adm_mask,
|
"libvirtd-tcp.socket",
|
||||||
unix_sock_gid,
|
config->listen_addr,
|
||||||
REMOTE_AUTH_NONE,
|
config->tcp_port,
|
||||||
NULL,
|
AF_UNSPEC,
|
||||||
false,
|
config->auth_tcp,
|
||||||
config->admin_max_queued_clients,
|
NULL,
|
||||||
config->admin_max_client_requests)))
|
false,
|
||||||
goto cleanup;
|
config->max_queued_clients,
|
||||||
|
config->max_client_requests) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
if (virNetServerAddService(srvAdm, svcAdm) < 0)
|
if (((ipsock && config->listen_tls) || (act && virSystemdActivationHasName(act, "ip-tls")))) {
|
||||||
goto cleanup;
|
virNetTLSContextPtr ctxt = NULL;
|
||||||
}
|
|
||||||
|
|
||||||
if (ipsock) {
|
if (config->ca_file ||
|
||||||
if (config->listen_tcp) {
|
config->cert_file ||
|
||||||
VIR_DEBUG("Registering TCP socket %s:%s",
|
config->key_file) {
|
||||||
config->listen_addr, config->tcp_port);
|
if (!config->ca_file) {
|
||||||
if (!(svcTCP = virNetServerServiceNewTCP(config->listen_addr,
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||||
config->tcp_port,
|
_("No CA certificate path set to match server key/cert"));
|
||||||
AF_UNSPEC,
|
|
||||||
config->auth_tcp,
|
|
||||||
NULL,
|
|
||||||
false,
|
|
||||||
config->max_queued_clients,
|
|
||||||
config->max_client_requests)))
|
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
}
|
||||||
if (virNetServerAddService(srv, svcTCP) < 0)
|
if (!config->cert_file) {
|
||||||
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||||
|
_("No server certificate path set to match server key"));
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
if (!config->key_file) {
|
||||||
if (config->listen_tls) {
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||||
virNetTLSContextPtr ctxt = NULL;
|
_("No server key path set to match server cert"));
|
||||||
|
goto cleanup;
|
||||||
if (config->ca_file ||
|
}
|
||||||
config->cert_file ||
|
VIR_DEBUG("Using CA='%s' cert='%s' key='%s'",
|
||||||
config->key_file) {
|
config->ca_file, config->cert_file, config->key_file);
|
||||||
if (!config->ca_file) {
|
if (!(ctxt = virNetTLSContextNewServer(config->ca_file,
|
||||||
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
config->crl_file,
|
||||||
_("No CA certificate path set to match server key/cert"));
|
config->cert_file,
|
||||||
goto cleanup;
|
config->key_file,
|
||||||
}
|
(const char *const*)config->tls_allowed_dn_list,
|
||||||
if (!config->cert_file) {
|
config->tls_priority,
|
||||||
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
config->tls_no_sanity_certificate ? false : true,
|
||||||
_("No server certificate path set to match server key"));
|
config->tls_no_verify_certificate ? false : true)))
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
} else {
|
||||||
if (!config->key_file) {
|
if (!(ctxt = virNetTLSContextNewServerPath(NULL,
|
||||||
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
!privileged,
|
||||||
_("No server key path set to match server cert"));
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
VIR_DEBUG("Using CA='%s' cert='%s' key='%s'",
|
|
||||||
config->ca_file, config->cert_file, config->key_file);
|
|
||||||
if (!(ctxt = virNetTLSContextNewServer(config->ca_file,
|
|
||||||
config->crl_file,
|
|
||||||
config->cert_file,
|
|
||||||
config->key_file,
|
|
||||||
(const char *const*)config->tls_allowed_dn_list,
|
(const char *const*)config->tls_allowed_dn_list,
|
||||||
config->tls_priority,
|
config->tls_priority,
|
||||||
config->tls_no_sanity_certificate ? false : true,
|
config->tls_no_sanity_certificate ? false : true,
|
||||||
config->tls_no_verify_certificate ? false : true)))
|
config->tls_no_verify_certificate ? false : true)))
|
||||||
goto cleanup;
|
|
||||||
} else {
|
|
||||||
if (!(ctxt = virNetTLSContextNewServerPath(NULL,
|
|
||||||
!privileged,
|
|
||||||
(const char *const*)config->tls_allowed_dn_list,
|
|
||||||
config->tls_priority,
|
|
||||||
config->tls_no_sanity_certificate ? false : true,
|
|
||||||
config->tls_no_verify_certificate ? false : true)))
|
|
||||||
goto cleanup;
|
|
||||||
}
|
|
||||||
|
|
||||||
VIR_DEBUG("Registering TLS socket %s:%s",
|
|
||||||
config->listen_addr, config->tls_port);
|
|
||||||
if (!(svcTLS =
|
|
||||||
virNetServerServiceNewTCP(config->listen_addr,
|
|
||||||
config->tls_port,
|
|
||||||
AF_UNSPEC,
|
|
||||||
config->auth_tls,
|
|
||||||
ctxt,
|
|
||||||
false,
|
|
||||||
config->max_queued_clients,
|
|
||||||
config->max_client_requests))) {
|
|
||||||
virObjectUnref(ctxt);
|
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
|
||||||
if (virNetServerAddService(srv, svcTLS) < 0)
|
|
||||||
goto cleanup;
|
|
||||||
|
|
||||||
virObjectUnref(ctxt);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VIR_DEBUG("Registering TLS socket %s:%s",
|
||||||
|
config->listen_addr, config->tls_port);
|
||||||
|
if (virNetServerAddServiceTCP(srv,
|
||||||
|
act,
|
||||||
|
"libvirtd-tls.socket",
|
||||||
|
config->listen_addr,
|
||||||
|
config->tls_port,
|
||||||
|
AF_UNSPEC,
|
||||||
|
config->auth_tls,
|
||||||
|
ctxt,
|
||||||
|
false,
|
||||||
|
config->max_queued_clients,
|
||||||
|
config->max_client_requests) < 0) {
|
||||||
|
virObjectUnref(ctxt);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
virObjectUnref(ctxt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (act &&
|
||||||
|
virSystemdActivationComplete(act) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
#if WITH_SASL
|
#if WITH_SASL
|
||||||
if (virNetServerNeedsAuth(srv, REMOTE_AUTH_SASL) &&
|
if (virNetServerNeedsAuth(srv, REMOTE_AUTH_SASL) &&
|
||||||
!(saslCtxt = virNetSASLContextNewServer(
|
!(saslCtxt = virNetSASLContextNewServer(
|
||||||
(const char *const*)config->sasl_allowed_username_list)))
|
(const char *const*)config->sasl_allowed_username_list)))
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
virObjectUnref(svcTLS);
|
|
||||||
virObjectUnref(svcTCP);
|
|
||||||
virObjectUnref(svcRO);
|
|
||||||
virObjectUnref(svcAdm);
|
|
||||||
virObjectUnref(svc);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,9 +28,12 @@
|
|||||||
#include "viralloc.h"
|
#include "viralloc.h"
|
||||||
#include "virerror.h"
|
#include "virerror.h"
|
||||||
#include "virthread.h"
|
#include "virthread.h"
|
||||||
|
#include "virlog.h"
|
||||||
|
|
||||||
#define VIR_FROM_THIS VIR_FROM_RPC
|
#define VIR_FROM_THIS VIR_FROM_RPC
|
||||||
|
|
||||||
|
VIR_LOG_INIT("rpc.netserverservice");
|
||||||
|
|
||||||
struct _virNetServerService {
|
struct _virNetServerService {
|
||||||
virObject parent;
|
virObject parent;
|
||||||
|
|
||||||
@ -201,6 +204,8 @@ virNetServerServicePtr virNetServerServiceNewTCP(const char *nodename,
|
|||||||
virNetSocketPtr *socks;
|
virNetSocketPtr *socks;
|
||||||
size_t nsocks;
|
size_t nsocks;
|
||||||
|
|
||||||
|
VIR_DEBUG("Creating new TCP server nodename='%s' service='%s'",
|
||||||
|
NULLSTR(nodename), NULLSTR(service));
|
||||||
if (virNetSocketNewListenTCP(nodename,
|
if (virNetSocketNewListenTCP(nodename,
|
||||||
service,
|
service,
|
||||||
family,
|
family,
|
||||||
@ -236,6 +241,8 @@ virNetServerServicePtr virNetServerServiceNewUNIX(const char *path,
|
|||||||
virNetServerServicePtr svc;
|
virNetServerServicePtr svc;
|
||||||
virNetSocketPtr sock;
|
virNetSocketPtr sock;
|
||||||
|
|
||||||
|
VIR_DEBUG("Creating new UNIX server path='%s' mask=%o gid=%u",
|
||||||
|
path, mask, grp);
|
||||||
if (virNetSocketNewListenUNIX(path,
|
if (virNetSocketNewListenUNIX(path,
|
||||||
mask,
|
mask,
|
||||||
-1,
|
-1,
|
||||||
|
Loading…
Reference in New Issue
Block a user