Update the remote API

This 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@linux.vnet.ibm.com>
This commit is contained in:
Marcelo Cerri 2012-08-15 19:10:39 -03:00 committed by Michal Privoznik
parent 6d6bff3a46
commit 2f8a09fbce
10 changed files with 264 additions and 1 deletions

View File

@ -1416,6 +1416,69 @@ cleanup:
return rv;
}
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,

View File

@ -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> */

View File

@ -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

View File

@ -319,6 +319,9 @@ typedef int
typedef int
(*virDrvDomainGetSecurityLabel) (virDomainPtr domain,
virSecurityLabelPtr seclabel);
typedef int
(*virDrvDomainGetSecurityLabelList) (virDomainPtr domain,
virSecurityLabelPtr* seclabels);
typedef int
(*virDrvNodeGetSecurityModel) (virConnectPtr conn,
virSecurityModelPtr secmodel);
@ -941,6 +944,7 @@ struct _virDriver {
virDrvDomainGetVcpus domainGetVcpus;
virDrvDomainGetMaxVcpus domainGetMaxVcpus;
virDrvDomainGetSecurityLabel domainGetSecurityLabel;
virDrvDomainGetSecurityLabelList domainGetSecurityLabelList;
virDrvNodeGetSecurityModel nodeGetSecurityModel;
virDrvDomainGetXMLDesc domainGetXMLDesc;
virDrvConnectDomainXMLFromNative domainXMLFromNative;

View File

@ -9020,6 +9020,53 @@ error:
return -1;
}
/**
* 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 number of elemnets in @seclabels on 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

View File

@ -549,6 +549,7 @@ LIBVIRT_0.10.0 {
virDomainGetHostname;
virConnectRegisterCloseCallback;
virConnectUnregisterCloseCallback;
virDomainGetSecurityLabelList;
} LIBVIRT_0.9.13;
# .... define new API here using predicted next version number ....

View File

@ -4119,6 +4119,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)
{
@ -13422,6 +13494,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 */

View File

@ -1957,6 +1957,51 @@ done:
return rv;
}
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,
@ -5260,6 +5305,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 */

View File

@ -168,6 +168,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.
*/
@ -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 ?

View File

@ -749,6 +749,16 @@ struct remote_domain_get_security_label_ret {
} 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;
@ -2259,4 +2269,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,
};