On Thu, Aug 29, 2013 at 02:58:44PM +0200, Michal Privoznik wrote:
On 29.08.2013 14:55, Daniel P. Berrange wrote:
> On Thu, Aug 29, 2013 at 02:34:15PM +0200, Michal Privoznik wrote:
>> 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.
>
> As mentioned in the cover letter, we explicitly want to check data
> received from the server, because this is a robustness issue. If the
> data stream gets corrupted for some reason, it can cause the client
> to allocate unbounded amounts of memory. We want to prevent that.
>
> Compatibility when raising limits is already going to be a problem,
> because the generated xdr methods for decoding the return values will
> be enforcing this limit. They have really crappy (ie non-existant)
> error reporting, so the user wil just get a "Unable to decode message
> payload" error message. These explicit checks in libvirt code ensure
> we get a useful error message instead.
>
>>> 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?
>
> Yes, it will return an error both at decode or encode time if the
> length exceeds the limit. We want to get better error reporting
> though, hence duplicating the checks ourselves.
>
> One day we really ought to just throw away the XDR library code and
> write our own, can we can dynamic buffer allocation and sensible
> error reporting.
>
> Daniel
>
Aah, okay. Thanks for your explanation. Makes sense now. In that case:
ACK series and I vote for push now, prior the release.
Thanks, I pushed this series to master, and the CVE patch I have pushed
to v1.1.0-maint and v1.1.1-maint too
Daniel
--
|:
http://berrange.com -o-
http://www.flickr.com/photos/dberrange/ :|
|:
http://libvirt.org -o-
http://virt-manager.org :|
|:
http://autobuild.org -o-
http://search.cpan.org/~danberr/ :|
|:
http://entangle-photo.org -o-
http://live.gnome.org/gtk-vnc :|