mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-22 05:35:25 +00:00
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:
parent
6d6bff3a46
commit
2f8a09fbce
@ -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,
|
||||
|
@ -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> */
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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 ....
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
@ -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 ?
|
||||
|
@ -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,
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user