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(a)redhat.com>
---
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