It's almost simpler to revert the botched CVE-2014-0028 patch and show just the final result with filtering in the right location. Signed-off-by: Eric Blake <eblake@xxxxxxxxxx> --- Created by squashing the original CVE fix together with the updates to filter in remote.c; this representation avoids dealing with the churn of reverting hunks between patches. daemon/remote.c | 224 ++++++++++++++++++++++++++----------------- src/access/viraccessperm.h | 4 +- src/check-aclrules.pl | 7 +- src/remote/remote_protocol.x | 8 +- 4 files changed, 148 insertions(+), 95 deletions(-) diff --git a/daemon/remote.c b/daemon/remote.c index f3de6a0..22960bb 100644 --- a/daemon/remote.c +++ b/daemon/remote.c @@ -49,6 +49,8 @@ #include "qemu_protocol.h" #include "lxc_protocol.h" #include "virstring.h" +#include "domain_conf.h" +#include "viraccessapicheck.h" #define VIR_FROM_THIS VIR_FROM_RPC @@ -114,16 +116,45 @@ remoteDispatchDomainEventSend(virNetServerClientPtr client, xdrproc_t proc, void *data); -static int remoteRelayDomainEventLifecycle(virConnectPtr conn ATTRIBUTE_UNUSED, - virDomainPtr dom, - int event, - int detail, - void *opaque) + +static bool +remoteRelayDomainEventCheckACL(virNetServerClientPtr client, + virConnectPtr conn, virDomainPtr dom) +{ + virDomainDef def; + virIdentityPtr identity = NULL; + bool ret = false; + + /* For now, we just create a virDomainDef with enough contents to + * satisfy what viraccessdriverpolkit.c references. This is a bit + * fragile, but I don't know of anything better. */ + def.name = dom->name; + memcpy(def.uuid, dom->uuid, VIR_UUID_BUFLEN); + + if (!(identity = virNetServerClientGetIdentity(client))) + goto cleanup; + if (virIdentitySetCurrent(identity) < 0) + goto cleanup; + ret = virConnectDomainEventRegisterAnyCheckACL(conn, &def); + +cleanup: + ignore_value(virIdentitySetCurrent(NULL)); + virObjectUnref(identity); + return ret; +} + + +static int +remoteRelayDomainEventLifecycle(virConnectPtr conn, + virDomainPtr dom, + int event, + int detail, + void *opaque) { virNetServerClientPtr client = opaque; remote_domain_event_lifecycle_msg data; - if (!client) + if (!client || !remoteRelayDomainEventCheckACL(client, conn, dom)) return -1; VIR_DEBUG("Relaying domain lifecycle event %d %d", event, detail); @@ -141,14 +172,15 @@ static int remoteRelayDomainEventLifecycle(virConnectPtr conn ATTRIBUTE_UNUSED, return 0; } -static int remoteRelayDomainEventReboot(virConnectPtr conn ATTRIBUTE_UNUSED, - virDomainPtr dom, - void *opaque) +static int +remoteRelayDomainEventReboot(virConnectPtr conn, + virDomainPtr dom, + void *opaque) { virNetServerClientPtr client = opaque; remote_domain_event_reboot_msg data; - if (!client) + if (!client || !remoteRelayDomainEventCheckACL(client, conn, dom)) return -1; VIR_DEBUG("Relaying domain reboot event %s %d", dom->name, dom->id); @@ -165,15 +197,16 @@ static int remoteRelayDomainEventReboot(virConnectPtr conn ATTRIBUTE_UNUSED, } -static int remoteRelayDomainEventRTCChange(virConnectPtr conn ATTRIBUTE_UNUSED, - virDomainPtr dom, - long long offset, - void *opaque) +static int +remoteRelayDomainEventRTCChange(virConnectPtr conn, + virDomainPtr dom, + long long offset, + void *opaque) { virNetServerClientPtr client = opaque; remote_domain_event_rtc_change_msg data; - if (!client) + if (!client || !remoteRelayDomainEventCheckACL(client, conn, dom)) return -1; VIR_DEBUG("Relaying domain rtc change event %s %d %lld", dom->name, dom->id, offset); @@ -191,15 +224,16 @@ static int remoteRelayDomainEventRTCChange(virConnectPtr conn ATTRIBUTE_UNUSED, } -static int remoteRelayDomainEventWatchdog(virConnectPtr conn ATTRIBUTE_UNUSED, - virDomainPtr dom, - int action, - void *opaque) +static int +remoteRelayDomainEventWatchdog(virConnectPtr conn, + virDomainPtr dom, + int action, + void *opaque) { virNetServerClientPtr client = opaque; remote_domain_event_watchdog_msg data; - if (!client) + if (!client || !remoteRelayDomainEventCheckACL(client, conn, dom)) return -1; VIR_DEBUG("Relaying domain watchdog event %s %d %d", dom->name, dom->id, action); @@ -217,17 +251,18 @@ static int remoteRelayDomainEventWatchdog(virConnectPtr conn ATTRIBUTE_UNUSED, } -static int remoteRelayDomainEventIOError(virConnectPtr conn ATTRIBUTE_UNUSED, - virDomainPtr dom, - const char *srcPath, - const char *devAlias, - int action, - void *opaque) +static int +remoteRelayDomainEventIOError(virConnectPtr conn, + virDomainPtr dom, + const char *srcPath, + const char *devAlias, + int action, + void *opaque) { virNetServerClientPtr client = opaque; remote_domain_event_io_error_msg data; - if (!client) + if (!client || !remoteRelayDomainEventCheckACL(client, conn, dom)) return -1; VIR_DEBUG("Relaying domain io error %s %d %s %s %d", dom->name, dom->id, srcPath, devAlias, action); @@ -252,18 +287,19 @@ error: } -static int remoteRelayDomainEventIOErrorReason(virConnectPtr conn ATTRIBUTE_UNUSED, - virDomainPtr dom, - const char *srcPath, - const char *devAlias, - int action, - const char *reason, - void *opaque) +static int +remoteRelayDomainEventIOErrorReason(virConnectPtr conn, + virDomainPtr dom, + const char *srcPath, + const char *devAlias, + int action, + const char *reason, + void *opaque) { virNetServerClientPtr client = opaque; remote_domain_event_io_error_reason_msg data; - if (!client) + if (!client || !remoteRelayDomainEventCheckACL(client, conn, dom)) return -1; VIR_DEBUG("Relaying domain io error %s %d %s %s %d %s", @@ -293,20 +329,21 @@ error: } -static int remoteRelayDomainEventGraphics(virConnectPtr conn ATTRIBUTE_UNUSED, - virDomainPtr dom, - int phase, - virDomainEventGraphicsAddressPtr local, - virDomainEventGraphicsAddressPtr remote, - const char *authScheme, - virDomainEventGraphicsSubjectPtr subject, - void *opaque) +static int +remoteRelayDomainEventGraphics(virConnectPtr conn, + virDomainPtr dom, + int phase, + virDomainEventGraphicsAddressPtr local, + virDomainEventGraphicsAddressPtr remote, + const char *authScheme, + virDomainEventGraphicsSubjectPtr subject, + void *opaque) { virNetServerClientPtr client = opaque; remote_domain_event_graphics_msg data; size_t i; - if (!client) + if (!client || !remoteRelayDomainEventCheckACL(client, conn, dom)) return -1; VIR_DEBUG("Relaying domain graphics event %s %d %d - %d %s %s - %d %s %s - %s", dom->name, dom->id, phase, @@ -364,17 +401,18 @@ error: return -1; } -static int remoteRelayDomainEventBlockJob(virConnectPtr conn ATTRIBUTE_UNUSED, - virDomainPtr dom, - const char *path, - int type, - int status, - void *opaque) +static int +remoteRelayDomainEventBlockJob(virConnectPtr conn, + virDomainPtr dom, + const char *path, + int type, + int status, + void *opaque) { virNetServerClientPtr client = opaque; remote_domain_event_block_job_msg data; - if (!client) + if (!client || !remoteRelayDomainEventCheckACL(client, conn, dom)) return -1; VIR_DEBUG("Relaying domain block job event %s %d %s %i, %i", @@ -399,14 +437,15 @@ error: } -static int remoteRelayDomainEventControlError(virConnectPtr conn ATTRIBUTE_UNUSED, - virDomainPtr dom, - void *opaque) +static int +remoteRelayDomainEventControlError(virConnectPtr conn, + virDomainPtr dom, + void *opaque) { virNetServerClientPtr client = opaque; remote_domain_event_control_error_msg data; - if (!client) + if (!client || !remoteRelayDomainEventCheckACL(client, conn, dom)) return -1; VIR_DEBUG("Relaying domain control error %s %d", dom->name, dom->id); @@ -423,19 +462,20 @@ static int remoteRelayDomainEventControlError(virConnectPtr conn ATTRIBUTE_UNUSE } -static int remoteRelayDomainEventDiskChange(virConnectPtr conn ATTRIBUTE_UNUSED, - virDomainPtr dom, - const char *oldSrcPath, - const char *newSrcPath, - const char *devAlias, - int reason, - void *opaque) +static int +remoteRelayDomainEventDiskChange(virConnectPtr conn, + virDomainPtr dom, + const char *oldSrcPath, + const char *newSrcPath, + const char *devAlias, + int reason, + void *opaque) { virNetServerClientPtr client = opaque; remote_domain_event_disk_change_msg data; char **oldSrcPath_p = NULL, **newSrcPath_p = NULL; - if (!client) + if (!client || !remoteRelayDomainEventCheckACL(client, conn, dom)) return -1; VIR_DEBUG("Relaying domain %s %d disk change %s %s %s %d", @@ -474,15 +514,17 @@ error: } -static int remoteRelayDomainEventTrayChange(virConnectPtr conn ATTRIBUTE_UNUSED, - virDomainPtr dom, - const char *devAlias, - int reason, - void *opaque) { +static int +remoteRelayDomainEventTrayChange(virConnectPtr conn, + virDomainPtr dom, + const char *devAlias, + int reason, + void *opaque) +{ virNetServerClientPtr client = opaque; remote_domain_event_tray_change_msg data; - if (!client) + if (!client || !remoteRelayDomainEventCheckACL(client, conn, dom)) return -1; VIR_DEBUG("Relaying domain %s %d tray change devAlias: %s reason: %d", @@ -504,14 +546,16 @@ static int remoteRelayDomainEventTrayChange(virConnectPtr conn ATTRIBUTE_UNUSED, return 0; } -static int remoteRelayDomainEventPMWakeup(virConnectPtr conn ATTRIBUTE_UNUSED, - virDomainPtr dom, - int reason ATTRIBUTE_UNUSED, - void *opaque) { +static int +remoteRelayDomainEventPMWakeup(virConnectPtr conn, + virDomainPtr dom, + int reason ATTRIBUTE_UNUSED, + void *opaque) +{ virNetServerClientPtr client = opaque; remote_domain_event_pmwakeup_msg data; - if (!client) + if (!client || !remoteRelayDomainEventCheckACL(client, conn, dom)) return -1; VIR_DEBUG("Relaying domain %s %d system pmwakeup", dom->name, dom->id); @@ -527,14 +571,16 @@ static int remoteRelayDomainEventPMWakeup(virConnectPtr conn ATTRIBUTE_UNUSED, return 0; } -static int remoteRelayDomainEventPMSuspend(virConnectPtr conn ATTRIBUTE_UNUSED, - virDomainPtr dom, - int reason ATTRIBUTE_UNUSED, - void *opaque) { +static int +remoteRelayDomainEventPMSuspend(virConnectPtr conn, + virDomainPtr dom, + int reason ATTRIBUTE_UNUSED, + void *opaque) +{ virNetServerClientPtr client = opaque; remote_domain_event_pmsuspend_msg data; - if (!client) + if (!client || !remoteRelayDomainEventCheckACL(client, conn, dom)) return -1; VIR_DEBUG("Relaying domain %s %d system pmsuspend", dom->name, dom->id); @@ -551,7 +597,7 @@ static int remoteRelayDomainEventPMSuspend(virConnectPtr conn ATTRIBUTE_UNUSED, } static int -remoteRelayDomainEventBalloonChange(virConnectPtr conn ATTRIBUTE_UNUSED, +remoteRelayDomainEventBalloonChange(virConnectPtr conn, virDomainPtr dom, unsigned long long actual, void *opaque) @@ -559,7 +605,7 @@ remoteRelayDomainEventBalloonChange(virConnectPtr conn ATTRIBUTE_UNUSED, virNetServerClientPtr client = opaque; remote_domain_event_balloon_change_msg data; - if (!client) + if (!client || !remoteRelayDomainEventCheckACL(client, conn, dom)) return -1; VIR_DEBUG("Relaying domain balloon change event %s %d %lld", dom->name, dom->id, actual); @@ -577,14 +623,16 @@ remoteRelayDomainEventBalloonChange(virConnectPtr conn ATTRIBUTE_UNUSED, } -static int remoteRelayDomainEventPMSuspendDisk(virConnectPtr conn ATTRIBUTE_UNUSED, - virDomainPtr dom, - int reason ATTRIBUTE_UNUSED, - void *opaque) { +static int +remoteRelayDomainEventPMSuspendDisk(virConnectPtr conn, + virDomainPtr dom, + int reason ATTRIBUTE_UNUSED, + void *opaque) +{ virNetServerClientPtr client = opaque; remote_domain_event_pmsuspend_disk_msg data; - if (!client) + if (!client || !remoteRelayDomainEventCheckACL(client, conn, dom)) return -1; VIR_DEBUG("Relaying domain %s %d system pmsuspend-disk", dom->name, dom->id); @@ -601,7 +649,7 @@ static int remoteRelayDomainEventPMSuspendDisk(virConnectPtr conn ATTRIBUTE_UNUS } static int -remoteRelayDomainEventDeviceRemoved(virConnectPtr conn ATTRIBUTE_UNUSED, +remoteRelayDomainEventDeviceRemoved(virConnectPtr conn, virDomainPtr dom, const char *devAlias, void *opaque) @@ -609,7 +657,7 @@ remoteRelayDomainEventDeviceRemoved(virConnectPtr conn ATTRIBUTE_UNUSED, virNetServerClientPtr client = opaque; remote_domain_event_device_removed_msg data; - if (!client) + if (!client || !remoteRelayDomainEventCheckACL(client, conn, dom)) return -1; VIR_DEBUG("Relaying domain device removed event %s %d %s", diff --git a/src/access/viraccessperm.h b/src/access/viraccessperm.h index fdc461b..1036b08 100644 --- a/src/access/viraccessperm.h +++ b/src/access/viraccessperm.h @@ -1,7 +1,7 @@ /* * viraccessperm.h: access control permissions * - * Copyright (C) 2012-2013 Red Hat, Inc. + * Copyright (C) 2012-2014 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -47,7 +47,7 @@ typedef enum { /** * @desc: List domains - * @message: Listing domains requires authorization + * @message: Listing domains or using domain events requires authorization * @anonymous: 1 */ VIR_ACCESS_PERM_CONNECT_SEARCH_DOMAINS, diff --git a/src/check-aclrules.pl b/src/check-aclrules.pl index 057517e..f54b934 100644 --- a/src/check-aclrules.pl +++ b/src/check-aclrules.pl @@ -1,6 +1,6 @@ #!/usr/bin/perl # -# Copyright (C) 2013 Red Hat, Inc. +# Copyright (C) 2013-2014 Red Hat, Inc. # # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public @@ -140,7 +140,10 @@ while (<PROTO>) { } elsif ($filtered && m,REMOTE_PROC_(.*)\s+=\s*\d+,) { my $api = name_to_ProcName($1); - $filtered{$api} = 1; + # Event filtering is handled in daemon/remote.c instead of drivers + if (! m,_EVENT_REGISTER,) { + $filtered{$api} = 1; + } $incomment = 0; } } diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x index f942670..8c40208 100644 --- a/src/remote/remote_protocol.x +++ b/src/remote/remote_protocol.x @@ -1955,7 +1955,7 @@ struct remote_node_device_destroy_args { /* * Events Register/Deregister: - * It would seem rpcgen does not like both args, and ret + * It would seem rpcgen does not like both args and ret * to be null. It will not generate the prototype otherwise. * Pass back a redundant boolean to force prototype generation. */ @@ -3620,7 +3620,8 @@ enum remote_procedure { /** * @generate: none * @priority: high - * @acl: connect:read + * @acl: connect:search_domains + * @aclfilter: domain:getattr */ REMOTE_PROC_CONNECT_DOMAIN_EVENT_REGISTER = 105, @@ -4052,7 +4053,8 @@ enum remote_procedure { /** * @generate: none * @priority: high - * @acl: connect:read + * @acl: connect:search_domains + * @aclfilter: domain:getattr */ REMOTE_PROC_CONNECT_DOMAIN_EVENT_REGISTER_ANY = 167, -- 1.8.5.3 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list