mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-07-11 04:15:49 +00:00
API: add VIR_TYPED_PARAM_STRING
This allows strings to be transported between client and server in the context of name-type-value virTypedParameter functions. For compatibility, o new clients will not send strings to old servers, based on a feature check o new servers will not send strings to old clients without the flag VIR_TYPED_PARAM_STRING_OKAY; this will be enforced at the RPC layer in the next patch, so that drivers need not worry about it in general. The one exception is that virDomainGetSchedulerParameters lacks a flags argument, so it must not return a string; drivers that forward that function on to virDomainGetSchedulerParametersFlags will have to pay attention to the flag. o the flag VIR_TYPED_PARAM_STRING_OKAY is set automatically, based on a feature check (so far, no driver implements it), so clients do not have to worry about it Future patches can then enable the feature on a per-driver basis. This patch also ensures that drivers can blindly strdup() field names (previously, a malicious client could stuff 80 non-NUL bytes into field and cause a read overrun). * src/libvirt_internal.h (VIR_DRV_FEATURE_TYPED_PARAM_STRING): New driver feature. * src/libvirt.c (virTypedParameterValidateSet) (virTypedParameterSanitizeGet): New helper functions. (virDomainSetMemoryParameters, virDomainSetBlkioParameters) (virDomainSetSchedulerParameters) (virDomainSetSchedulerParametersFlags) (virDomainGetMemoryParameters, virDomainGetBlkioParameters) (virDomainGetSchedulerParameters) (virDomainGetSchedulerParametersFlags, virDomainBlockStatsFlags): Use them. * src/util/util.h (virTypedParameterArrayClear): New helper function. * src/util/util.c (virTypedParameterArrayClear): Implement it. * src/libvirt_private.syms (util.h): Export it. Based on an initial patch by Hu Tao, with feedback from Daniel P. Berrange. Signed-off-by: Eric Blake <eblake@redhat.com>
This commit is contained in:
parent
329b2b2819
commit
a218c81da2
@ -200,11 +200,14 @@ typedef virDomainControlInfo *virDomainControlInfoPtr;
|
|||||||
* current domain state. VIR_DOMAIN_AFFECT_LIVE requires a running
|
* current domain state. VIR_DOMAIN_AFFECT_LIVE requires a running
|
||||||
* domain, and VIR_DOMAIN_AFFECT_CONFIG requires a persistent domain
|
* domain, and VIR_DOMAIN_AFFECT_CONFIG requires a persistent domain
|
||||||
* (whether or not it is running).
|
* (whether or not it is running).
|
||||||
|
*
|
||||||
|
* These enums should not conflict with those of virTypedParameterFlags.
|
||||||
*/
|
*/
|
||||||
typedef enum {
|
typedef enum {
|
||||||
VIR_DOMAIN_AFFECT_CURRENT = 0, /* Affect current domain state. */
|
VIR_DOMAIN_AFFECT_CURRENT = 0, /* Affect current domain state. */
|
||||||
VIR_DOMAIN_AFFECT_LIVE = 1 << 0, /* Affect running domain state. */
|
VIR_DOMAIN_AFFECT_LIVE = 1 << 0, /* Affect running domain state. */
|
||||||
VIR_DOMAIN_AFFECT_CONFIG = 1 << 1, /* Affect persistent domain state. */
|
VIR_DOMAIN_AFFECT_CONFIG = 1 << 1, /* Affect persistent domain state. */
|
||||||
|
/* 1 << 2 is reserved for virTypedParameterFlags */
|
||||||
} virDomainModificationImpact;
|
} virDomainModificationImpact;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -489,9 +492,35 @@ typedef enum {
|
|||||||
VIR_TYPED_PARAM_LLONG = 3, /* long long case */
|
VIR_TYPED_PARAM_LLONG = 3, /* long long case */
|
||||||
VIR_TYPED_PARAM_ULLONG = 4, /* unsigned long long case */
|
VIR_TYPED_PARAM_ULLONG = 4, /* unsigned long long case */
|
||||||
VIR_TYPED_PARAM_DOUBLE = 5, /* double case */
|
VIR_TYPED_PARAM_DOUBLE = 5, /* double case */
|
||||||
VIR_TYPED_PARAM_BOOLEAN = 6 /* boolean(character) case */
|
VIR_TYPED_PARAM_BOOLEAN = 6, /* boolean(character) case */
|
||||||
|
VIR_TYPED_PARAM_STRING = 7, /* string case */
|
||||||
} virTypedParameterType;
|
} virTypedParameterType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* virTypedParameterFlags:
|
||||||
|
*
|
||||||
|
* Flags related to libvirt APIs that use virTypedParameter.
|
||||||
|
*
|
||||||
|
* These enums should not conflict with those of virDomainModificationImpact.
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
/* 1 << 0 is reserved for virDomainModificationImpact */
|
||||||
|
/* 1 << 1 is reserved for virDomainModificationImpact */
|
||||||
|
|
||||||
|
/* Older servers lacked the ability to handle string typed
|
||||||
|
* parameters. Attempts to set a string parameter with an older
|
||||||
|
* server will fail at the client, but attempts to retrieve
|
||||||
|
* parameters must not return strings from a new server to an
|
||||||
|
* older client, so this flag exists to identify newer clients to
|
||||||
|
* newer servers. This flag is automatically set when needed, so
|
||||||
|
* the user does not have to worry about it; however, manually
|
||||||
|
* setting the flag can be used to reject servers that cannot
|
||||||
|
* return typed strings, even if no strings would be returned.
|
||||||
|
*/
|
||||||
|
VIR_TYPED_PARAM_STRING_OKAY = 1 << 2,
|
||||||
|
|
||||||
|
} virTypedParameterFlags;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* VIR_TYPED_PARAM_FIELD_LENGTH:
|
* VIR_TYPED_PARAM_FIELD_LENGTH:
|
||||||
*
|
*
|
||||||
@ -520,6 +549,7 @@ struct _virTypedParameter {
|
|||||||
unsigned long long int ul; /* type is ULLONG */
|
unsigned long long int ul; /* type is ULLONG */
|
||||||
double d; /* type is DOUBLE */
|
double d; /* type is DOUBLE */
|
||||||
char b; /* type is BOOLEAN */
|
char b; /* type is BOOLEAN */
|
||||||
|
char *s; /* type is STRING, may not be NULL */
|
||||||
} value; /* parameter value */
|
} value; /* parameter value */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -3583,6 +3583,50 @@ error:
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Helper function called to validate incoming client array on any
|
||||||
|
* interface that sets typed parameters in the hypervisor. */
|
||||||
|
static int
|
||||||
|
virTypedParameterValidateSet(virDomainPtr domain,
|
||||||
|
virTypedParameterPtr params,
|
||||||
|
int nparams)
|
||||||
|
{
|
||||||
|
bool string_okay;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
string_okay = VIR_DRV_SUPPORTS_FEATURE(domain->conn->driver,
|
||||||
|
domain->conn,
|
||||||
|
VIR_DRV_FEATURE_TYPED_PARAM_STRING);
|
||||||
|
for (i = 0; i < nparams; i++) {
|
||||||
|
if (strnlen(params[i].field, VIR_TYPED_PARAM_FIELD_LENGTH) ==
|
||||||
|
VIR_TYPED_PARAM_FIELD_LENGTH) {
|
||||||
|
virLibDomainError(VIR_ERR_INVALID_ARG,
|
||||||
|
_("string parameter name '%.*s' too long"),
|
||||||
|
VIR_TYPED_PARAM_FIELD_LENGTH,
|
||||||
|
params[i].field);
|
||||||
|
virDispatchError(NULL);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (params[i].type == VIR_TYPED_PARAM_STRING) {
|
||||||
|
if (string_okay) {
|
||||||
|
if (!params[i].value.s) {
|
||||||
|
virLibDomainError(VIR_ERR_INVALID_ARG,
|
||||||
|
_("NULL string parameter '%s'"),
|
||||||
|
params[i].field);
|
||||||
|
virDispatchError(NULL);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
virLibDomainError(VIR_ERR_INVALID_ARG,
|
||||||
|
_("string parameter '%s' unsupported"),
|
||||||
|
params[i].field);
|
||||||
|
virDispatchError(NULL);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* virDomainSetMemoryParameters:
|
* virDomainSetMemoryParameters:
|
||||||
* @domain: pointer to domain object
|
* @domain: pointer to domain object
|
||||||
@ -3621,6 +3665,9 @@ virDomainSetMemoryParameters(virDomainPtr domain,
|
|||||||
virLibDomainError(VIR_ERR_INVALID_ARG, __FUNCTION__);
|
virLibDomainError(VIR_ERR_INVALID_ARG, __FUNCTION__);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
if (virTypedParameterValidateSet(domain, params, nparams) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
conn = domain->conn;
|
conn = domain->conn;
|
||||||
|
|
||||||
if (conn->driver->domainSetMemoryParameters) {
|
if (conn->driver->domainSetMemoryParameters) {
|
||||||
@ -3644,7 +3691,7 @@ error:
|
|||||||
* @params: pointer to memory parameter object
|
* @params: pointer to memory parameter object
|
||||||
* (return value, allocated by the caller)
|
* (return value, allocated by the caller)
|
||||||
* @nparams: pointer to number of memory parameters; input and output
|
* @nparams: pointer to number of memory parameters; input and output
|
||||||
* @flags: one of virDomainModificationImpact
|
* @flags: bitwise-OR of virDomainModificationImpact and virTypedParameterFlags
|
||||||
*
|
*
|
||||||
* Get all memory parameters. On input, @nparams gives the size of the
|
* Get all memory parameters. On input, @nparams gives the size of the
|
||||||
* @params array; on output, @nparams gives how many slots were filled
|
* @params array; on output, @nparams gives how many slots were filled
|
||||||
@ -3695,6 +3742,9 @@ virDomainGetMemoryParameters(virDomainPtr domain,
|
|||||||
virLibDomainError(VIR_ERR_INVALID_ARG, __FUNCTION__);
|
virLibDomainError(VIR_ERR_INVALID_ARG, __FUNCTION__);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
if (VIR_DRV_SUPPORTS_FEATURE(domain->conn->driver, domain->conn,
|
||||||
|
VIR_DRV_FEATURE_TYPED_PARAM_STRING))
|
||||||
|
flags |= VIR_TYPED_PARAM_STRING_OKAY;
|
||||||
conn = domain->conn;
|
conn = domain->conn;
|
||||||
|
|
||||||
if (conn->driver->domainGetMemoryParameters) {
|
if (conn->driver->domainGetMemoryParameters) {
|
||||||
@ -3717,7 +3767,7 @@ error:
|
|||||||
* @params: pointer to blkio parameter objects
|
* @params: pointer to blkio parameter objects
|
||||||
* @nparams: number of blkio parameters (this value can be the same or
|
* @nparams: number of blkio parameters (this value can be the same or
|
||||||
* less than the number of parameters supported)
|
* less than the number of parameters supported)
|
||||||
* @flags: an OR'ed set of virDomainModificationImpact
|
* @flags: bitwise-OR of virDomainModificationImpact
|
||||||
*
|
*
|
||||||
* Change all or a subset of the blkio tunables.
|
* Change all or a subset of the blkio tunables.
|
||||||
* This function may require privileged access to the hypervisor.
|
* This function may require privileged access to the hypervisor.
|
||||||
@ -3749,6 +3799,9 @@ virDomainSetBlkioParameters(virDomainPtr domain,
|
|||||||
virLibDomainError(VIR_ERR_INVALID_ARG, __FUNCTION__);
|
virLibDomainError(VIR_ERR_INVALID_ARG, __FUNCTION__);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
if (virTypedParameterValidateSet(domain, params, nparams) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
conn = domain->conn;
|
conn = domain->conn;
|
||||||
|
|
||||||
if (conn->driver->domainSetBlkioParameters) {
|
if (conn->driver->domainSetBlkioParameters) {
|
||||||
@ -3772,7 +3825,7 @@ error:
|
|||||||
* @params: pointer to blkio parameter object
|
* @params: pointer to blkio parameter object
|
||||||
* (return value, allocated by the caller)
|
* (return value, allocated by the caller)
|
||||||
* @nparams: pointer to number of blkio parameters; input and output
|
* @nparams: pointer to number of blkio parameters; input and output
|
||||||
* @flags: an OR'ed set of virDomainModificationImpact
|
* @flags: bitwise-OR of virDomainModificationImpact and virTypedParameterFlags
|
||||||
*
|
*
|
||||||
* Get all blkio parameters. On input, @nparams gives the size of the
|
* Get all blkio parameters. On input, @nparams gives the size of the
|
||||||
* @params array; on output, @nparams gives how many slots were filled
|
* @params array; on output, @nparams gives how many slots were filled
|
||||||
@ -3814,6 +3867,9 @@ virDomainGetBlkioParameters(virDomainPtr domain,
|
|||||||
virLibDomainError(VIR_ERR_INVALID_ARG, __FUNCTION__);
|
virLibDomainError(VIR_ERR_INVALID_ARG, __FUNCTION__);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
if (VIR_DRV_SUPPORTS_FEATURE(domain->conn->driver, domain->conn,
|
||||||
|
VIR_DRV_FEATURE_TYPED_PARAM_STRING))
|
||||||
|
flags |= VIR_TYPED_PARAM_STRING_OKAY;
|
||||||
conn = domain->conn;
|
conn = domain->conn;
|
||||||
|
|
||||||
if (conn->driver->domainGetBlkioParameters) {
|
if (conn->driver->domainGetBlkioParameters) {
|
||||||
@ -6410,7 +6466,7 @@ error:
|
|||||||
* @nparams: pointer to number of scheduler parameter
|
* @nparams: pointer to number of scheduler parameter
|
||||||
* (this value should be same than the returned value
|
* (this value should be same than the returned value
|
||||||
* nparams of virDomainGetSchedulerType()); input and output
|
* nparams of virDomainGetSchedulerType()); input and output
|
||||||
* @flags: one of virDomainModificationImpact
|
* @flags: bitwise-OR of virDomainModificationImpact and virTypedParameterFlags
|
||||||
*
|
*
|
||||||
* Get all scheduler parameters. On input, @nparams gives the size of the
|
* Get all scheduler parameters. On input, @nparams gives the size of the
|
||||||
* @params array; on output, @nparams gives how many slots were filled
|
* @params array; on output, @nparams gives how many slots were filled
|
||||||
@ -6456,6 +6512,9 @@ virDomainGetSchedulerParametersFlags(virDomainPtr domain,
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (VIR_DRV_SUPPORTS_FEATURE(domain->conn->driver, domain->conn,
|
||||||
|
VIR_DRV_FEATURE_TYPED_PARAM_STRING))
|
||||||
|
flags |= VIR_TYPED_PARAM_STRING_OKAY;
|
||||||
conn = domain->conn;
|
conn = domain->conn;
|
||||||
|
|
||||||
if (conn->driver->domainGetSchedulerParametersFlags) {
|
if (conn->driver->domainGetSchedulerParametersFlags) {
|
||||||
@ -6505,15 +6564,17 @@ virDomainSetSchedulerParameters(virDomainPtr domain,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (params == NULL || nparams < 0) {
|
|
||||||
virLibDomainError(VIR_ERR_INVALID_ARG, __FUNCTION__);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (domain->conn->flags & VIR_CONNECT_RO) {
|
if (domain->conn->flags & VIR_CONNECT_RO) {
|
||||||
virLibDomainError(VIR_ERR_OPERATION_DENIED, __FUNCTION__);
|
virLibDomainError(VIR_ERR_OPERATION_DENIED, __FUNCTION__);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
if (params == NULL || nparams < 0) {
|
||||||
|
virLibDomainError(VIR_ERR_INVALID_ARG, __FUNCTION__);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
if (virTypedParameterValidateSet(domain, params, nparams) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
conn = domain->conn;
|
conn = domain->conn;
|
||||||
|
|
||||||
if (conn->driver->domainSetSchedulerParameters) {
|
if (conn->driver->domainSetSchedulerParameters) {
|
||||||
@ -6568,15 +6629,17 @@ virDomainSetSchedulerParametersFlags(virDomainPtr domain,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (params == NULL || nparams < 0) {
|
|
||||||
virLibDomainError(VIR_ERR_INVALID_ARG, __FUNCTION__);
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (domain->conn->flags & VIR_CONNECT_RO) {
|
if (domain->conn->flags & VIR_CONNECT_RO) {
|
||||||
virLibDomainError(VIR_ERR_OPERATION_DENIED, __FUNCTION__);
|
virLibDomainError(VIR_ERR_OPERATION_DENIED, __FUNCTION__);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
if (params == NULL || nparams < 0) {
|
||||||
|
virLibDomainError(VIR_ERR_INVALID_ARG, __FUNCTION__);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
if (virTypedParameterValidateSet(domain, params, nparams) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
conn = domain->conn;
|
conn = domain->conn;
|
||||||
|
|
||||||
if (conn->driver->domainSetSchedulerParametersFlags) {
|
if (conn->driver->domainSetSchedulerParametersFlags) {
|
||||||
@ -6665,7 +6728,7 @@ error:
|
|||||||
* @params: pointer to block stats parameter object
|
* @params: pointer to block stats parameter object
|
||||||
* (return value)
|
* (return value)
|
||||||
* @nparams: pointer to number of block stats; input and output
|
* @nparams: pointer to number of block stats; input and output
|
||||||
* @flags: unused, always pass 0
|
* @flags: bitwise-OR of virTypedParameterFlags
|
||||||
*
|
*
|
||||||
* This function is to get block stats parameters for block
|
* This function is to get block stats parameters for block
|
||||||
* devices attached to the domain.
|
* devices attached to the domain.
|
||||||
@ -6715,6 +6778,9 @@ int virDomainBlockStatsFlags(virDomainPtr dom,
|
|||||||
virLibConnError(VIR_ERR_INVALID_ARG, __FUNCTION__);
|
virLibConnError(VIR_ERR_INVALID_ARG, __FUNCTION__);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
if (VIR_DRV_SUPPORTS_FEATURE(dom->conn->driver, dom->conn,
|
||||||
|
VIR_DRV_FEATURE_TYPED_PARAM_STRING))
|
||||||
|
flags |= VIR_TYPED_PARAM_STRING_OKAY;
|
||||||
conn = dom->conn;
|
conn = dom->conn;
|
||||||
|
|
||||||
if (conn->driver->domainBlockStatsFlags) {
|
if (conn->driver->domainBlockStatsFlags) {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* libvirt.h: publically exported APIs, not for public use
|
* libvirt.h: publically exported APIs, not for public use
|
||||||
*
|
*
|
||||||
* Copyright (C) 2006-2008 Red Hat, Inc.
|
* Copyright (C) 2006-2008, 2011 Red Hat, Inc.
|
||||||
*
|
*
|
||||||
* This library is free software; you can redistribute it and/or
|
* This library is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
@ -83,7 +83,12 @@ enum {
|
|||||||
/*
|
/*
|
||||||
* Support for file descriptor passing
|
* Support for file descriptor passing
|
||||||
*/
|
*/
|
||||||
VIR_DRV_FEATURE_FD_PASSING = 8
|
VIR_DRV_FEATURE_FD_PASSING = 8,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Support for VIR_TYPED_PARAM_STRING
|
||||||
|
*/
|
||||||
|
VIR_DRV_FEATURE_TYPED_PARAM_STRING = 9,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -1162,6 +1162,7 @@ virStrncpy;
|
|||||||
virTimeMs;
|
virTimeMs;
|
||||||
virTimestamp;
|
virTimestamp;
|
||||||
virTrimSpaces;
|
virTrimSpaces;
|
||||||
|
virTypedParameterArrayClear;
|
||||||
virVasprintf;
|
virVasprintf;
|
||||||
|
|
||||||
|
|
||||||
|
@ -2607,3 +2607,17 @@ or other application using the libvirt API.\n\
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
virTypedParameterArrayClear(virTypedParameterPtr params, int nparams)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!params)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (i = 0; i < nparams; i++) {
|
||||||
|
if (params[i].type == VIR_TYPED_PARAM_STRING)
|
||||||
|
VIR_FREE(params[i].value.s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -258,4 +258,6 @@ bool virIsDevMapperDevice(const char *dev_name) ATTRIBUTE_NONNULL(1);
|
|||||||
int virEmitXMLWarning(int fd,
|
int virEmitXMLWarning(int fd,
|
||||||
const char *name,
|
const char *name,
|
||||||
const char *cmd) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
|
const char *cmd) ATTRIBUTE_NONNULL(2) ATTRIBUTE_NONNULL(3);
|
||||||
|
|
||||||
|
void virTypedParameterArrayClear(virTypedParameterPtr params, int nparams);
|
||||||
#endif /* __VIR_UTIL_H__ */
|
#endif /* __VIR_UTIL_H__ */
|
||||||
|
Loading…
Reference in New Issue
Block a user