On 29.08.2013 12:49, Daniel P. Berrange wrote:
From: "Daniel P. Berrange" <berrange(a)redhat.com>
The parameters for the virDomainMigrate*Params RPC calls were
not bounds checks, meaning a malicious client can cause libvirtd
to consume arbitrary memory
This issue was introduced in the 1.1.0 release of libvirt
Signed-off-by: Daniel P. Berrange <berrange(a)redhat.com>
---
daemon/remote.c | 42 ++++++++++++++++++++++++++++++++++++++++++
src/remote/remote_driver.c | 42 ++++++++++++++++++++++++++++++++++++++++++
src/remote/remote_protocol.x | 15 +++++++++------
3 files changed, 93 insertions(+), 6 deletions(-)
diff --git a/daemon/remote.c b/daemon/remote.c
index 03d5557..a11ba94 100644
--- a/daemon/remote.c
+++ b/daemon/remote.c
@@ -4620,6 +4620,13 @@ remoteDispatchDomainMigrateBegin3Params(
goto cleanup;
}
+ if (args->params.params_len > REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX) {
+ virReportError(VIR_ERR_RPC,
+ _("Too many migration parameters '%d' for limit
'%d'"),
+ args->params.params_len,
REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX);
+ goto cleanup;
+ }
+
if (!(dom = get_nonnull_domain(priv->conn, args->dom)))
goto cleanup;
@@ -4671,6 +4678,13 @@ remoteDispatchDomainMigratePrepare3Params(
goto cleanup;
}
+ if (args->params.params_len > REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX) {
+ virReportError(VIR_ERR_RPC,
+ _("Too many migration parameters '%d' for limit
'%d'"),
+ args->params.params_len,
REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX);
+ goto cleanup;
+ }
+
if (!(params = remoteDeserializeTypedParameters(args->params.params_val,
args->params.params_len,
0, &nparams)))
@@ -4726,6 +4740,13 @@ remoteDispatchDomainMigratePrepareTunnel3Params(
goto cleanup;
}
+ if (args->params.params_len > REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX) {
+ virReportError(VIR_ERR_RPC,
+ _("Too many migration parameters '%d' for limit
'%d'"),
+ args->params.params_len,
REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX);
+ goto cleanup;
+ }
+
if (!(params = remoteDeserializeTypedParameters(args->params.params_val,
args->params.params_len,
0, &nparams)))
@@ -4790,6 +4811,13 @@ remoteDispatchDomainMigratePerform3Params(
goto cleanup;
}
+ if (args->params.params_len > REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX) {
+ virReportError(VIR_ERR_RPC,
+ _("Too many migration parameters '%d' for limit
'%d'"),
+ args->params.params_len,
REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX);
+ goto cleanup;
+ }
+
if (!(dom = get_nonnull_domain(priv->conn, args->dom)))
goto cleanup;
@@ -4845,6 +4873,13 @@ remoteDispatchDomainMigrateFinish3Params(
goto cleanup;
}
+ if (args->params.params_len > REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX) {
+ virReportError(VIR_ERR_RPC,
+ _("Too many migration parameters '%d' for limit
'%d'"),
+ args->params.params_len,
REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX);
+ goto cleanup;
+ }
+
if (!(params = remoteDeserializeTypedParameters(args->params.params_val,
args->params.params_len,
0, &nparams)))
@@ -4897,6 +4932,13 @@ remoteDispatchDomainMigrateConfirm3Params(
goto cleanup;
}
+ if (args->params.params_len > REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX) {
+ virReportError(VIR_ERR_RPC,
+ _("Too many migration parameters '%d' for limit
'%d'"),
+ args->params.params_len,
REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX);
+ goto cleanup;
+ }
+
if (!(dom = get_nonnull_domain(priv->conn, args->dom)))
goto cleanup;
While the above is correct as it fixes the libvirtd (sanitizes input).
However, I don't think we need the following, esp. if we ever change the
limit. The older client won't be able to pass more parameters whereas it
currently can.
diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
index 71d0034..30f8f90 100644
--- a/src/remote/remote_driver.c
+++ b/src/remote/remote_driver.c
@@ -6037,6 +6037,13 @@ remoteDomainMigrateBegin3Params(virDomainPtr domain,
make_nonnull_domain(&args.dom, domain);
args.flags = flags;
+ if (nparams > REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX) {
+ virReportError(VIR_ERR_RPC,
+ _("Too many migration parameters '%d' for limit
'%d'"),
+ nparams, REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX);
+ goto cleanup;
+ }
+
if (remoteSerializeTypedParameters(params, nparams,
&args.params.params_val,
&args.params.params_len) < 0) {
@@ -6096,6 +6103,13 @@ remoteDomainMigratePrepare3Params(virConnectPtr dconn,
memset(&args, 0, sizeof(args));
memset(&ret, 0, sizeof(ret));
+ if (nparams > REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX) {
+ virReportError(VIR_ERR_RPC,
+ _("Too many migration parameters '%d' for limit
'%d'"),
+ nparams, REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX);
+ goto cleanup;
+ }
+
if (remoteSerializeTypedParameters(params, nparams,
&args.params.params_val,
&args.params.params_len) < 0) {
@@ -6171,6 +6185,13 @@ remoteDomainMigratePrepareTunnel3Params(virConnectPtr dconn,
memset(&args, 0, sizeof(args));
memset(&ret, 0, sizeof(ret));
+ if (nparams > REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX) {
+ virReportError(VIR_ERR_RPC,
+ _("Too many migration parameters '%d' for limit
'%d'"),
+ nparams, REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX);
+ goto cleanup;
+ }
+
args.cookie_in.cookie_in_val = (char *)cookiein;
args.cookie_in.cookie_in_len = cookieinlen;
args.flags = flags;
@@ -6250,6 +6271,13 @@ remoteDomainMigratePerform3Params(virDomainPtr dom,
memset(&args, 0, sizeof(args));
memset(&ret, 0, sizeof(ret));
+ if (nparams > REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX) {
+ virReportError(VIR_ERR_RPC,
+ _("Too many migration parameters '%d' for limit
'%d'"),
+ nparams, REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX);
+ goto cleanup;
+ }
+
make_nonnull_domain(&args.dom, dom);
args.dconnuri = dconnuri == NULL ? NULL : (char **) &dconnuri;
args.cookie_in.cookie_in_val = (char *)cookiein;
@@ -6315,6 +6343,13 @@ remoteDomainMigrateFinish3Params(virConnectPtr dconn,
memset(&args, 0, sizeof(args));
memset(&ret, 0, sizeof(ret));
+ if (nparams > REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX) {
+ virReportError(VIR_ERR_RPC,
+ _("Too many migration parameters '%d' for limit
'%d'"),
+ nparams, REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX);
+ goto cleanup;
+ }
+
args.cookie_in.cookie_in_val = (char *)cookiein;
args.cookie_in.cookie_in_len = cookieinlen;
args.flags = flags;
@@ -6380,6 +6415,13 @@ remoteDomainMigrateConfirm3Params(virDomainPtr domain,
memset(&args, 0, sizeof(args));
+ if (nparams > REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX) {
+ virReportError(VIR_ERR_RPC,
+ _("Too many migration parameters '%d' for limit
'%d'"),
+ nparams, REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX);
+ goto cleanup;
+ }
+
make_nonnull_domain(&args.dom, domain);
args.cookie_in.cookie_in_len = cookieinlen;
args.cookie_in.cookie_in_val = (char *) cookiein;
diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x
index 7cfebdf..4262c34 100644
--- a/src/remote/remote_protocol.x
+++ b/src/remote/remote_protocol.x
@@ -234,6 +234,9 @@ const REMOTE_DOMAIN_DISK_ERRORS_MAX = 256;
*/
const REMOTE_NODE_MEMORY_PARAMETERS_MAX = 64;
+/* Upper limit on migrate parameters */
+const REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX = 64;
+
/* UUID. VIR_UUID_BUFLEN definition comes from libvirt.h */
typedef opaque remote_uuid[VIR_UUID_BUFLEN];
@@ -2770,7 +2773,7 @@ struct remote_domain_fstrim_args {
struct remote_domain_migrate_begin3_params_args {
remote_nonnull_domain dom;
- remote_typed_param params<>;
+ remote_typed_param params<REMOTE_DOMAIN_MIGRATE_PARAM_LIST_MAX>;
unsigned int flags;
};
Moreover, after you introduce this - won't XDR complain if we try to
encode more than _MAX items?
Michal