On 03.08.2012 16:18, Marcelo Cerri wrote: > Thist patch updates libvirt's API to allow applications to inspect the > full list of security labels of a domain. > > Signed-off-by: Marcelo Cerri <mhcerri@xxxxxxxxxxxxxxxxxx> > --- > daemon/remote.c | 63 ++++++++++++++++++++++++++++++++++++ > include/libvirt/libvirt.h.in | 2 + > python/generator.py | 1 + > src/driver.h | 4 ++ > src/libvirt.c | 47 +++++++++++++++++++++++++++ > src/libvirt_public.syms | 5 +++ > src/qemu/qemu_driver.c | 73 ++++++++++++++++++++++++++++++++++++++++++ > src/remote/remote_driver.c | 46 ++++++++++++++++++++++++++ > src/remote/remote_protocol.x | 17 +++++++++- > src/remote_protocol-structs | 1 + > 10 files changed, 258 insertions(+), 1 deletions(-) > > diff --git a/daemon/remote.c b/daemon/remote.c > index d25717c..367180a 100644 > --- a/daemon/remote.c > +++ b/daemon/remote.c > @@ -1420,6 +1420,69 @@ cleanup: > } > > static int > +remoteDispatchDomainGetSecurityLabelList(virNetServerPtr server ATTRIBUTE_UNUSED, > + virNetServerClientPtr client ATTRIBUTE_UNUSED, > + virNetMessagePtr msg ATTRIBUTE_UNUSED, > + virNetMessageErrorPtr rerr, > + remote_domain_get_security_label_list_args *args, > + remote_domain_get_security_label_list_ret *ret) > +{ > + virDomainPtr dom = NULL; > + virSecurityLabelPtr seclabels = NULL; > + int i, len, rv = -1; > + struct daemonClientPrivate *priv = > + virNetServerClientGetPrivateData(client); > + > + if (!priv->conn) { > + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open")); > + goto cleanup; > + } > + > + if (!(dom = get_nonnull_domain(priv->conn, args->dom))) > + goto cleanup; > + > + if ((len = virDomainGetSecurityLabelList(dom, &seclabels)) < 0) { > + ret->ret = len; > + ret->labels.labels_len = 0; > + ret->labels.labels_val = NULL; > + goto done; > + } > + > + if (VIR_ALLOC_N(ret->labels.labels_val, len) < 0) { > + virReportOOMError(); > + goto cleanup; > + } > + > + for (i = 0; i < len; i++) { > + size_t label_len = strlen(seclabels[i].label) + 1; > + remote_domain_get_security_label_ret *cur = &ret->labels.labels_val[i]; > + if (VIR_ALLOC_N(cur->label.label_val, label_len) < 0) { > + virReportOOMError(); > + goto cleanup; > + } > + if (virStrcpy(cur->label.label_val, seclabels[i].label, label_len) == NULL) { > + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", > + _("failed to copy security label")); > + goto cleanup; > + } > + cur->label.label_len = label_len; > + cur->enforcing = seclabels[i].enforcing; > + } > + ret->labels.labels_len = ret->ret = len; > + > +done: > + rv = 0; > + > +cleanup: > + if (rv < 0) > + virNetMessageSaveError(rerr); > + if (dom) > + virDomainFree(dom); > + VIR_FREE(seclabels); > + return rv; > +} > + > +static int > remoteDispatchNodeGetSecurityModel(virNetServerPtr server ATTRIBUTE_UNUSED, > virNetServerClientPtr client ATTRIBUTE_UNUSED, > virNetMessagePtr msg ATTRIBUTE_UNUSED, > diff --git a/include/libvirt/libvirt.h.in b/include/libvirt/libvirt.h.in > index d21d029..0985dd3 100644 > --- a/include/libvirt/libvirt.h.in > +++ b/include/libvirt/libvirt.h.in > @@ -1593,6 +1593,8 @@ int virDomainGetSecurityLabel (virDomainPtr domain, > virSecurityLabelPtr seclabel); > char * virDomainGetHostname (virDomainPtr domain, > unsigned int flags); > +int virDomainGetSecurityLabelList (virDomainPtr domain, > + virSecurityLabelPtr* seclabels); > > typedef enum { > VIR_DOMAIN_METADATA_DESCRIPTION = 0, /* Operate on <description> */ > diff --git a/python/generator.py b/python/generator.py > index 6559ece..1f87195 100755 > --- a/python/generator.py > +++ b/python/generator.py > @@ -448,6 +448,7 @@ skip_function = ( > 'virConnectOpenAuth', # Python C code is manually written > 'virDefaultErrorFunc', # Python virErrorFuncHandler impl calls this from C > 'virDomainGetSecurityLabel', # Needs investigation... > + 'virDomainGetSecurityLabelList', # Needs investigation... > 'virNodeGetSecurityModel', # Needs investigation... > 'virConnectDomainEventRegister', # overridden in virConnect.py > 'virConnectDomainEventDeregister', # overridden in virConnect.py > diff --git a/src/driver.h b/src/driver.h > index aab9766..203497d 100644 > --- a/src/driver.h > +++ b/src/driver.h > @@ -320,6 +320,9 @@ typedef int > (*virDrvDomainGetSecurityLabel) (virDomainPtr domain, > virSecurityLabelPtr seclabel); > typedef int > + (*virDrvDomainGetSecurityLabelList) (virDomainPtr domain, > + virSecurityLabelPtr* seclabels); > +typedef int > (*virDrvNodeGetSecurityModel) (virConnectPtr conn, > virSecurityModelPtr secmodel); > typedef int > @@ -941,6 +944,7 @@ struct _virDriver { > virDrvDomainGetVcpus domainGetVcpus; > virDrvDomainGetMaxVcpus domainGetMaxVcpus; > virDrvDomainGetSecurityLabel domainGetSecurityLabel; > + virDrvDomainGetSecurityLabelList domainGetSecurityLabelList; > virDrvNodeGetSecurityModel nodeGetSecurityModel; > virDrvDomainGetXMLDesc domainGetXMLDesc; > virDrvConnectDomainXMLFromNative domainXMLFromNative; > diff --git a/src/libvirt.c b/src/libvirt.c > index 3c4bf8c..dfe49eb 100644 > --- a/src/libvirt.c > +++ b/src/libvirt.c > @@ -9027,6 +9027,53 @@ error: > } > > /** > + * virDomainGetSecurityLabelList: > + * @domain: a domain object > + * @seclabels: will be auto-allocated and filled with domains' security labels. > + * Caller must free memory on return. > + * > + * Extract the security labels of an active domain. The 'label' field > + * in the @seclabels argument will be initialized to the empty > + * string if the domain is not running under a security model. > + * > + * Returns 0 in case of success, -1 in case of failure > + */ > +int > +virDomainGetSecurityLabelList(virDomainPtr domain, > + virSecurityLabelPtr* seclabels) > +{ > + virConnectPtr conn; > + > + VIR_DOMAIN_DEBUG(domain, "seclabels=%p", seclabels); > + > + if (!VIR_IS_CONNECTED_DOMAIN(domain)) { > + virLibDomainError(VIR_ERR_INVALID_DOMAIN, __FUNCTION__); > + virDispatchError(NULL); > + return -1; > + } > + > + if (seclabels == NULL) { > + virLibDomainError(VIR_ERR_INVALID_ARG, __FUNCTION__); > + goto error; > + } > + > + conn = domain->conn; > + > + if (conn->driver->domainGetSecurityLabelList) { > + int ret; > + ret = conn->driver->domainGetSecurityLabelList(domain, seclabels); > + if (ret < 0) > + goto error; > + return ret; > + } > + > + virLibConnError(VIR_ERR_NO_SUPPORT, __FUNCTION__); > + > +error: > + virDispatchError(domain->conn); > + return -1; > +} > +/** > * virDomainSetMetadata: > * @domain: a domain object > * @type: type of description, from virDomainMetadataType > diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms > index e3ba119..06ef08a 100644 > --- a/src/libvirt_public.syms > +++ b/src/libvirt_public.syms > @@ -551,4 +551,9 @@ LIBVIRT_0.10.0 { > virConnectUnregisterCloseCallback; > } LIBVIRT_0.9.13; > > +LIBVIRT_0.10.1{ > + global: > + virDomainGetSecurityLabelList; > +} LIBVIRT_0.10.0; > + Since 0.10.0 is not out yet, I guess this can be squashed into 0.10.0 (okay, we've release -rc0 but that's because patch flow is lower making our release prolonged about twice). > # .... define new API here using predicted next version number .... > diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c > index ec0f02b..7d95fef 100644 > --- a/src/qemu/qemu_driver.c > +++ b/src/qemu/qemu_driver.c > @@ -4089,6 +4089,78 @@ cleanup: > return ret; > } > > +static int qemuDomainGetSecurityLabelList(virDomainPtr dom, > + virSecurityLabelPtr* seclabels) > +{ > + struct qemud_driver *driver = dom->conn->privateData; > + virDomainObjPtr vm; > + int i, ret = -1; > + > + /* Protect domain data with qemu lock */ > + qemuDriverLock(driver); > + vm = virDomainFindByUUID(&driver->domains, dom->uuid); > + > + if (!vm) { > + char uuidstr[VIR_UUID_STRING_BUFLEN]; > + virUUIDFormat(dom->uuid, uuidstr); > + virReportError(VIR_ERR_NO_DOMAIN, > + _("no domain with matching uuid '%s'"), uuidstr); > + goto cleanup; > + } > + > + if (!virDomainVirtTypeToString(vm->def->virtType)) { > + virReportError(VIR_ERR_INTERNAL_ERROR, > + _("unknown virt type in domain definition '%d'"), > + vm->def->virtType); > + goto cleanup; > + } > + > + /* > + * Check the comment in qemudDomainGetSecurityLabel function. > + */ > + if (!virDomainObjIsActive(vm)) { > + /* No seclabels */ > + *seclabels = NULL; > + ret = 0; > + } else { > + int len = 0; > + virSecurityManagerPtr* mgrs = virSecurityManagerGetNested( > + driver->securityManager); > + if (!mgrs) > + goto cleanup; > + > + /* Allocate seclabels array */ > + for (i = 0; mgrs[i]; i++) > + len++; > + > + if (VIR_ALLOC_N((*seclabels), len) < 0) { > + virReportOOMError(); > + VIR_FREE(mgrs); > + goto cleanup; > + } > + memset(*seclabels, 0, sizeof(**seclabels) * len); > + > + /* Fill the array */ > + for (i = 0; i < len; i++) { > + if (virSecurityManagerGetProcessLabel(mgrs[i], vm->def, vm->pid, > + &(*seclabels)[i]) < 0) { > + virReportError(VIR_ERR_INTERNAL_ERROR, > + "%s", _("Failed to get security label")); > + VIR_FREE(mgrs); > + VIR_FREE(*seclabels); > + goto cleanup; > + } > + } > + ret = len; > + VIR_FREE(mgrs); > + } > + > +cleanup: > + if (vm) > + virDomainObjUnlock(vm); > + qemuDriverUnlock(driver); > + return ret; > +} > static int qemudNodeGetSecurityModel(virConnectPtr conn, > virSecurityModelPtr secmodel) > { > @@ -13332,6 +13404,7 @@ static virDriver qemuDriver = { > .domainGetVcpus = qemudDomainGetVcpus, /* 0.4.4 */ > .domainGetMaxVcpus = qemudDomainGetMaxVcpus, /* 0.4.4 */ > .domainGetSecurityLabel = qemudDomainGetSecurityLabel, /* 0.6.1 */ > + .domainGetSecurityLabelList = qemuDomainGetSecurityLabelList, /* 0.10.0 */ > .nodeGetSecurityModel = qemudNodeGetSecurityModel, /* 0.6.1 */ > .domainGetXMLDesc = qemuDomainGetXMLDesc, /* 0.2.0 */ > .domainXMLFromNative = qemuDomainXMLFromNative, /* 0.6.4 */ > diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c > index afd367b..6f56ee6 100644 > --- a/src/remote/remote_driver.c > +++ b/src/remote/remote_driver.c > @@ -1956,6 +1956,51 @@ done: > } > > static int > +remoteDomainGetSecurityLabelList (virDomainPtr domain, virSecurityLabelPtr* seclabels) > +{ > + remote_domain_get_security_label_list_args args; > + remote_domain_get_security_label_list_ret ret; > + struct private_data *priv = domain->conn->privateData; > + int i, rv = -1; > + > + remoteDriverLock(priv); > + > + make_nonnull_domain (&args.dom, domain); > + memset(&ret, 0, sizeof(ret)); > + > + if (call (domain->conn, priv, 0, REMOTE_PROC_DOMAIN_GET_SECURITY_LABEL_LIST, > + (xdrproc_t) xdr_remote_domain_get_security_label_list_args, (char *)&args, > + (xdrproc_t) xdr_remote_domain_get_security_label_list_ret, (char *)&ret) == -1) { > + goto done; > + } > + > + if (VIR_ALLOC_N(*seclabels, ret.labels.labels_len) < 0) > + goto cleanup; > + > + for (i = 0; i < ret.labels.labels_len; i++) { > + remote_domain_get_security_label_ret *cur = &ret.labels.labels_val[i]; > + if (cur->label.label_val != NULL) { > + if (strlen(cur->label.label_val) >= sizeof((*seclabels)->label)) { > + virReportError(VIR_ERR_RPC, _("security label exceeds maximum: %zd"), > + sizeof((*seclabels)->label) - 1); > + VIR_FREE(*seclabels); > + goto cleanup; > + } > + strcpy((*seclabels)[i].label, cur->label.label_val); > + (*seclabels)[i].enforcing = cur->enforcing; > + } > + } > + rv = ret.ret; > + > +cleanup: > + xdr_free((xdrproc_t) xdr_remote_domain_get_security_label_list_ret, (char *)&ret); > + > +done: > + remoteDriverUnlock(priv); > + return rv; > +} > + > +static int > remoteDomainGetState(virDomainPtr domain, > int *state, > int *reason, > @@ -5258,6 +5303,7 @@ static virDriver remote_driver = { > .domainGetVcpus = remoteDomainGetVcpus, /* 0.3.0 */ > .domainGetMaxVcpus = remoteDomainGetMaxVcpus, /* 0.3.0 */ > .domainGetSecurityLabel = remoteDomainGetSecurityLabel, /* 0.6.1 */ > + .domainGetSecurityLabelList = remoteDomainGetSecurityLabelList, /* 0.10.0*/ > .nodeGetSecurityModel = remoteNodeGetSecurityModel, /* 0.6.1 */ > .domainGetXMLDesc = remoteDomainGetXMLDesc, /* 0.3.0 */ > .domainXMLFromNative = remoteDomainXMLFromNative, /* 0.6.4 */ > diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x > index 200fe75..3be15f5 100644 > --- a/src/remote/remote_protocol.x > +++ b/src/remote/remote_protocol.x > @@ -169,6 +169,11 @@ const REMOTE_DOMAIN_BLOCK_PEEK_BUFFER_MAX = 1048576; > const REMOTE_DOMAIN_MEMORY_PEEK_BUFFER_MAX = 1048576; > > /* > + * Maximum length of a security label list. > + */ > +const REMOTE_SECURITY_LABEL_LIST_MAX=64; > + > +/* > * Maximum length of a security model field. > */ > const REMOTE_SECURITY_MODEL_MAX = VIR_SECURITY_MODEL_BUFLEN; > @@ -1082,6 +1087,15 @@ struct remote_domain_get_security_label_ret { > int enforcing; > }; > > +struct remote_domain_get_security_label_list_args { > + remote_nonnull_domain dom; > +}; > + > +struct remote_domain_get_security_label_list_ret { > + remote_domain_get_security_label_ret labels<REMOTE_SECURITY_LABEL_LIST_MAX>; > + int ret; > +}; > + > struct remote_node_get_security_model_ret { > char model<REMOTE_SECURITY_MODEL_MAX>; > char doi<REMOTE_SECURITY_DOI_MAX>; > @@ -2854,7 +2868,8 @@ enum remote_procedure { > REMOTE_PROC_DOMAIN_LIST_ALL_SNAPSHOTS = 274, /* skipgen skipgen priority:high */ > REMOTE_PROC_DOMAIN_SNAPSHOT_LIST_ALL_CHILDREN = 275, /* skipgen skipgen priority:high */ > REMOTE_PROC_DOMAIN_EVENT_BALLOON_CHANGE = 276, /* autogen autogen */ > - REMOTE_PROC_DOMAIN_GET_HOSTNAME = 277 /* autogen autogen */ > + REMOTE_PROC_DOMAIN_GET_HOSTNAME = 277, /* autogen autogen */ > + REMOTE_PROC_DOMAIN_GET_SECURITY_LABEL_LIST = 278 /* skipgen skipgen priority:high */ > > /* > * Notice how the entries are grouped in sets of 10 ? > diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs > index 8d09138..9cfd285 100644 > --- a/src/remote_protocol-structs > +++ b/src/remote_protocol-structs > @@ -2259,4 +2259,5 @@ enum remote_procedure { > REMOTE_PROC_DOMAIN_SNAPSHOT_LIST_ALL_CHILDREN = 275, > REMOTE_PROC_DOMAIN_EVENT_BALLOON_CHANGE = 276, > REMOTE_PROC_DOMAIN_GET_HOSTNAME = 277, > + REMOTE_PROC_DOMAIN_GET_SECURITY_LABEL_LIST = 278, > }; > ACK with this squashed in: --- remote_protocol-structs 2012-08-06 14:47:40.813120178 +0200 +++ remote_protocol-struct-t3 2012-08-06 15:22:39.223650145 +0200 @@ -749,6 +749,16 @@ } label; int enforcing; }; +struct remote_domain_get_security_label_list_args { + remote_nonnull_domain dom; +}; +struct remote_domain_get_security_label_list_ret { + struct { + u_int labels_len; + remote_domain_get_security_label_ret * labels_val; + } labels; + int ret; +}; struct remote_node_get_security_model_ret { struct { u_int model_len; and libvirt_public.syms updated. Michal -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list