[libvirt] [PATCH 00/19] Support for access control

From: "Daniel P. Berrange" <berrange@redhat.com> This series (which depends on the Xen refactoring patches) adds support for access control checks on all APIs that run inside libvirtd. The first patch defines the basic objects which can be checked and the permissions associated with each object. In addition it provides the basic internal (pluggable) API for access control checks Later there are policykit and selinux drivers for the access control framework. Neither of these is currently optimal but they have basic functionality working To ensure that we don't forget access control checks when adding new APIs, we maintain metadata in the remote_protocol.x file against each method declaring what access control check must be done. There are actually two checks possible. The first check is against the object being used. The optional second check is against the objects being returned (if any). The latter is used to filter what can be seen when asking for a list of objects (eg 'virsh list' gets filtered) Again to ensure accurate checks, we automate the generation of methods for applying access control checks to each API. These helper methods are named to match the public API names. The last patch ensures that every method listed in the virXXXXDriverPtr tables has a call to an access control helper with the same name as the public API. And of course there are the patches which actually add the access control checks. Still todo - Not all Xen methods have access control checks yet. This causes the test case in the last patch to report failures - Have not wired up the checks for filtering the returned objects in any driver yet - The polkit driver is inefficient since it spawns pkcheck for each check. We need to talk to DBus directly since ACL checks will be very frequent and need to be lightweight - The SELinux driver is validating against the label of libvirtd. We need to validate against the label of the virDomainDefPtr security model or some equivalent for other objects. - Need to write a generic RBAC access control impl. It was hoped that new polkit would make this obsolete. Polkit is still unable to do access control checks for non-local users though eg it can't validate against SASL usernames or x509 certs. Daniel P. Berrange (19): Define basic internal API for access control Set conn->driver before running driver connectOpen method Setup default access control manager in libvirtd Add a policy kit access control driver Add an SELinux access control driver Add ACL annotations to all RPC messages Auto-generate helpers for checking access control rules Add ACL checks into the QEMU driver Add ACL checks into the LXC driver Add ACL checks into the UML driver Add ACL checks into the Xen driver Add ACL checks into the libxl driver Add ACL checks into the storage driver Add ACL checks into the network driver Add ACL checks into the interface driver Add ACL checks into the node device driver Add ACL checks into the nwfilter driver Add ACL checks into the secrets driver Add validation that all APIs contain ACL checks .gitignore | 10 + daemon/Makefile.am | 1 + daemon/libvirtd-config.c | 4 + daemon/libvirtd-config.h | 2 + daemon/libvirtd.aug | 1 + daemon/libvirtd.c | 27 ++ daemon/libvirtd.conf | 9 + daemon/test_libvirtd.aug.in | 4 + include/libvirt/virterror.h | 4 + m4/virt-compile-warnings.m4 | 1 + m4/virt-selinux.m4 | 2 + po/POTFILES.in | 3 + src/Makefile.am | 128 +++++- src/access/genpolkit.pl | 119 ++++++ src/access/viraccessdriver.h | 89 ++++ src/access/viraccessdrivernop.c | 118 ++++++ src/access/viraccessdrivernop.h | 28 ++ src/access/viraccessdriverpolkit.c | 399 ++++++++++++++++++ src/access/viraccessdriverpolkit.h | 28 ++ src/access/viraccessdriverselinux.c | 565 +++++++++++++++++++++++++ src/access/viraccessdriverselinux.h | 28 ++ src/access/viraccessdriverstack.c | 285 +++++++++++++ src/access/viraccessdriverstack.h | 32 ++ src/access/viraccessmanager.c | 352 ++++++++++++++++ src/access/viraccessmanager.h | 91 ++++ src/access/viraccessperm.c | 84 ++++ src/access/viraccessperm.h | 647 +++++++++++++++++++++++++++++ src/check-aclrules.pl | 144 +++++++ src/interface/interface_backend_netcf.c | 114 +++++ src/interface/interface_backend_udev.c | 85 +++- src/internal.h | 4 + src/libvirt.c | 11 +- src/libvirt_private.syms | 37 ++ src/libxl/libxl_driver.c | 187 ++++++++- src/locking/lock_protocol.x | 8 + src/lxc/lxc_driver.c | 219 +++++++++- src/network/bridge_driver.c | 61 +++ src/node_device/node_device_driver.c | 36 ++ src/nwfilter/nwfilter_driver.c | 26 ++ src/qemu/qemu_driver.c | 716 ++++++++++++++++++++++++++++---- src/remote/lxc_protocol.x | 1 + src/remote/qemu_protocol.x | 4 + src/remote/remote_protocol.x | 406 ++++++++++++++++++ src/rpc/gendispatch.pl | 212 +++++++++- src/secret/secret_driver.c | 31 ++ src/storage/storage_driver.c | 155 ++++++- src/uml/uml_driver.c | 174 +++++++- src/util/virerror.c | 8 + src/util/virlog.c | 3 +- src/util/virlog.h | 1 + src/xen/xen_driver.c | 217 +++++++++- 51 files changed, 5785 insertions(+), 136 deletions(-) create mode 100755 src/access/genpolkit.pl create mode 100644 src/access/viraccessdriver.h create mode 100644 src/access/viraccessdrivernop.c create mode 100644 src/access/viraccessdrivernop.h create mode 100644 src/access/viraccessdriverpolkit.c create mode 100644 src/access/viraccessdriverpolkit.h create mode 100644 src/access/viraccessdriverselinux.c create mode 100644 src/access/viraccessdriverselinux.h create mode 100644 src/access/viraccessdriverstack.c create mode 100644 src/access/viraccessdriverstack.h create mode 100644 src/access/viraccessmanager.c create mode 100644 src/access/viraccessmanager.h create mode 100644 src/access/viraccessperm.c create mode 100644 src/access/viraccessperm.h create mode 100644 src/check-aclrules.pl -- 1.8.1.4

From: "Daniel P. Berrange" <berrange@redhat.com> This patch introduces the virAccessManagerPtr class as the interface between virtualization drivers and the access control drivers. The viraccessperm.h file defines the various permissions that will be used for each type of object libvirt manages Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- include/libvirt/virterror.h | 4 + po/POTFILES.in | 1 + src/Makefile.am | 16 + src/access/viraccessdriver.h | 89 ++++++ src/access/viraccessdrivernop.c | 118 +++++++ src/access/viraccessdrivernop.h | 28 ++ src/access/viraccessdriverstack.c | 285 +++++++++++++++++ src/access/viraccessdriverstack.h | 32 ++ src/access/viraccessmanager.c | 340 ++++++++++++++++++++ src/access/viraccessmanager.h | 91 ++++++ src/access/viraccessperm.c | 84 +++++ src/access/viraccessperm.h | 647 ++++++++++++++++++++++++++++++++++++++ src/libvirt.c | 6 +- src/libvirt_private.syms | 37 +++ src/util/virerror.c | 8 + 15 files changed, 1784 insertions(+), 2 deletions(-) create mode 100644 src/access/viraccessdriver.h create mode 100644 src/access/viraccessdrivernop.c create mode 100644 src/access/viraccessdrivernop.h create mode 100644 src/access/viraccessdriverstack.c create mode 100644 src/access/viraccessdriverstack.h create mode 100644 src/access/viraccessmanager.c create mode 100644 src/access/viraccessmanager.h create mode 100644 src/access/viraccessperm.c create mode 100644 src/access/viraccessperm.h diff --git a/include/libvirt/virterror.h b/include/libvirt/virterror.h index 3864a31..7a582f5 100644 --- a/include/libvirt/virterror.h +++ b/include/libvirt/virterror.h @@ -118,6 +118,8 @@ typedef enum { VIR_FROM_IDENTITY = 53, /* Error from identity code */ VIR_FROM_CGROUP = 54, /* Error from cgroups */ + VIR_FROM_ACCESS = 55, /* Error from access control manager */ + # ifdef VIR_ENUM_SENTINELS VIR_ERR_DOMAIN_LAST # endif @@ -290,6 +292,8 @@ typedef enum { VIR_ERR_AGENT_UNRESPONSIVE = 86, /* guest agent is unresponsive, not running or not usable */ VIR_ERR_RESOURCE_BUSY = 87, /* resource is already in use */ + VIR_ERR_ACCESS_DENIED = 88, /* operation on the object/resource + was denied */ } virErrorNumber; /** diff --git a/po/POTFILES.in b/po/POTFILES.in index bf5a864..37c6019 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -6,6 +6,7 @@ daemon/remote_dispatch.h daemon/stream.c gnulib/lib/gai_strerror.c gnulib/lib/regcomp.c +src/access/viraccessmanager.c src/conf/cpu_conf.c src/conf/device_conf.c src/conf/domain_conf.c diff --git a/src/Makefile.am b/src/Makefile.am index 6175b84..babd019 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -772,6 +772,13 @@ SECURITY_DRIVER_APPARMOR_SOURCES = \ security/security_apparmor.h security/security_apparmor.c +ACCESS_DRIVER_SOURCES = \ + access/viraccessperm.h access/viraccessperm.c \ + access/viraccessmanager.h access/viraccessmanager.c \ + access/viraccessdriver.h \ + access/viraccessdrivernop.h access/viraccessdrivernop.c \ + access/viraccessdriverstack.h access/viraccessdriverstack.c + NODE_DEVICE_DRIVER_SOURCES = \ node_device/node_device_driver.c \ node_device/node_device_driver.h \ @@ -1344,6 +1351,15 @@ libvirt_security_manager_la_SOURCES += $(SECURITY_DRIVER_APPARMOR_SOURCES) libvirt_security_manager_la_CFLAGS += $(APPARMOR_CFLAGS) endif +libvirt_driver_access_la_SOURCES = $(ACCESS_DRIVER_SOURCES) +noinst_LTLIBRARIES += libvirt_driver_access.la +libvirt_la_BUILT_LIBADD += libvirt_driver_access.la +libvirt_driver_access_la_CFLAGS = \ + -I$(top_srcdir)/src/conf $(AM_CFLAGS) +libvirt_driver_access_la_LDFLAGS = $(AM_LDFLAGS) +libvirt_driver_access_la_LIBADD = + + # Add all conditional sources just in case... EXTRA_DIST += \ $(TEST_DRIVER_SOURCES) \ diff --git a/src/access/viraccessdriver.h b/src/access/viraccessdriver.h new file mode 100644 index 0000000..e3050b6 --- /dev/null +++ b/src/access/viraccessdriver.h @@ -0,0 +1,89 @@ +/* + * viraccessdriver.h: access control driver + * + * Copyright (C) 2012-2013 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 + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <http://www.gnu.org/licenses/>. + */ + +#ifndef __VIR_ACCESS_DRIVER_H__ +# define __VIR_ACCESS_DRIVER_H__ + +# include "conf/domain_conf.h" +# include "access/viraccessmanager.h" + +typedef int (*virAccessDriverCheckConnectDrv)(virAccessManagerPtr manager, + const char *driverName, + virAccessPermConnect av); +typedef int (*virAccessDriverCheckDomainDrv)(virAccessManagerPtr manager, + const char *driverName, + virDomainDefPtr domain, + virAccessPermDomain av); +typedef int (*virAccessDriverCheckInterfaceDrv)(virAccessManagerPtr manager, + const char *driverName, + virInterfaceDefPtr iface, + virAccessPermInterface av); +typedef int (*virAccessDriverCheckNetworkDrv)(virAccessManagerPtr manager, + const char *driverName, + virNetworkDefPtr network, + virAccessPermNetwork av); +typedef int (*virAccessDriverCheckNodeDeviceDrv)(virAccessManagerPtr manager, + const char *driverName, + virNodeDeviceDefPtr nodedev, + virAccessPermNodeDevice av); +typedef int (*virAccessDriverCheckNWFilterDrv)(virAccessManagerPtr manager, + const char *driverName, + virNWFilterDefPtr nwfilter, + virAccessPermNWFilter av); +typedef int (*virAccessDriverCheckSecretDrv)(virAccessManagerPtr manager, + const char *driverName, + virSecretDefPtr secret, + virAccessPermSecret av); +typedef int (*virAccessDriverCheckStoragePoolDrv)(virAccessManagerPtr manager, + const char *driverName, + virStoragePoolDefPtr pool, + virAccessPermStoragePool av); +typedef int (*virAccessDriverCheckStorageVolDrv)(virAccessManagerPtr manager, + const char *driverName, + virStoragePoolDefPtr pool, + virStorageVolDefPtr vol, + virAccessPermStorageVol av); + +typedef int (*virAccessDriverSetupDrv)(virAccessManagerPtr manager); +typedef void (*virAccessDriverCleanupDrv)(virAccessManagerPtr manager); + +typedef struct _virAccessDriver virAccessDriver; +typedef virAccessDriver *virAccessDriverPtr; + +struct _virAccessDriver { + size_t privateDataLen; + const char *name; + + virAccessDriverSetupDrv setup; + virAccessDriverCleanupDrv cleanup; + + virAccessDriverCheckConnectDrv checkConnect; + virAccessDriverCheckDomainDrv checkDomain; + virAccessDriverCheckInterfaceDrv checkInterface; + virAccessDriverCheckNetworkDrv checkNetwork; + virAccessDriverCheckNodeDeviceDrv checkNodeDevice; + virAccessDriverCheckNWFilterDrv checkNWFilter; + virAccessDriverCheckSecretDrv checkSecret; + virAccessDriverCheckStoragePoolDrv checkStoragePool; + virAccessDriverCheckStorageVolDrv checkStorageVol; +}; + + +#endif /* __VIR_ACCESS_DRIVER_H__ */ diff --git a/src/access/viraccessdrivernop.c b/src/access/viraccessdrivernop.c new file mode 100644 index 0000000..86ceef3 --- /dev/null +++ b/src/access/viraccessdrivernop.c @@ -0,0 +1,118 @@ +/* + * viraccessdrivernop.c: no-op access control driver + * + * Copyright (C) 2012-2013 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 + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <http://www.gnu.org/licenses/>. + */ + +#include <config.h> + +#include "access/viraccessdrivernop.h" + +static int +virAccessDriverNopCheckConnect(virAccessManagerPtr manager ATTRIBUTE_UNUSED, + const char *driverName ATTRIBUTE_UNUSED, + virAccessPermConnect perm ATTRIBUTE_UNUSED) +{ + return 1; /* Allow */ +} + +static int +virAccessDriverNopCheckDomain(virAccessManagerPtr manager ATTRIBUTE_UNUSED, + const char *driverName ATTRIBUTE_UNUSED, + virDomainDefPtr domain ATTRIBUTE_UNUSED, + virAccessPermDomain perm ATTRIBUTE_UNUSED) +{ + return 1; /* Allow */ +} + +static int +virAccessDriverNopCheckInterface(virAccessManagerPtr manager ATTRIBUTE_UNUSED, + const char *driverName ATTRIBUTE_UNUSED, + virInterfaceDefPtr iface ATTRIBUTE_UNUSED, + virAccessPermInterface perm ATTRIBUTE_UNUSED) +{ + return 1; /* Allow */ +} + +static int +virAccessDriverNopCheckNetwork(virAccessManagerPtr manager ATTRIBUTE_UNUSED, + const char *driverName ATTRIBUTE_UNUSED, + virNetworkDefPtr network ATTRIBUTE_UNUSED, + virAccessPermNetwork perm ATTRIBUTE_UNUSED) +{ + return 1; /* Allow */ +} + +static int +virAccessDriverNopCheckNodeDevice(virAccessManagerPtr manager ATTRIBUTE_UNUSED, + const char *driverName ATTRIBUTE_UNUSED, + virNodeDeviceDefPtr nodedev ATTRIBUTE_UNUSED, + virAccessPermNodeDevice perm ATTRIBUTE_UNUSED) +{ + return 1; /* Allow */ +} + +static int +virAccessDriverNopCheckNWFilter(virAccessManagerPtr manager ATTRIBUTE_UNUSED, + const char *driverName ATTRIBUTE_UNUSED, + virNWFilterDefPtr nwfilter ATTRIBUTE_UNUSED, + virAccessPermNWFilter perm ATTRIBUTE_UNUSED) +{ + return 1; /* Allow */ +} + +static int +virAccessDriverNopCheckSecret(virAccessManagerPtr manager ATTRIBUTE_UNUSED, + const char *driverName ATTRIBUTE_UNUSED, + virSecretDefPtr secret ATTRIBUTE_UNUSED, + virAccessPermSecret perm ATTRIBUTE_UNUSED) +{ + return 1; /* Allow */ +} + +static int +virAccessDriverNopCheckStoragePool(virAccessManagerPtr manager ATTRIBUTE_UNUSED, + const char *driverName ATTRIBUTE_UNUSED, + virStoragePoolDefPtr pool ATTRIBUTE_UNUSED, + virAccessPermStoragePool perm ATTRIBUTE_UNUSED) +{ + return 1; /* Allow */ +} + +static int +virAccessDriverNopCheckStorageVol(virAccessManagerPtr manager ATTRIBUTE_UNUSED, + const char *driverName ATTRIBUTE_UNUSED, + virStoragePoolDefPtr pool ATTRIBUTE_UNUSED, + virStorageVolDefPtr vol ATTRIBUTE_UNUSED, + virAccessPermStorageVol perm ATTRIBUTE_UNUSED) +{ + return 1; /* Allow */ +} + + +virAccessDriver accessDriverNop = { + .name = "none", + .checkConnect = virAccessDriverNopCheckConnect, + .checkDomain = virAccessDriverNopCheckDomain, + .checkInterface = virAccessDriverNopCheckInterface, + .checkNetwork = virAccessDriverNopCheckNetwork, + .checkNodeDevice = virAccessDriverNopCheckNodeDevice, + .checkNWFilter = virAccessDriverNopCheckNWFilter, + .checkSecret = virAccessDriverNopCheckSecret, + .checkStoragePool = virAccessDriverNopCheckStoragePool, + .checkStorageVol = virAccessDriverNopCheckStorageVol, +}; diff --git a/src/access/viraccessdrivernop.h b/src/access/viraccessdrivernop.h new file mode 100644 index 0000000..0b5d413 --- /dev/null +++ b/src/access/viraccessdrivernop.h @@ -0,0 +1,28 @@ +/* + * viraccessdrivernop.h: no-op access control driver + * + * Copyright (C) 2012-2013 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 + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <http://www.gnu.org/licenses/>. + */ + +#ifndef __VIR_ACCESS_DRIVER_NOP_H__ +# define __VIR_ACCESS_DRIVER_NOP_H__ + +# include "access/viraccessdriver.h" + +extern virAccessDriver accessDriverNop; + +#endif /* __VIR_ACCESS_DRIVER_NOP_H__ */ diff --git a/src/access/viraccessdriverstack.c b/src/access/viraccessdriverstack.c new file mode 100644 index 0000000..4c9f0c4 --- /dev/null +++ b/src/access/viraccessdriverstack.c @@ -0,0 +1,285 @@ +/* + * viraccessdriverstack.c: stacked access control driver + * + * Copyright (C) 2012-2013 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 + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <http://www.gnu.org/licenses/>. + */ + +#include <config.h> + +#include "viraccessdriverstack.h" +#include "viralloc.h" +#include "virerror.h" + +#define VIR_FROM_THIS VIR_FROM_ACCESS + +typedef struct _virAccessDriverStackPrivate virAccessDriverStackPrivate; +typedef virAccessDriverStackPrivate *virAccessDriverStackPrivatePtr; + +struct _virAccessDriverStackPrivate { + virAccessManagerPtr *managers; + size_t managersLen; +}; + + +int virAccessDriverStackAppend(virAccessManagerPtr manager, + virAccessManagerPtr child) +{ + virAccessDriverStackPrivatePtr priv = virAccessManagerGetPrivateData(manager); + + if (VIR_EXPAND_N(priv->managers, priv->managersLen, 1) < 0) { + virReportOOMError(); + return -1; + } + + priv->managers[priv->managersLen-1] = child; + + return 0; +} + + +static void virAccessDriverStackCleanup(virAccessManagerPtr manager) +{ + virAccessDriverStackPrivatePtr priv = virAccessManagerGetPrivateData(manager); + size_t i; + + for (i = 0 ; i < priv->managersLen ; i++) { + virObjectUnref(priv->managers[i]); + } + VIR_FREE(priv->managers); +} + + +static int +virAccessDriverStackCheckConnect(virAccessManagerPtr manager, + const char *driverName, + virAccessPermConnect perm) +{ + virAccessDriverStackPrivatePtr priv = virAccessManagerGetPrivateData(manager); + int ret = 1; + size_t i; + + for (i = 0 ; i < priv->managersLen ; i++) { + int rv; + /* We do not short-circuit on first denial - always check all drivers */ + rv = virAccessManagerCheckConnect(priv->managers[i], driverName, perm); + if (rv == 0 && ret != -1) + ret = 0; + else if (rv == -1) + ret = -1; + } + + return ret; +} + +static int +virAccessDriverStackCheckDomain(virAccessManagerPtr manager, + const char *driverName, + virDomainDefPtr domain, + virAccessPermDomain perm) +{ + virAccessDriverStackPrivatePtr priv = virAccessManagerGetPrivateData(manager); + int ret = 1; + size_t i; + + for (i = 0 ; i < priv->managersLen ; i++) { + int rv; + /* We do not short-circuit on first denial - always check all drivers */ + rv = virAccessManagerCheckDomain(priv->managers[i], driverName, domain, perm); + if (rv == 0 && ret != -1) + ret = 0; + else if (rv == -1) + ret = -1; + } + + return ret; +} + +static int +virAccessDriverStackCheckInterface(virAccessManagerPtr manager, + const char *driverName, + virInterfaceDefPtr iface, + virAccessPermInterface perm) +{ + virAccessDriverStackPrivatePtr priv = virAccessManagerGetPrivateData(manager); + int ret = 1; + size_t i; + + for (i = 0 ; i < priv->managersLen ; i++) { + int rv; + /* We do not short-circuit on first denial - always check all drivers */ + rv = virAccessManagerCheckInterface(priv->managers[i], driverName, iface, perm); + if (rv == 0 && ret != -1) + ret = 0; + else if (rv == -1) + ret = -1; + } + + return ret; +} + +static int +virAccessDriverStackCheckNetwork(virAccessManagerPtr manager, + const char *driverName, + virNetworkDefPtr network, + virAccessPermNetwork perm) +{ + virAccessDriverStackPrivatePtr priv = virAccessManagerGetPrivateData(manager); + int ret = 1; + size_t i; + + for (i = 0 ; i < priv->managersLen ; i++) { + int rv; + /* We do not short-circuit on first denial - always check all drivers */ + rv = virAccessManagerCheckNetwork(priv->managers[i], driverName, network, perm); + if (rv == 0 && ret != -1) + ret = 0; + else if (rv == -1) + ret = -1; + } + + return ret; +} + +static int +virAccessDriverStackCheckNodeDevice(virAccessManagerPtr manager, + const char *driverName, + virNodeDeviceDefPtr nodedev, + virAccessPermNodeDevice perm) +{ + virAccessDriverStackPrivatePtr priv = virAccessManagerGetPrivateData(manager); + int ret = 1; + size_t i; + + for (i = 0 ; i < priv->managersLen ; i++) { + int rv; + /* We do not short-circuit on first denial - always check all drivers */ + rv = virAccessManagerCheckNodeDevice(priv->managers[i], driverName, nodedev, perm); + if (rv == 0 && ret != -1) + ret = 0; + else if (rv == -1) + ret = -1; + } + + return ret; +} + +static int +virAccessDriverStackCheckNWFilter(virAccessManagerPtr manager, + const char *driverName, + virNWFilterDefPtr nwfilter, + virAccessPermNWFilter perm) +{ + virAccessDriverStackPrivatePtr priv = virAccessManagerGetPrivateData(manager); + int ret = 1; + size_t i; + + for (i = 0 ; i < priv->managersLen ; i++) { + int rv; + /* We do not short-circuit on first denial - always check all drivers */ + rv = virAccessManagerCheckNWFilter(priv->managers[i], driverName, nwfilter, perm); + if (rv == 0 && ret != -1) + ret = 0; + else if (rv == -1) + ret = -1; + } + + return ret; +} + +static int +virAccessDriverStackCheckSecret(virAccessManagerPtr manager, + const char *driverName, + virSecretDefPtr secret, + virAccessPermSecret perm) +{ + virAccessDriverStackPrivatePtr priv = virAccessManagerGetPrivateData(manager); + int ret = 1; + size_t i; + + for (i = 0 ; i < priv->managersLen ; i++) { + int rv; + /* We do not short-circuit on first denial - always check all drivers */ + rv = virAccessManagerCheckSecret(priv->managers[i], driverName, secret, perm); + if (rv == 0 && ret != -1) + ret = 0; + else if (rv == -1) + ret = -1; + } + + return ret; +} + +static int +virAccessDriverStackCheckStoragePool(virAccessManagerPtr manager, + const char *driverName, + virStoragePoolDefPtr pool, + virAccessPermStoragePool perm) +{ + virAccessDriverStackPrivatePtr priv = virAccessManagerGetPrivateData(manager); + int ret = 1; + size_t i; + + for (i = 0 ; i < priv->managersLen ; i++) { + int rv; + /* We do not short-circuit on first denial - always check all drivers */ + rv = virAccessManagerCheckStoragePool(priv->managers[i], driverName, pool, perm); + if (rv == 0 && ret != -1) + ret = 0; + else if (rv == -1) + ret = -1; + } + + return ret; +} + +static int +virAccessDriverStackCheckStorageVol(virAccessManagerPtr manager, + const char *driverName, + virStoragePoolDefPtr pool, + virStorageVolDefPtr vol, + virAccessPermStorageVol perm) +{ + virAccessDriverStackPrivatePtr priv = virAccessManagerGetPrivateData(manager); + int ret = 1; + size_t i; + + for (i = 0 ; i < priv->managersLen ; i++) { + int rv; + /* We do not short-circuit on first denial - always check all drivers */ + rv = virAccessManagerCheckStorageVol(priv->managers[i], driverName, pool, vol, perm); + if (rv == 0 && ret != -1) + ret = 0; + else if (rv == -1) + ret = -1; + } + + return ret; +} + +virAccessDriver accessDriverStack = { + .name = "stack", + .cleanup = virAccessDriverStackCleanup, + .checkConnect = virAccessDriverStackCheckConnect, + .checkDomain = virAccessDriverStackCheckDomain, + .checkInterface = virAccessDriverStackCheckInterface, + .checkNetwork = virAccessDriverStackCheckNetwork, + .checkNodeDevice = virAccessDriverStackCheckNodeDevice, + .checkNWFilter = virAccessDriverStackCheckNWFilter, + .checkSecret = virAccessDriverStackCheckSecret, + .checkStoragePool = virAccessDriverStackCheckStoragePool, + .checkStorageVol = virAccessDriverStackCheckStorageVol, +}; diff --git a/src/access/viraccessdriverstack.h b/src/access/viraccessdriverstack.h new file mode 100644 index 0000000..4e34d5f --- /dev/null +++ b/src/access/viraccessdriverstack.h @@ -0,0 +1,32 @@ +/* + * viraccessdriverstack.h: stacked access control driver + * + * Copyright (C) 2012-2013 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 + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <http://www.gnu.org/licenses/>. + */ + +#ifndef __VIR_ACCESS_DRIVER_STACK_H__ +# define __VIR_ACCESS_DRIVER_STACK_H__ + +# include "access/viraccessdriver.h" + + +int virAccessDriverStackAppend(virAccessManagerPtr manager, + virAccessManagerPtr child); + +extern virAccessDriver accessDriverStack; + +#endif /* __VIR_ACCESS_DRIVER_STACK_H__ */ diff --git a/src/access/viraccessmanager.c b/src/access/viraccessmanager.c new file mode 100644 index 0000000..ff1a538 --- /dev/null +++ b/src/access/viraccessmanager.c @@ -0,0 +1,340 @@ +/* + * viraccessmanager.c: access control manager + * + * Copyright (C) 2012-2013 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 + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <http://www.gnu.org/licenses/>. + */ + +#include <config.h> + +#include "viraccessmanager.h" +#include "viraccessdrivernop.h" +#include "viraccessdriverstack.h" +#include "viralloc.h" +#include "virerror.h" +#include "virobject.h" +#include "virthread.h" +#include "virlog.h" + +#define VIR_FROM_THIS VIR_FROM_ACCESS +#define virAccessError(code, ...) \ + virReportErrorHelper(VIR_FROM_THIS, code, __FILE__, \ + __FUNCTION__, __LINE__, __VA_ARGS__) + +struct _virAccessManager { + virObjectLockable parent; + + virAccessDriverPtr drv; + void *privateData; +}; + +static virClassPtr virAccessManagerClass; +static virAccessManagerPtr virAccessManagerDefault; + +static void virAccessManagerDispose(void *obj); + +static int virAccessManagerOnceInit(void) +{ + if (!(virAccessManagerClass = virClassNew(virClassForObjectLockable(), + "virAccessManagerClass", + sizeof(virAccessManager), + virAccessManagerDispose))) + return -1; + + return 0; +} + +VIR_ONCE_GLOBAL_INIT(virAccessManager); + + +virAccessManagerPtr virAccessManagerGetDefault(void) +{ + return virObjectRef(virAccessManagerDefault); +} + + +void virAccessManagerSetDefault(virAccessManagerPtr mgr) +{ + virObjectUnref(virAccessManagerDefault); + + virAccessManagerDefault = virObjectRef(mgr); +} + + +static virAccessManagerPtr virAccessManagerNewDriver(virAccessDriverPtr drv) +{ + virAccessManagerPtr mgr; + char *privateData; + + if (virAccessManagerInitialize() < 0) + return NULL; + + if (VIR_ALLOC_N(privateData, drv->privateDataLen) < 0) { + virReportOOMError(); + return NULL; + } + + if (!(mgr = virObjectLockableNew(virAccessManagerClass))) { + VIR_FREE(privateData); + return NULL; + } + + mgr->drv = drv; + mgr->privateData = privateData; + + if (mgr->drv->setup && + mgr->drv->setup(mgr) < 0) { + virObjectUnref(mgr); + return NULL; + } + + VIR_DEBUG("Initialized with %s", mgr->drv->name); + return mgr; +} + + +static virAccessDriverPtr accessDrivers[] = { + &accessDriverNop, +}; + + +static virAccessDriverPtr virAccessManagerFindDriver(const char *name) +{ + size_t i; + for (i = 0 ; i < ARRAY_CARDINALITY(accessDrivers) ; i++) { + if (STREQ(name, accessDrivers[i]->name)) + return accessDrivers[i]; + } + + return NULL; +} + + +virAccessManagerPtr virAccessManagerNew(const char *name) +{ + virAccessDriverPtr drv; + + if (virAccessManagerInitialize() < 0) + return NULL; + + if (!(drv = virAccessManagerFindDriver(name))) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Cannot find security driver '%s'"), + name); + return NULL; + } + + return virAccessManagerNewDriver(drv); +} + + +virAccessManagerPtr virAccessManagerNewStack(const char **names) +{ + virAccessManagerPtr manager = virAccessManagerNewDriver(&accessDriverStack); + size_t i; + + if (!manager) + return NULL; + + for (i = 0 ; names[i] != NULL ; i++) { + virAccessManagerPtr child = virAccessManagerNew(names[i]); + + if (!child) + goto error; + + if (virAccessDriverStackAppend(manager, child) < 0) { + virObjectUnref(child); + goto error; + } + } + + return manager; + +error: + virObjectUnref(manager); + return NULL; +} + + +void *virAccessManagerGetPrivateData(virAccessManagerPtr mgr) +{ + return mgr->privateData; +} + + +static void virAccessManagerDispose(void *object) +{ + virAccessManagerPtr mgr = object; + + if (mgr->drv->cleanup) + mgr->drv->cleanup(mgr); + VIR_FREE(mgr->privateData); +} + + +/* Standard security practice is to not tell the caller *why* + * they were denied access. So this method takes the real + * libvirt errors & replaces it with a generic error. Fortunately + * the daemon logs will still contain the original error message + * should the admin need to debug things + */ +static int +virAccessManagerSanitizeError(int ret) +{ + if (ret < 0) { + virResetLastError(); + virAccessError(VIR_ERR_ACCESS_DENIED, NULL); + } + + return ret; +} + +int virAccessManagerCheckConnect(virAccessManagerPtr manager, + const char *driverName, + virAccessPermConnect perm) +{ + int ret = 0; + VIR_DEBUG("manager=%p(name=%s) driver=%s perm=%d", + manager, manager->drv->name, driverName, perm); + + if (manager->drv->checkConnect) + ret = manager->drv->checkConnect(manager, driverName, perm); + + return virAccessManagerSanitizeError(ret); +} + + +int virAccessManagerCheckDomain(virAccessManagerPtr manager, + const char *driverName, + virDomainDefPtr domain, + virAccessPermDomain perm) +{ + int ret = 0; + VIR_DEBUG("manager=%p(name=%s) driver=%s domain=%p perm=%d", + manager, manager->drv->name, driverName, domain, perm); + + if (manager->drv->checkDomain) + ret = manager->drv->checkDomain(manager, driverName, domain, perm); + + return virAccessManagerSanitizeError(ret); +} + +int virAccessManagerCheckInterface(virAccessManagerPtr manager, + const char *driverName, + virInterfaceDefPtr iface, + virAccessPermInterface perm) +{ + int ret = 0; + VIR_DEBUG("manager=%p(name=%s) driver=%s iface=%p perm=%d", + manager, manager->drv->name, driverName, iface, perm); + + if (manager->drv->checkInterface) + ret = manager->drv->checkInterface(manager, driverName, iface, perm); + + return virAccessManagerSanitizeError(ret); +} + +int virAccessManagerCheckNetwork(virAccessManagerPtr manager, + const char *driverName, + virNetworkDefPtr network, + virAccessPermNetwork perm) +{ + int ret = 0; + VIR_DEBUG("manager=%p(name=%s) driver=%s network=%p perm=%d", + manager, manager->drv->name, driverName, network, perm); + + if (manager->drv->checkNetwork) + ret = manager->drv->checkNetwork(manager, driverName, network, perm); + + return virAccessManagerSanitizeError(ret); +} + +int virAccessManagerCheckNodeDevice(virAccessManagerPtr manager, + const char *driverName, + virNodeDeviceDefPtr nodedev, + virAccessPermNodeDevice perm) +{ + int ret = 0; + VIR_DEBUG("manager=%p(name=%s) driver=%s nodedev=%p perm=%d", + manager, manager->drv->name, driverName, nodedev, perm); + + if (manager->drv->checkNodeDevice) + ret = manager->drv->checkNodeDevice(manager, driverName, nodedev, perm); + + return virAccessManagerSanitizeError(ret); +} + +int virAccessManagerCheckNWFilter(virAccessManagerPtr manager, + const char *driverName, + virNWFilterDefPtr nwfilter, + virAccessPermNWFilter perm) +{ + int ret = 0; + VIR_DEBUG("manager=%p(name=%s) driver=%s nwfilter=%p perm=%d", + manager, manager->drv->name, driverName, nwfilter, perm); + + if (manager->drv->checkNWFilter) + ret = manager->drv->checkNWFilter(manager, driverName, nwfilter, perm); + + return virAccessManagerSanitizeError(ret); +} + +int virAccessManagerCheckSecret(virAccessManagerPtr manager, + const char *driverName, + virSecretDefPtr secret, + virAccessPermSecret perm) +{ + int ret = 0; + VIR_DEBUG("manager=%p(name=%s) driver=%s secret=%p perm=%d", + manager, manager->drv->name, driverName, secret, perm); + + if (manager->drv->checkSecret) + ret = manager->drv->checkSecret(manager, driverName, secret, perm); + + return virAccessManagerSanitizeError(ret); +} + +int virAccessManagerCheckStoragePool(virAccessManagerPtr manager, + const char *driverName, + virStoragePoolDefPtr pool, + virAccessPermStoragePool perm) +{ + int ret = 0; + VIR_DEBUG("manager=%p(name=%s) driver=%s pool=%p perm=%d", + manager, manager->drv->name, driverName, pool, perm); + + if (manager->drv->checkStoragePool) + ret = manager->drv->checkStoragePool(manager, driverName, pool, perm); + + return virAccessManagerSanitizeError(ret); +} + +int virAccessManagerCheckStorageVol(virAccessManagerPtr manager, + const char *driverName, + virStoragePoolDefPtr pool, + virStorageVolDefPtr vol, + virAccessPermStorageVol perm) +{ + int ret = 0; + VIR_DEBUG("manager=%p(name=%s) driver=%s pool=%p vol=%p perm=%d", + manager, manager->drv->name, driverName, pool, vol, perm); + + if (manager->drv->checkStorageVol) + ret = manager->drv->checkStorageVol(manager, driverName, pool, vol, perm); + + return virAccessManagerSanitizeError(ret); +} + diff --git a/src/access/viraccessmanager.h b/src/access/viraccessmanager.h new file mode 100644 index 0000000..e7eb15d --- /dev/null +++ b/src/access/viraccessmanager.h @@ -0,0 +1,91 @@ +/* + * viraccessmanager.h: access control manager + * + * Copyright (C) 2012-2013 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 + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <http://www.gnu.org/licenses/>. + */ + +#ifndef __VIR_ACCESS_MANAGER_H__ +# define __VIR_ACCESS_MANAGER_H__ + +# include "viridentity.h" +# include "conf/domain_conf.h" +# include "conf/network_conf.h" +# include "conf/nwfilter_conf.h" +# include "conf/node_device_conf.h" +# include "conf/storage_conf.h" +# include "conf/secret_conf.h" +# include "conf/interface_conf.h" +# include "access/viraccessperm.h" + +typedef struct _virAccessManager virAccessManager; +typedef virAccessManager *virAccessManagerPtr; + +virAccessManagerPtr virAccessManagerGetDefault(void); +void virAccessManagerSetDefault(virAccessManagerPtr manager); + +virAccessManagerPtr virAccessManagerNew(const char *name); +virAccessManagerPtr virAccessManagerNewStack(const char **names); + + +void *virAccessManagerGetPrivateData(virAccessManagerPtr manager); + + +/* + * The virAccessManagerCheckXXX functions will + * Return -1 on error + * Return 0 on auth deny + * Return 1 on auth allow + */ +int virAccessManagerCheckConnect(virAccessManagerPtr manager, + const char *driverName, + virAccessPermConnect perm); +int virAccessManagerCheckDomain(virAccessManagerPtr manager, + const char *driverName, + virDomainDefPtr domain, + virAccessPermDomain perm); +int virAccessManagerCheckInterface(virAccessManagerPtr manager, + const char *driverName, + virInterfaceDefPtr iface, + virAccessPermInterface perm); +int virAccessManagerCheckNetwork(virAccessManagerPtr manager, + const char *driverName, + virNetworkDefPtr network, + virAccessPermNetwork perm); +int virAccessManagerCheckNodeDevice(virAccessManagerPtr manager, + const char *driverName, + virNodeDeviceDefPtr nodedev, + virAccessPermNodeDevice perm); +int virAccessManagerCheckNWFilter(virAccessManagerPtr manager, + const char *driverName, + virNWFilterDefPtr nwfilter, + virAccessPermNWFilter perm); +int virAccessManagerCheckSecret(virAccessManagerPtr manager, + const char *driverName, + virSecretDefPtr secret, + virAccessPermSecret perm); +int virAccessManagerCheckStoragePool(virAccessManagerPtr manager, + const char *driverName, + virStoragePoolDefPtr pool, + virAccessPermStoragePool perm); +int virAccessManagerCheckStorageVol(virAccessManagerPtr manager, + const char *driverName, + virStoragePoolDefPtr pool, + virStorageVolDefPtr vol, + virAccessPermStorageVol perm); + + +#endif /* __VIR_ACCESS_MANAGER_H__ */ diff --git a/src/access/viraccessperm.c b/src/access/viraccessperm.c new file mode 100644 index 0000000..17f6243 --- /dev/null +++ b/src/access/viraccessperm.c @@ -0,0 +1,84 @@ +/* + * viraccessperm.c: access control permissions + * + * Copyright (C) 2012-2013 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 + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <http://www.gnu.org/licenses/>. + */ + +#include <config.h> + +#include "viraccessperm.h" + + +VIR_ENUM_IMPL(virAccessPermConnect, + VIR_ACCESS_PERM_CONNECT_LAST, + "getattr", "read", "write", + "search_domains", "search_networks", + "search_storage_pools", "search_node_devices", + "search_interfaces", "search_secrets", + "search_nwfilters", + "detect_storage_pool", "pm_control", + "interface_transaction"); + +VIR_ENUM_IMPL(virAccessPermDomain, + VIR_ACCESS_PERM_DOMAIN_LAST, + "getattr", "read", "write", "read_secure", + "start", "stop", "reset", + "save", "delete", + "migrate", "snapshot", "suspend", "hibernate", "core_dump", "pm_control", + "init_control", "inject_nmi", "send_input", "send_signal", "fs_trim", + "block_read", "block_write", "mem_read", + "open_graphics", "open_device", "screenshot", + "open_namespace"); + +VIR_ENUM_IMPL(virAccessPermInterface, + VIR_ACCESS_PERM_INTERFACE_LAST, + "getattr", "read", "write", "save", + "delete", "start", "stop"); + +VIR_ENUM_IMPL(virAccessPermNetwork, + VIR_ACCESS_PERM_NETWORK_LAST, + "getattr", "read", "write", + "save", "delete", "start", "stop"); + +VIR_ENUM_IMPL(virAccessPermNodeDevice, + VIR_ACCESS_PERM_NODE_DEVICE_LAST, + "getattr", "read", "write", + "start", "stop", + "dettach"); + +VIR_ENUM_IMPL(virAccessPermNWFilter, + VIR_ACCESS_PERM_NWFILTER_LAST, + "getattr", "read", "write", + "save", "delete"); + +VIR_ENUM_IMPL(virAccessPermSecret, + VIR_ACCESS_PERM_SECRET_LAST, + "getattr", "read", "write", + "read_secure", "save", "delete"); + +VIR_ENUM_IMPL(virAccessPermStoragePool, + VIR_ACCESS_PERM_STORAGE_POOL_LAST, + "getattr", "read", "write", + "save", "delete", "start", "stop", + "refresh", "search_storage_vols", + "format"); + +VIR_ENUM_IMPL(virAccessPermStorageVol, + VIR_ACCESS_PERM_STORAGE_VOL_LAST, + "getattr", "read", "create", "delete", + "format", "resize", "data_read", + "data_write"); diff --git a/src/access/viraccessperm.h b/src/access/viraccessperm.h new file mode 100644 index 0000000..6f171f9 --- /dev/null +++ b/src/access/viraccessperm.h @@ -0,0 +1,647 @@ +/* + * viraccessperm.h: access control permissions + * + * Copyright (C) 2012-2013 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 + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <http://www.gnu.org/licenses/>. + */ + +#ifndef __VIR_ACCESS_PERM_H__ +# define __VIR_ACCESS_PERM_H__ + +# include "internal.h" +# include "virutil.h" + +typedef enum { + /** + * @desc: Access connection + * @message: Accessing the connection requires authorization + * @anonymous: 1 + */ + VIR_ACCESS_PERM_CONNECT_GETATTR, + + /** + * @desc: Read host + * @message: Reading the host configuration requires authorization + * @anonymous: 1 + */ + VIR_ACCESS_PERM_CONNECT_READ, + + /** + * @desc: Write host + * @message: Writing the host configuration requires authorization + */ + VIR_ACCESS_PERM_CONNECT_WRITE, + + /** + * @desc: List domains + * @message: Listing domains requires authorization + * @anonymous: 1 + */ + VIR_ACCESS_PERM_CONNECT_SEARCH_DOMAINS, + + /** + * @desc: List networks + * @message: Listing networks requires authorization + * @anonymous: 1 + */ + VIR_ACCESS_PERM_CONNECT_SEARCH_NETWORKS, + + /** + * @desc: List storage pools + * @message: Listing storage pools requires authorization + * @anonymous: 1 + */ + VIR_ACCESS_PERM_CONNECT_SEARCH_STORAGE_POOLS, + + /** + * @desc: List node devices + * @message: Listing node devices requires authorization + * @anonymous: 1 + */ + VIR_ACCESS_PERM_CONNECT_SEARCH_NODE_DEVICES, + + /** + * @desc: List interfaces + * @message: Listing interfaces requires authorization + * @anonymous: 1 + */ + VIR_ACCESS_PERM_CONNECT_SEARCH_INTERFACES, + + /** + * @desc: List secrets + * @message: Listing secrets requires authorization + * @anonymous: 1 + */ + VIR_ACCESS_PERM_CONNECT_SEARCH_SECRETS, + + /** + * @desc: List network filters + * @message: Listing network filters requires authorization + * @anonymous: 1 + */ + VIR_ACCESS_PERM_CONNECT_SEARCH_NWFILTERS, + + + /** + * @desc: Detect storage pools + * @message: Detecting storage pools requires authorization + */ + VIR_ACCESS_PERM_CONNECT_DETECT_STORAGE_POOLS, + + /** + * @desc: Use host power management + * @message: Using host power management requires authorization + */ + VIR_ACCESS_PERM_CONNECT_PM_CONTROL, + + /** + * @desc: Interface transactions + * @message: Using interface transactions requires authorization + */ + VIR_ACCESS_PERM_CONNECT_INTERFACE_TRANSACTION, + + VIR_ACCESS_PERM_CONNECT_LAST, +} virAccessPermConnect; + +typedef enum { + /** + * @desc: Access domain + * @message: Accessing the domain requires authorization + * @anonymous: 1 + */ + VIR_ACCESS_PERM_DOMAIN_GETATTR, /* Name/ID/UUID access */ + + /** + * @desc: Read domain + * @message: Reading domain configuration requires authorization + * @anonymous: 1 + */ + VIR_ACCESS_PERM_DOMAIN_READ, /* Config view */ + + /** + * @desc: Write domain + * @message: Writing domain configuration requires authorization + */ + VIR_ACCESS_PERM_DOMAIN_WRITE, /* Config change */ + + /** + * @desc: Read secure domain + * @message: Reading secure domain configuration requires authorization + */ + VIR_ACCESS_PERM_DOMAIN_READ_SECURE, /* Config access of passwords */ + + /** + * @desc: Start domain + * @message: Starting the domain requires authorization + */ + VIR_ACCESS_PERM_DOMAIN_START, /* Power on */ + + /** + * @desc: Stop domain + * @message: Stopping the domain requires authorization + */ + VIR_ACCESS_PERM_DOMAIN_STOP, /* Power off */ + + /** + * @desc: Reset domain + * @message: Resetting the domain requires authorization + */ + VIR_ACCESS_PERM_DOMAIN_RESET, /* Power reset */ + + /** + * @desc: Save domain + * @message: Saving domain configuration requires authorization + */ + VIR_ACCESS_PERM_DOMAIN_SAVE, /* Write out persistent config */ + + /** + * @desc: Delete domain + * @message: Deleting domain configuration requires authorization + */ + VIR_ACCESS_PERM_DOMAIN_DELETE, /* Remove persistent config */ + + + /** + * @desc: Migrate domain + * @message: Migrating domain requires authorization + */ + VIR_ACCESS_PERM_DOMAIN_MIGRATE, /* Host migration */ + + /** + * @desc: Snapshot domain + * @message: Snapshotting domain requires authorization + */ + VIR_ACCESS_PERM_DOMAIN_SNAPSHOT, /* Snapshot disks/memory */ + + /** + * @desc: Suspend domain + * @message: Suspending domain CPUs requires authorization + */ + VIR_ACCESS_PERM_DOMAIN_SUSPEND, /* Pause/resume CPUs */ + + /** + * @desc: Hibernate domain + * @message: Saving domain state requires authorization + */ + VIR_ACCESS_PERM_DOMAIN_HIBERNATE, /* Save state to host */ + + /** + * @desc: Dump domain + * @message: Dumping domain corefile requires authorization + */ + VIR_ACCESS_PERM_DOMAIN_CORE_DUMP, /* Dump guest core */ + + /** + * @desc: Use domain power management + * @message: Using domain power management requires authoriation + */ + VIR_ACCESS_PERM_DOMAIN_PM_CONTROL, /* S3/S5 suspend/wakeup */ + + /* Interactions with guest OS */ + + /** + * @desc: Domain init control + * @message: Controlling domain init process requires authorization + */ + VIR_ACCESS_PERM_DOMAIN_INIT_CONTROL, /* Init shutdown/reboot request */ + + /** + * @desc: Inject domain NMI + * @message: Injecting interrupt requries authoriation + */ + VIR_ACCESS_PERM_DOMAIN_INJECT_NMI, /* Trigger interrupts */ + + /** + * @desc: Send domain input + * @message: Sending input events to domain requires authorization + */ + VIR_ACCESS_PERM_DOMAIN_SEND_INPUT, /* Send guest input device (key/mouse) events */ + + /** + * @desc: Send domain signal + * @message: Sending signals to processes in domain requires authorization + */ + VIR_ACCESS_PERM_DOMAIN_SEND_SIGNAL, /* Send a signal to processes inside */ + + /** + * @desc: Trim domain filesystems + * @message: Trimming domain filesystems require authorization + */ + VIR_ACCESS_PERM_DOMAIN_FS_TRIM, /* Issue TRIM to guest filesystems */ + + /* Peeking at guest */ + + /** + * @desc: Read domain block + * @message: Reading domain block devices requires authorization + */ + VIR_ACCESS_PERM_DOMAIN_BLOCK_READ, /* Read data from block devices */ + + /** + * @desc: Write domain block + * @message: Writing domain block devices requires authorization + */ + VIR_ACCESS_PERM_DOMAIN_BLOCK_WRITE, /* resize/pull/rebase/commit */ + + /** + * @desc: Read domain memory + * @message: Reading domain memory requires authorization + */ + VIR_ACCESS_PERM_DOMAIN_MEM_READ, /* Read data from guest memory */ + + /* Device interaction */ + + /** + * @desc: Open domain graphics + * @message: Opening domain graphics console requires authorization + */ + VIR_ACCESS_PERM_DOMAIN_OPEN_GRAPHICS, /* Open graphical console */ + + /** + * @desc: Open domain device + * @message: Opening domain devices requires authorization + */ + VIR_ACCESS_PERM_DOMAIN_OPEN_DEVICE, /* Open a guest console/channel */ + + /** + * @desc: Take domain screenshot + * @message: Taking domain screenshots requires authorization + */ + VIR_ACCESS_PERM_DOMAIN_SCREENSHOT, /* Trigger a screen shot */ + + + /** + * @desc: Open domain namespace + * @message: Opening domain namespaces requires authorization + */ + VIR_ACCESS_PERM_DOMAIN_OPEN_NAMESPACE, + + VIR_ACCESS_PERM_DOMAIN_LAST, +} virAccessPermDomain; + +typedef enum { + + /** + * @desc: Access interface + * @message: Accessing interface requires authorization + * @anonymous: 1 + */ + VIR_ACCESS_PERM_INTERFACE_GETATTR, + + /** + * @desc: Read interface + * @message: Reading interface configuration requires authorization + * @anonymous: 1 + */ + VIR_ACCESS_PERM_INTERFACE_READ, + + /** + * @desc: Write interface + * @message: Writing interface configuration requires authorization + */ + VIR_ACCESS_PERM_INTERFACE_WRITE, + + /** + * @desc: Save interface + * @message: Saving interface configuration requires authorization + */ + VIR_ACCESS_PERM_INTERFACE_SAVE, + + /** + * @desc: Delete interface + * @message: Deleting interface configuration requires authorization + */ + VIR_ACCESS_PERM_INTERFACE_DELETE, + + /** + * @desc: Start interface + * @message: Starting interface requires authorization + */ + VIR_ACCESS_PERM_INTERFACE_START, + + /** + * @desc: Stop interface + * @message: Stopping interface requires authorization + */ + VIR_ACCESS_PERM_INTERFACE_STOP, + + VIR_ACCESS_PERM_INTERFACE_LAST +} virAccessPermInterface; + +typedef enum { + + /** + * @desc: Access network + * @message: Accessing network requires authorization + * @anonymous: 1 + */ + VIR_ACCESS_PERM_NETWORK_GETATTR, + + /** + * @desc: Read network + * @message: Reading network configuration requires authorization + * @anonymous: 1 + */ + VIR_ACCESS_PERM_NETWORK_READ, + + /** + * @desc: Write network + * @message: Writing network configuration requries authorization + */ + VIR_ACCESS_PERM_NETWORK_WRITE, + + /** + * @desc: Save network + * @message: Saving network configuration requires authorization + */ + VIR_ACCESS_PERM_NETWORK_SAVE, + + /** + * @desc: Delete network + * @message: Deleting network configuration requires authorization + */ + VIR_ACCESS_PERM_NETWORK_DELETE, + + /** + * @desc: Start network + * @message: Starting network requires authorization + */ + VIR_ACCESS_PERM_NETWORK_START, + + /** + * @desc: Stop network + * @message: Stopping network requires authorization + */ + VIR_ACCESS_PERM_NETWORK_STOP, + + VIR_ACCESS_PERM_NETWORK_LAST +} virAccessPermNetwork; + +typedef enum { + + /** + * @desc: Access node device + * @message: Accesing node device requires authorization + * @anonymous: 1 + */ + VIR_ACCESS_PERM_NODE_DEVICE_GETATTR, + + /** + * @desc: Read node device + * @message: Reading node device configuration requires authorization + */ + VIR_ACCESS_PERM_NODE_DEVICE_READ, + + /** + * @desc: Write node device + * @message: Writing node device configuration requires authorization + */ + VIR_ACCESS_PERM_NODE_DEVICE_WRITE, + + /** + * @desc: Start node device + * @message: Starting node device requires authorization + */ + VIR_ACCESS_PERM_NODE_DEVICE_START, + + /** + * @desc: Stop node device + * @message: Stopping node device requires authorization + */ + VIR_ACCESS_PERM_NODE_DEVICE_STOP, + + /** + * @desc: Detach node device + * @message: Detaching node device driver requires authorization + */ + VIR_ACCESS_PERM_NODE_DEVICE_DETTACH, + + VIR_ACCESS_PERM_NODE_DEVICE_LAST +} virAccessPermNodeDevice; + +typedef enum { + + /** + * @desc: Access network filter + * @message: Accessing network filter requires authorization + * @anonymous: 1 + */ + VIR_ACCESS_PERM_NWFILTER_GETATTR, + + /** + * @desc: Read network filter + * @message: Reading network filter configuration requires authorization + * @anonymous: 1 + */ + VIR_ACCESS_PERM_NWFILTER_READ, + + /** + * @desc: Write network filter + * @message: Writing network filter configuration requires authorization + */ + VIR_ACCESS_PERM_NWFILTER_WRITE, + + /** + * @desc: Save network filter + * @message: Saving network filter configuration requires authorization + */ + VIR_ACCESS_PERM_NWFILTER_SAVE, + + /** + * @desc: Delete network filter + * @message: Deleting network filter configuration requires authorization + */ + VIR_ACCESS_PERM_NWFILTER_DELETE, + + VIR_ACCESS_PERM_NWFILTER_LAST +} virAccessPermNWFilter; + +typedef enum { + + /** + * @desc: Access secret + * @message: Accessing secret requires authorization + * @anonymous: 1 + */ + VIR_ACCESS_PERM_SECRET_GETATTR, + + /** + * @desc: Read secret + * @message: Reading secret configuration requires authorization + * @anonymous: 1 + */ + VIR_ACCESS_PERM_SECRET_READ, + + /** + * @desc: Write secret + * @message: Writing secret configuration requires authorization + */ + VIR_ACCESS_PERM_SECRET_WRITE, + + /** + * @desc: Read secure secret + * @message: Reading secure secret configuration requires authorization + */ + VIR_ACCESS_PERM_SECRET_READ_SECURE, + + /** + * @desc: Save secret + * @message: Saving secret configuration requires authorization + */ + VIR_ACCESS_PERM_SECRET_SAVE, + + /** + * @desc: Delete secret + * @message: Deleting secret configuration requires authorization + */ + VIR_ACCESS_PERM_SECRET_DELETE, + + VIR_ACCESS_PERM_SECRET_LAST +} virAccessPermSecret; + +typedef enum { + + /** + * @desc: Access storage pool + * @message: Accessing storage pool requires authorization + * @anonymous: 1 + */ + VIR_ACCESS_PERM_STORAGE_POOL_GETATTR, + + /** + * @desc: Read storage pool + * @message: Reading storage pool configuration requires authorization + * @anonymous: 1 + */ + VIR_ACCESS_PERM_STORAGE_POOL_READ, + + /** + * @desc: Write storage pool + * @message: Writing storage pool configuration requires authorization + */ + VIR_ACCESS_PERM_STORAGE_POOL_WRITE, + + /** + * @desc: Save storage pool + * @message: Saving storage pool configuration requires authorization + */ + VIR_ACCESS_PERM_STORAGE_POOL_SAVE, + + /** + * @desc: Delete storage pool + * @message: Deleting storage pool configuration requires authorization + */ + VIR_ACCESS_PERM_STORAGE_POOL_DELETE, + + /** + * @desc: Start storage pool + * @message: Starting storage pool configuration requires authorization + */ + VIR_ACCESS_PERM_STORAGE_POOL_START, + + /** + * @desc: Stop storage pool + * @message: Stopping storage pool configuration requires authorization + */ + VIR_ACCESS_PERM_STORAGE_POOL_STOP, + + /** + * @desc: Refresh storage pool + * @message: Refreshing storage pool volumes requires authorization + */ + VIR_ACCESS_PERM_STORAGE_POOL_REFRESH, + + /** + * @desc: List storage pool volumes + * @message: Listing storage pool volumes requires authorization + */ + VIR_ACCESS_PERM_STORAGE_POOL_SEARCH_STORAGE_VOLS, + + /** + * @desc: Format storage pool + * @message: Formatting storage pool data requires authorization + */ + VIR_ACCESS_PERM_STORAGE_POOL_FORMAT, + + VIR_ACCESS_PERM_STORAGE_POOL_LAST +} virAccessPermStoragePool; + +typedef enum { + + /** + * @desc: Access storage volume + * @message: Acceessing storage volume requires authorization + * @anonymous: 1 + */ + VIR_ACCESS_PERM_STORAGE_VOL_GETATTR, + + /** + * @desc: Read storage volume + * @message: Reading storage volume configuration requires authorization + * @anonymous: 1 + */ + VIR_ACCESS_PERM_STORAGE_VOL_READ, + + /** + * @desc: Create storage volume + * @message: Creating storage volume requires authorization + */ + VIR_ACCESS_PERM_STORAGE_VOL_CREATE, + + /** + * @desc: Delete storage volume + * @message: Deleting storage volume requires authorization + */ + VIR_ACCESS_PERM_STORAGE_VOL_DELETE, + + /** + * @desc: Format storage volume + * @message: Formatting storage volume data requires authorization + */ + VIR_ACCESS_PERM_STORAGE_VOL_FORMAT, + + /** + * @desc: Resize storage volume + * @message: Resizing storage volume requires authorization + */ + VIR_ACCESS_PERM_STORAGE_VOL_RESIZE, + + /** + * @desc: Read storage volume data + * @message: Reading storage volume data requires authorization + */ + VIR_ACCESS_PERM_STORAGE_VOL_DATA_READ, + + /** + * @desc: Write storage volume data + * @message: Writing storage volume data requires authorization + */ + VIR_ACCESS_PERM_STORAGE_VOL_DATA_WRITE, + + VIR_ACCESS_PERM_STORAGE_VOL_LAST +} virAccessPermStorageVol; + +VIR_ENUM_DECL(virAccessPermConnect); +VIR_ENUM_DECL(virAccessPermDomain); +VIR_ENUM_DECL(virAccessPermInterface); +VIR_ENUM_DECL(virAccessPermNetwork); +VIR_ENUM_DECL(virAccessPermNodeDevice); +VIR_ENUM_DECL(virAccessPermNWFilter); +VIR_ENUM_DECL(virAccessPermSecret); +VIR_ENUM_DECL(virAccessPermStoragePool); +VIR_ENUM_DECL(virAccessPermStorageVol); + +#endif /* __VIR_ACCESS_PERM_H__ */ diff --git a/src/libvirt.c b/src/libvirt.c index 4087b5a..eee67d9 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -835,8 +835,10 @@ int virStateInitialize(bool privileged, if (virStateDriverTab[i]->stateInitialize(privileged, callback, opaque) < 0) { - VIR_ERROR(_("Initialization of %s state driver failed"), - virStateDriverTab[i]->name); + virErrorPtr err = virGetLastError(); + VIR_ERROR(_("Initialization of %s state driver failed: %s"), + virStateDriverTab[i]->name, + err && err->message ? err->message : _("Unknown problem")); return -1; } } diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index d2f5827..0edb68d 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -5,6 +5,43 @@ # Keep this file sorted by header name, then by symbols with each header. # +# access/viraccessmanager.h +virAccessManagerCheckConnect; +virAccessManagerCheckDomain; +virAccessManagerCheckInterface; +virAccessManagerCheckNetwork; +virAccessManagerCheckNodeDevice; +virAccessManagerCheckNWFilter; +virAccessManagerCheckSecret; +virAccessManagerCheckStoragePool; +virAccessManagerCheckStorageVol; +virAccessManagerGetDefault; +virAccessManagerNew; +virAccessManagerNewStack; +virAccessManagerSetDefault; + + +# access/viraccessperm.h +virAccessPermConnectTypeFromString; +virAccessPermConnectTypeToString; +virAccessPermDomainTypeFromString; +virAccessPermDomainTypeToString; +virAccessPermInterfaceTypeFromString; +virAccessPermInterfaceTypeToString; +virAccessPermNetworkTypeFromString; +virAccessPermNetworkTypeToString; +virAccessPermNodeDeviceTypeFromString; +virAccessPermNodeDeviceTypeToString; +virAccessPermNWFilterTypeFromString; +virAccessPermNWFilterTypeToString; +virAccessPermSecretTypeFromString; +virAccessPermSecretTypeToString; +virAccessPermStoragePoolTypeFromString; +virAccessPermStoragePoolTypeToString; +virAccessPermStorageVolTypeFromString; +virAccessPermStorageVolTypeToString; + + # conf/capabilities.h virCapabilitiesAddGuest; virCapabilitiesAddGuestDomain; diff --git a/src/util/virerror.c b/src/util/virerror.c index af4da8c..ec30a69 100644 --- a/src/util/virerror.c +++ b/src/util/virerror.c @@ -121,6 +121,8 @@ VIR_ENUM_IMPL(virErrorDomain, VIR_ERR_DOMAIN_LAST, "Init control", "Identity", "Cgroup", + + "Access Manager", /* 55 */ ) @@ -1216,6 +1218,12 @@ virErrorMsg(virErrorNumber error, const char *info) else errmsg = _("resource busy %s"); break; + case VIR_ERR_ACCESS_DENIED: + if (info == NULL) + errmsg = _("access denied"); + else + errmsg = _("access denied: %s"); + break; } return errmsg; } -- 1.8.1.4

From: "Daniel P. Berrange" <berrange@redhat.com> The access control checks in the 'connectOpen' driver method will require 'conn->driver' to be non-NULL. Set this before running the 'connectOpen' method and NULL-ify it again on failure. Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- src/libvirt.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/libvirt.c b/src/libvirt.c index eee67d9..23e2a9a 100644 --- a/src/libvirt.c +++ b/src/libvirt.c @@ -1213,6 +1213,7 @@ do_open(const char *name, } VIR_DEBUG("trying driver %d (%s) ...", i, virDriverTab[i]->name); + ret->driver = virDriverTab[i]; res = virDriverTab[i]->connectOpen(ret, auth, flags); VIR_DEBUG("driver %d %s returned %s", i, virDriverTab[i]->name, @@ -1221,10 +1222,12 @@ do_open(const char *name, (res == VIR_DRV_OPEN_ERROR ? "ERROR" : "unknown status"))); if (res == VIR_DRV_OPEN_SUCCESS) { - ret->driver = virDriverTab[i]; break; } else if (res == VIR_DRV_OPEN_ERROR) { + ret->driver = NULL; goto failed; + } else { + ret->driver = NULL; } } -- 1.8.1.4

From: "Daniel P. Berrange" <berrange@redhat.com> Add a new 'access_drivers' config parameter to the libvirtd.conf configuration file. This allows admins to setup the default access control drivers to use for API authorization. The same driver is to be used by all internal drivers & APIs Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- daemon/Makefile.am | 1 + daemon/libvirtd-config.c | 4 ++++ daemon/libvirtd-config.h | 2 ++ daemon/libvirtd.aug | 1 + daemon/libvirtd.c | 27 +++++++++++++++++++++++++++ daemon/libvirtd.conf | 9 +++++++++ daemon/test_libvirtd.aug.in | 4 ++++ 7 files changed, 48 insertions(+) diff --git a/daemon/Makefile.am b/daemon/Makefile.am index 64126e5..201369a 100644 --- a/daemon/Makefile.am +++ b/daemon/Makefile.am @@ -11,6 +11,7 @@ INCLUDES = \ -I$(top_srcdir)/src/conf \ -I$(top_srcdir)/src/rpc \ -I$(top_srcdir)/src/remote \ + -I$(top_srcdir)/src/access \ $(GETTEXT_CPPFLAGS) CLEANFILES = diff --git a/daemon/libvirtd-config.c b/daemon/libvirtd-config.c index 1c57475..d56e09b 100644 --- a/daemon/libvirtd-config.c +++ b/daemon/libvirtd-config.c @@ -379,6 +379,10 @@ daemonConfigLoadOptions(struct daemonConfig *data, if (remoteConfigGetAuth(conf, "auth_tls", &data->auth_tls, filename) < 0) goto error; + if (remoteConfigGetStringList(conf, "access_drivers", + &data->access_drivers, filename) < 0) + goto error; + GET_CONF_STR(conf, filename, unix_sock_group); GET_CONF_STR(conf, filename, unix_sock_ro_perms); GET_CONF_STR(conf, filename, unix_sock_rw_perms); diff --git a/daemon/libvirtd-config.h b/daemon/libvirtd-config.h index 07118de..973e0ea 100644 --- a/daemon/libvirtd-config.h +++ b/daemon/libvirtd-config.h @@ -45,6 +45,8 @@ struct daemonConfig { int auth_tcp; int auth_tls; + char **access_drivers; + int mdns_adv; char *mdns_name; diff --git a/daemon/libvirtd.aug b/daemon/libvirtd.aug index f32b3a1..7c56a41 100644 --- a/daemon/libvirtd.aug +++ b/daemon/libvirtd.aug @@ -51,6 +51,7 @@ module Libvirtd = | bool_entry "tls_no_sanity_certificate" | str_array_entry "tls_allowed_dn_list" | str_array_entry "sasl_allowed_username_list" + | str_array_entry "access_drivers" let processing_entry = int_entry "min_workers" | int_entry "max_workers" diff --git a/daemon/libvirtd.c b/daemon/libvirtd.c index 1ac8e30..e2ff750 100644 --- a/daemon/libvirtd.c +++ b/daemon/libvirtd.c @@ -52,8 +52,10 @@ #include "remote.h" #include "virhook.h" #include "viraudit.h" +#include "virstring.h" #include "locking/lock_manager.h" #include "virstring.h" +#include "viraccessmanager.h" #ifdef WITH_DRIVER_MODULES # include "driver.h" @@ -719,6 +721,26 @@ error: } +static int +daemonSetupAccessManager(struct daemonConfig *config) +{ + virAccessManagerPtr mgr; + const char *none[] = { "none", NULL }; + const char **driver = (const char **)config->access_drivers; + + if (!driver || + !driver[0]) + driver = none; + + if (!(mgr = virAccessManagerNewStack(driver))) + return -1; + + virAccessManagerSetDefault(mgr); + virObjectUnref(mgr); + return 0; +} + + /* Display version information. */ static void daemonVersion(const char *argv0) @@ -1251,6 +1273,11 @@ int main(int argc, char **argv) { exit(EXIT_FAILURE); } + if (daemonSetupAccessManager(config) < 0) { + VIR_ERROR(_("Can't initialize access manager")); + exit(EXIT_FAILURE); + } + if (!pid_file && daemonPidFilePath(privileged, &pid_file) < 0) { diff --git a/daemon/libvirtd.conf b/daemon/libvirtd.conf index 47da520..75196a0 100644 --- a/daemon/libvirtd.conf +++ b/daemon/libvirtd.conf @@ -155,6 +155,15 @@ #auth_tls = "none" +# Change the API access control scheme +# +# By default an authenticated user is allowed access +# to all APIs. Access drivers can place restrictions +# on this. By default the 'nop' driver is enabled, +# meaning no access control checks are done once a +# client has authenticated with libvirtd +# +#access_drivers = [ "polkit", "selinux" ] ################################################################# # diff --git a/daemon/test_libvirtd.aug.in b/daemon/test_libvirtd.aug.in index 455b74a..9215337 100644 --- a/daemon/test_libvirtd.aug.in +++ b/daemon/test_libvirtd.aug.in @@ -17,6 +17,10 @@ module Test_libvirtd = { "auth_unix_rw" = "none" } { "auth_tcp" = "sasl" } { "auth_tls" = "none" } + { "access_drivers" + { "1" = "polkit" } + { "2" = "selinux" } + } { "key_file" = "/etc/pki/libvirt/private/serverkey.pem" } { "cert_file" = "/etc/pki/libvirt/servercert.pem" } { "ca_file" = "/etc/pki/CA/cacert.pem" } -- 1.8.1.4

From: "Daniel P. Berrange" <berrange@redhat.com> Add an access control driver that uses the pkcheck command to check authorization requests. This is fairly inefficient, particularly for cases where an API returns a list of objects and needs to check permission for each object. It would be desirable to use the polkit API but this links to glib with abort-on-OOM behaviour, so can't be used. The other alternative is to speak to dbus directly Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- .gitignore | 1 + po/POTFILES.in | 1 + src/Makefile.am | 28 ++- src/access/genpolkit.pl | 119 +++++++++++ src/access/viraccessdriverpolkit.c | 399 +++++++++++++++++++++++++++++++++++++ src/access/viraccessdriverpolkit.h | 28 +++ src/access/viraccessmanager.c | 6 + 7 files changed, 581 insertions(+), 1 deletion(-) create mode 100755 src/access/genpolkit.pl create mode 100644 src/access/viraccessdriverpolkit.c create mode 100644 src/access/viraccessdriverpolkit.h diff --git a/.gitignore b/.gitignore index 5e50b52..76ee420 100644 --- a/.gitignore +++ b/.gitignore @@ -104,6 +104,7 @@ /run /sc_* /src/.*.stamp +/src/access/org.libvirt.api.policy /src/esx/*.generated.* /src/hyperv/*.generated.* /src/libvirt*.def diff --git a/po/POTFILES.in b/po/POTFILES.in index 37c6019..02713c1 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -6,6 +6,7 @@ daemon/remote_dispatch.h daemon/stream.c gnulib/lib/gai_strerror.c gnulib/lib/regcomp.c +src/access/viraccessdriverpolkit.c src/access/viraccessmanager.c src/conf/cpu_conf.c src/conf/device_conf.c diff --git a/src/Makefile.am b/src/Makefile.am index babd019..3e6c3df 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -779,6 +779,13 @@ ACCESS_DRIVER_SOURCES = \ access/viraccessdrivernop.h access/viraccessdrivernop.c \ access/viraccessdriverstack.h access/viraccessdriverstack.c +ACCESS_DRIVER_POLKIT_SOURCES = \ + access/viraccessdriverpolkit.h access/viraccessdriverpolkit.c + +ACCESS_DRIVER_POLKIT_POLICY = \ + access/org.libvirt.api.policy + + NODE_DEVICE_DRIVER_SOURCES = \ node_device/node_device_driver.c \ node_device/node_device_driver.h \ @@ -1359,6 +1366,24 @@ libvirt_driver_access_la_CFLAGS = \ libvirt_driver_access_la_LDFLAGS = $(AM_LDFLAGS) libvirt_driver_access_la_LIBADD = +EXTRA_DIST += access/genpolkit.pl + +if WITH_POLKIT1 +libvirt_driver_access_la_SOURCES += $(ACCESS_DRIVER_POLKIT_SOURCES) + +polkitactiondir = $(datadir)/polkit-1/actions +polkitaction_DATA = $(ACCESS_DRIVER_POLKIT_POLICY) + +$(ACCESS_DRIVER_POLKIT_POLICY): $(srcdir)/access/viraccessperm.h \ + $(srcdir)/access/genpolkit.pl Makefile.am + $(AM_V_GEN)$(PERL) $(srcdir)/access/genpolkit.pl < $< > $@ || rm -f $@ + +CLEANFILES += $(ACCESS_DRIVER_POLKIT_POLICY) +BUILT_SOURCES += $(ACCESS_DRIVER_POLKIT_POLICY) +else +EXTRA_DIST += $(ACCESS_DRIVER_POLKIT_SOURCES) +endif + # Add all conditional sources just in case... EXTRA_DIST += \ @@ -1398,7 +1423,8 @@ EXTRA_DIST += \ $(SECRET_DRIVER_SOURCES) \ $(VBOX_DRIVER_EXTRA_DIST) \ $(VMWARE_DRIVER_SOURCES) \ - $(XENXS_SOURCES) + $(XENXS_SOURCES) \ + $(ACCESS_DRIVER_POLKIT_POLICY) check-local: check-augeas diff --git a/src/access/genpolkit.pl b/src/access/genpolkit.pl new file mode 100755 index 0000000..eb7069a --- /dev/null +++ b/src/access/genpolkit.pl @@ -0,0 +1,119 @@ +#!/usr/bin/perl +# +# Copyright (C) 2012-2013 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 +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library. If not, see +# <http://www.gnu.org/licenses/>. +# + +use strict; +use warnings; + +my @objects = ( + "CONNECT", "DOMAIN", "INTERFACE", + "NETWORK","NODE_DEVICE", "NWFILTER", + "SECRET", "STORAGE_POOL", "STORAGE_VOL", + ); + +my $objects = join ("|", @objects); + +# Data we're going to be generating looks like this +# +# <policyconfig> +# <action id="org.libvirt.unix.monitor"> +# <description>Monitor local virtualized systems</description> +# <message>System policy prevents monitoring of local virtualized systems</message> +# <defaults> +# <allow_any>yes</allow_any> +# <allow_inactive>yes</allow_inactive> +# <allow_active>yes</allow_active> +# </defaults> +# </action> +# ...more <action> rules... +# </policyconfig> + +my %opts; +my $in_opts = 0; + +my %perms; + +while (<>) { + if ($in_opts) { + if (m,\*/,) { + $in_opts = 0; + } elsif (/\*\s*\@(\w+):\s*(.*?)\s*$/) { + $opts{$1} = $2; + } + } elsif (m,/\*\*,) { + $in_opts = 1; + } elsif (/VIR_ACCESS_PERM_($objects)_((?:\w|_)+),/) { + my $object = lc $1; + my $perm = lc $2; + next if $perm eq "last"; + + $object =~ s/_/-/g; + $perm =~ s/_/-/g; + + $perms{$object} = {} unless exists $perms{$object}; + $perms{$object}->{$perm} = { + desc => $opts{desc}, + message => $opts{message}, + anonymous => $opts{anonymous} + }; + %opts = (); + } +} + +print <<EOF; +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE policyconfig PUBLIC "-//freedesktop//DTD polkit Policy Configuration 1.0//EN" + "http://www.freedesktop.org/software/polkit/policyconfig-1.dtd"> +<policyconfig> + <vendor>Libvirt Project</vendor> + <vendor_url>http://libvirt.org</vendor_url> +EOF + +foreach my $object (sort { $a cmp $b } keys %perms) { + foreach my $perm (sort { $a cmp $b } keys %{$perms{$object}}) { + my $description = $perms{$object}->{$perm}->{desc}; + my $message = $perms{$object}->{$perm}->{message}; + my $anonymous = $perms{$object}->{$perm}->{anonymous}; + + die "missing description for $object.$perm" unless + defined $description; + die "missing message for $object.$perm" unless + defined $message; + + my $allow_any = $anonymous ? "yes" : "no"; + my $allow_inactive = $allow_any; + my $allow_active = $allow_any; + + print <<EOF; + <action id="org.libvirt.api.$object.$perm"> + <description>$description</description> + <message>$message</message> + <defaults> + <allow_any>$allow_any</allow_any> + <allow_inactive>$allow_inactive</allow_inactive> + <allow_active>$allow_active</allow_active> + </defaults> + </action> +EOF + + } +} + +print <<EOF; +</policyconfig> +EOF diff --git a/src/access/viraccessdriverpolkit.c b/src/access/viraccessdriverpolkit.c new file mode 100644 index 0000000..0426fda --- /dev/null +++ b/src/access/viraccessdriverpolkit.c @@ -0,0 +1,399 @@ +/* + * viraccessdriverpolkit.c: polkited access control driver + * + * Copyright (C) 2012 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 + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <http://www.gnu.org/licenses/>. + */ + +#include <config.h> + +#include "viraccessdriverpolkit.h" +#include "viralloc.h" +#include "vircommand.h" +#include "virlog.h" +#include "virprocess.h" +#include "virerror.h" +#include "virstring.h" + +#define VIR_FROM_THIS VIR_FROM_ACCESS +#define virAccessError(code, ...) \ + virReportErrorHelper(VIR_FROM_THIS, code, __FILE__, \ + __FUNCTION__, __LINE__, __VA_ARGS__) + +#define VIR_ACCESS_DRIVER_POLKIT_ACTION_PREFIX "org.libvirt.api" + +typedef struct _virAccessDriverPolkitPrivate virAccessDriverPolkitPrivate; +typedef virAccessDriverPolkitPrivate *virAccessDriverPolkitPrivatePtr; + +struct _virAccessDriverPolkitPrivate { + bool ignore; +}; + + +static void virAccessDriverPolkitCleanup(virAccessManagerPtr manager ATTRIBUTE_UNUSED) +{ +} + + +static char * +virAccessDriverPolkitFormatAction(const char *typename, + const char *permname) +{ + char *actionid = NULL; + size_t i; + + if (virAsprintf(&actionid, "%s.%s.%s", + VIR_ACCESS_DRIVER_POLKIT_ACTION_PREFIX, + typename, permname) < 0) { + virReportOOMError(); + return NULL; + } + + for (i = 0 ; actionid[i] ; i++) + if (actionid[i] == '_') + actionid[i] = '-'; + + return actionid; +} + + +static char * +virAccessDriverPolkitFormatProcess(const char *actionid) +{ + virIdentityPtr identity = virIdentityGetCurrent(); + const char *process = NULL; + char *ret = NULL; + + if (!identity) { + virAccessError(VIR_ERR_ACCESS_DENIED, + _("Policy kit denied action %s from <anonymous>"), + actionid); + return NULL; + } + if (virIdentityGetAttr(identity, VIR_IDENTITY_ATTR_UNIX_PROCESS_ID, &process) < 0) + goto cleanup; + + if (!process) { + virAccessError(VIR_ERR_INTERNAL_ERROR, "%s", + _("No UNIX process ID available")); + goto cleanup; + } + + if (VIR_STRDUP(ret, process) < 0) + goto cleanup; + +cleanup: + virObjectUnref(identity); + return ret; +} + + +static int +virAccessDriverPolkitCheck(virAccessManagerPtr manager ATTRIBUTE_UNUSED, + const char *typename, + const char *permname, + const char **attrs) +{ + char *actionid = NULL; + char *process = NULL; + virCommandPtr cmd = NULL; + int status; + int ret = -1; + + if (!(actionid = virAccessDriverPolkitFormatAction(typename, permname))) + goto cleanup; + + if (!(process = virAccessDriverPolkitFormatProcess(actionid))) + goto cleanup; + + cmd = virCommandNewArgList(PKCHECK_PATH, + "--action-id", actionid, + "--process", process, + NULL); + + while (attrs && attrs[0] && attrs[1]) { + virCommandAddArgList(cmd, "--detail", attrs[0], attrs[1], NULL); + attrs += 2; + } + + if (virCommandRun(cmd, &status) < 0) + goto cleanup; + + if (status == 0) { + ret = 1; /* Allowed */ + } else { + if (status == 1 || + status == 2 || + status == 3) { + ret = 0; /* Denied */ + } else { + ret = -1; /* Error */ + char *tmp = virProcessTranslateStatus(status); + virAccessError(VIR_ERR_ACCESS_DENIED, + _("Policy kit denied action %s from %s: %s"), + actionid, process, NULLSTR(tmp)); + VIR_FREE(tmp); + } + goto cleanup; + } + +cleanup: + virCommandFree(cmd); + VIR_FREE(actionid); + VIR_FREE(process); + return ret; +} + + +static int +virAccessDriverPolkitCheckConnect(virAccessManagerPtr manager, + const char *driverName, + virAccessPermConnect perm) +{ + const char *attrs[] = { + "connect-driver", driverName, + NULL, + }; + + return virAccessDriverPolkitCheck(manager, + "connect", + virAccessPermConnectTypeToString(perm), + attrs); +} + +static int +virAccessDriverPolkitCheckDomain(virAccessManagerPtr manager, + const char *driverName, + virDomainDefPtr domain, + virAccessPermDomain perm) +{ + char uuidstr[VIR_UUID_STRING_BUFLEN]; + const char *attrs[] = { + "connect-driver", driverName, + "domain-name", domain->name, + "domain-uuid", uuidstr, + NULL, + }; + virUUIDFormat(domain->uuid, uuidstr); + + return virAccessDriverPolkitCheck(manager, + "domain", + virAccessPermDomainTypeToString(perm), + attrs); +} + +static int +virAccessDriverPolkitCheckInterface(virAccessManagerPtr manager, + const char *driverName, + virInterfaceDefPtr iface, + virAccessPermInterface perm) +{ + const char *attrs[] = { + "connect-driver", driverName, + "interface-name", iface->name, + "interface-macaddr", iface->mac, + NULL, + }; + + return virAccessDriverPolkitCheck(manager, + "interface", + virAccessPermInterfaceTypeToString(perm), + attrs); +} + +static int +virAccessDriverPolkitCheckNetwork(virAccessManagerPtr manager, + const char *driverName, + virNetworkDefPtr network, + virAccessPermNetwork perm) +{ + char uuidstr[VIR_UUID_STRING_BUFLEN]; + const char *attrs[] = { + "connect-driver", driverName, + "network-name", network->name, + "network-uuid", uuidstr, + NULL, + }; + virUUIDFormat(network->uuid, uuidstr); + + return virAccessDriverPolkitCheck(manager, + "network", + virAccessPermNetworkTypeToString(perm), + attrs); +} + +static int +virAccessDriverPolkitCheckNodeDevice(virAccessManagerPtr manager, + const char *driverName, + virNodeDeviceDefPtr nodedev, + virAccessPermNodeDevice perm) +{ + const char *attrs[] = { + "connect-driver", driverName, + "node-device-name", nodedev->name, + NULL, + }; + + return virAccessDriverPolkitCheck(manager, + "nodedevice", + virAccessPermNodeDeviceTypeToString(perm), + attrs); +} + +static int +virAccessDriverPolkitCheckNWFilter(virAccessManagerPtr manager, + const char *driverName, + virNWFilterDefPtr nwfilter, + virAccessPermNWFilter perm) +{ + char uuidstr[VIR_UUID_STRING_BUFLEN]; + const char *attrs[] = { + "connect-driver", driverName, + "nwfilter-name", nwfilter->name, + "nwfilter-uuid", uuidstr, + NULL, + }; + virUUIDFormat(nwfilter->uuid, uuidstr); + + return virAccessDriverPolkitCheck(manager, + "nwfilter", + virAccessPermNWFilterTypeToString(perm), + attrs); +} + +static int +virAccessDriverPolkitCheckSecret(virAccessManagerPtr manager, + const char *driverName, + virSecretDefPtr secret, + virAccessPermSecret perm) +{ + char uuidstr[VIR_UUID_STRING_BUFLEN]; + virUUIDFormat(secret->uuid, uuidstr); + + switch (secret->usage_type) { + default: + case VIR_SECRET_USAGE_TYPE_NONE: { + const char *attrs[] = { + "connect-driver", driverName, + "secret-uuid", uuidstr, + NULL, + }; + + return virAccessDriverPolkitCheck(manager, + "secret", + virAccessPermSecretTypeToString(perm), + attrs); + } break; + case VIR_SECRET_USAGE_TYPE_VOLUME: { + const char *attrs[] = { + "connect-driver", driverName, + "secret-uuid", uuidstr, + "secret-usage-volume", secret->usage.volume, + NULL, + }; + + return virAccessDriverPolkitCheck(manager, + "secret", + virAccessPermSecretTypeToString(perm), + attrs); + } break; + case VIR_SECRET_USAGE_TYPE_CEPH: { + const char *attrs[] = { + "connect-driver", driverName, + "secret-uuid", uuidstr, + "secret-usage-ceph", secret->usage.ceph, + NULL, + }; + + return virAccessDriverPolkitCheck(manager, + "secret", + virAccessPermSecretTypeToString(perm), + attrs); + } break; + case VIR_SECRET_USAGE_TYPE_ISCSI: { + const char *attrs[] = { + "connect-driver", driverName, + "secret-uuid", uuidstr, + "secret-usage-target", secret->usage.target, + NULL, + }; + + return virAccessDriverPolkitCheck(manager, + "secret", + virAccessPermSecretTypeToString(perm), + attrs); + } break; + } +} + +static int +virAccessDriverPolkitCheckStoragePool(virAccessManagerPtr manager, + const char *driverName, + virStoragePoolDefPtr pool, + virAccessPermStoragePool perm) +{ + char uuidstr[VIR_UUID_STRING_BUFLEN]; + const char *attrs[] = { + "connect-driver", driverName, + "pool-name", pool->name, + "pool-uuid", uuidstr, + NULL, + }; + virUUIDFormat(pool->uuid, uuidstr); + + return virAccessDriverPolkitCheck(manager, + "pool", + virAccessPermStoragePoolTypeToString(perm), + attrs); +} + +static int +virAccessDriverPolkitCheckStorageVol(virAccessManagerPtr manager, + const char *driverName, + virStoragePoolDefPtr pool, + virStorageVolDefPtr vol, + virAccessPermStorageVol perm) +{ + char uuidstr[VIR_UUID_STRING_BUFLEN]; + const char *attrs[] = { + "connect-driver", driverName, + "pool-name", pool->name, + "pool-uuid", uuidstr, + "vol-name", vol->name, + "vol-key", vol->key, + NULL, + }; + virUUIDFormat(pool->uuid, uuidstr); + + return virAccessDriverPolkitCheck(manager, + "vol", + virAccessPermStorageVolTypeToString(perm), + attrs); +} + +virAccessDriver accessDriverPolkit = { + .name = "polkit", + .cleanup = virAccessDriverPolkitCleanup, + .checkConnect = virAccessDriverPolkitCheckConnect, + .checkDomain = virAccessDriverPolkitCheckDomain, + .checkInterface = virAccessDriverPolkitCheckInterface, + .checkNetwork = virAccessDriverPolkitCheckNetwork, + .checkNodeDevice = virAccessDriverPolkitCheckNodeDevice, + .checkNWFilter = virAccessDriverPolkitCheckNWFilter, + .checkSecret = virAccessDriverPolkitCheckSecret, + .checkStoragePool = virAccessDriverPolkitCheckStoragePool, + .checkStorageVol = virAccessDriverPolkitCheckStorageVol, +}; diff --git a/src/access/viraccessdriverpolkit.h b/src/access/viraccessdriverpolkit.h new file mode 100644 index 0000000..00b044f --- /dev/null +++ b/src/access/viraccessdriverpolkit.h @@ -0,0 +1,28 @@ +/* + * viraccessdriverpolkit.h: polkited access control driver + * + * Copyright (C) 2012 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 + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <http://www.gnu.org/licenses/>. + */ + +#ifndef __VIR_ACCESS_DRIVER_POLKIT_H__ +# define __VIR_ACCESS_DRIVER_POLKIT_H__ + +# include "viraccessdriver.h" + +extern virAccessDriver accessDriverPolkit; + +#endif /* __VIR_ACCESS_DRIVER_POLKIT_H__ */ diff --git a/src/access/viraccessmanager.c b/src/access/viraccessmanager.c index ff1a538..f8c0cae 100644 --- a/src/access/viraccessmanager.c +++ b/src/access/viraccessmanager.c @@ -23,6 +23,9 @@ #include "viraccessmanager.h" #include "viraccessdrivernop.h" #include "viraccessdriverstack.h" +#if WITH_POLKIT1 +# include "viraccessdriverpolkit.h" +#endif #include "viralloc.h" #include "virerror.h" #include "virobject.h" @@ -108,6 +111,9 @@ static virAccessManagerPtr virAccessManagerNewDriver(virAccessDriverPtr drv) static virAccessDriverPtr accessDrivers[] = { &accessDriverNop, +#if WITH_POLKIT1 + &accessDriverPolkit, +#endif }; -- 1.8.1.4

From: "Daniel P. Berrange" <berrange@redhat.com> Introduce an access control driver that uses the SELinux framework for validating API authorization. Each libvirt object is represented as a new class in SELinux policy, along with all permissions. The actual policy is not included here, it has to be part of the core SELinux policy dist, since you can't define new object classes/permissions in external loadable modules As well as going to the audit system, all SELinux AVC denials also get reported in libvirtd system logs Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- m4/virt-compile-warnings.m4 | 1 + m4/virt-selinux.m4 | 2 + po/POTFILES.in | 1 + src/Makefile.am | 9 + src/access/viraccessdriverselinux.c | 565 ++++++++++++++++++++++++++++++++++++ src/access/viraccessdriverselinux.h | 28 ++ src/access/viraccessmanager.c | 6 + src/internal.h | 4 + src/util/virlog.c | 3 +- src/util/virlog.h | 1 + 10 files changed, 619 insertions(+), 1 deletion(-) create mode 100644 src/access/viraccessdriverselinux.c create mode 100644 src/access/viraccessdriverselinux.h diff --git a/m4/virt-compile-warnings.m4 b/m4/virt-compile-warnings.m4 index e054913..05798d3 100644 --- a/m4/virt-compile-warnings.m4 +++ b/m4/virt-compile-warnings.m4 @@ -94,6 +94,7 @@ AC_DEFUN([LIBVIRT_COMPILE_WARNINGS],[ dontwarn="$dontwarn -Wmissing-prototypes" dontwarn="$dontwarn -Wmissing-declarations" dontwarn="$dontwarn -Wcast-align" + dontwarn="$dontwarn -Wmissing-format-attribute" fi dnl Check whether strchr(s, char variable) causes a bogus compile diff --git a/m4/virt-selinux.m4 b/m4/virt-selinux.m4 index abb0d12..f849858 100644 --- a/m4/virt-selinux.m4 +++ b/m4/virt-selinux.m4 @@ -43,6 +43,8 @@ AC_DEFUN([LIBVIRT_CHECK_SELINUX],[ dnl We prefer to use <selinux/label.h> and selabel_open, but can fall dnl back to matchpathcon for the sake of RHEL 5's version of libselinux. AC_CHECK_HEADERS([selinux/label.h]) + + AC_CHECK_FUNCS([security_deny_unknown]) fi ]) diff --git a/po/POTFILES.in b/po/POTFILES.in index 02713c1..5723a0f 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -7,6 +7,7 @@ daemon/stream.c gnulib/lib/gai_strerror.c gnulib/lib/regcomp.c src/access/viraccessdriverpolkit.c +src/access/viraccessdriverselinux.c src/access/viraccessmanager.c src/conf/cpu_conf.c src/conf/device_conf.c diff --git a/src/Makefile.am b/src/Makefile.am index 3e6c3df..20ce083 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -782,6 +782,9 @@ ACCESS_DRIVER_SOURCES = \ ACCESS_DRIVER_POLKIT_SOURCES = \ access/viraccessdriverpolkit.h access/viraccessdriverpolkit.c +ACCESS_DRIVER_SELINUX_SOURCES = \ + access/viraccessdriverselinux.h access/viraccessdriverselinux.c + ACCESS_DRIVER_POLKIT_POLICY = \ access/org.libvirt.api.policy @@ -1368,6 +1371,12 @@ libvirt_driver_access_la_LIBADD = EXTRA_DIST += access/genpolkit.pl +if WITH_SELINUX +libvirt_driver_access_la_SOURCES += $(ACCESS_DRIVER_SELINUX_SOURCES) +else +EXTRA_DIST += $(ACCESS_DRIVER_SELINUX_SOURCES) +endif + if WITH_POLKIT1 libvirt_driver_access_la_SOURCES += $(ACCESS_DRIVER_POLKIT_SOURCES) diff --git a/src/access/viraccessdriverselinux.c b/src/access/viraccessdriverselinux.c new file mode 100644 index 0000000..235760d --- /dev/null +++ b/src/access/viraccessdriverselinux.c @@ -0,0 +1,565 @@ +/* + * viraccessdriverselinux.c: selinuxed access control driver + * + * Copyright (C) 2012 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 + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <http://www.gnu.org/licenses/>. + */ + +#include <config.h> + +#include "viraccessdriverselinux.h" +#include "viralloc.h" +#include "vircommand.h" +#include "virlog.h" +#include "virthread.h" +#include "virerror.h" +#include "virutil.h" + +#include <selinux/selinux.h> +#include <selinux/avc.h> +#include <selinux/av_permissions.h> +#include <selinux/flask.h> + + +#define VIR_FROM_THIS VIR_FROM_ACCESS +#define virAccessError(code, ...) \ + virReportErrorHelper(VIR_FROM_THIS, code, __FILE__, \ + __FUNCTION__, __LINE__, __VA_ARGS__) + +typedef enum { + VIR_ACCESS_DRIVER_SELINUX_CLASS_CONNECT, + VIR_ACCESS_DRIVER_SELINUX_CLASS_DOMAIN, + + VIR_ACCESS_DRIVER_SELINUX_CLASS_LAST +} virAccessDriverSELinuxClass; + +VIR_ENUM_DECL(virAccessDriverSELinuxClass) +VIR_ENUM_IMPL(virAccessDriverSELinuxClass, + VIR_ACCESS_DRIVER_SELINUX_CLASS_LAST, + "vir_connect", + "vir_domain") + +static void virAccessDriverSELinuxAVCLog(const char *fmt, ...) ATTRIBUTE_FMT_PRINTF(1, 2); +static void virAccessDriverSELinuxAVCLogAudit(void *data, security_class_t class, char *buf, size_t bufleft); +static void *virAccessDriverSELinuxAVCCreateThread(void (*run)(void)); +static void virAccessDriverSELinuxAVCStopThread(void *thread); +static void *virAccessDriverSELinuxAVCAllocLock(void); +static void virAccessDriverSELinuxAVCGetLock(void *lock); +static void virAccessDriverSELinuxAVCReleaseLock(void *lock); +static void virAccessDriverSELinuxAVCFreeLock(void *lock); + + +/* AVC callback structures for use in avc_init. */ +static const struct avc_memory_callback virAccessDriverSELinuxAVCMemCallbacks = +{ + .func_malloc = malloc, + .func_free = free, +}; + +VIR_WARNINGS_NO_MISSING_FORMAT +static const struct avc_log_callback virAccessDriverSELinuxAVCLogCallbacks = +{ + .func_log = virAccessDriverSELinuxAVCLog, + .func_audit = virAccessDriverSELinuxAVCLogAudit, +}; +VIR_WARNINGS_RESET + +static const struct avc_thread_callback virAccessDriverSELinuxAVCThreadCallbacks = +{ + .func_create_thread = virAccessDriverSELinuxAVCCreateThread, + .func_stop_thread = virAccessDriverSELinuxAVCStopThread, +}; +static const struct avc_lock_callback virAccessDriverSELinuxAVCLockCallbacks = +{ + .func_alloc_lock = virAccessDriverSELinuxAVCAllocLock, + .func_get_lock = virAccessDriverSELinuxAVCGetLock, + .func_release_lock = virAccessDriverSELinuxAVCReleaseLock, + .func_free_lock = virAccessDriverSELinuxAVCFreeLock, +}; + + +typedef struct _virAccessDriverSELinuxPrivate virAccessDriverSELinuxPrivate; +typedef virAccessDriverSELinuxPrivate *virAccessDriverSELinuxPrivatePtr; + +struct _virAccessDriverSELinuxPrivate { + bool enabled; + + /* Cache for AVCs */ + struct avc_entry_ref aeref; + + /* SID of the daemon */ + security_id_t selfSid; +}; + + +static int virAccessDriverSELinuxSetup(virAccessManagerPtr manager) +{ + virAccessDriverSELinuxPrivatePtr priv = virAccessManagerGetPrivateData(manager); + int r; + security_context_t localCon; + int ret = -1; + + if ((r = is_selinux_enabled()) < 0) { + virReportSystemError(errno, "%s", + _("Unable to determine if SELinux is enabled")); + return -1; + } + priv->enabled = r != 0; + priv->selfSid = SECSID_WILD; + + avc_entry_ref_init(&priv->aeref); + + if (avc_init("avc", + &virAccessDriverSELinuxAVCMemCallbacks, + &virAccessDriverSELinuxAVCLogCallbacks, + &virAccessDriverSELinuxAVCThreadCallbacks, + &virAccessDriverSELinuxAVCLockCallbacks) < 0) { + virReportSystemError(errno, "%s", + _("Unable to initialize AVC system")); + goto cleanup; + } + + if (getcon(&localCon) < 0) { + virReportSystemError(errno, "%s", + _("Unable to get context of daemon")); + goto cleanup; + } + + if (avc_context_to_sid(localCon, &priv->selfSid) < 0) { + virReportSystemError(errno, + _("Unable to convert context %s to SID"), + (char*)localCon); + goto cleanup; + } + VIR_FREE(localCon); + + ret = 0; +cleanup: + if (ret < 0) + priv->selfSid = SECSID_WILD; + freecon(localCon); + return ret; +} + + +static void virAccessDriverSELinuxCleanup(virAccessManagerPtr manager) +{ + virAccessDriverSELinuxPrivatePtr priv = virAccessManagerGetPrivateData(manager); + + priv->selfSid = SECSID_WILD; +} + + +static security_id_t +virAccessDriverSELinuxGetClientSID(void) +{ + virIdentityPtr identity = virIdentityGetCurrent(); + const char *seccon = NULL; + security_id_t sid = SECSID_WILD; + + if (!identity) { + virAccessError(VIR_ERR_ACCESS_DENIED, "%s", + _("SELinux denying due to lack of identity")); + return NULL; + } + if (virIdentityGetAttr(identity, VIR_IDENTITY_ATTR_SELINUX_CONTEXT, &seccon) < 0) + goto cleanup; + + if (!seccon) { + virAccessError(VIR_ERR_INTERNAL_ERROR, "%s", + _("No security context available")); + goto cleanup; + } + + if (avc_context_to_sid((security_context_t)seccon, &sid) < 0) { + virReportSystemError(errno, + _("Unable to convert context %s to SID"), + seccon); + sid = SECSID_WILD; + goto cleanup; + } + +cleanup: + virObjectUnref(identity); + return sid; +} + + +static security_class_t +virAccessDriverSELinuxGetObjectClass(const char *klassname) +{ + security_class_t ret; + + if ((ret = string_to_security_class(klassname)) == 0) { + virReportSystemError(errno, + _("Unable to find security class '%s'"), klassname); + return 0; + } + + return ret; +} + + +static access_vector_t +virAccessDriverSELinuxGetObjectPerm(const char *permname, + const char *klassname, + security_class_t objectClass) +{ + access_vector_t ret; + + if (objectClass == 0) + return 0; + + if ((ret = string_to_av_perm(objectClass, permname)) == 0) { + virReportSystemError(errno, + _("Unable to lookup permission '%s' for class '%s'"), + permname, klassname); + return 0; + } + + return ret; +} + +static int +virAccessDriverSELinuxCheck(virAccessManagerPtr manager, + security_id_t objectSid, + virAccessDriverSELinuxClass klass, + const char *permname) +{ + virAccessDriverSELinuxPrivatePtr priv = virAccessManagerGetPrivateData(manager); + const char *klassname = virAccessDriverSELinuxClassTypeToString(klass); + security_id_t clientSid = virAccessDriverSELinuxGetClientSID(); + security_class_t klassId = virAccessDriverSELinuxGetObjectClass(klassname); + access_vector_t perm = virAccessDriverSELinuxGetObjectPerm(permname, klassname, klassId); + int ret; + + if (clientSid == SECSID_WILD || + klassId == 0 || + perm == 0) { +#ifdef HAVE_SECURITY_DENY_UNKNOWN + if (security_deny_unknown() == 0) { + VIR_WARN("Allow access, because policy does not deny unknown objects"); + ret = 1; /* Allow */ + } else { + ret = 0; /* Deny */ + } +#else + ret = 0; /* Deny */ +#endif + goto cleanup; + } + + if (avc_has_perm(clientSid, objectSid, + klassId, perm, + &priv->aeref, NULL) < 0) { + int save_errno = errno; + if (security_getenforce() == 0) { + char ebuf[1024]; + VIR_WARN("Ignoring denial in non-enforcing mode: %s", + virStrerror(save_errno, ebuf, sizeof(ebuf))); + ret = 1; /* Allow */ + goto cleanup; + } + switch (save_errno) { + case EACCES: + ret = 0; /* Deny */ + break; + case EINVAL: + ret = -1; /* Error */ + virAccessError(VIR_ERR_ACCESS_DENIED, "%s", + _("SELinux denying due to invalid security context")); + break; + default: + ret = -1; /* Error */ + virReportSystemError(errno, "%s", + _("SELinux denying")); + break; + } + goto cleanup; + } + + ret = 1; + +cleanup: + return ret; +} + + +static int +virAccessDriverSELinuxCheckConnect(virAccessManagerPtr manager, + const char *driverName ATTRIBUTE_UNUSED, + virAccessPermConnect perm) +{ + virAccessDriverSELinuxPrivatePtr priv = virAccessManagerGetPrivateData(manager); + + /* There's no object to use for targetSid here, so we + * instead use the daemon's context as the targetSid */ + return virAccessDriverSELinuxCheck(manager, + priv->selfSid, + VIR_ACCESS_DRIVER_SELINUX_CLASS_CONNECT, + virAccessPermConnectTypeToString(perm)); +} + + +static int +virAccessDriverSELinuxCheckDomain(virAccessManagerPtr manager, + const char *driverName ATTRIBUTE_UNUSED, + virDomainDefPtr domain ATTRIBUTE_UNUSED, + virAccessPermDomain perm) +{ + security_id_t objectSid; + + virAccessDriverSELinuxPrivatePtr priv = virAccessManagerGetPrivateData(manager); + + objectSid = priv->selfSid; /* XXX take from def ? */ + + return virAccessDriverSELinuxCheck(manager, + objectSid, + VIR_ACCESS_DRIVER_SELINUX_CLASS_DOMAIN, + virAccessPermDomainTypeToString(perm)); +} + + +static int +virAccessDriverSELinuxCheckInterface(virAccessManagerPtr manager, + const char *driverName ATTRIBUTE_UNUSED, + virInterfaceDefPtr iface ATTRIBUTE_UNUSED, + virAccessPermInterface perm) +{ + security_id_t objectSid; + + virAccessDriverSELinuxPrivatePtr priv = virAccessManagerGetPrivateData(manager); + + objectSid = priv->selfSid; /* XXX take from def ? */ + + return virAccessDriverSELinuxCheck(manager, + objectSid, + VIR_ACCESS_DRIVER_SELINUX_CLASS_DOMAIN, + virAccessPermInterfaceTypeToString(perm)); +} + + +static int +virAccessDriverSELinuxCheckNetwork(virAccessManagerPtr manager, + const char *driverName ATTRIBUTE_UNUSED, + virNetworkDefPtr network ATTRIBUTE_UNUSED, + virAccessPermNetwork perm) +{ + security_id_t objectSid; + + virAccessDriverSELinuxPrivatePtr priv = virAccessManagerGetPrivateData(manager); + + objectSid = priv->selfSid; /* XXX take from def ? */ + + return virAccessDriverSELinuxCheck(manager, + objectSid, + VIR_ACCESS_DRIVER_SELINUX_CLASS_DOMAIN, + virAccessPermNetworkTypeToString(perm)); +} + + +static int +virAccessDriverSELinuxCheckNodeDevice(virAccessManagerPtr manager, + const char *driverName ATTRIBUTE_UNUSED, + virNodeDeviceDefPtr nodedev ATTRIBUTE_UNUSED, + virAccessPermNodeDevice perm) +{ + security_id_t objectSid; + + virAccessDriverSELinuxPrivatePtr priv = virAccessManagerGetPrivateData(manager); + + objectSid = priv->selfSid; /* XXX take from def ? */ + + return virAccessDriverSELinuxCheck(manager, + objectSid, + VIR_ACCESS_DRIVER_SELINUX_CLASS_DOMAIN, + virAccessPermNodeDeviceTypeToString(perm)); +} + + +static int +virAccessDriverSELinuxCheckNWFilter(virAccessManagerPtr manager, + const char *driverName ATTRIBUTE_UNUSED, + virNWFilterDefPtr nwfilter ATTRIBUTE_UNUSED, + virAccessPermNWFilter perm) +{ + security_id_t objectSid; + + virAccessDriverSELinuxPrivatePtr priv = virAccessManagerGetPrivateData(manager); + + objectSid = priv->selfSid; /* XXX take from def ? */ + + return virAccessDriverSELinuxCheck(manager, + objectSid, + VIR_ACCESS_DRIVER_SELINUX_CLASS_DOMAIN, + virAccessPermNWFilterTypeToString(perm)); +} + + +static int +virAccessDriverSELinuxCheckSecret(virAccessManagerPtr manager, + const char *driverName ATTRIBUTE_UNUSED, + virSecretDefPtr secret ATTRIBUTE_UNUSED, + virAccessPermSecret perm) +{ + security_id_t objectSid; + + virAccessDriverSELinuxPrivatePtr priv = virAccessManagerGetPrivateData(manager); + + objectSid = priv->selfSid; /* XXX take from def ? */ + + return virAccessDriverSELinuxCheck(manager, + objectSid, + VIR_ACCESS_DRIVER_SELINUX_CLASS_DOMAIN, + virAccessPermSecretTypeToString(perm)); +} + + +static int +virAccessDriverSELinuxCheckStoragePool(virAccessManagerPtr manager, + const char *driverName ATTRIBUTE_UNUSED, + virStoragePoolDefPtr pool ATTRIBUTE_UNUSED, + virAccessPermStoragePool perm) +{ + security_id_t objectSid; + + virAccessDriverSELinuxPrivatePtr priv = virAccessManagerGetPrivateData(manager); + + objectSid = priv->selfSid; /* XXX take from def ? */ + + return virAccessDriverSELinuxCheck(manager, + objectSid, + VIR_ACCESS_DRIVER_SELINUX_CLASS_DOMAIN, + virAccessPermStoragePoolTypeToString(perm)); +} + + +static int +virAccessDriverSELinuxCheckStorageVol(virAccessManagerPtr manager, + const char *driverName ATTRIBUTE_UNUSED, + virStoragePoolDefPtr pool ATTRIBUTE_UNUSED, + virStorageVolDefPtr vol ATTRIBUTE_UNUSED, + virAccessPermStorageVol perm) +{ + security_id_t objectSid; + + virAccessDriverSELinuxPrivatePtr priv = virAccessManagerGetPrivateData(manager); + + objectSid = priv->selfSid; /* XXX take from def ? */ + + return virAccessDriverSELinuxCheck(manager, + objectSid, + VIR_ACCESS_DRIVER_SELINUX_CLASS_DOMAIN, + virAccessPermStorageVolTypeToString(perm)); +} + + +static void virAccessDriverSELinuxAVCLog(const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + virLogVMessage(VIR_LOG_FROM_ACCESS, VIR_LOG_WARN, + __FILE__, __LINE__ ,__func__, + NULL, fmt, ap); + va_end(ap); +} + + +static void virAccessDriverSELinuxAVCLogAudit(void *data ATTRIBUTE_UNUSED, + security_class_t class ATTRIBUTE_UNUSED, + char *buf ATTRIBUTE_UNUSED, + size_t bufleft ATTRIBUTE_UNUSED) +{ +} + + +static void *virAccessDriverSELinuxAVCCreateThread(void (*run)(void)) +{ + virThreadPtr thread; + + if (VIR_ALLOC(thread) < 0) { + virReportOOMError(); + return NULL; + } + + if (virThreadCreate(thread, false, (virThreadFunc)run, NULL) < 0) { + virReportSystemError(errno, "%s", + _("Unable to create thread")); + VIR_FREE(thread); + } + + return thread; +} + + +static void virAccessDriverSELinuxAVCStopThread(void *thread) +{ + virThreadCancel(thread); + VIR_FREE(thread); +} + + +static void *virAccessDriverSELinuxAVCAllocLock(void) +{ + virMutexPtr lock; + if (VIR_ALLOC(lock) < 0) { + virReportOOMError(); + return NULL; + } + if (virMutexInit(lock) < 0) { + virReportSystemError(errno, "%s", + _("Unable to initialize mutex")); + VIR_FREE(lock); + return NULL; + } + return lock; +} + + +static void virAccessDriverSELinuxAVCGetLock(void *lock) +{ + virMutexLock(lock); +} + + +static void virAccessDriverSELinuxAVCReleaseLock(void *lock) +{ + virMutexUnlock(lock); +} + + +static void virAccessDriverSELinuxAVCFreeLock(void *lock) +{ + virMutexDestroy(lock); + VIR_FREE(lock); +} + + +virAccessDriver accessDriverSELinux = { + .privateDataLen = sizeof(virAccessDriverSELinuxPrivate), + .name = "selinux", + .setup = virAccessDriverSELinuxSetup, + .cleanup = virAccessDriverSELinuxCleanup, + .checkConnect = virAccessDriverSELinuxCheckConnect, + .checkDomain = virAccessDriverSELinuxCheckDomain, + .checkInterface = virAccessDriverSELinuxCheckInterface, + .checkNetwork = virAccessDriverSELinuxCheckNetwork, + .checkNodeDevice = virAccessDriverSELinuxCheckNodeDevice, + .checkNWFilter = virAccessDriverSELinuxCheckNWFilter, + .checkSecret = virAccessDriverSELinuxCheckSecret, + .checkStoragePool = virAccessDriverSELinuxCheckStoragePool, + .checkStorageVol = virAccessDriverSELinuxCheckStorageVol, +}; diff --git a/src/access/viraccessdriverselinux.h b/src/access/viraccessdriverselinux.h new file mode 100644 index 0000000..e2b26e2 --- /dev/null +++ b/src/access/viraccessdriverselinux.h @@ -0,0 +1,28 @@ +/* + * viraccessdriverselinux.h: selinuxed access control driver + * + * Copyright (C) 2012 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 + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see + * <http://www.gnu.org/licenses/>. + */ + +#ifndef __VIR_ACCESS_DRIVER_SELINUX_H__ +# define __VIR_ACCESS_DRIVER_SELINUX_H__ + +# include "viraccessdriver.h" + +extern virAccessDriver accessDriverSELinux; + +#endif /* __VIR_ACCESS_DRIVER_SELINUX_H__ */ diff --git a/src/access/viraccessmanager.c b/src/access/viraccessmanager.c index f8c0cae..71c3470 100644 --- a/src/access/viraccessmanager.c +++ b/src/access/viraccessmanager.c @@ -26,6 +26,9 @@ #if WITH_POLKIT1 # include "viraccessdriverpolkit.h" #endif +#if WITH_SELINUX +# include "viraccessdriverselinux.h" +#endif #include "viralloc.h" #include "virerror.h" #include "virobject.h" @@ -114,6 +117,9 @@ static virAccessDriverPtr accessDrivers[] = { #if WITH_POLKIT1 &accessDriverPolkit, #endif +#if WITH_SELINUX + &accessDriverSELinux, +#endif }; diff --git a/src/internal.h b/src/internal.h index d819aa3..9b56fa2 100644 --- a/src/internal.h +++ b/src/internal.h @@ -219,11 +219,15 @@ # define VIR_WARNINGS_NO_CAST_ALIGN \ _Pragma ("GCC diagnostic push") \ _Pragma ("GCC diagnostic ignored \"-Wcast-align\"") +# define VIR_WARNINGS_NO_MISSING_FORMAT \ + _Pragma ("GCC diagnostic push") \ + _Pragma ("GCC diagnostic ignored \"-Wmissing-format-attribute\"") # define VIR_WARNINGS_RESET \ _Pragma ("GCC diagnostic pop") # else # define VIR_WARNINGS_NO_CAST_ALIGN +# define VIR_WARNINGS_NO_MISSING_FORMAT # define VIR_WARNINGS_RESET # endif diff --git a/src/util/virlog.c b/src/util/virlog.c index 62ff838..152191c 100644 --- a/src/util/virlog.c +++ b/src/util/virlog.c @@ -66,7 +66,8 @@ VIR_ENUM_IMPL(virLogSource, VIR_LOG_FROM_LAST, "error", "audit", "trace", - "library"); + "library", + "access"); /* * A logging buffer to keep some history over logs diff --git a/src/util/virlog.h b/src/util/virlog.h index 6b83245..08d12c0 100644 --- a/src/util/virlog.h +++ b/src/util/virlog.h @@ -50,6 +50,7 @@ typedef enum { VIR_LOG_FROM_AUDIT, VIR_LOG_FROM_TRACE, VIR_LOG_FROM_LIBRARY, + VIR_LOG_FROM_ACCESS, VIR_LOG_FROM_LAST, } virLogSource; -- 1.8.1.4

From: "Daniel P. Berrange" <berrange@redhat.com> Introduce annotations to all RPC messages to declare what access control checks are required. There are two new annotations defined: @acl: <object>:<permission> @acl: <object>:<permission>:<flagname> Declare the access control requirements for the API. May be repeated multiple times, if multiple rules are required. <object> is one of 'connect', 'domain', 'network', 'storagepool', 'interface', 'nodedev', 'secret'. <permission> is one of the permissions in access/viraccessperm.h <flagname> indicates the rule only applies if the named flag is set in the API call @aclfilter: <object>:<permission> Declare an access control filter that will be applied to a list of objects being returned by an API. This allows the returned list to be filtered to only show those the user has permissions against Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- src/locking/lock_protocol.x | 8 + src/remote/lxc_protocol.x | 1 + src/remote/qemu_protocol.x | 4 + src/remote/remote_protocol.x | 406 +++++++++++++++++++++++++++++++++++++++++++ src/rpc/gendispatch.pl | 2 +- 5 files changed, 420 insertions(+), 1 deletion(-) diff --git a/src/locking/lock_protocol.x b/src/locking/lock_protocol.x index f69f2e8..354d51a 100644 --- a/src/locking/lock_protocol.x +++ b/src/locking/lock_protocol.x @@ -105,41 +105,49 @@ enum virLockSpaceProtocolProcedure { /** * @generate: none + * @acl: none */ VIR_LOCK_SPACE_PROTOCOL_PROC_REGISTER = 1, /** * @generate: none + * @acl: none */ VIR_LOCK_SPACE_PROTOCOL_PROC_RESTRICT = 2, /** * @generate: none + * @acl: none */ VIR_LOCK_SPACE_PROTOCOL_PROC_NEW = 3, /** * @generate: none + * @acl: none */ VIR_LOCK_SPACE_PROTOCOL_PROC_CREATE_RESOURCE = 4, /** * @generate: none + * @acl: none */ VIR_LOCK_SPACE_PROTOCOL_PROC_DELETE_RESOURCE = 5, /** * @generate: none + * @acl: none */ VIR_LOCK_SPACE_PROTOCOL_PROC_ACQUIRE_RESOURCE = 6, /** * @generate: none + * @acl: none */ VIR_LOCK_SPACE_PROTOCOL_PROC_RELEASE_RESOURCE = 7, /** * @generate: none + * @acl: none */ VIR_LOCK_SPACE_PROTOCOL_PROC_CREATE_LOCKSPACE = 8 }; diff --git a/src/remote/lxc_protocol.x b/src/remote/lxc_protocol.x index f6cd590..1cde90e 100644 --- a/src/remote/lxc_protocol.x +++ b/src/remote/lxc_protocol.x @@ -65,6 +65,7 @@ enum lxc_procedure { /** * @generate: none * @priority: low + * @acl: domain:open_namespace */ LXC_PROC_DOMAIN_OPEN_NAMESPACE = 1 }; diff --git a/src/remote/qemu_protocol.x b/src/remote/qemu_protocol.x index 63fd92f..1e7cf7c 100644 --- a/src/remote/qemu_protocol.x +++ b/src/remote/qemu_protocol.x @@ -91,18 +91,22 @@ enum qemu_procedure { /** * @generate: none * @priority: low + * @acl: domain:write */ QEMU_PROC_DOMAIN_MONITOR_COMMAND = 1, /** * @generate: both * @priority: low + * @acl: domain:start + * @acl: domain:write */ QEMU_PROC_DOMAIN_ATTACH = 2, /** * @generate: both * @priority: low + * @acl: domain:write */ QEMU_PROC_DOMAIN_AGENT_COMMAND = 3 }; diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x index f61d10c..33fb338 100644 --- a/src/remote/remote_protocol.x +++ b/src/remote/remote_protocol.x @@ -2775,1664 +2775,2070 @@ enum remote_procedure { * to this rule, e.g. domainDestroy. Other APIs MAY be marked as high * priority. If in doubt, it's safe to choose low. Low is taken as default, * and thus can be left out. + * + * - @acl: <object>:<permission> + * - @acl: <object>:<permission>:<flagname> + * + * Declare the access control requirements for the API. May be repeated + * multiple times, if multiple rules are required. + * + * <object> is one of 'connect', 'domain', 'network', 'storagepool', + * 'interface', 'nodedev', 'secret'. + * <permission> is one of the permissions in access/viraccessperm.h + * <flagname> indicates the rule only applies if the named flag + * is set in the API call + * + * - @aclfilter: <object>:<permission> + * + * Declare an access control filter that will be applied to a list + * of objects being returned by an API. This allows the returned + * list to be filtered to only show those the user has permissions + * against */ /** * @generate: none * @priority: high + * @acl: connect:getattr */ REMOTE_PROC_CONNECT_OPEN = 1, /** * @generate: none * @priority: high + * @acl: none */ REMOTE_PROC_CONNECT_CLOSE = 2, /** * @generate: server * @priority: high + * @acl: connect:getattr */ REMOTE_PROC_CONNECT_GET_TYPE = 3, /** * @generate: both * @priority: high + * @acl: connect:getattr */ REMOTE_PROC_CONNECT_GET_VERSION = 4, /** * @generate: both * @priority: high + * @acl: connect:read */ REMOTE_PROC_CONNECT_GET_MAX_VCPUS = 5, /** * @generate: both * @priority: high + * @acl: connect:read */ REMOTE_PROC_NODE_GET_INFO = 6, /** * @generate: both + * @acl: connect:read */ REMOTE_PROC_CONNECT_GET_CAPABILITIES = 7, /** * @generate: both + * @acl: domain:write */ REMOTE_PROC_DOMAIN_ATTACH_DEVICE = 8, /** * @generate: server + * @acl: domain:start */ REMOTE_PROC_DOMAIN_CREATE = 9, /** * @generate: both + * @acl: domain:write + * @acl: domain:start */ REMOTE_PROC_DOMAIN_CREATE_XML = 10, /** * @generate: both * @priority: high + * @acl: domain:write + * @acl: domain:save */ REMOTE_PROC_DOMAIN_DEFINE_XML = 11, /** * @generate: both * @priority: high + * @acl: domain:stop */ REMOTE_PROC_DOMAIN_DESTROY = 12, /** * @generate: both + * @acl: domain:write */ REMOTE_PROC_DOMAIN_DETACH_DEVICE = 13, /** * @generate: both + * @acl: domain:read + * @acl: domain:read_secure:VIR_DOMAIN_XML_SECURE */ REMOTE_PROC_DOMAIN_GET_XML_DESC = 14, /** * @generate: both * @priority: high + * @acl: domain:read */ REMOTE_PROC_DOMAIN_GET_AUTOSTART = 15, /** * @generate: both + * @acl: domain:read */ REMOTE_PROC_DOMAIN_GET_INFO = 16, /** * @generate: both * @priority: high + * @acl: domain:read */ REMOTE_PROC_DOMAIN_GET_MAX_MEMORY = 17, /** * @generate: both * @priority: high + * @acl: domain:read */ REMOTE_PROC_DOMAIN_GET_MAX_VCPUS = 18, /** * @generate: both * @priority: high + * @acl: domain:read */ REMOTE_PROC_DOMAIN_GET_OS_TYPE = 19, /** * @generate: none * @priority: high + * @acl: domain:read */ REMOTE_PROC_DOMAIN_GET_VCPUS = 20, /** * @generate: both * @priority: high + * @acl: connect:search_domains + * @aclfilter: domain:getattr */ REMOTE_PROC_CONNECT_LIST_DEFINED_DOMAINS = 21, /** * @generate: both * @priority: high + * @acl: domain:getattr */ REMOTE_PROC_DOMAIN_LOOKUP_BY_ID = 22, /** * @generate: both * @priority: high + * @acl: domain:getattr */ REMOTE_PROC_DOMAIN_LOOKUP_BY_NAME = 23, /** * @generate: both * @priority: high + * @acl: domain:getattr */ REMOTE_PROC_DOMAIN_LOOKUP_BY_UUID = 24, /** * @generate: both * @priority: high + * @acl: connect:search_domains + * @aclfilter: domain:getattr */ REMOTE_PROC_CONNECT_NUM_OF_DEFINED_DOMAINS = 25, /** * @generate: both + * @acl: domain:write */ REMOTE_PROC_DOMAIN_PIN_VCPU = 26, /** * @generate: both + * @acl: domain:init_control */ REMOTE_PROC_DOMAIN_REBOOT = 27, /** * @generate: both + * @acl: domain:suspend */ REMOTE_PROC_DOMAIN_RESUME = 28, /** * @generate: both * @priority: high + * @acl: domain:write */ REMOTE_PROC_DOMAIN_SET_AUTOSTART = 29, /** * @generate: both * @priority: high + * @acl: domain:write */ REMOTE_PROC_DOMAIN_SET_MAX_MEMORY = 30, /** * @generate: both + * @acl: domain:write */ REMOTE_PROC_DOMAIN_SET_MEMORY = 31, /** * @generate: both + * @acl: domain:write */ REMOTE_PROC_DOMAIN_SET_VCPUS = 32, /** * @generate: both + * @acl: domain:init_control */ REMOTE_PROC_DOMAIN_SHUTDOWN = 33, /** * @generate: both + * @acl: domain:suspend */ REMOTE_PROC_DOMAIN_SUSPEND = 34, /** * @generate: both * @priority: high + * @acl: domain:delete */ REMOTE_PROC_DOMAIN_UNDEFINE = 35, /** * @generate: both * @priority: high + * @acl: connect:search_networks + * @aclfilter: network:getattr */ REMOTE_PROC_CONNECT_LIST_DEFINED_NETWORKS = 36, /** * @generate: server * @priority: high + * @acl: connect:search_domains + * @aclfilter: domain:getattr */ REMOTE_PROC_CONNECT_LIST_DOMAINS = 37, /** * @generate: both * @priority: high + * @acl: connect:search_networks + * @aclfilter: network:getattr */ REMOTE_PROC_CONNECT_LIST_NETWORKS = 38, /** * @generate: both + * @acl: network:start */ REMOTE_PROC_NETWORK_CREATE = 39, /** * @generate: both + * @acl: network:write + * @acl: network:start */ REMOTE_PROC_NETWORK_CREATE_XML = 40, /** * @generate: both * @priority: high + * @acl: network:write + * @acl: network:save */ REMOTE_PROC_NETWORK_DEFINE_XML = 41, /** * @generate: both * @priority: high + * @acl: network:stop */ REMOTE_PROC_NETWORK_DESTROY = 42, /** * @generate: both * @priority: high + * @acl: network:read */ REMOTE_PROC_NETWORK_GET_XML_DESC = 43, /** * @generate: both * @priority: high + * @acl: network:read */ REMOTE_PROC_NETWORK_GET_AUTOSTART = 44, /** * @generate: both * @priority: high + * @acl: network:read */ REMOTE_PROC_NETWORK_GET_BRIDGE_NAME = 45, /** * @generate: both * @priority: high + * @acl: network:getattr */ REMOTE_PROC_NETWORK_LOOKUP_BY_NAME = 46, /** * @generate: both * @priority: high + * @acl: network:getattr */ REMOTE_PROC_NETWORK_LOOKUP_BY_UUID = 47, /** * @generate: both * @priority: high + * @acl: network:write */ REMOTE_PROC_NETWORK_SET_AUTOSTART = 48, /** * @generate: both * @priority: high + * @acl: network:delete */ REMOTE_PROC_NETWORK_UNDEFINE = 49, /** * @generate: both * @priority: high + * @acl: connect:search_networks + * @aclfilter: network:getattr */ REMOTE_PROC_CONNECT_NUM_OF_DEFINED_NETWORKS = 50, /** * @generate: both * @priority: high + * @acl: connect:search_domains + * @aclfilter: domain:getattr */ REMOTE_PROC_CONNECT_NUM_OF_DOMAINS = 51, /** * @generate: both * @priority: high + * @acl: connect:search_networks + * @aclfilter: network:getattr */ REMOTE_PROC_CONNECT_NUM_OF_NETWORKS = 52, /** * @generate: both + * @acl: domain:core_dump */ REMOTE_PROC_DOMAIN_CORE_DUMP = 53, /** * @generate: both + * @acl: domain:start + * @acl: domain:write */ REMOTE_PROC_DOMAIN_RESTORE = 54, /** * @generate: both + * @acl: domain:hibernate */ REMOTE_PROC_DOMAIN_SAVE = 55, /** * @generate: none + * @acl: domain:read */ REMOTE_PROC_DOMAIN_GET_SCHEDULER_TYPE = 56, /** * @generate: client + * @acl: domain:read */ REMOTE_PROC_DOMAIN_GET_SCHEDULER_PARAMETERS = 57, /** * @generate: both + * @acl: domain:read */ REMOTE_PROC_DOMAIN_SET_SCHEDULER_PARAMETERS = 58, /** * @generate: both * @priority: high + * @acl: connect:getattr */ REMOTE_PROC_CONNECT_GET_HOSTNAME = 59, /** * @generate: client * @priority: high + * @acl: connect:getattr */ REMOTE_PROC_CONNECT_SUPPORTS_FEATURE = 60, /** * @generate: none + * @acl: domain:migrate + * @acl: domain:start + * @acl: domain:write */ REMOTE_PROC_DOMAIN_MIGRATE_PREPARE = 61, /** * @generate: both + * @acl: domain:migrate */ REMOTE_PROC_DOMAIN_MIGRATE_PERFORM = 62, /** * @generate: both + * @acl: domain:migrate */ REMOTE_PROC_DOMAIN_MIGRATE_FINISH = 63, /** * @generate: both + * @acl: domain:read */ REMOTE_PROC_DOMAIN_BLOCK_STATS = 64, /** * @generate: both * @priority: high + * @acl: domain:read */ REMOTE_PROC_DOMAIN_INTERFACE_STATS = 65, /** * @generate: none * @priority: high + * @acl: none */ REMOTE_PROC_AUTH_LIST = 66, /** * @generate: none * @priority: high + * @acl: none */ REMOTE_PROC_AUTH_SASL_INIT = 67, /** * @generate: none * @priority: high + * @acl: none */ REMOTE_PROC_AUTH_SASL_START = 68, /** * @generate: none * @priority: high + * @acl: none */ REMOTE_PROC_AUTH_SASL_STEP = 69, /** * @generate: none * @priority: high + * @acl: none */ REMOTE_PROC_AUTH_POLKIT = 70, /** * @generate: both * @priority: high + * @acl: connect:search_storage_pools + * @aclfilter: storage_pool:getattr */ REMOTE_PROC_CONNECT_NUM_OF_STORAGE_POOLS = 71, /** * @generate: both * @priority: high + * @acl: connect:search_storage_pools + * @aclfilter: storage_pool:getattr */ REMOTE_PROC_CONNECT_LIST_STORAGE_POOLS = 72, /** * @generate: both * @priority: high + * @acl: connect:search_storage_pools + * @aclfilter: storage_pool:getattr */ REMOTE_PROC_CONNECT_NUM_OF_DEFINED_STORAGE_POOLS = 73, /** * @generate: both * @priority: high + * @acl: connect:search_storage_pools + * @aclfilter: storage_pool:getattr */ REMOTE_PROC_CONNECT_LIST_DEFINED_STORAGE_POOLS = 74, /** * @generate: server + * @acl: connect:detect_storage_pools */ REMOTE_PROC_CONNECT_FIND_STORAGE_POOL_SOURCES = 75, /** * @generate: both + * @acl: storage_pool:start + * @acl: storage_pool:write */ REMOTE_PROC_STORAGE_POOL_CREATE_XML = 76, /** * @generate: both * @priority: high + * @acl: storage_pool:write + * @acl: storage_pool:save */ REMOTE_PROC_STORAGE_POOL_DEFINE_XML = 77, /** * @generate: both + * @acl: storage_pool:start */ REMOTE_PROC_STORAGE_POOL_CREATE = 78, /** * @generate: both + * @acl: storage_pool:format */ REMOTE_PROC_STORAGE_POOL_BUILD = 79, /** * @generate: both * @priority: high + * @acl: storage_pool:stop */ REMOTE_PROC_STORAGE_POOL_DESTROY = 80, /** * @generate: both + * @acl: storage_pool:format */ REMOTE_PROC_STORAGE_POOL_DELETE = 81, /** * @generate: both * @priority: high + * @acl: storage_pool:delete */ REMOTE_PROC_STORAGE_POOL_UNDEFINE = 82, /** * @generate: both + * @acl: storage_pool:refresh */ REMOTE_PROC_STORAGE_POOL_REFRESH = 83, /** * @generate: both * @priority: high + * @acl: storage_pool:getattr */ REMOTE_PROC_STORAGE_POOL_LOOKUP_BY_NAME = 84, /** * @generate: both * @priority: high + * @acl: storage_pool:getattr */ REMOTE_PROC_STORAGE_POOL_LOOKUP_BY_UUID = 85, /** * @generate: both * @priority: high + * @acl: storage_pool:getattr */ REMOTE_PROC_STORAGE_POOL_LOOKUP_BY_VOLUME = 86, /** * @generate: both * @priority: high + * @acl: storage_pool:read */ REMOTE_PROC_STORAGE_POOL_GET_INFO = 87, /** * @generate: both * @priority: high + * @acl: storage_pool:read */ REMOTE_PROC_STORAGE_POOL_GET_XML_DESC = 88, /** * @generate: both * @priority: high + * @acl: storage_pool:read */ REMOTE_PROC_STORAGE_POOL_GET_AUTOSTART = 89, /** * @generate: both * @priority: high + * @acl: storage_pool:write */ REMOTE_PROC_STORAGE_POOL_SET_AUTOSTART = 90, /** * @generate: both * @priority: high + * @acl: storage_pool:search_storage_vols + * @aclfilter: storage_vol:getattr */ REMOTE_PROC_STORAGE_POOL_NUM_OF_VOLUMES = 91, /** * @generate: both * @priority: high + * @acl: storage_pool:search_storage_vols + * @aclfilter: storage_vol:getattr */ REMOTE_PROC_STORAGE_POOL_LIST_VOLUMES = 92, /** * @generate: both + * @acl: storage_vol:create */ REMOTE_PROC_STORAGE_VOL_CREATE_XML = 93, /** * @generate: both + * @acl: storage_vol:delete */ REMOTE_PROC_STORAGE_VOL_DELETE = 94, /** * @generate: both * @priority: high + * @acl: storage_vol:getattr */ REMOTE_PROC_STORAGE_VOL_LOOKUP_BY_NAME = 95, /** * @generate: both * @priority: high + * @acl: storage_vol:getattr */ REMOTE_PROC_STORAGE_VOL_LOOKUP_BY_KEY = 96, /** * @generate: both * @priority: high + * @acl: storage_vol:getattr */ REMOTE_PROC_STORAGE_VOL_LOOKUP_BY_PATH = 97, /** * @generate: both * @priority: high + * @acl: storage_vol:read */ REMOTE_PROC_STORAGE_VOL_GET_INFO = 98, /** * @generate: both * @priority: high + * @acl: storage_vol:read */ REMOTE_PROC_STORAGE_VOL_GET_XML_DESC = 99, /** * @generate: both * @priority: high + * @acl: storage_vol:read */ REMOTE_PROC_STORAGE_VOL_GET_PATH = 100, /** * @generate: server * @priority: high + * @acl: connect:read */ REMOTE_PROC_NODE_GET_CELLS_FREE_MEMORY = 101, /** * @generate: both * @priority: high + * @acl: connect:read */ REMOTE_PROC_NODE_GET_FREE_MEMORY = 102, /** * @generate: none + * @acl: domain:block_read */ REMOTE_PROC_DOMAIN_BLOCK_PEEK = 103, /** * @generate: none + * @acl: domain:mem_read */ REMOTE_PROC_DOMAIN_MEMORY_PEEK = 104, /** * @generate: none * @priority: high + * @acl: connect:read */ REMOTE_PROC_CONNECT_DOMAIN_EVENT_REGISTER = 105, /** * @generate: none * @priority: high + * @acl: connect:read */ REMOTE_PROC_CONNECT_DOMAIN_EVENT_DEREGISTER = 106, /** * @generate: both + * @acl: none */ REMOTE_PROC_DOMAIN_EVENT_LIFECYCLE = 107, /** * @generate: none + * @acl: domain:migrate + * @acl: domain:start + * @acl: domain:write */ REMOTE_PROC_DOMAIN_MIGRATE_PREPARE2 = 108, /** * @generate: both + * @acl: domain:migrate */ REMOTE_PROC_DOMAIN_MIGRATE_FINISH2 = 109, /** * @generate: server * @priority: high + * @acl: connect:getattr */ REMOTE_PROC_CONNECT_GET_URI = 110, /** * @generate: both * @priority: high + * @acl: connect:search_node_devices + * @aclfilter: node_device:getattr */ REMOTE_PROC_NODE_NUM_OF_DEVICES = 111, /** * @generate: both * @priority: high + * @acl: connect:search_node_devices + * @aclfilter: node_device:getattr */ REMOTE_PROC_NODE_LIST_DEVICES = 112, /** * @generate: both * @priority: high + * @acl: node_device:getattr */ REMOTE_PROC_NODE_DEVICE_LOOKUP_BY_NAME = 113, /** * @generate: both + * @acl: node_device:read */ REMOTE_PROC_NODE_DEVICE_GET_XML_DESC = 114, /** * @generate: client * @priority: high + * @acl: node_device:read */ REMOTE_PROC_NODE_DEVICE_GET_PARENT = 115, /** * @generate: both * @priority: high + * @acl: node_device:read */ REMOTE_PROC_NODE_DEVICE_NUM_OF_CAPS = 116, /** * @generate: both * @priority: high + * @acl: node_device:read */ REMOTE_PROC_NODE_DEVICE_LIST_CAPS = 117, /** * @generate: server + * @acl: node_device:dettach */ REMOTE_PROC_NODE_DEVICE_DETTACH = 118, /** * @generate: server + * @acl: node_device:dettach */ REMOTE_PROC_NODE_DEVICE_RE_ATTACH = 119, /** * @generate: server + * @acl: node_device:dettach */ REMOTE_PROC_NODE_DEVICE_RESET = 120, /** * @generate: none * @priority: high + * @acl: domain:read */ REMOTE_PROC_DOMAIN_GET_SECURITY_LABEL = 121, /** * @generate: none * @priority: high + * @acl: connect:read */ REMOTE_PROC_NODE_GET_SECURITY_MODEL = 122, /** * @generate: both + * @acl: node_device:write + * @acl: node_device:start */ REMOTE_PROC_NODE_DEVICE_CREATE_XML = 123, /** * @generate: both * @priority: high + * @acl: node_device:stop */ REMOTE_PROC_NODE_DEVICE_DESTROY = 124, /** * @generate: both + * @acl: storage_vol:create */ REMOTE_PROC_STORAGE_VOL_CREATE_XML_FROM = 125, /** * @generate: both * @priority: high + * @acl: connect:search_interfaces + * @aclfilter: interface:getattr */ REMOTE_PROC_CONNECT_NUM_OF_INTERFACES = 126, /** * @generate: both * @priority: high + * @acl: connect:search_interfaces + * @aclfilter: interface:getattr */ REMOTE_PROC_CONNECT_LIST_INTERFACES = 127, /** * @generate: both * @priority: high + * @acl: interface:getattr */ REMOTE_PROC_INTERFACE_LOOKUP_BY_NAME = 128, /** * @generate: both * @priority: high + * @acl: interface:getattr */ REMOTE_PROC_INTERFACE_LOOKUP_BY_MAC_STRING = 129, /** * @generate: both + * @acl: interface:read */ REMOTE_PROC_INTERFACE_GET_XML_DESC = 130, /** * @generate: both * @priority: high + * @acl: interface:write + * @acl: interface:save */ REMOTE_PROC_INTERFACE_DEFINE_XML = 131, /** * @generate: both * @priority: high + * @acl: interface:delete */ REMOTE_PROC_INTERFACE_UNDEFINE = 132, /** * @generate: both + * @acl: interface:start */ REMOTE_PROC_INTERFACE_CREATE = 133, /** * @generate: both * @priority: high + * @acl: interface:stop */ REMOTE_PROC_INTERFACE_DESTROY = 134, /** * @generate: both + * @acl: connect:read */ REMOTE_PROC_CONNECT_DOMAIN_XML_FROM_NATIVE = 135, /** * @generate: both + * @acl: connect:read */ REMOTE_PROC_CONNECT_DOMAIN_XML_TO_NATIVE = 136, /** * @generate: both * @priority: high + * @acl: connect:search_interfaces + * @aclfilter: interface:getattr */ REMOTE_PROC_CONNECT_NUM_OF_DEFINED_INTERFACES = 137, /** * @generate: both * @priority: high + * @acl: connect:search_interfaces + * @aclfilter: interface:getattr */ REMOTE_PROC_CONNECT_LIST_DEFINED_INTERFACES = 138, /** * @generate: both * @priority: high + * @acl: connect:search_secrets + * @aclfilter: secret:getattr */ REMOTE_PROC_CONNECT_NUM_OF_SECRETS = 139, /** * @generate: both * @priority: high + * @acl: connect:search_secrets + * @aclfilter: secret:getattr */ REMOTE_PROC_CONNECT_LIST_SECRETS = 140, /** * @generate: both * @priority: high + * @acl: secret:getattr */ REMOTE_PROC_SECRET_LOOKUP_BY_UUID = 141, /** * @generate: both * @priority: high + * @acl: secret:write + * @acl: secret:save */ REMOTE_PROC_SECRET_DEFINE_XML = 142, /** * @generate: both * @priority: high + * @acl: secret:read */ REMOTE_PROC_SECRET_GET_XML_DESC = 143, /** * @generate: both * @priority: high + * @acl: secret:write */ REMOTE_PROC_SECRET_SET_VALUE = 144, /** * @generate: none * @priority: high + * @acl: secret:read_secure */ REMOTE_PROC_SECRET_GET_VALUE = 145, /** * @generate: both * @priority: high + * @acl: secret:delete */ REMOTE_PROC_SECRET_UNDEFINE = 146, /** * @generate: both * @priority: high + * @acl: secret:getattr */ REMOTE_PROC_SECRET_LOOKUP_BY_USAGE = 147, /** * @generate: both * @writestream: 1 + * @acl: domain:migrate + * @acl: domain:start + * @acl: domain:write */ REMOTE_PROC_DOMAIN_MIGRATE_PREPARE_TUNNEL = 148, /** * @generate: server * @priority: high + * @acl: none */ REMOTE_PROC_CONNECT_IS_SECURE = 149, /** * @generate: both * @priority: high + * @acl: domain:read */ REMOTE_PROC_DOMAIN_IS_ACTIVE = 150, /** * @generate: both * @priority: high + * @acl: domain:read */ REMOTE_PROC_DOMAIN_IS_PERSISTENT = 151, /** * @generate: both * @priority: high + * @acl: network:read */ REMOTE_PROC_NETWORK_IS_ACTIVE = 152, /** * @generate: both * @priority: high + * @acl: network:read */ REMOTE_PROC_NETWORK_IS_PERSISTENT = 153, /** * @generate: both * @priority: high + * @acl: storage_pool:read */ REMOTE_PROC_STORAGE_POOL_IS_ACTIVE = 154, /** * @generate: both * @priority: high + * @acl: storage_pool:read */ REMOTE_PROC_STORAGE_POOL_IS_PERSISTENT = 155, /** * @generate: both * @priority: high + * @acl: interface:read */ REMOTE_PROC_INTERFACE_IS_ACTIVE = 156, /** * @generate: both * @priority: high + * @acl: connect:getattr */ REMOTE_PROC_CONNECT_GET_LIB_VERSION = 157, /** * @generate: both * @priority: high + * @acl: connect:read */ REMOTE_PROC_CONNECT_COMPARE_CPU = 158, /** * @generate: none + * @acl: domain:read */ REMOTE_PROC_DOMAIN_MEMORY_STATS = 159, /** * @generate: both + * @acl: domain:write + * @acl: domain:save:!VIR_DOMAIN_AFFECT_CONFIG|VIR_DOMAIN_AFFECT_LIVE + * @acl: domain:save:VIR_DOMAIN_AFFECT_CONFIG */ REMOTE_PROC_DOMAIN_ATTACH_DEVICE_FLAGS = 160, /** * @generate: both + * @acl: domain:write + * @acl: domain:save:!VIR_DOMAIN_AFFECT_CONFIG|VIR_DOMAIN_AFFECT_LIVE + * @acl: domain:save:VIR_DOMAIN_AFFECT_CONFIG */ REMOTE_PROC_DOMAIN_DETACH_DEVICE_FLAGS = 161, /** * @generate: both + * @acl: connect:read */ REMOTE_PROC_CONNECT_BASELINE_CPU = 162, /** * @generate: both + * @acl: domain:read */ REMOTE_PROC_DOMAIN_GET_JOB_INFO = 163, /** * @generate: both + * @acl: domain:write */ REMOTE_PROC_DOMAIN_ABORT_JOB = 164, /** * @generate: both + * @acl: storage_vol:format */ REMOTE_PROC_STORAGE_VOL_WIPE = 165, /** * @generate: both + * @acl: domain:migrate */ REMOTE_PROC_DOMAIN_MIGRATE_SET_MAX_DOWNTIME = 166, /** * @generate: none * @priority: high + * @acl: connect:read */ REMOTE_PROC_CONNECT_DOMAIN_EVENT_REGISTER_ANY = 167, /** * @generate: none * @priority: high + * @acl: connect:read */ REMOTE_PROC_CONNECT_DOMAIN_EVENT_DEREGISTER_ANY = 168, /** * @generate: both + * @acl: none */ REMOTE_PROC_DOMAIN_EVENT_REBOOT = 169, /** * @generate: both + * @acl: none */ REMOTE_PROC_DOMAIN_EVENT_RTC_CHANGE = 170, /** * @generate: both + * @acl: none */ REMOTE_PROC_DOMAIN_EVENT_WATCHDOG = 171, /** * @generate: both + * @acl: none */ REMOTE_PROC_DOMAIN_EVENT_IO_ERROR = 172, /** * @generate: both + * @acl: none */ REMOTE_PROC_DOMAIN_EVENT_GRAPHICS = 173, /** * @generate: both + * @acl: domain:write + * @acl: domain:save:!VIR_DOMAIN_AFFECT_CONFIG|VIR_DOMAIN_AFFECT_LIVE + * @acl: domain:save:VIR_DOMAIN_AFFECT_CONFIG */ REMOTE_PROC_DOMAIN_UPDATE_DEVICE_FLAGS = 174, /** * @generate: both * @priority: high + * @acl: nwfilter:getattr */ REMOTE_PROC_NWFILTER_LOOKUP_BY_NAME = 175, /** * @generate: both * @priority: high + * @acl: nwfilter:getattr */ REMOTE_PROC_NWFILTER_LOOKUP_BY_UUID = 176, /** * @generate: both * @priority: high + * @acl: nwfilter:read */ REMOTE_PROC_NWFILTER_GET_XML_DESC = 177, /** * @generate: both * @priority: high + * @acl: connect:search_nwfilters + * @aclfilter: nwfilter:getattr */ REMOTE_PROC_CONNECT_NUM_OF_NWFILTERS = 178, /** * @generate: both * @priority: high + * @acl: connect:search_nwfilters + * @aclfilter: nwfilter:getattr */ REMOTE_PROC_CONNECT_LIST_NWFILTERS = 179, /** * @generate: both * @priority: high + * @acl: nwfilter:write + * @acl: nwfilter:save */ REMOTE_PROC_NWFILTER_DEFINE_XML = 180, /** * @generate: both * @priority: high + * @acl: nwfilter:delete */ REMOTE_PROC_NWFILTER_UNDEFINE = 181, /** * @generate: both + * @acl: domain:hibernate */ REMOTE_PROC_DOMAIN_MANAGED_SAVE = 182, /** * @generate: both + * @acl: domain:read */ REMOTE_PROC_DOMAIN_HAS_MANAGED_SAVE_IMAGE = 183, /** * @generate: both + * @acl: domain:hibernate */ REMOTE_PROC_DOMAIN_MANAGED_SAVE_REMOVE = 184, /** * @generate: both + * @acl: domain:snapshot */ REMOTE_PROC_DOMAIN_SNAPSHOT_CREATE_XML = 185, /** * @generate: both * @priority: high + * @acl: domain:read */ REMOTE_PROC_DOMAIN_SNAPSHOT_GET_XML_DESC = 186, /** * @generate: both * @priority: high + * @acl: domain:read */ REMOTE_PROC_DOMAIN_SNAPSHOT_NUM = 187, /** * @generate: both * @priority: high + * @acl: domain:read */ REMOTE_PROC_DOMAIN_SNAPSHOT_LIST_NAMES = 188, /** * @generate: both * @priority: high + * @acl: domain:read */ REMOTE_PROC_DOMAIN_SNAPSHOT_LOOKUP_BY_NAME = 189, /** * @generate: both + * @acl: domain:read */ REMOTE_PROC_DOMAIN_HAS_CURRENT_SNAPSHOT = 190, /** * @generate: both + * @acl: domain:read */ REMOTE_PROC_DOMAIN_SNAPSHOT_CURRENT = 191, /** * @generate: both + * @acl: domain:snapshot */ REMOTE_PROC_DOMAIN_REVERT_TO_SNAPSHOT = 192, /** * @generate: both + * @acl: domain:snapshot */ REMOTE_PROC_DOMAIN_SNAPSHOT_DELETE = 193, /** * @generate: both + * @acl: domain:read */ REMOTE_PROC_DOMAIN_GET_BLOCK_INFO = 194, /** * @generate: both + * @acl: none */ REMOTE_PROC_DOMAIN_EVENT_IO_ERROR_REASON = 195, /** * @generate: both + * @acl: domain:start */ REMOTE_PROC_DOMAIN_CREATE_WITH_FLAGS = 196, /** * @generate: both + * @acl: domain:write + * @acl: domain:save:!VIR_DOMAIN_AFFECT_CONFIG|VIR_DOMAIN_AFFECT_LIVE + * @acl: domain:save:VIR_DOMAIN_AFFECT_CONFIG */ REMOTE_PROC_DOMAIN_SET_MEMORY_PARAMETERS = 197, /** * @generate: none + * @acl: domain:read */ REMOTE_PROC_DOMAIN_GET_MEMORY_PARAMETERS = 198, /** * @generate: both + * @acl: domain:write + * @acl: domain:save:!VIR_DOMAIN_AFFECT_CONFIG|VIR_DOMAIN_AFFECT_LIVE + * @acl: domain:save:VIR_DOMAIN_AFFECT_CONFIG */ REMOTE_PROC_DOMAIN_SET_VCPUS_FLAGS = 199, /** * @generate: both + * @acl: domain:read */ REMOTE_PROC_DOMAIN_GET_VCPUS_FLAGS = 200, /** * @generate: both * @readstream: 2 + * @acl: domain:open_device */ REMOTE_PROC_DOMAIN_OPEN_CONSOLE = 201, /** * @generate: both * @priority: high + * @acl: domain:read */ REMOTE_PROC_DOMAIN_IS_UPDATED = 202, /** * @generate: both * @priority: high + * @acl: connect:read */ REMOTE_PROC_CONNECT_GET_SYSINFO = 203, /** * @generate: both + * @acl: domain:write + * @acl: domain:save:!VIR_DOMAIN_AFFECT_CONFIG|VIR_DOMAIN_AFFECT_LIVE + * @acl: domain:save:VIR_DOMAIN_AFFECT_CONFIG */ REMOTE_PROC_DOMAIN_SET_MEMORY_FLAGS = 204, /** * @generate: both + * @acl: domain:write + * @acl: domain:save:!VIR_DOMAIN_AFFECT_CONFIG|VIR_DOMAIN_AFFECT_LIVE + * @acl: domain:save:VIR_DOMAIN_AFFECT_CONFIG */ REMOTE_PROC_DOMAIN_SET_BLKIO_PARAMETERS = 205, /** * @generate: none + * @acl: domain:read */ REMOTE_PROC_DOMAIN_GET_BLKIO_PARAMETERS = 206, /** * @generate: both + * @acl: domain:migrate */ REMOTE_PROC_DOMAIN_MIGRATE_SET_MAX_SPEED = 207, /** * @generate: both * @writestream: 1 + * @acl: storage_vol:data_write */ REMOTE_PROC_STORAGE_VOL_UPLOAD = 208, /** * @generate: both * @readstream: 1 + * @acl: storage_vol:data_read */ REMOTE_PROC_STORAGE_VOL_DOWNLOAD = 209, /** * @generate: both + * @acl: domain:inject_nmi */ REMOTE_PROC_DOMAIN_INJECT_NMI = 210, /** * @generate: both * @readstream: 1 + * @acl: domain:screenshot */ REMOTE_PROC_DOMAIN_SCREENSHOT = 211, /** * @generate: none * @priority: high + * @acl: domain:read */ REMOTE_PROC_DOMAIN_GET_STATE = 212, /** * @generate: none + * @acl: domain:migrate */ REMOTE_PROC_DOMAIN_MIGRATE_BEGIN3 = 213, /** * @generate: none + * @acl: domain:migrate + * @acl: domain:start + * @acl: domain:write */ REMOTE_PROC_DOMAIN_MIGRATE_PREPARE3 = 214, /** * @generate: server * @writestream: 1 + * @acl: domain:migrate + * @acl: domain:start + * @acl: domain:write */ REMOTE_PROC_DOMAIN_MIGRATE_PREPARE_TUNNEL3 = 215, /** * @generate: none + * @acl: domain:migrate */ REMOTE_PROC_DOMAIN_MIGRATE_PERFORM3 = 216, /** * @generate: none + * @acl: domain:migrate */ REMOTE_PROC_DOMAIN_MIGRATE_FINISH3 = 217, /** * @generate: none + * @acl: domain:migrate */ REMOTE_PROC_DOMAIN_MIGRATE_CONFIRM3 = 218, /** * @generate: both + * @acl: domain:write + * @acl: domain:save:!VIR_DOMAIN_AFFECT_CONFIG|VIR_DOMAIN_AFFECT_LIVE + * @acl: domain:save:VIR_DOMAIN_AFFECT_CONFIG */ REMOTE_PROC_DOMAIN_SET_SCHEDULER_PARAMETERS_FLAGS = 219, /** * @generate: both + * @acl: connect:interface_transaction */ REMOTE_PROC_INTERFACE_CHANGE_BEGIN = 220, /** * @generate: both + * @acl: connect:interface_transaction */ REMOTE_PROC_INTERFACE_CHANGE_COMMIT = 221, /** * @generate: both + * @acl: connect:interface_transaction */ REMOTE_PROC_INTERFACE_CHANGE_ROLLBACK = 222, /** * @generate: client + * @acl: domain:read */ REMOTE_PROC_DOMAIN_GET_SCHEDULER_PARAMETERS_FLAGS = 223, /** * @generate: none + * @acl: none */ REMOTE_PROC_DOMAIN_EVENT_CONTROL_ERROR = 224, /** * @generate: both + * @acl: domain:write + * @acl: domain:save:!VIR_DOMAIN_AFFECT_CONFIG|VIR_DOMAIN_AFFECT_LIVE + * @acl: domain:save:VIR_DOMAIN_AFFECT_CONFIG */ REMOTE_PROC_DOMAIN_PIN_VCPU_FLAGS = 225, /** * @generate: both + * @acl: domain:send_input */ REMOTE_PROC_DOMAIN_SEND_KEY = 226, /** * @generate: none * @priority: high + * @acl: connect:read */ REMOTE_PROC_NODE_GET_CPU_STATS = 227, /** * @generate: none * @priority: high + * @acl: connect:read */ REMOTE_PROC_NODE_GET_MEMORY_STATS = 228, /** * @generate: both * @priority: high + * @acl: domain:read */ REMOTE_PROC_DOMAIN_GET_CONTROL_INFO = 229, /** * @generate: none + * @acl: domain:read */ REMOTE_PROC_DOMAIN_GET_VCPU_PIN_INFO = 230, /** * @generate: both * @priority: high + * @acl: domain:delete */ REMOTE_PROC_DOMAIN_UNDEFINE_FLAGS = 231, /** * @generate: both + * @acl: domain:hibernate */ REMOTE_PROC_DOMAIN_SAVE_FLAGS = 232, /** * @generate: both + * @acl: domain:start + * @acl: domain:write */ REMOTE_PROC_DOMAIN_RESTORE_FLAGS = 233, /** * @generate: both * @priority: high + * @acl: domain:stop */ REMOTE_PROC_DOMAIN_DESTROY_FLAGS = 234, /** * @generate: both * @priority: high + * @acl: domain:read */ REMOTE_PROC_DOMAIN_SAVE_IMAGE_GET_XML_DESC = 235, /** * @generate: both * @priority: high + * @acl: domain:write + * @acl: domain:hibernate */ REMOTE_PROC_DOMAIN_SAVE_IMAGE_DEFINE_XML = 236, /** * @generate: both + * @acl: domain:write */ REMOTE_PROC_DOMAIN_BLOCK_JOB_ABORT = 237, /** * @generate: none + * @acl: domain:read */ REMOTE_PROC_DOMAIN_GET_BLOCK_JOB_INFO = 238, /** * @generate: both + * @acl: domain:write */ REMOTE_PROC_DOMAIN_BLOCK_JOB_SET_SPEED = 239, /** * @generate: both + * @acl: domain:block_write */ REMOTE_PROC_DOMAIN_BLOCK_PULL = 240, /** * @generate: none + * @acl: none */ REMOTE_PROC_DOMAIN_EVENT_BLOCK_JOB = 241, /** * @generate: both + * @acl: domain:migrate */ REMOTE_PROC_DOMAIN_MIGRATE_GET_MAX_SPEED = 242, /** * @generate: none + * @acl: domain:read */ REMOTE_PROC_DOMAIN_BLOCK_STATS_FLAGS = 243, /** * @generate: both * @priority: high + * @acl: domain:read */ REMOTE_PROC_DOMAIN_SNAPSHOT_GET_PARENT = 244, /** * @generate: both + * @acl: domain:reset */ REMOTE_PROC_DOMAIN_RESET = 245, /** * @generate: both * @priority: high + * @acl: domain:read */ REMOTE_PROC_DOMAIN_SNAPSHOT_NUM_CHILDREN = 246, /** * @generate: both * @priority: high + * @acl: domain:read */ REMOTE_PROC_DOMAIN_SNAPSHOT_LIST_CHILDREN_NAMES = 247, /** * @generate: none + * @acl: none */ REMOTE_PROC_DOMAIN_EVENT_DISK_CHANGE = 248, /** * @generate: none + * @acl: domain:open_graphics */ REMOTE_PROC_DOMAIN_OPEN_GRAPHICS = 249, /** * @generate: both + * @acl: connect:pm_control */ REMOTE_PROC_NODE_SUSPEND_FOR_DURATION = 250, /** * @generate: both + * @acl: domain:block_write */ REMOTE_PROC_DOMAIN_BLOCK_RESIZE = 251, /** * @generate: both + * @acl: domain:write + * @acl: domain:save:!VIR_DOMAIN_AFFECT_CONFIG|VIR_DOMAIN_AFFECT_LIVE + * @acl: domain:save:VIR_DOMAIN_AFFECT_CONFIG */ REMOTE_PROC_DOMAIN_SET_BLOCK_IO_TUNE = 252, /** * @generate: none + * @acl: domain:read */ REMOTE_PROC_DOMAIN_GET_BLOCK_IO_TUNE = 253, /** * @generate: both + * @acl: domain:write + * @acl: domain:save:!VIR_DOMAIN_AFFECT_CONFIG|VIR_DOMAIN_AFFECT_LIVE + * @acl: domain:save:VIR_DOMAIN_AFFECT_CONFIG */ REMOTE_PROC_DOMAIN_SET_NUMA_PARAMETERS = 254, /** * @generate: none + * @acl: domain:read */ REMOTE_PROC_DOMAIN_GET_NUMA_PARAMETERS = 255, /** * @generate: both + * @acl: domain:write + * @acl: domain:save:!VIR_DOMAIN_AFFECT_CONFIG|VIR_DOMAIN_AFFECT_LIVE + * @acl: domain:save:VIR_DOMAIN_AFFECT_CONFIG */ REMOTE_PROC_DOMAIN_SET_INTERFACE_PARAMETERS = 256, /** * @generate: none + * @acl: domain:read */ REMOTE_PROC_DOMAIN_GET_INTERFACE_PARAMETERS = 257, /** * @generate: both + * @acl: domain:init_control */ REMOTE_PROC_DOMAIN_SHUTDOWN_FLAGS = 258, /** * @generate: both + * @acl: storage_vol:format */ REMOTE_PROC_STORAGE_VOL_WIPE_PATTERN = 259, /** * @generate: both + * @acl: storage_vol:resize */ REMOTE_PROC_STORAGE_VOL_RESIZE = 260, /** * @generate: both + * @acl: domain:pm_control */ REMOTE_PROC_DOMAIN_PM_SUSPEND_FOR_DURATION = 261, /** * @generate: none + * @acl: domain:read */ REMOTE_PROC_DOMAIN_GET_CPU_STATS = 262, /** * @generate: none + * @acl: domain:read */ REMOTE_PROC_DOMAIN_GET_DISK_ERRORS = 263, /** * @generate: both + * @acl: domain:write + * @acl: domain:save:!VIR_DOMAIN_AFFECT_CONFIG|VIR_DOMAIN_AFFECT_LIVE + * @acl: domain:save:VIR_DOMAIN_AFFECT_CONFIG */ REMOTE_PROC_DOMAIN_SET_METADATA = 264, /** * @generate: both + * @acl: domain:read */ REMOTE_PROC_DOMAIN_GET_METADATA = 265, /** * @generate: both + * @acl: domain:block_write */ REMOTE_PROC_DOMAIN_BLOCK_REBASE = 266, /** * @generate: both + * @acl: domain:pm_control */ REMOTE_PROC_DOMAIN_PM_WAKEUP = 267, /** * @generate: both + * @acl: none */ REMOTE_PROC_DOMAIN_EVENT_TRAY_CHANGE = 268, /** * @generate: both + * @acl: none */ REMOTE_PROC_DOMAIN_EVENT_PMWAKEUP = 269, /** * @generate: both + * @acl: none */ REMOTE_PROC_DOMAIN_EVENT_PMSUSPEND = 270, /** * @generate: both + * @acl: domain:read */ REMOTE_PROC_DOMAIN_SNAPSHOT_IS_CURRENT = 271, /** * @generate: both + * @acl: domain:read */ REMOTE_PROC_DOMAIN_SNAPSHOT_HAS_METADATA = 272, /** * @generate: none * @priority: high + * @acl: connect:search_domains + * @aclfilter: domain:getattr */ REMOTE_PROC_CONNECT_LIST_ALL_DOMAINS = 273, /** * @generate: none * @priority: high + * @acl: domain:read */ REMOTE_PROC_DOMAIN_LIST_ALL_SNAPSHOTS = 274, /** * @generate: none * @priority: high + * @acl: domain:read */ REMOTE_PROC_DOMAIN_SNAPSHOT_LIST_ALL_CHILDREN = 275, /** * @generate: both + * @acl: none */ REMOTE_PROC_DOMAIN_EVENT_BALLOON_CHANGE = 276, /** * @generate: both + * @acl: domain:read */ REMOTE_PROC_DOMAIN_GET_HOSTNAME = 277, /** * @generate: none * @priority: high + * @acl: domain:read */ REMOTE_PROC_DOMAIN_GET_SECURITY_LABEL_LIST = 278, /** * @generate: none + * @acl: domain:write + * @acl: domain:save:!VIR_DOMAIN_AFFECT_CONFIG|VIR_DOMAIN_AFFECT_LIVE + * @acl: domain:save:VIR_DOMAIN_AFFECT_CONFIG */ REMOTE_PROC_DOMAIN_PIN_EMULATOR = 279, /** * @generate: none + * @acl: domain:read */ REMOTE_PROC_DOMAIN_GET_EMULATOR_PIN_INFO = 280, /** * @generate: none * @priority: high + * @acl: connect:search_storage_pools + * @aclfilter: storage_pool:getattr */ REMOTE_PROC_CONNECT_LIST_ALL_STORAGE_POOLS = 281, /** * @generate: none * @priority: high + * @acl: storage_pool:search_storage_vols + * @aclfilter: storage_vol:getattr */ REMOTE_PROC_STORAGE_POOL_LIST_ALL_VOLUMES = 282, /** * @generate: none * @priority: high + * @acl: connect:search_networks + * @aclfilter: network:getattr */ REMOTE_PROC_CONNECT_LIST_ALL_NETWORKS = 283, /** * @generate: none * @priority: high + * @acl: connect:search_interfaces + * @aclfilter: interface:getattr */ REMOTE_PROC_CONNECT_LIST_ALL_INTERFACES = 284, /** * @generate: none * @priority: high + * @acl: connect:search_node_devices + * @aclfilter: node_device:getattr */ REMOTE_PROC_CONNECT_LIST_ALL_NODE_DEVICES = 285, /** * @generate: none * @priority: high + * @acl: connect:search_nwfilters + * @aclfilter: nwfilter:getattr */ REMOTE_PROC_CONNECT_LIST_ALL_NWFILTERS = 286, /** * @generate: none * @priority: high + * @acl: connect:search_secrets + * @aclfilter: secret:getattr */ REMOTE_PROC_CONNECT_LIST_ALL_SECRETS = 287, /** * @generate: both + * @acl: connect:write */ REMOTE_PROC_NODE_SET_MEMORY_PARAMETERS = 288, /** * @generate: none + * @acl: connect:read */ REMOTE_PROC_NODE_GET_MEMORY_PARAMETERS = 289, /** * @generate: both + * @acl: domain:block_write */ REMOTE_PROC_DOMAIN_BLOCK_COMMIT = 290, /** * @generate: both * @priority: high + * @acl: network:write + * @acl: network:save:!VIR_NETWORK_UPDATE_AFFECT_CONFIG|VIR_NETWORK_UPDATE_AFFECT_LIVE + * @acl: network:save:VIR_NETWORK_UPDATE_AFFECT_CONFIG */ REMOTE_PROC_NETWORK_UPDATE = 291, /** * @generate: both + * @acl: none */ REMOTE_PROC_DOMAIN_EVENT_PMSUSPEND_DISK = 292, /** * @generate: none + * @acl: connect:read */ REMOTE_PROC_NODE_GET_CPU_MAP = 293, /** * @generate: both + * @acl: domain:fs_trim */ REMOTE_PROC_DOMAIN_FSTRIM = 294, /** * @generate: both + * @acl: domain:send_signal */ REMOTE_PROC_DOMAIN_SEND_PROCESS_SIGNAL = 295, /** * @generate: both * @readstream: 2 + * @acl: domain:open_device */ REMOTE_PROC_DOMAIN_OPEN_CHANNEL = 296, /** * @generate: both * @priority: high + * @acl: node_device:getattr */ REMOTE_PROC_NODE_DEVICE_LOOKUP_SCSI_HOST_BY_WWN = 297, /** * @generate: none + * @acl: domain:read */ REMOTE_PROC_DOMAIN_GET_JOB_STATS = 298, /** * @generate: both + * @acl: domain:migrate */ REMOTE_PROC_DOMAIN_MIGRATE_GET_COMPRESSION_CACHE = 299, /** * @generate: both + * @acl: domain:migrate */ REMOTE_PROC_DOMAIN_MIGRATE_SET_COMPRESSION_CACHE = 300, /** * @generate: server + * @acl: node_device:dettach */ REMOTE_PROC_NODE_DEVICE_DETACH_FLAGS = 301 diff --git a/src/rpc/gendispatch.pl b/src/rpc/gendispatch.pl index 8d3b013..0bf76da 100755 --- a/src/rpc/gendispatch.pl +++ b/src/rpc/gendispatch.pl @@ -107,7 +107,7 @@ while (<PROTOCOL>) { push(@{$calls{$name}->{ret_members}}, $1); } } elsif ($collect_opts) { - if (m,^\s*\*\s*\@(\w+)\s*:\s*(\w+)\s*$,) { + if (m,^\s*\*\s*\@(\w+)\s*:\s*((?:\w|:|\!|\|)+)\s*$,) { $opts{$1} = $2; } elsif (m,^\s*\*/\s*$,) { $collect_opts = 0; -- 1.8.1.4

From: "Daniel P. Berrange" <berrange@redhat.com> Extend the 'gendispatch.pl' script to be able to generate three new types of file. - 'aclheader' - defines signatures of helper APIs for doing authorization checks. There is one helper API for each API requiring an auth check. Any @acl annotations result in a method being generated with a suffix of 'EnsureACL'. If the ACL check requires examination of flags, an extra 'flags' param will be present. Some examples extern int virConnectBaselineCPUEnsureACL(void); extern int virConnectDomainEventDeregisterEnsureACL(virDomainDefPtr domain); extern int virDomainAttachDeviceFlagsEnsureACL(virDomainDefPtr domain, unsigned int flags); Any @aclfilter annotations resuilt in a method being generated with a suffix of 'CheckACL'. extern int virConnectListAllDomainsCheckACL(virDomainDefPtr domain); These are used for filtering individual objects from APIs which return a list of objects - 'aclbody' - defines the actual implementation of the methods described above. This calls into the access manager APIs. A complex example: /* Returns: -1 on error (denied==error), 0 on allowed */ int virDomainAttachDeviceFlagsEnsureACL(virConnectPtr conn, virDomainDefPtr domain, unsigned int flags) { virAccessManagerPtr mgr; int rv; if (!(mgr = virAccessManagerGetDefault())) return -1; if ((rv = virAccessManagerCheckDomain(mgr, conn->driver->name, domain, VIR_ACCESS_PERM_DOMAIN_WRITE)) <= 0) { if (rv == 0) virReportError(VIR_ERR_ACCESS_DENIED, NULL); return -1; } if (((flags & (VIR_DOMAIN_AFFECT_CONFIG|VIR_DOMAIN_AFFECT_LIVE)) == 0) && (rv = virAccessManagerCheckDomain(mgr, conn->driver->name, domain, VIR_ACCESS_PERM_DOMAIN_SAVE)) <= 0) { if (rv == 0) virReportError(VIR_ERR_ACCESS_DENIED, NULL); return -1; } if (((flags & (VIR_DOMAIN_AFFECT_CONFIG)) == (VIR_DOMAIN_AFFECT_CONFIG)) && (rv = virAccessManagerCheckDomain(mgr, conn->driver->name, domain, VIR_ACCESS_PERM_DOMAIN_SAVE)) <= 0) { if (rv == 0) virReportError(VIR_ERR_ACCESS_DENIED, NULL); return -1; } return 0; } - 'aclsyms' - generates a linker script to export the APIs to drivers. Some examples virConnectBaselineCPUEnsureACL; virConnectCompareCPUEnsureACL; Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- .gitignore | 9 +++ src/Makefile.am | 55 ++++++++++++- src/rpc/gendispatch.pl | 210 ++++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 269 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index 76ee420..2deeccf 100644 --- a/.gitignore +++ b/.gitignore @@ -105,10 +105,19 @@ /sc_* /src/.*.stamp /src/access/org.libvirt.api.policy +/src/access/viraccessapicheck.c +/src/access/viraccessapicheck.h +/src/access/viraccessapichecklxc.c +/src/access/viraccessapichecklxc.h +/src/access/viraccessapicheckqemu.c +/src/access/viraccessapicheckqemu.h /src/esx/*.generated.* /src/hyperv/*.generated.* /src/libvirt*.def /src/libvirt.syms +/src/libvirt_access.syms +/src/libvirt_access_lxc.syms +/src/libvirt_access_qemu.syms /src/libvirt_*.stp /src/libvirt_*helper /src/libvirt_*probes.h diff --git a/src/Makefile.am b/src/Makefile.am index 20ce083..93af8fd 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -771,6 +771,15 @@ SECURITY_DRIVER_SELINUX_SOURCES = \ SECURITY_DRIVER_APPARMOR_SOURCES = \ security/security_apparmor.h security/security_apparmor.c +ACCESS_DRIVER_GENERATED = \ + access/viraccessapicheck.h access/viraccessapicheck.c \ + access/viraccessapicheckqemu.h access/viraccessapicheckqemu.c \ + access/viraccessapichecklxc.h access/viraccessapichecklxc.c + +ACCESS_DRIVER_SYMFILES = \ + libvirt_access.syms \ + libvirt_access_qemu.syms \ + libvirt_access_lxc.syms ACCESS_DRIVER_SOURCES = \ access/viraccessperm.h access/viraccessperm.c \ @@ -1361,7 +1370,7 @@ libvirt_security_manager_la_SOURCES += $(SECURITY_DRIVER_APPARMOR_SOURCES) libvirt_security_manager_la_CFLAGS += $(APPARMOR_CFLAGS) endif -libvirt_driver_access_la_SOURCES = $(ACCESS_DRIVER_SOURCES) +libvirt_driver_access_la_SOURCES = $(ACCESS_DRIVER_SOURCES) $(ACCESS_DRIVER_GENERATED) noinst_LTLIBRARIES += libvirt_driver_access.la libvirt_la_BUILT_LIBADD += libvirt_driver_access.la libvirt_driver_access_la_CFLAGS = \ @@ -1394,6 +1403,50 @@ EXTRA_DIST += $(ACCESS_DRIVER_POLKIT_SOURCES) endif +USED_SYM_FILES += $(ACCESS_DRIVER_SYMFILES) +BUILT_SOURCES += $(ACCESS_DRIVER_GENERATED) $(ACCESS_DRIVER_SYMFILES) +CLEANFILES += $(ACCESS_DRIVER_GENERATED) $(ACCESS_DRIVER_SYMFILES) + +libvirt_access.syms: $(srcdir)/rpc/gendispatch.pl \ + $(REMOTE_PROTOCOL) Makefile.am + $(AM_V_GEN)$(PERL) -w $(srcdir)/rpc/gendispatch.pl --mode=aclsym \ + remote REMOTE $(REMOTE_PROTOCOL) > $@ +libvirt_access_qemu.syms: $(srcdir)/rpc/gendispatch.pl \ + $(QEMU_PROTOCOL) Makefile.am + $(AM_V_GEN)$(PERL) -w $(srcdir)/rpc/gendispatch.pl --mode=aclsym \ + qemu QEMU $(QEMU_PROTOCOL) > $@ +libvirt_access_lxc.syms: $(srcdir)/rpc/gendispatch.pl \ + $(LXC_PROTOCOL) Makefile.am + $(AM_V_GEN)$(PERL) -w $(srcdir)/rpc/gendispatch.pl --mode=aclsym \ + lxc LXC $(LXC_PROTOCOL) > $@ + +access/viraccessapicheck.h: $(srcdir)/rpc/gendispatch.pl \ + $(REMOTE_PROTOCOL) Makefile.am + $(AM_V_GEN)$(PERL) -w $(srcdir)/rpc/gendispatch.pl --mode=aclheader \ + remote REMOTE $(REMOTE_PROTOCOL) > $@ +access/viraccessapicheck.c: $(srcdir)/rpc/gendispatch.pl \ + $(REMOTE_PROTOCOL) Makefile.am + $(AM_V_GEN)$(PERL) -w $(srcdir)/rpc/gendispatch.pl --mode=aclbody \ + remote REMOTE $(REMOTE_PROTOCOL) access/viraccessapicheck.h > $@ + +access/viraccessapicheckqemu.h: $(srcdir)/rpc/gendispatch.pl \ + $(QEMU_PROTOCOL) Makefile.am + $(AM_V_GEN)$(PERL) -w $(srcdir)/rpc/gendispatch.pl --mode=aclheader \ + qemu QEMU $(QEMU_PROTOCOL) > $@ +access/viraccessapicheckqemu.c: $(srcdir)/rpc/gendispatch.pl \ + $(QEMU_PROTOCOL) Makefile.am + $(AM_V_GEN)$(PERL) -w $(srcdir)/rpc/gendispatch.pl --mode=aclbody \ + qemu QEMU $(QEMU_PROTOCOL) access/viraccessapicheckqemu.h > $@ + +access/viraccessapichecklxc.h: $(srcdir)/rpc/gendispatch.pl \ + $(LXC_PROTOCOL) Makefile.am + $(AM_V_GEN)$(PERL) -w $(srcdir)/rpc/gendispatch.pl --mode=aclheader \ + lxc LXC $(LXC_PROTOCOL) > $@ +access/viraccessapichecklxc.c: $(srcdir)/rpc/gendispatch.pl \ + $(LXC_PROTOCOL) Makefile.am + $(AM_V_GEN)$(PERL) -w $(srcdir)/rpc/gendispatch.pl --mode=aclbody \ + lxc LXC $(LXC_PROTOCOL) access/viraccessapichecklxc.h > $@ + # Add all conditional sources just in case... EXTRA_DIST += \ $(TEST_DRIVER_SOURCES) \ diff --git a/src/rpc/gendispatch.pl b/src/rpc/gendispatch.pl index 0bf76da..1179420 100755 --- a/src/rpc/gendispatch.pl +++ b/src/rpc/gendispatch.pl @@ -24,8 +24,9 @@ my $res = GetOptions("mode=s" => \$mode); die "cannot parse command line options" unless $res; -die "unknown mode '$mode', expecting 'client', 'server' or 'debug'" - unless $mode =~ /^(client|server|debug)$/; +die "unknown mode '$mode', expecting 'client', 'server', " . + "'aclheader', 'aclbody', 'aclsym' or 'debug'" + unless $mode =~ /^(client|server|aclheader|aclbody|aclsym|debug)$/; my $structprefix = shift or die "missing struct prefix argument"; my $procprefix = shift or die "missing procedure prefix argument"; @@ -108,7 +109,13 @@ while (<PROTOCOL>) { } } elsif ($collect_opts) { if (m,^\s*\*\s*\@(\w+)\s*:\s*((?:\w|:|\!|\|)+)\s*$,) { - $opts{$1} = $2; + if ($1 eq "acl" || + $1 eq "aclfilter") { + $opts{$1} = [] unless exists $opts{$1}; + push @{$opts{$1}}, $2; + } else { + $opts{$1} = $2; + } } elsif (m,^\s*\*/\s*$,) { $collect_opts = 0; } elsif (m,^\s*\*\s*$,) { @@ -235,6 +242,8 @@ while (<PROTOCOL>) { $calls{$name}->{streamflag} = "none"; } + $calls{$name}->{acl} = $opts{acl}; + $calls{$name}->{aclfilter} = $opts{aclfilter}; # for now, we distinguish only two levels of priority: # low (0) and high (1) @@ -321,11 +330,18 @@ sub hyper_to_long #---------------------------------------------------------------------- # Output -print <<__EOF__; +if ($mode eq "aclsym") { + print <<__EOF__; +# Automatically generated by gendispatch.pl. +# Do not edit this file. Any changes you make will be lost. +__EOF__ +} else { + print <<__EOF__; /* Automatically generated by gendispatch.pl. * Do not edit this file. Any changes you make will be lost. */ __EOF__ +} # Debugging. if ($mode eq "debug") { @@ -1617,4 +1633,190 @@ elsif ($mode eq "client") { print " return rv;\n"; print "}\n"; } +} elsif ($mode eq "aclheader" || + $mode eq "aclbody" || + $mode eq "aclsym") { + my %generate = map { $_ => 1 } @autogen; + my @keys = keys %calls; + + if ($mode eq "aclsym") { + @keys = sort { my $c = $a . "ensureacl"; + my $d = $b . "ensureacl"; + $c cmp $d } @keys; + } else { + @keys = sort { $a cmp $b } @keys; + } + + if ($mode eq "aclheader") { + my @headers = ( + "internal.h", + "domain_conf.h", + "network_conf.h", + "secret_conf.h", + "storage_conf.h", + "nwfilter_conf.h", + "node_device_conf.h", + "interface_conf.h" + ); + foreach my $hdr (@headers) { + print "#include \"$hdr\"\n"; + } + } elsif ($mode eq "aclbody") { + my $header = shift; + print "#include <config.h>\n"; + print "#include \"$header\"\n"; + print "#include \"access/viraccessmanager.h\"\n"; + print "#include \"datatypes.h\"\n"; + print "#include \"virerror.h\"\n"; + print "\n"; + print "#define VIR_FROM_THIS VIR_FROM_ACCESS\n"; + } + print "\n"; + + foreach (@keys) { + my $call = $calls{$_}; + + die "missing 'acl' option for $call->{ProcName}" + unless exists $call->{acl} && + $#{$call->{acl}} != -1; + + next if $call->{acl}->[0] eq "none"; + + if ($mode eq "aclsym") { + my $apiname = "vir" . $call->{ProcName}; + if ($structprefix eq "qemu") { + $apiname =~ s/virDomain/virDomainQemu/; + } elsif ($structprefix eq "lxc") { + $apiname =~ s/virDomain/virDomainLxc/; + } + if (defined $call->{aclfilter}) { + print $apiname . "CheckACL;\n"; + } + print $apiname . "EnsureACL;\n"; + } else { + &generate_acl($call, $call->{acl}, "Ensure"); + if (defined $call->{aclfilter}) { + &generate_acl($call, $call->{aclfilter}, "Check"); + } + } + + sub generate_acl { + my $call = shift; + my $acl = shift; + my $action = shift; + + my @acl; + foreach (@{$acl}) { + my @bits = split /:/; + push @acl, { object => $bits[0], perm => $bits[1], flags => $bits[2] } + } + + my $checkflags = 0; + for (my $i = 1 ; $i <= $#acl ; $i++) { + if ($acl[$i]->{object} ne $acl[0]->{object}) { + die "acl for '$call->{ProcName}' cannot check different objects"; + } + if (defined $acl[$i]->{flags}) { + $checkflags = 1; + } + } + + my $apiname = "vir" . $call->{ProcName}; + if ($structprefix eq "qemu") { + $apiname =~ s/virDomain/virDomainQemu/; + } elsif ($structprefix eq "lxc") { + $apiname =~ s/virDomain/virDomainLxc/; + } + + my $object = $acl[0]->{object}; + my $arg = $acl[0]->{object}; + $arg =~ s/^.*_(\w+)$/$1/; + $object =~ s/^(\w)/uc $1/e; + $object =~ s/_(\w)/uc $1/e; + $object =~ s/Nwfilter/NWFilter/; + my $objecttype = "vir" . $object . "DefPtr"; + $apiname .= $action . "ACL"; + + if ($arg eq "interface") { + $arg = "iface"; + } + + my @argdecls; + push @argdecls, "virConnectPtr conn"; + if ($object ne "Connect") { + if ($object eq "StorageVol") { + push @argdecls, "virStoragePoolDefPtr pool"; + } + push @argdecls, "$objecttype $arg"; + } + if ($checkflags) { + push @argdecls, "unsigned int flags"; + } + + if ($mode eq "aclheader") { + print "extern int $apiname(" . join(", ", @argdecls) . ");\n"; + } else { + my @argvars; + push @argvars, "mgr"; + push @argvars, "conn->driver->name"; + if ($object ne "Connect") { + if ($object eq "StorageVol") { + push @argvars, "pool"; + } + push @argvars, $arg; + } + + if ($action eq "Check") { + print "/* Returns: -1 on error, 0 on denied, 1 on allowed */\n"; + } else { + print "/* Returns: -1 on error (denied==error), 0 on allowed */\n"; + } + print "int $apiname(" . join(", ", @argdecls) . ")\n"; + print "{\n"; + print " virAccessManagerPtr mgr;\n"; + print " int rv;\n"; + print "\n"; + print " if (!(mgr = virAccessManagerGetDefault()))\n"; + print " return -1;\n"; + print "\n"; + + foreach my $acl (@acl) { + my $perm = "vir_access_perm_" . $acl->{object} . "_" . $acl->{perm}; + $perm =~ tr/a-z/A-Z/; + + my $method = "virAccessManagerCheck" . $object; + my $space = ' ' x length($method); + print " if ("; + if (defined $acl->{flags}) { + my $flags = $acl->{flags}; + if ($flags =~ /^\!/) { + $flags = substr $flags, 1; + print "((flags & ($flags)) == 0) &&\n"; + } else { + print "((flags & ($flags)) == ($flags)) &&\n"; + } + print " "; + } + print "(rv = $method(" . join(", ", @argvars, $perm) . ")) <= 0) {\n"; + if ($action eq "Ensure") { + print " if (rv == 0)\n"; + print " virReportError(VIR_ERR_ACCESS_DENIED, NULL);\n"; + print " return -1;\n"; + } else { + print " return rv;\n"; + } + print " }"; + print "\n"; + } + + if ($action eq "Check") { + print " return 1;\n"; + } else { + print " return 0;\n"; + } + print "}\n\n"; + } + } + } } + -- 1.8.1.4

From: "Daniel P. Berrange" <berrange@redhat.com> Insert calls to the ACL checking APIs in all QEMU driver entrypoints. Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- src/qemu/qemu_driver.c | 716 +++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 639 insertions(+), 77 deletions(-) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index 5005afa..3214901 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -92,6 +92,8 @@ #include "virtypedparam.h" #include "virbitmap.h" #include "virstring.h" +#include "access/viraccessapicheck.h" +#include "access/viraccessapicheckqemu.h" #define VIR_FROM_THIS VIR_FROM_QEMU @@ -1041,6 +1043,10 @@ static virDrvOpenStatus qemuConnectOpen(virConnectPtr conn, } } } + + if (virConnectOpenEnsureACL(conn) < 0) + goto cleanup; + conn->privateData = qemu_driver; ret = VIR_DRV_OPEN_SUCCESS; @@ -1063,8 +1069,11 @@ static int qemuConnectClose(virConnectPtr conn) /* Which features are supported by this driver? */ static int -qemuConnectSupportsFeature(virConnectPtr conn ATTRIBUTE_UNUSED, int feature) +qemuConnectSupportsFeature(virConnectPtr conn, int feature) { + if (virConnectSupportsFeatureEnsureACL(conn) < 0) + return -1; + switch (feature) { case VIR_DRV_FEATURE_MIGRATION_V2: case VIR_DRV_FEATURE_MIGRATION_V3: @@ -1081,6 +1090,9 @@ qemuConnectSupportsFeature(virConnectPtr conn ATTRIBUTE_UNUSED, int feature) } static const char *qemuConnectGetType(virConnectPtr conn ATTRIBUTE_UNUSED) { + if (virConnectGetTypeEnsureACL(conn) < 0) + return NULL; + return "QEMU"; } @@ -1142,6 +1154,9 @@ qemuConnectGetSysinfo(virConnectPtr conn, unsigned int flags) virCheckFlags(0, NULL); + if (virConnectGetSysinfoEnsureACL(conn) < 0) + return NULL; + if (!driver->hostsysinfo) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("Host SMBIOS information is not available")); @@ -1158,6 +1173,9 @@ qemuConnectGetSysinfo(virConnectPtr conn, unsigned int flags) } static int qemuConnectGetMaxVcpus(virConnectPtr conn ATTRIBUTE_UNUSED, const char *type) { + if (virConnectGetMaxVcpusEnsureACL(conn) < 0) + return -1; + if (!type) return 16; @@ -1181,6 +1199,9 @@ static char *qemuConnectGetCapabilities(virConnectPtr conn) { virCapsPtr caps = NULL; char *xml = NULL; + if (virConnectGetCapabilitiesEnsureACL(conn) < 0) + return NULL; + if (!(caps = virQEMUDriverGetCapabilities(driver, true))) goto cleanup; @@ -1284,6 +1305,9 @@ static virDomainPtr qemuDomainLookupByID(virConnectPtr conn, goto cleanup; } + if (virDomainLookupByIDEnsureACL(conn, vm->def) < 0) + goto cleanup; + dom = virGetDomain(conn, vm->def->name, vm->def->uuid); if (dom) dom->id = vm->def->id; @@ -1309,6 +1333,9 @@ static virDomainPtr qemuDomainLookupByUUID(virConnectPtr conn, goto cleanup; } + if (virDomainLookupByUUIDEnsureACL(conn, vm->def) < 0) + goto cleanup; + dom = virGetDomain(conn, vm->def->name, vm->def->uuid); if (dom) dom->id = vm->def->id; @@ -1332,6 +1359,9 @@ static virDomainPtr qemuDomainLookupByName(virConnectPtr conn, goto cleanup; } + if (virDomainLookupByNameEnsureACL(conn, vm->def) < 0) + goto cleanup; + dom = virGetDomain(conn, vm->def->name, vm->def->uuid); if (dom) dom->id = vm->def->id; @@ -1350,6 +1380,9 @@ static int qemuDomainIsActive(virDomainPtr dom) if (!(obj = qemuDomObjFromDomain(dom))) goto cleanup; + if (virDomainIsActiveEnsureACL(dom->conn, obj->def) < 0) + goto cleanup; + ret = virDomainObjIsActive(obj); cleanup: @@ -1366,6 +1399,9 @@ static int qemuDomainIsPersistent(virDomainPtr dom) if (!(obj = qemuDomObjFromDomain(dom))) goto cleanup; + if (virDomainIsPersistentEnsureACL(dom->conn, obj->def) < 0) + goto cleanup; + ret = obj->persistent; cleanup: @@ -1382,6 +1418,9 @@ static int qemuDomainIsUpdated(virDomainPtr dom) if (!(obj = qemuDomObjFromDomain(dom))) goto cleanup; + if (virDomainIsUpdatedEnsureACL(dom->conn, obj->def) < 0) + goto cleanup; + ret = obj->updated; cleanup: @@ -1396,6 +1435,9 @@ static int qemuConnectGetVersion(virConnectPtr conn, unsigned long *version) { unsigned int qemuVersion = 0; virCapsPtr caps = NULL; + if (virConnectGetVersionEnsureACL(conn) < 0) + return -1; + if (!(caps = virQEMUDriverGetCapabilities(driver, false))) goto cleanup; @@ -1413,8 +1455,11 @@ cleanup: } -static char *qemuConnectGetHostname(virConnectPtr conn ATTRIBUTE_UNUSED) +static char *qemuConnectGetHostname(virConnectPtr conn) { + if (virConnectGetHostnameEnsureACL(conn) < 0) + return NULL; + return virGetHostname(); } @@ -1423,6 +1468,9 @@ static int qemuConnectListDomains(virConnectPtr conn, int *ids, int nids) { virQEMUDriverPtr driver = conn->privateData; int n; + if (virConnectListDomainsEnsureACL(conn) < 0) + return -1; + n = virDomainObjListGetActiveIDs(driver->domains, ids, nids); return n; @@ -1432,6 +1480,9 @@ static int qemuConnectNumOfDomains(virConnectPtr conn) { virQEMUDriverPtr driver = conn->privateData; int n; + if (virConnectNumOfDomainsEnsureACL(conn) < 0) + return -1; + n = virDomainObjListNumOfDomains(driver->domains, 1); return n; @@ -1489,6 +1540,9 @@ static virDomainPtr qemuDomainCreateXML(virConnectPtr conn, VIR_DOMAIN_XML_INACTIVE))) goto cleanup; + if (virDomainCreateXMLEnsureACL(conn, def) < 0) + goto cleanup; + if (virSecurityManagerVerify(driver->securityManager, def) < 0) goto cleanup; @@ -1573,6 +1627,9 @@ static int qemuDomainSuspend(virDomainPtr dom) { if (!(vm = qemuDomObjFromDomain(dom))) return -1; + if (virDomainSuspendEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (!virDomainObjIsActive(vm)) { virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("domain is not running")); @@ -1651,6 +1708,9 @@ static int qemuDomainResume(virDomainPtr dom) { cfg = virQEMUDriverGetConfig(driver); + if (virDomainResumeEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0) goto cleanup; @@ -1719,6 +1779,9 @@ static int qemuDomainShutdownFlags(virDomainPtr dom, unsigned int flags) { if (agentRequested || (!flags && priv->agent)) useAgent = true; + if (virDomainShutdownFlagsEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (priv->agentError) { if (agentRequested && !acpiRequested) { virReportError(VIR_ERR_AGENT_UNRESPONSIVE, "%s", @@ -1808,6 +1871,9 @@ qemuDomainReboot(virDomainPtr dom, unsigned int flags) priv = vm->privateData; + if (virDomainRebootEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if ((flags & VIR_DOMAIN_REBOOT_GUEST_AGENT) || (!(flags & VIR_DOMAIN_REBOOT_ACPI_POWER_BTN) && priv->agent)) @@ -1889,6 +1955,9 @@ qemuDomainReset(virDomainPtr dom, unsigned int flags) if (!(vm = qemuDomObjFromDomain(dom))) goto cleanup; + if (virDomainResetEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0) goto cleanup; @@ -1946,6 +2015,9 @@ qemuDomainDestroyFlags(virDomainPtr dom, priv = vm->privateData; + if (virDomainDestroyFlagsEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + qemuDomainSetFakeReboot(driver, vm, false); @@ -2021,6 +2093,9 @@ static char *qemuDomainGetOSType(virDomainPtr dom) { if (!(vm = qemuDomObjFromDomain(dom))) goto cleanup; + if (virDomainGetOSTypeEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (!(type = strdup(vm->def->os.type))) virReportOOMError(); @@ -2040,6 +2115,9 @@ qemuDomainGetMaxMemory(virDomainPtr dom) if (!(vm = qemuDomObjFromDomain(dom))) goto cleanup; + if (virDomainGetMaxMemoryEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + ret = vm->def->mem.max_balloon; cleanup: @@ -2067,6 +2145,9 @@ static int qemuDomainSetMemoryFlags(virDomainPtr dom, unsigned long newmem, cfg = virQEMUDriverGetConfig(driver); + if (virDomainSetMemoryFlagsEnsureACL(dom->conn, vm->def, flags) < 0) + goto cleanup; + if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0) goto cleanup; @@ -2167,6 +2248,9 @@ static int qemuDomainInjectNMI(virDomainPtr domain, unsigned int flags) if (!(vm = qemuDomObjFromDomain(domain))) return -1; + if (virDomainInjectNMIEnsureACL(domain->conn, vm->def) < 0) + goto cleanup; + if (!virDomainObjIsActive(vm)) { virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("domain is not running")); @@ -2238,6 +2322,9 @@ static int qemuDomainSendKey(virDomainPtr domain, priv = vm->privateData; + if (virDomainSendKeyEnsureACL(domain->conn, vm->def) < 0) + goto cleanup; + if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0) goto cleanup; @@ -2273,6 +2360,9 @@ static int qemuDomainGetInfo(virDomainPtr dom, if (!(vm = qemuDomObjFromDomain(dom))) goto cleanup; + if (virDomainGetInfoEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + info->state = virDomainObjGetState(vm, NULL); if (!virDomainObjIsActive(vm)) { @@ -2352,6 +2442,9 @@ qemuDomainGetState(virDomainPtr dom, if (!(vm = qemuDomObjFromDomain(dom))) goto cleanup; + if (virDomainGetStateEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + *state = virDomainObjGetState(vm, reason); ret = 0; @@ -2375,6 +2468,9 @@ qemuDomainGetControlInfo(virDomainPtr dom, if (!(vm = qemuDomObjFromDomain(dom))) goto cleanup; + if (virDomainGetControlInfoEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (!virDomainObjIsActive(vm)) { virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("domain is not running")); @@ -2944,6 +3040,9 @@ qemuDomainSaveFlags(virDomainPtr dom, const char *path, const char *dxml, if (!(vm = qemuDomObjFromDomain(dom))) goto cleanup; + if (virDomainSaveFlagsEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (!virDomainObjIsActive(vm)) { virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("domain is not running")); @@ -2999,6 +3098,9 @@ qemuDomainManagedSave(virDomainPtr dom, unsigned int flags) if (!(vm = qemuDomObjFromDomain(dom))) return -1; + if (virDomainManagedSaveEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (!virDomainObjIsActive(vm)) { virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("domain is not running")); @@ -3057,14 +3159,19 @@ static int qemuDomainHasManagedSaveImage(virDomainPtr dom, unsigned int flags) { virDomainObjPtr vm = NULL; - int ret; + int ret = -1; virCheckFlags(0, -1); if (!(vm = qemuDomObjFromDomain(dom))) return -1; + if (virDomainHasManagedSaveImageEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + ret = vm->hasManagedSave; + +cleanup: virObjectUnlock(vm); return ret; } @@ -3082,6 +3189,9 @@ qemuDomainManagedSaveRemove(virDomainPtr dom, unsigned int flags) if (!(vm = qemuDomObjFromDomain(dom))) return -1; + if (virDomainManagedSaveRemoveEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (!(name = qemuDomainManagedSavePath(driver, vm))) goto cleanup; @@ -3244,6 +3354,9 @@ static int qemuDomainCoreDump(virDomainPtr dom, if (!(vm = qemuDomObjFromDomain(dom))) return -1; + if (virDomainCoreDumpEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (qemuDomainObjBeginAsyncJob(driver, vm, QEMU_ASYNC_JOB_DUMP) < 0) goto cleanup; @@ -3350,6 +3463,9 @@ qemuDomainScreenshot(virDomainPtr dom, priv = vm->privateData; cfg = virQEMUDriverGetConfig(driver); + if (virDomainScreenshotEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0) goto cleanup; @@ -3706,11 +3822,15 @@ qemuDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus, return -1; } + if (!(vm = qemuDomObjFromDomain(dom))) + goto cleanup; + cfg = virQEMUDriverGetConfig(driver); - if (!(caps = virQEMUDriverGetCapabilities(driver, false))) + + if (virDomainSetVcpusFlagsEnsureACL(dom->conn, vm->def, flags) < 0) goto cleanup; - if (!(vm = qemuDomObjFromDomain(dom))) + if (!(caps = virQEMUDriverGetCapabilities(driver, false))) goto cleanup; if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0) @@ -3805,6 +3925,9 @@ qemuDomainPinVcpuFlags(virDomainPtr dom, if (!(vm = qemuDomObjFromDomain(dom))) goto cleanup; + if (virDomainPinVcpuFlagsEnsureACL(dom->conn, vm->def, flags) < 0) + goto cleanup; + if (!(caps = virQEMUDriverGetCapabilities(driver, false))) goto cleanup; @@ -3988,6 +4111,9 @@ qemuDomainGetVcpuPinInfo(virDomainPtr dom, if (!(vm = qemuDomObjFromDomain(dom))) goto cleanup; + if (virDomainGetVcpuPinInfoEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (!(caps = virQEMUDriverGetCapabilities(driver, false))) goto cleanup; @@ -4076,6 +4202,9 @@ qemuDomainPinEmulator(virDomainPtr dom, if (!(vm = qemuDomObjFromDomain(dom))) goto cleanup; + if (virDomainPinEmulatorEnsureACL(dom->conn, vm->def, flags) < 0) + goto cleanup; + if (!(caps = virQEMUDriverGetCapabilities(driver, false))) goto cleanup; @@ -4230,6 +4359,9 @@ qemuDomainGetEmulatorPinInfo(virDomainPtr dom, if (!(vm = qemuDomObjFromDomain(dom))) goto cleanup; + if (virDomainGetEmulatorPinInfoEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (!(caps = virQEMUDriverGetCapabilities(driver, false))) goto cleanup; @@ -4295,6 +4427,9 @@ qemuDomainGetVcpus(virDomainPtr dom, if (!(vm = qemuDomObjFromDomain(dom))) goto cleanup; + if (virDomainGetVcpusEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (!virDomainObjIsActive(vm)) { virReportError(VIR_ERR_OPERATION_INVALID, "%s", @@ -4387,6 +4522,9 @@ qemuDomainGetVcpusFlags(virDomainPtr dom, unsigned int flags) if (!(vm = qemuDomObjFromDomain(dom))) goto cleanup; + if (virDomainGetVcpusFlagsEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (!(caps = virQEMUDriverGetCapabilities(driver, false))) goto cleanup; @@ -4425,6 +4563,9 @@ static int qemuDomainGetSecurityLabel(virDomainPtr dom, virSecurityLabelPtr secl if (!(vm = qemuDomObjFromDomain(dom))) return -1; + if (virDomainGetSecurityLabelEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (!virDomainVirtTypeToString(vm->def->virtType)) { virReportError(VIR_ERR_INTERNAL_ERROR, _("unknown virt type in domain definition '%d'"), @@ -4473,6 +4614,9 @@ static int qemuDomainGetSecurityLabelList(virDomainPtr dom, if (!(vm = qemuDomObjFromDomain(dom))) return -1; + if (virDomainGetSecurityLabelListEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (!virDomainVirtTypeToString(vm->def->virtType)) { virReportError(VIR_ERR_INTERNAL_ERROR, _("unknown virt type in domain definition '%d'"), @@ -4540,6 +4684,9 @@ static int qemuNodeGetSecurityModel(virConnectPtr conn, if (!(caps = virQEMUDriverGetCapabilities(driver, false))) goto cleanup; + if (virNodeGetSecurityModelEnsureACL(conn) < 0) + goto cleanup; + /* We treat no driver as success, but simply return no data in *secmodel */ if (caps->host.nsecModels == 0 || caps->host.secModels[0].model == NULL) @@ -4868,6 +5015,9 @@ qemuDomainRestoreFlags(virConnectPtr conn, if (fd < 0) goto cleanup; + if (virDomainRestoreFlagsEnsureACL(conn, def) < 0) + goto cleanup; + if (!(vm = virDomainObjListAdd(driver->domains, def, driver->xmlopt, VIR_DOMAIN_OBJ_LIST_ADD_LIVE | @@ -4926,6 +5076,9 @@ qemuDomainSaveImageGetXMLDesc(virConnectPtr conn, const char *path, if (fd < 0) goto cleanup; + if (virDomainSaveImageGetXMLDescEnsureACL(conn, def) < 0) + goto cleanup; + ret = qemuDomainDefFormatXML(driver, def, flags); cleanup: @@ -4965,6 +5118,9 @@ qemuDomainSaveImageDefineXML(virConnectPtr conn, const char *path, goto cleanup; } + if (virDomainSaveImageDefineXMLEnsureACL(conn, def) < 0) + goto cleanup; + xml = qemuDomainDefFormatXML(driver, def, VIR_DOMAIN_XML_INACTIVE | VIR_DOMAIN_XML_SECURE | @@ -5075,6 +5231,9 @@ static char *qemuDomainGetXMLDesc(virDomainPtr dom, priv = vm->privateData; + if (virDomainGetXMLDescEnsureACL(dom->conn, vm->def, flags) < 0) + goto cleanup; + /* Refresh current memory based on balloon info if supported */ if ((vm->def->memballoon != NULL) && (vm->def->memballoon->model != VIR_DOMAIN_MEMBALLOON_MODEL_NONE) && @@ -5133,6 +5292,9 @@ static char *qemuConnectDomainXMLFromNative(virConnectPtr conn, virCheckFlags(0, NULL); + if (virConnectDomainXMLFromNativeEnsureACL(conn) < 0) + goto cleanup; + if (STRNEQ(format, QEMU_CONFIG_FORMAT_ARGV)) { virReportError(VIR_ERR_INVALID_ARG, _("unsupported config type %s"), format); @@ -5181,6 +5343,9 @@ static char *qemuConnectDomainXMLToNative(virConnectPtr conn, cfg = virQEMUDriverGetConfig(driver); + if (virConnectDomainXMLToNativeEnsureACL(conn) < 0) + goto cleanup; + if (STRNEQ(format, QEMU_CONFIG_FORMAT_ARGV)) { virReportError(VIR_ERR_INVALID_ARG, _("unsupported config type %s"), format); @@ -5354,19 +5519,28 @@ cleanup: static int qemuConnectListDefinedDomains(virConnectPtr conn, char **const names, int nnames) { virQEMUDriverPtr driver = conn->privateData; - int n; + int ret = -1; - n = virDomainObjListGetInactiveNames(driver->domains, names, nnames); - return n; + if (virConnectListDefinedDomainsEnsureACL(conn) < 0) + goto cleanup; + + ret = virDomainObjListGetInactiveNames(driver->domains, names, nnames); + +cleanup: + return ret; } static int qemuConnectNumOfDefinedDomains(virConnectPtr conn) { virQEMUDriverPtr driver = conn->privateData; - int n; + int ret = -1; + + if (virConnectNumOfDefinedDomainsEnsureACL(conn) < 0) + goto cleanup; - n = virDomainObjListNumOfDomains(driver->domains, 0); + ret = virDomainObjListNumOfDomains(driver->domains, 0); - return n; +cleanup: + return ret; } @@ -5463,6 +5637,9 @@ qemuDomainCreateWithFlags(virDomainPtr dom, unsigned int flags) if (!(vm = qemuDomObjFromDomain(dom))) return -1; + if (virDomainCreateWithFlagsEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0) goto cleanup; @@ -5514,6 +5691,9 @@ static virDomainPtr qemuDomainDefineXML(virConnectPtr conn, const char *xml) { VIR_DOMAIN_XML_INACTIVE))) goto cleanup; + if (virDomainDefineXMLEnsureACL(conn, def) < 0) + goto cleanup; + if (virSecurityManagerVerify(driver->securityManager, def) < 0) goto cleanup; @@ -5603,6 +5783,9 @@ qemuDomainUndefineFlags(virDomainPtr dom, cfg = virQEMUDriverGetConfig(driver); + if (virDomainUndefineFlagsEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (!vm->persistent) { virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("cannot undefine transient domain")); @@ -6369,6 +6552,9 @@ static int qemuDomainAttachDeviceFlags(virDomainPtr dom, const char *xml, priv = vm->privateData; + if (virDomainAttachDeviceFlagsEnsureACL(dom->conn, vm->def, flags) < 0) + goto cleanup; + if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0) goto cleanup; @@ -6509,6 +6695,9 @@ static int qemuDomainUpdateDeviceFlags(virDomainPtr dom, priv = vm->privateData; + if (virDomainUpdateDeviceFlagsEnsureACL(dom->conn, vm->def, flags) < 0) + goto cleanup; + if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0) goto cleanup; @@ -6641,6 +6830,9 @@ static int qemuDomainDetachDeviceFlags(virDomainPtr dom, const char *xml, priv = vm->privateData; + if (virDomainDetachDeviceFlagsEnsureACL(dom->conn, vm->def, flags) < 0) + goto cleanup; + if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0) goto cleanup; @@ -6756,6 +6948,9 @@ static int qemuDomainGetAutostart(virDomainPtr dom, if (!(vm = qemuDomObjFromDomain(dom))) goto cleanup; + if (virDomainGetAutostartEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + *autostart = vm->autostart; ret = 0; @@ -6778,6 +6973,9 @@ static int qemuDomainSetAutostart(virDomainPtr dom, cfg = virQEMUDriverGetConfig(driver); + if (virDomainSetAutostartEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (!vm->persistent) { virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("cannot set autostart for transient domain")); @@ -6879,6 +7077,9 @@ static char *qemuDomainGetSchedulerType(virDomainPtr dom, } priv = vm->privateData; + if (virDomainGetSchedulerTypeEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_CPU)) { virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("cgroup CPU controller is not mounted")); @@ -7063,6 +7264,10 @@ qemuDomainSetBlkioParameters(virDomainPtr dom, priv = vm->privateData; cfg = virQEMUDriverGetConfig(driver); + + if (virDomainSetBlkioParametersEnsureACL(dom->conn, vm->def, flags) < 0) + goto cleanup; + if (!(caps = virQEMUDriverGetCapabilities(driver, false))) goto cleanup; @@ -7210,6 +7415,9 @@ qemuDomainGetBlkioParameters(virDomainPtr dom, priv = vm->privateData; + if (virDomainGetBlkioParametersEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (!(caps = virQEMUDriverGetCapabilities(driver, false))) goto cleanup; @@ -7399,6 +7607,9 @@ qemuDomainSetMemoryParameters(virDomainPtr dom, priv = vm->privateData; cfg = virQEMUDriverGetConfig(driver); + if (virDomainSetMemoryParametersEnsureACL(dom->conn, vm->def, flags) < 0) + goto cleanup; + if (!(caps = virQEMUDriverGetCapabilities(driver, false))) goto cleanup; @@ -7519,6 +7730,10 @@ qemuDomainGetMemoryParameters(virDomainPtr dom, return -1; priv = vm->privateData; + + if (virDomainGetMemoryParametersEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (!(caps = virQEMUDriverGetCapabilities(driver, false))) goto cleanup; @@ -7671,6 +7886,9 @@ qemuDomainSetNumaParameters(virDomainPtr dom, priv = vm->privateData; cfg = virQEMUDriverGetConfig(driver); + if (virDomainSetNumaParametersEnsureACL(dom->conn, vm->def, flags) < 0) + goto cleanup; + if (!(caps = virQEMUDriverGetCapabilities(driver, false))) goto cleanup; @@ -7813,6 +8031,9 @@ qemuDomainGetNumaParameters(virDomainPtr dom, priv = vm->privateData; + if (virDomainGetNumaParametersEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (!(caps = virQEMUDriverGetCapabilities(driver, false))) goto cleanup; @@ -8012,6 +8233,9 @@ qemuDomainSetSchedulerParametersFlags(virDomainPtr dom, priv = vm->privateData; cfg = virQEMUDriverGetConfig(driver); + if (virDomainSetSchedulerParametersFlagsEnsureACL(dom->conn, vm->def, flags) < 0) + goto cleanup; + if (!(caps = virQEMUDriverGetCapabilities(driver, false))) goto cleanup; @@ -8281,6 +8505,9 @@ qemuDomainGetSchedulerParametersFlags(virDomainPtr dom, priv = vm->privateData; + if (virDomainGetSchedulerParametersFlagsEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (*nparams > 1) { rc = qemuGetCpuBWStatus(priv->cgroup); if (rc < 0) @@ -8437,6 +8664,9 @@ qemuDomainBlockResize(virDomainPtr dom, priv = vm->privateData; + if (virDomainBlockResizeEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0) goto cleanup; @@ -8497,6 +8727,9 @@ qemuDomainBlockStats(virDomainPtr dom, if (!(vm = qemuDomObjFromDomain(dom))) goto cleanup; + if (virDomainBlockStatsEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (!virDomainObjIsActive(vm)) { virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("domain is not running")); @@ -8574,6 +8807,9 @@ qemuDomainBlockStatsFlags(virDomainPtr dom, if (!(vm = qemuDomObjFromDomain(dom))) goto cleanup; + if (virDomainBlockStatsFlagsEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0) goto cleanup; @@ -8727,6 +8963,9 @@ qemuDomainInterfaceStats(virDomainPtr dom, if (!(vm = qemuDomObjFromDomain(dom))) goto cleanup; + if (virDomainInterfaceStatsEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (!virDomainObjIsActive(vm)) { virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("domain is not running")); @@ -8805,6 +9044,9 @@ qemuDomainSetInterfaceParameters(virDomainPtr dom, cfg = virQEMUDriverGetConfig(driver); + if (virDomainSetInterfaceParametersEnsureACL(dom->conn, vm->def, flags) < 0) + goto cleanup; + if (!(caps = virQEMUDriverGetCapabilities(driver, false))) goto cleanup; @@ -8964,6 +9206,9 @@ qemuDomainGetInterfaceParameters(virDomainPtr dom, if (!(vm = qemuDomObjFromDomain(dom))) return -1; + if (virDomainGetInterfaceParametersEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (!(caps = virQEMUDriverGetCapabilities(driver, false))) goto cleanup; @@ -9070,6 +9315,9 @@ qemuDomainMemoryStats(virDomainPtr dom, if (!(vm = qemuDomObjFromDomain(dom))) goto cleanup; + if (virDomainMemoryStatsEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0) goto cleanup; @@ -9121,6 +9369,9 @@ qemuDomainBlockPeek(virDomainPtr dom, if (!(vm = qemuDomObjFromDomain(dom))) goto cleanup; + if (virDomainBlockPeekEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (!path || path[0] == '\0') { virReportError(VIR_ERR_INVALID_ARG, "%s", _("NULL or empty path")); @@ -9183,6 +9434,9 @@ qemuDomainMemoryPeek(virDomainPtr dom, cfg = virQEMUDriverGetConfig(driver); + if (virDomainMemoryPeekEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (flags != VIR_MEMORY_VIRTUAL && flags != VIR_MEMORY_PHYSICAL) { virReportError(VIR_ERR_INVALID_ARG, "%s", _("flags parameter must be VIR_MEMORY_VIRTUAL or VIR_MEMORY_PHYSICAL")); @@ -9276,6 +9530,9 @@ static int qemuDomainGetBlockInfo(virDomainPtr dom, cfg = virQEMUDriverGetConfig(driver); + if (virDomainGetBlockInfoEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (!path || path[0] == '\0') { virReportError(VIR_ERR_INVALID_ARG, "%s", _("NULL or empty path")); @@ -9410,12 +9667,19 @@ qemuConnectDomainEventRegister(virConnectPtr conn, virFreeCallback freecb) { virQEMUDriverPtr driver = conn->privateData; - int ret; + int ret = -1; - ret = virDomainEventStateRegister(conn, - driver->domainEventState, - callback, opaque, freecb); + if (virConnectDomainEventRegisterEnsureACL(conn) < 0) + goto cleanup; + + if (virDomainEventStateRegister(conn, + driver->domainEventState, + callback, opaque, freecb) < 0) + goto cleanup; + ret = 0; + +cleanup: return ret; } @@ -9425,12 +9689,19 @@ qemuConnectDomainEventDeregister(virConnectPtr conn, virConnectDomainEventCallback callback) { virQEMUDriverPtr driver = conn->privateData; - int ret; + int ret = -1; - ret = virDomainEventStateDeregister(conn, - driver->domainEventState, - callback); + if (virConnectDomainEventDeregisterEnsureACL(conn) < 0) + goto cleanup; + + if (virDomainEventStateDeregister(conn, + driver->domainEventState, + callback) < 0) + goto cleanup; + + ret = 0; +cleanup: return ret; } @@ -9444,14 +9715,20 @@ qemuConnectDomainEventRegisterAny(virConnectPtr conn, virFreeCallback freecb) { virQEMUDriverPtr driver = conn->privateData; - int ret; + int ret = -1; + + if (virConnectDomainEventRegisterAnyEnsureACL(conn) < 0) + goto cleanup; if (virDomainEventStateRegisterID(conn, driver->domainEventState, dom, eventID, callback, opaque, freecb, &ret) < 0) - ret = -1; + goto cleanup; + ret = 0; + +cleanup: return ret; } @@ -9461,12 +9738,19 @@ qemuConnectDomainEventDeregisterAny(virConnectPtr conn, int callbackID) { virQEMUDriverPtr driver = conn->privateData; - int ret; + int ret = -1; - ret = virDomainEventStateDeregisterID(conn, - driver->domainEventState, - callbackID); + if (virConnectDomainEventDeregisterAnyEnsureACL(conn) < 0) + goto cleanup; + if (virDomainEventStateDeregisterID(conn, + driver->domainEventState, + callbackID) < 0) + goto cleanup; + + ret = 0; + +cleanup: return ret; } @@ -9534,6 +9818,9 @@ qemuDomainMigratePrepareTunnel(virConnectPtr dconn, } } + if (virDomainMigratePrepareTunnelEnsureACL(dconn, def) < 0) + goto cleanup; + ret = qemuMigrationPrepareTunnel(driver, dconn, NULL, 0, NULL, NULL, /* No cookies in v2 */ st, def, flags); @@ -9607,6 +9894,9 @@ qemuDomainMigratePrepare2(virConnectPtr dconn, } } + if (virDomainMigratePrepare2EnsureACL(dconn, def) < 0) + goto cleanup; + /* Do not use cookies in v2 protocol, since the cookie * length was not sufficiently large, causing failures * migrating between old & new libvirtd @@ -9651,6 +9941,9 @@ qemuDomainMigratePerform(virDomainPtr dom, if (!(vm = qemuDomObjFromDomain(dom))) goto cleanup; + if (virDomainMigratePerformEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (flags & VIR_MIGRATE_PEER2PEER) { dconnuri = uri; uri = NULL; @@ -9695,6 +9988,9 @@ qemuDomainMigrateFinish2(virConnectPtr dconn, goto cleanup; } + if (virDomainMigrateFinish2EnsureACL(dconn, vm->def) < 0) + goto cleanup; + /* Do not use cookies in v2 protocol, since the cookie * length was not sufficiently large, causing failures * migrating between old & new libvirtd @@ -9731,6 +10027,9 @@ qemuDomainMigrateBegin3(virDomainPtr domain, if (!(vm = qemuDomObjFromDomain(domain))) return NULL; + if (virDomainMigrateBegin3EnsureACL(domain->conn, vm->def) < 0) + goto cleanup; + if ((flags & VIR_MIGRATE_CHANGE_PROTECTION)) { if (qemuMigrationJobStart(driver, vm, QEMU_ASYNC_JOB_MIGRATION_OUT) < 0) goto cleanup; @@ -9848,6 +10147,9 @@ qemuDomainMigratePrepare3(virConnectPtr dconn, } } + if (virDomainMigratePrepare3EnsureACL(dconn, def) < 0) + goto cleanup; + ret = qemuMigrationPrepareDirect(driver, dconn, cookiein, cookieinlen, cookieout, cookieoutlen, @@ -9913,6 +10215,9 @@ qemuDomainMigratePrepareTunnel3(virConnectPtr dconn, } } + if (virDomainMigratePrepareTunnel3EnsureACL(dconn, def) < 0) + goto cleanup; + ret = qemuMigrationPrepareTunnel(driver, dconn, cookiein, cookieinlen, cookieout, cookieoutlen, @@ -9947,6 +10252,11 @@ qemuDomainMigratePerform3(virDomainPtr dom, if (!(vm = qemuDomObjFromDomain(dom))) return -1; + if (virDomainMigratePerform3EnsureACL(dom->conn, vm->def) < 0) { + virObjectUnlock(vm); + return -1; + } + return qemuMigrationPerform(driver, dom->conn, vm, xmlin, dconnuri, uri, cookiein, cookieinlen, cookieout, cookieoutlen, @@ -9979,6 +10289,9 @@ qemuDomainMigrateFinish3(virConnectPtr dconn, goto cleanup; } + if (virDomainMigrateFinish3EnsureACL(dconn, vm->def) < 0) + goto cleanup; + dom = qemuMigrationFinish(driver, dconn, vm, cookiein, cookieinlen, cookieout, cookieoutlen, @@ -10008,6 +10321,9 @@ qemuDomainMigrateConfirm3(virDomainPtr domain, cfg = virQEMUDriverGetConfig(driver); + if (virDomainMigrateConfirm3EnsureACL(domain->conn, vm->def) < 0) + goto cleanup; + if (!qemuMigrationJobIsActive(vm, QEMU_ASYNC_JOB_MIGRATION_OUT)) goto cleanup; @@ -10043,25 +10359,15 @@ cleanup: static int -qemuNodeDeviceGetPciInfo(virNodeDevicePtr dev, +qemuNodeDeviceGetPciInfo(virNodeDeviceDefPtr def, unsigned *domain, unsigned *bus, unsigned *slot, unsigned *function) { - virNodeDeviceDefPtr def = NULL; virNodeDevCapsDefPtr cap; - char *xml = NULL; int ret = -1; - xml = virNodeDeviceGetXMLDesc(dev, 0); - if (!xml) - goto out; - - def = virNodeDeviceDefParseString(xml, EXISTING_DEVICE, NULL); - if (!def) - goto out; - cap = def->caps; while (cap) { if (cap->type == VIR_NODE_DEV_CAP_PCI_DEV) { @@ -10077,14 +10383,12 @@ qemuNodeDeviceGetPciInfo(virNodeDevicePtr dev, if (!cap) { virReportError(VIR_ERR_INVALID_ARG, - _("device %s is not a PCI device"), dev->name); + _("device %s is not a PCI device"), def->name); goto out; } ret = 0; out: - virNodeDeviceDefFree(def); - VIR_FREE(xml); return ret; } @@ -10098,15 +10402,28 @@ qemuNodeDeviceDetachFlags(virNodeDevicePtr dev, unsigned domain, bus, slot, function; int ret = -1; bool in_inactive_list = false; + virNodeDeviceDefPtr def = NULL; + char *xml = NULL; virCheckFlags(0, -1); - if (qemuNodeDeviceGetPciInfo(dev, &domain, &bus, &slot, &function) < 0) - return -1; + xml = virNodeDeviceGetXMLDesc(dev, 0); + if (!xml) + goto cleanup; + + def = virNodeDeviceDefParseString(xml, EXISTING_DEVICE, NULL); + if (!def) + goto cleanup; + + if (virNodeDeviceDetachFlagsEnsureACL(dev->conn, def) < 0) + goto cleanup; + + if (qemuNodeDeviceGetPciInfo(def, &domain, &bus, &slot, &function) < 0) + goto cleanup; pci = virPCIDeviceNew(domain, bus, slot, function); if (!pci) - return -1; + goto cleanup; if (!driverName || STREQ(driverName, "kvm")) { virPCIDeviceSetStubDriver(pci, "pci-stub"); @@ -10132,6 +10449,9 @@ out: virObjectUnlock(driver->activePciHostdevs); if (in_inactive_list) virPCIDeviceFree(pci); +cleanup: + virNodeDeviceDefFree(def); + VIR_FREE(xml); return ret; } @@ -10145,17 +10465,30 @@ static int qemuNodeDeviceReAttach(virNodeDevicePtr dev) { virQEMUDriverPtr driver = dev->conn->privateData; - virPCIDevicePtr pci; + virPCIDevicePtr pci = NULL; virPCIDevicePtr other; unsigned domain, bus, slot, function; int ret = -1; + virNodeDeviceDefPtr def = NULL; + char *xml = NULL; - if (qemuNodeDeviceGetPciInfo(dev, &domain, &bus, &slot, &function) < 0) - return -1; + xml = virNodeDeviceGetXMLDesc(dev, 0); + if (!xml) + goto cleanup; + + def = virNodeDeviceDefParseString(xml, EXISTING_DEVICE, NULL); + if (!def) + goto cleanup; + + if (virNodeDeviceReAttachEnsureACL(dev->conn, def) < 0) + goto cleanup; + + if (qemuNodeDeviceGetPciInfo(def, &domain, &bus, &slot, &function) < 0) + goto cleanup; pci = virPCIDeviceNew(domain, bus, slot, function); if (!pci) - return -1; + goto cleanup; virObjectLock(driver->activePciHostdevs); virObjectLock(driver->inactivePciHostdevs); @@ -10185,6 +10518,9 @@ out: virObjectUnlock(driver->inactivePciHostdevs); virObjectUnlock(driver->activePciHostdevs); virPCIDeviceFree(pci); +cleanup: + virNodeDeviceDefFree(def); + VIR_FREE(xml); return ret; } @@ -10195,13 +10531,26 @@ qemuNodeDeviceReset(virNodeDevicePtr dev) virPCIDevicePtr pci; unsigned domain, bus, slot, function; int ret = -1; + virNodeDeviceDefPtr def = NULL; + char *xml = NULL; - if (qemuNodeDeviceGetPciInfo(dev, &domain, &bus, &slot, &function) < 0) - return -1; + xml = virNodeDeviceGetXMLDesc(dev, 0); + if (!xml) + goto cleanup; + + def = virNodeDeviceDefParseString(xml, EXISTING_DEVICE, NULL); + if (!def) + goto cleanup; + + if (virNodeDeviceResetEnsureACL(dev->conn, def) < 0) + goto cleanup; + + if (qemuNodeDeviceGetPciInfo(def, &domain, &bus, &slot, &function) < 0) + goto cleanup; pci = virPCIDeviceNew(domain, bus, slot, function); if (!pci) - return -1; + goto cleanup; virObjectLock(driver->activePciHostdevs); virObjectLock(driver->inactivePciHostdevs); @@ -10215,6 +10564,9 @@ out: virObjectUnlock(driver->inactivePciHostdevs); virObjectUnlock(driver->activePciHostdevs); virPCIDeviceFree(pci); +cleanup: + virNodeDeviceDefFree(def); + VIR_FREE(xml); return ret; } @@ -10229,6 +10581,9 @@ qemuConnectCompareCPU(virConnectPtr conn, virCheckFlags(0, VIR_CPU_COMPARE_ERROR); + if (virConnectCompareCPUEnsureACL(conn) < 0) + goto cleanup; + if (!(caps = virQEMUDriverGetCapabilities(driver, false))) goto cleanup; @@ -10252,12 +10607,16 @@ qemuConnectBaselineCPU(virConnectPtr conn ATTRIBUTE_UNUSED, unsigned int ncpus, unsigned int flags) { - char *cpu; + char *cpu = NULL; virCheckFlags(0, NULL); + if (virConnectBaselineCPUEnsureACL(conn) < 0) + goto cleanup; + cpu = cpuBaselineXML(xmlCPUs, ncpus, NULL, 0); +cleanup: return cpu; } @@ -10273,6 +10632,9 @@ static int qemuDomainGetJobInfo(virDomainPtr dom, priv = vm->privateData; + if (virDomainGetJobInfoEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (virDomainObjIsActive(vm)) { if (priv->job.asyncJob && !priv->job.dump_memory_only) { memcpy(info, &priv->job.info, sizeof(*info)); @@ -10325,6 +10687,9 @@ qemuDomainGetJobStats(virDomainPtr dom, priv = vm->privateData; + if (virDomainGetJobStatsEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (!virDomainObjIsActive(vm)) { virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("domain is not running")); @@ -10453,6 +10818,9 @@ static int qemuDomainAbortJob(virDomainPtr dom) { if (!(vm = qemuDomObjFromDomain(dom))) goto cleanup; + if (virDomainAbortJobEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_ABORT) < 0) goto cleanup; @@ -10507,6 +10875,9 @@ qemuDomainMigrateSetMaxDowntime(virDomainPtr dom, if (!(vm = qemuDomObjFromDomain(dom))) goto cleanup; + if (virDomainMigrateSetMaxDowntimeEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MIGRATION_OP) < 0) goto cleanup; @@ -10554,6 +10925,9 @@ qemuDomainMigrateGetCompressionCache(virDomainPtr dom, if (!(vm = qemuDomObjFromDomain(dom))) goto cleanup; + if (virDomainMigrateGetCompressionCacheEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0) goto cleanup; @@ -10606,6 +10980,9 @@ qemuDomainMigrateSetCompressionCache(virDomainPtr dom, if (!(vm = qemuDomObjFromDomain(dom))) goto cleanup; + if (virDomainMigrateSetCompressionCacheEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MIGRATION_OP) < 0) goto cleanup; @@ -10660,6 +11037,10 @@ qemuDomainMigrateSetMaxSpeed(virDomainPtr dom, goto cleanup; priv = vm->privateData; + + if (virDomainMigrateSetMaxSpeedEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (virDomainObjIsActive(vm)) { if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MIGRATION_OP) < 0) goto cleanup; @@ -10707,6 +11088,10 @@ qemuDomainMigrateGetMaxSpeed(virDomainPtr dom, goto cleanup; priv = vm->privateData; + + if (virDomainMigrateGetMaxSpeedEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + *bandwidth = priv->migMaxBandwidth; ret = 0; @@ -11668,6 +12053,9 @@ qemuDomainSnapshotCreateXML(virDomainPtr domain, cfg = virQEMUDriverGetConfig(driver); + if (virDomainSnapshotCreateXMLEnsureACL(domain->conn, vm->def) < 0) + goto cleanup; + if (!(caps = virQEMUDriverGetCapabilities(driver, false))) goto cleanup; @@ -12010,6 +12398,9 @@ static int qemuDomainSnapshotListNames(virDomainPtr domain, char **names, if (!(vm = qemuDomObjFromDomain(domain))) goto cleanup; + if (virDomainSnapshotListNamesEnsureACL(domain->conn, vm->def) < 0) + goto cleanup; + n = virDomainSnapshotObjListGetNames(vm->snapshots, NULL, names, nameslen, flags); @@ -12031,6 +12422,9 @@ static int qemuDomainSnapshotNum(virDomainPtr domain, if (!(vm = qemuDomObjFromDomain(domain))) goto cleanup; + if (virDomainSnapshotNumEnsureACL(domain->conn, vm->def) < 0) + goto cleanup; + n = virDomainSnapshotObjListNum(vm->snapshots, NULL, flags); cleanup: @@ -12052,6 +12446,9 @@ qemuDomainListAllSnapshots(virDomainPtr domain, virDomainSnapshotPtr **snaps, if (!(vm = qemuDomObjFromDomain(domain))) goto cleanup; + if (virDomainListAllSnapshotsEnsureACL(domain->conn, vm->def) < 0) + goto cleanup; + n = virDomainListSnapshots(vm->snapshots, NULL, domain, snaps, flags); cleanup: @@ -12076,6 +12473,9 @@ qemuDomainSnapshotListChildrenNames(virDomainSnapshotPtr snapshot, if (!(vm = qemuDomObjFromSnapshot(snapshot))) goto cleanup; + if (virDomainSnapshotListChildrenNamesEnsureACL(snapshot->domain->conn, vm->def) < 0) + goto cleanup; + if (!(snap = qemuSnapObjFromSnapshot(vm, snapshot))) goto cleanup; @@ -12102,6 +12502,9 @@ qemuDomainSnapshotNumChildren(virDomainSnapshotPtr snapshot, if (!(vm = qemuDomObjFromSnapshot(snapshot))) goto cleanup; + if (virDomainSnapshotNumChildrenEnsureACL(snapshot->domain->conn, vm->def) < 0) + goto cleanup; + if (!(snap = qemuSnapObjFromSnapshot(vm, snapshot))) goto cleanup; @@ -12128,6 +12531,9 @@ qemuDomainSnapshotListAllChildren(virDomainSnapshotPtr snapshot, if (!(vm = qemuDomObjFromSnapshot(snapshot))) goto cleanup; + if (virDomainSnapshotListAllChildrenEnsureACL(snapshot->domain->conn, vm->def) < 0) + goto cleanup; + if (!(snap = qemuSnapObjFromSnapshot(vm, snapshot))) goto cleanup; @@ -12153,6 +12559,9 @@ static virDomainSnapshotPtr qemuDomainSnapshotLookupByName(virDomainPtr domain, if (!(vm = qemuDomObjFromDomain(domain))) goto cleanup; + if (virDomainSnapshotLookupByNameEnsureACL(domain->conn, vm->def) < 0) + goto cleanup; + if (!(snap = qemuSnapObjFromName(vm, name))) goto cleanup; @@ -12175,6 +12584,9 @@ static int qemuDomainHasCurrentSnapshot(virDomainPtr domain, if (!(vm = qemuDomObjFromDomain(domain))) goto cleanup; + if (virDomainHasCurrentSnapshotEnsureACL(domain->conn, vm->def) < 0) + goto cleanup; + ret = (vm->current_snapshot != NULL); cleanup: @@ -12196,6 +12608,9 @@ qemuDomainSnapshotGetParent(virDomainSnapshotPtr snapshot, if (!(vm = qemuDomObjFromSnapshot(snapshot))) goto cleanup; + if (virDomainSnapshotGetParentEnsureACL(snapshot->domain->conn, vm->def) < 0) + goto cleanup; + if (!(snap = qemuSnapObjFromSnapshot(vm, snapshot))) goto cleanup; @@ -12225,6 +12640,9 @@ static virDomainSnapshotPtr qemuDomainSnapshotCurrent(virDomainPtr domain, if (!(vm = qemuDomObjFromDomain(domain))) goto cleanup; + if (virDomainSnapshotCurrentEnsureACL(domain->conn, vm->def) < 0) + goto cleanup; + if (!vm->current_snapshot) { virReportError(VIR_ERR_NO_DOMAIN_SNAPSHOT, "%s", _("the domain does not have a current snapshot")); @@ -12252,6 +12670,9 @@ static char *qemuDomainSnapshotGetXMLDesc(virDomainSnapshotPtr snapshot, if (!(vm = qemuDomObjFromSnapshot(snapshot))) goto cleanup; + if (virDomainSnapshotGetXMLDescEnsureACL(snapshot->domain->conn, vm->def) < 0) + goto cleanup; + if (!(snap = qemuSnapObjFromSnapshot(vm, snapshot))) goto cleanup; @@ -12278,6 +12699,9 @@ qemuDomainSnapshotIsCurrent(virDomainSnapshotPtr snapshot, if (!(vm = qemuDomObjFromSnapshot(snapshot))) goto cleanup; + if (virDomainSnapshotIsCurrentEnsureACL(snapshot->domain->conn, vm->def) < 0) + goto cleanup; + if (!(snap = qemuSnapObjFromSnapshot(vm, snapshot))) goto cleanup; @@ -12304,6 +12728,9 @@ qemuDomainSnapshotHasMetadata(virDomainSnapshotPtr snapshot, if (!(vm = qemuDomObjFromSnapshot(snapshot))) goto cleanup; + if (virDomainSnapshotHasMetadataEnsureACL(snapshot->domain->conn, vm->def) < 0) + goto cleanup; + if (!(snap = qemuSnapObjFromSnapshot(vm, snapshot))) goto cleanup; @@ -12368,6 +12795,9 @@ static int qemuDomainRevertToSnapshot(virDomainSnapshotPtr snapshot, cfg = virQEMUDriverGetConfig(driver); + if (virDomainRevertToSnapshotEnsureACL(snapshot->domain->conn, vm->def) < 0) + goto cleanup; + if (!(caps = virQEMUDriverGetCapabilities(driver, false))) goto cleanup; @@ -12730,6 +13160,10 @@ static int qemuDomainSnapshotDelete(virDomainSnapshotPtr snapshot, return -1; cfg = virQEMUDriverGetConfig(driver); + + if (virDomainSnapshotDeleteEnsureACL(snapshot->domain->conn, vm->def) < 0) + goto cleanup; + if (!(snap = qemuSnapObjFromSnapshot(vm, snapshot))) goto cleanup; @@ -12829,6 +13263,9 @@ static int qemuDomainQemuMonitorCommand(virDomainPtr domain, const char *cmd, if (!(vm = qemuDomObjFromDomain(domain))) goto cleanup; + if (virDomainQemuMonitorCommandEnsureACL(domain->conn, vm->def) < 0) + goto cleanup; + if (!virDomainObjIsActive(vm)) { virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("domain is not running")); @@ -12890,6 +13327,9 @@ static virDomainPtr qemuDomainQemuAttach(virConnectPtr conn, &pidfile, &monConfig, &monJSON))) goto cleanup; + if (virDomainQemuAttachEnsureACL(conn, def) < 0) + goto cleanup; + if (!monConfig) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("No monitor connection for pid %u"), pid_value); @@ -12978,6 +13418,9 @@ qemuDomainOpenConsole(virDomainPtr dom, if (!(vm = qemuDomObjFromDomain(dom))) goto cleanup; + if (virDomainOpenConsoleEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (!virDomainObjIsActive(vm)) { virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("domain is not running")); @@ -13056,6 +13499,9 @@ qemuDomainOpenChannel(virDomainPtr dom, if (!(vm = qemuDomObjFromDomain(dom))) goto cleanup; + if (virDomainOpenChannelEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (!virDomainObjIsActive(vm)) { virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("domain is not running")); @@ -13292,12 +13738,13 @@ cleanup: } static int -qemuDomainBlockJobImpl(virDomainPtr dom, const char *path, const char *base, +qemuDomainBlockJobImpl(virDomainObjPtr vm, + virConnectPtr conn, + const char *path, const char *base, unsigned long bandwidth, virDomainBlockJobInfoPtr info, int mode, unsigned int flags) { - virQEMUDriverPtr driver = dom->conn->privateData; - virDomainObjPtr vm = NULL; + virQEMUDriverPtr driver = conn->privateData; qemuDomainObjPrivatePtr priv; char *device = NULL; int ret = -1; @@ -13306,9 +13753,6 @@ qemuDomainBlockJobImpl(virDomainPtr dom, const char *path, const char *base, int idx; virDomainDiskDefPtr disk; - if (!(vm = qemuDomObjFromDomain(dom))) - return -1; - if (!virDomainObjIsActive(vm)) { virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("domain is not running")); @@ -13365,7 +13809,7 @@ qemuDomainBlockJobImpl(virDomainPtr dom, const char *path, const char *base, if (disk->mirror && mode == BLOCK_JOB_ABORT && (flags & VIR_DOMAIN_BLOCK_JOB_ABORT_PIVOT)) { - ret = qemuDomainBlockPivot(dom->conn, driver, vm, device, disk); + ret = qemuDomainBlockPivot(conn, driver, vm, device, disk); goto endjob; } @@ -13455,9 +13899,20 @@ cleanup: static int qemuDomainBlockJobAbort(virDomainPtr dom, const char *path, unsigned int flags) { + virDomainObjPtr vm; + virCheckFlags(VIR_DOMAIN_BLOCK_JOB_ABORT_ASYNC | VIR_DOMAIN_BLOCK_JOB_ABORT_PIVOT, -1); - return qemuDomainBlockJobImpl(dom, path, NULL, 0, NULL, BLOCK_JOB_ABORT, + + if (!(vm = qemuDomObjFromDomain(dom))) + return -1; + + if (virDomainBlockJobAbortEnsureACL(dom->conn, vm->def) < 0) { + virObjectUnlock(vm); + return -1; + } + + return qemuDomainBlockJobImpl(vm, dom->conn, path, NULL, 0, NULL, BLOCK_JOB_ABORT, flags); } @@ -13465,8 +13920,18 @@ static int qemuDomainGetBlockJobInfo(virDomainPtr dom, const char *path, virDomainBlockJobInfoPtr info, unsigned int flags) { + virDomainObjPtr vm; virCheckFlags(0, -1); - return qemuDomainBlockJobImpl(dom, path, NULL, 0, info, BLOCK_JOB_INFO, + + if (!(vm = qemuDomObjFromDomain(dom))) + return -1; + + if (virDomainGetBlockJobInfoEnsureACL(dom->conn, vm->def) < 0) { + virObjectUnlock(vm); + return -1; + } + + return qemuDomainBlockJobImpl(vm, dom->conn, path, NULL, 0, info, BLOCK_JOB_INFO, flags); } @@ -13474,18 +13939,29 @@ static int qemuDomainBlockJobSetSpeed(virDomainPtr dom, const char *path, unsigned long bandwidth, unsigned int flags) { + virDomainObjPtr vm; virCheckFlags(0, -1); - return qemuDomainBlockJobImpl(dom, path, NULL, bandwidth, NULL, + + if (!(vm = qemuDomObjFromDomain(dom))) + return -1; + + if (virDomainBlockJobSetSpeedEnsureACL(dom->conn, vm->def) < 0) { + virObjectUnlock(vm); + return -1; + } + + return qemuDomainBlockJobImpl(vm, dom->conn, path, NULL, bandwidth, NULL, BLOCK_JOB_SPEED, flags); } static int -qemuDomainBlockCopy(virDomainPtr dom, const char *path, +qemuDomainBlockCopy(virDomainObjPtr vm, + virConnectPtr conn, + const char *path, const char *dest, const char *format, unsigned long bandwidth, unsigned int flags) { - virQEMUDriverPtr driver = dom->conn->privateData; - virDomainObjPtr vm; + virQEMUDriverPtr driver = conn->privateData; qemuDomainObjPrivatePtr priv; char *device = NULL; virDomainDiskDefPtr disk; @@ -13500,10 +13976,9 @@ qemuDomainBlockCopy(virDomainPtr dom, const char *path, virCheckFlags(VIR_DOMAIN_BLOCK_REBASE_SHALLOW | VIR_DOMAIN_BLOCK_REBASE_REUSE_EXT, -1); - if (!(vm = qemuDomObjFromDomain(dom))) - goto cleanup; priv = vm->privateData; cfg = virQEMUDriverGetConfig(driver); + if (!virDomainObjIsActive(vm)) { virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("domain is not running")); @@ -13657,21 +14132,31 @@ static int qemuDomainBlockRebase(virDomainPtr dom, const char *path, const char *base, unsigned long bandwidth, unsigned int flags) { + virDomainObjPtr vm; + virCheckFlags(VIR_DOMAIN_BLOCK_REBASE_SHALLOW | VIR_DOMAIN_BLOCK_REBASE_REUSE_EXT | VIR_DOMAIN_BLOCK_REBASE_COPY | VIR_DOMAIN_BLOCK_REBASE_COPY_RAW, -1); + if (!(vm = qemuDomObjFromDomain(dom))) + return -1; + + if (virDomainBlockRebaseEnsureACL(dom->conn, vm->def) < 0) { + virObjectUnlock(vm); + return -1; + } + if (flags & VIR_DOMAIN_BLOCK_REBASE_COPY) { const char *format = NULL; if (flags & VIR_DOMAIN_BLOCK_REBASE_COPY_RAW) format = "raw"; flags &= ~(VIR_DOMAIN_BLOCK_REBASE_COPY | VIR_DOMAIN_BLOCK_REBASE_COPY_RAW); - return qemuDomainBlockCopy(dom, path, base, format, bandwidth, flags); + return qemuDomainBlockCopy(vm, dom->conn, path, base, format, bandwidth, flags); } - return qemuDomainBlockJobImpl(dom, path, base, bandwidth, NULL, + return qemuDomainBlockJobImpl(vm, dom->conn, path, base, bandwidth, NULL, BLOCK_JOB_PULL, flags); } @@ -13679,8 +14164,18 @@ static int qemuDomainBlockPull(virDomainPtr dom, const char *path, unsigned long bandwidth, unsigned int flags) { + virDomainObjPtr vm; virCheckFlags(0, -1); - return qemuDomainBlockJobImpl(dom, path, NULL, bandwidth, NULL, + + if (!(vm = qemuDomObjFromDomain(dom))) + return -1; + + if (virDomainBlockPullEnsureACL(dom->conn, vm->def) < 0) { + virObjectUnlock(vm); + return -1; + } + + return qemuDomainBlockJobImpl(vm, dom->conn, path, NULL, bandwidth, NULL, BLOCK_JOB_PULL, flags); } @@ -13709,6 +14204,9 @@ qemuDomainBlockCommit(virDomainPtr dom, const char *path, const char *base, goto cleanup; priv = vm->privateData; + if (virDomainBlockCommitEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0) goto cleanup; @@ -13838,6 +14336,9 @@ qemuDomainOpenGraphics(virDomainPtr dom, if (!(vm = qemuDomObjFromDomain(dom))) return -1; + if (virDomainOpenGraphicsEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (!virDomainObjIsActive(vm)) { virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("domain is not running")); @@ -13930,6 +14431,9 @@ qemuDomainSetBlockIoTune(virDomainPtr dom, priv = vm->privateData; cfg = virQEMUDriverGetConfig(driver); + if (virDomainSetBlockIoTuneEnsureACL(dom->conn, vm->def, flags) < 0) + goto cleanup; + if (!(caps = virQEMUDriverGetCapabilities(driver, false))) goto cleanup; @@ -14083,6 +14587,9 @@ qemuDomainGetBlockIoTune(virDomainPtr dom, if (!(vm = qemuDomObjFromDomain(dom))) return -1; + if (virDomainGetBlockIoTuneEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (!(caps = virQEMUDriverGetCapabilities(driver, false))) goto cleanup; @@ -14210,6 +14717,9 @@ qemuDomainGetDiskErrors(virDomainPtr dom, priv = vm->privateData; + if (virDomainGetDiskErrorsEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0) goto cleanup; @@ -14288,6 +14798,9 @@ qemuDomainSetMetadata(virDomainPtr dom, cfg = virQEMUDriverGetConfig(driver); + if (virDomainSetMetadataEnsureACL(dom->conn, vm->def, flags) < 0) + goto cleanup; + if (!(caps = virQEMUDriverGetCapabilities(driver, false))) goto cleanup; @@ -14385,6 +14898,9 @@ qemuDomainGetMetadata(virDomainPtr dom, if (!(vm = qemuDomObjFromDomain(dom))) goto cleanup; + if (virDomainGetMetadataEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (!(caps = virQEMUDriverGetCapabilities(driver, false))) goto cleanup; @@ -14668,6 +15184,9 @@ qemuDomainGetCPUStats(virDomainPtr domain, priv = vm->privateData; + if (virDomainGetCPUStatsEnsureACL(domain->conn, vm->def) < 0) + goto cleanup; + isActive = virDomainObjIsActive(vm); if (!isActive) { virReportError(VIR_ERR_OPERATION_INVALID, "%s", @@ -14725,6 +15244,9 @@ qemuDomainPMSuspendForDuration(virDomainPtr dom, priv = vm->privateData; + if (virDomainPMSuspendForDurationEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (!virDomainObjIsActive(vm)) { virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("domain is not running")); @@ -14807,6 +15329,9 @@ qemuDomainPMWakeup(virDomainPtr dom, if (!(vm = qemuDomObjFromDomain(dom))) goto cleanup; + if (virDomainPMWakeupEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0) goto cleanup; @@ -14849,8 +15374,12 @@ qemuConnectListAllDomains(virConnectPtr conn, virCheckFlags(VIR_CONNECT_LIST_DOMAINS_FILTERS_ALL, -1); + if (virConnectListAllDomainsEnsureACL(conn) < 0) + goto cleanup; + ret = virDomainObjListExport(driver->domains, conn, domains, flags); +cleanup: return ret; } @@ -14873,6 +15402,9 @@ qemuDomainQemuAgentCommand(virDomainPtr domain, priv = vm->privateData; + if (virDomainQemuAgentCommandEnsureACL(domain->conn, vm->def) < 0) + goto cleanup; + if (!virDomainObjIsActive(vm)) { virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("domain is not running")); @@ -14946,6 +15478,9 @@ qemuDomainFSTrim(virDomainPtr dom, priv = vm->privateData; + if (virDomainFSTrimEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (!virDomainObjIsActive(vm)) { virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("domain is not running")); @@ -14990,88 +15525,115 @@ cleanup: static int -qemuNodeGetInfo(virConnectPtr conn ATTRIBUTE_UNUSED, +qemuNodeGetInfo(virConnectPtr conn, virNodeInfoPtr nodeinfo) { + if (virNodeGetInfoEnsureACL(conn) < 0) + return -1; + return nodeGetInfo(nodeinfo); } static int -qemuNodeGetCPUStats(virConnectPtr conn ATTRIBUTE_UNUSED, +qemuNodeGetCPUStats(virConnectPtr conn, int cpuNum, virNodeCPUStatsPtr params, int *nparams, unsigned int flags) { + if (virNodeGetCPUStatsEnsureACL(conn) < 0) + return -1; + return nodeGetCPUStats(cpuNum, params, nparams, flags); } static int -qemuNodeGetMemoryStats(virConnectPtr conn ATTRIBUTE_UNUSED, +qemuNodeGetMemoryStats(virConnectPtr conn, int cellNum, virNodeMemoryStatsPtr params, int *nparams, unsigned int flags) { + if (virNodeGetMemoryStatsEnsureACL(conn) < 0) + return -1; + return nodeGetMemoryStats(cellNum, params, nparams, flags); } static int -qemuNodeGetCellsFreeMemory(virConnectPtr conn ATTRIBUTE_UNUSED, +qemuNodeGetCellsFreeMemory(virConnectPtr conn, unsigned long long *freeMems, int startCell, int maxCells) { + if (virNodeGetCellsFreeMemoryEnsureACL(conn) < 0) + return -1; + return nodeGetCellsFreeMemory(freeMems, startCell, maxCells); } static unsigned long long -qemuNodeGetFreeMemory(virConnectPtr conn ATTRIBUTE_UNUSED) +qemuNodeGetFreeMemory(virConnectPtr conn) { + if (virNodeGetFreeMemoryEnsureACL(conn) < 0) + return 0; + return nodeGetFreeMemory(); } static int -qemuNodeGetMemoryParameters(virConnectPtr conn ATTRIBUTE_UNUSED, +qemuNodeGetMemoryParameters(virConnectPtr conn, virTypedParameterPtr params, int *nparams, unsigned int flags) { + if (virNodeGetMemoryParametersEnsureACL(conn) < 0) + return -1; + return nodeGetMemoryParameters(params, nparams, flags); } static int -qemuNodeSetMemoryParameters(virConnectPtr conn ATTRIBUTE_UNUSED, +qemuNodeSetMemoryParameters(virConnectPtr conn, virTypedParameterPtr params, int nparams, unsigned int flags) { + if (virNodeSetMemoryParametersEnsureACL(conn) < 0) + return -1; + return nodeSetMemoryParameters(params, nparams, flags); } static int -qemuNodeGetCPUMap(virConnectPtr conn ATTRIBUTE_UNUSED, +qemuNodeGetCPUMap(virConnectPtr conn, unsigned char **cpumap, unsigned int *online, unsigned int flags) { + if (virNodeGetCPUMapEnsureACL(conn) < 0) + return -1; + return nodeGetCPUMap(cpumap, online, flags); } static int -qemuNodeSuspendForDuration(virConnectPtr conn ATTRIBUTE_UNUSED, +qemuNodeSuspendForDuration(virConnectPtr conn, unsigned int target, unsigned long long duration, unsigned int flags) { + if (virNodeSuspendForDurationEnsureACL(conn) < 0) + return -1; + return nodeSuspendForDuration(target, duration, flags); } -- 1.8.1.4

From: "Daniel P. Berrange" <berrange@redhat.com> Insert calls to the ACL checking APIs in all LXC driver entrypoints. Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- src/lxc/lxc_driver.c | 219 ++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 207 insertions(+), 12 deletions(-) diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index 997f81d..e590612 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -68,6 +68,8 @@ #include "virtypedparam.h" #include "viruri.h" #include "virstring.h" +#include "access/viraccessapicheck.h" +#include "access/viraccessapichecklxc.h" #define VIR_FROM_THIS VIR_FROM_LXC @@ -148,6 +150,9 @@ static virDrvOpenStatus lxcConnectOpen(virConnectPtr conn, } } + if (virConnectOpenEnsureACL(conn) < 0) + return VIR_DRV_OPEN_ERROR; + conn->privateData = lxc_driver; return VIR_DRV_OPEN_SUCCESS; @@ -190,6 +195,9 @@ static char *lxcConnectGetCapabilities(virConnectPtr conn) { virLXCDriverPtr driver = conn->privateData; char *xml; + if (virConnectGetCapabilitiesEnsureACL(conn) < 0) + return NULL; + lxcDriverLock(driver); if ((xml = virCapabilitiesFormatXML(driver->caps)) == NULL) virReportOOMError(); @@ -216,6 +224,9 @@ static virDomainPtr lxcDomainLookupByID(virConnectPtr conn, goto cleanup; } + if (virDomainLookupByIDEnsureACL(conn, vm->def) < 0) + goto cleanup; + dom = virGetDomain(conn, vm->def->name, vm->def->uuid); if (dom) dom->id = vm->def->id; @@ -245,6 +256,9 @@ static virDomainPtr lxcDomainLookupByUUID(virConnectPtr conn, goto cleanup; } + if (virDomainLookupByUUIDEnsureACL(conn, vm->def) < 0) + goto cleanup; + dom = virGetDomain(conn, vm->def->name, vm->def->uuid); if (dom) dom->id = vm->def->id; @@ -271,6 +285,9 @@ static virDomainPtr lxcDomainLookupByName(virConnectPtr conn, goto cleanup; } + if (virDomainLookupByNameEnsureACL(conn, vm->def) < 0) + goto cleanup; + dom = virGetDomain(conn, vm->def->name, vm->def->uuid); if (dom) dom->id = vm->def->id; @@ -298,6 +315,10 @@ static int lxcDomainIsActive(virDomainPtr dom) _("No domain with matching uuid '%s'"), uuidstr); goto cleanup; } + + if (virDomainIsActiveEnsureACL(dom->conn, obj->def) < 0) + goto cleanup; + ret = virDomainObjIsActive(obj); cleanup: @@ -323,6 +344,10 @@ static int lxcDomainIsPersistent(virDomainPtr dom) _("No domain with matching uuid '%s'"), uuidstr); goto cleanup; } + + if (virDomainIsPersistentEnsureACL(dom->conn, obj->def) < 0) + goto cleanup; + ret = obj->persistent; cleanup: @@ -347,6 +372,10 @@ static int lxcDomainIsUpdated(virDomainPtr dom) _("No domain with matching uuid '%s'"), uuidstr); goto cleanup; } + + if (virDomainIsUpdatedEnsureACL(dom->conn, obj->def) < 0) + goto cleanup; + ret = obj->updated; cleanup: @@ -359,6 +388,9 @@ static int lxcConnectListDomains(virConnectPtr conn, int *ids, int nids) { virLXCDriverPtr driver = conn->privateData; int n; + if (virConnectListDomainsEnsureACL(conn) < 0) + return -1; + lxcDriverLock(driver); n = virDomainObjListGetActiveIDs(driver->domains, ids, nids); lxcDriverUnlock(driver); @@ -370,6 +402,9 @@ static int lxcConnectNumOfDomains(virConnectPtr conn) { virLXCDriverPtr driver = conn->privateData; int n; + if (virConnectNumOfDomainsEnsureACL(conn) < 0) + return -1; + lxcDriverLock(driver); n = virDomainObjListNumOfDomains(driver->domains, 1); lxcDriverUnlock(driver); @@ -382,6 +417,9 @@ static int lxcConnectListDefinedDomains(virConnectPtr conn, virLXCDriverPtr driver = conn->privateData; int n; + if (virConnectListDefinedDomainsEnsureACL(conn) < 0) + return -1; + lxcDriverLock(driver); n = virDomainObjListGetInactiveNames(driver->domains, names, nnames); lxcDriverUnlock(driver); @@ -394,6 +432,9 @@ static int lxcConnectNumOfDefinedDomains(virConnectPtr conn) { virLXCDriverPtr driver = conn->privateData; int n; + if (virConnectNumOfDefinedDomainsEnsureACL(conn) < 0) + return -1; + lxcDriverLock(driver); n = virDomainObjListNumOfDomains(driver->domains, 0); lxcDriverUnlock(driver); @@ -418,6 +459,9 @@ static virDomainPtr lxcDomainDefineXML(virConnectPtr conn, const char *xml) VIR_DOMAIN_XML_INACTIVE))) goto cleanup; + if (virDomainDefineXMLEnsureACL(conn, def) < 0) + goto cleanup; + if (virSecurityManagerVerify(driver->securityManager, def) < 0) goto cleanup; @@ -482,6 +526,9 @@ static int lxcDomainUndefineFlags(virDomainPtr dom, goto cleanup; } + if (virDomainUndefineFlagsEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (!vm->persistent) { virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Cannot undefine transient domain")); @@ -541,6 +588,9 @@ static int lxcDomainGetInfo(virDomainPtr dom, priv = vm->privateData; + if (virDomainGetInfoEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + info->state = virDomainObjGetState(vm, NULL); if (!virDomainObjIsActive(vm)) { @@ -599,6 +649,9 @@ lxcDomainGetState(virDomainPtr dom, goto cleanup; } + if (virDomainGetStateEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + *state = virDomainObjGetState(vm, reason); ret = 0; @@ -626,7 +679,11 @@ static char *lxcDomainGetOSType(virDomainPtr dom) goto cleanup; } - ignore_value(VIR_STRDUP(ret, vm->def->os.type)); + if (virDomainGetOSTypeEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + + if (VIR_STRDUP(ret, vm->def->os.type) < 0) + goto cleanup; cleanup: if (vm) @@ -654,6 +711,9 @@ lxcDomainGetMaxMemory(virDomainPtr dom) goto cleanup; } + if (virDomainGetMaxMemoryEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + ret = vm->def->mem.max_balloon; cleanup: @@ -679,6 +739,9 @@ static int lxcDomainSetMaxMemory(virDomainPtr dom, unsigned long newmax) { goto cleanup; } + if (virDomainSetMaxMemoryEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (newmax < vm->def->mem.cur_balloon) { virReportError(VIR_ERR_INVALID_ARG, "%s", _("Cannot set max memory lower than current memory")); @@ -712,6 +775,9 @@ static int lxcDomainSetMemory(virDomainPtr dom, unsigned long newmem) { } priv = vm->privateData; + if (virDomainSetMemoryEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (newmem > vm->def->mem.max_balloon) { virReportError(VIR_ERR_INVALID_ARG, "%s", _("Cannot set memory higher than max memory")); @@ -774,6 +840,9 @@ lxcDomainSetMemoryParameters(virDomainPtr dom, } priv = vm->privateData; + if (virDomainSetMemoryParametersEnsureACL(dom->conn, vm->def, flags) < 0) + goto cleanup; + ret = 0; for (i = 0; i < nparams; i++) { virTypedParameterPtr param = ¶ms[i]; @@ -837,6 +906,9 @@ lxcDomainGetMemoryParameters(virDomainPtr dom, } priv = vm->privateData; + if (virDomainGetMemoryParametersEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if ((*nparams) == 0) { /* Current number of memory parameters supported by cgroups */ *nparams = LXC_NB_MEM_PARAM; @@ -923,6 +995,9 @@ static char *lxcDomainGetXMLDesc(virDomainPtr dom, goto cleanup; } + if (virDomainGetXMLDescEnsureACL(dom->conn, vm->def, flags) < 0) + goto cleanup; + ret = virDomainDefFormat((flags & VIR_DOMAIN_XML_INACTIVE) && vm->newDef ? vm->newDef : vm->def, flags); @@ -961,6 +1036,9 @@ static int lxcDomainCreateWithFlags(virDomainPtr dom, unsigned int flags) goto cleanup; } + if (virDomainCreateWithFlagsEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if ((vm->def->nets != NULL) && !(driver->have_netns)) { virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("System lacks NETNS support")); @@ -1036,6 +1114,9 @@ lxcDomainCreateXML(virConnectPtr conn, VIR_DOMAIN_XML_INACTIVE))) goto cleanup; + if (virDomainCreateXMLEnsureACL(conn, def) < 0) + goto cleanup; + if (virSecurityManagerVerify(driver->securityManager, def) < 0) goto cleanup; @@ -1101,6 +1182,9 @@ static int lxcDomainGetSecurityLabel(virDomainPtr dom, virSecurityLabelPtr secla goto cleanup; } + if (virDomainGetSecurityLabelEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (!virDomainVirtTypeToString(vm->def->virtType)) { virReportError(VIR_ERR_INTERNAL_ERROR, _("unknown virt type in domain definition '%d'"), @@ -1157,6 +1241,9 @@ static int lxcNodeGetSecurityModel(virConnectPtr conn, lxcDriverLock(driver); memset(secmodel, 0, sizeof(*secmodel)); + if (virNodeGetSecurityModelEnsureACL(conn) < 0) + goto cleanup; + /* we treat no driver as success, but simply return no data in *secmodel */ if (driver->caps->host.nsecModels == 0 || driver->caps->host.secModels[0].model == NULL) @@ -1195,6 +1282,9 @@ lxcConnectDomainEventRegister(virConnectPtr conn, virLXCDriverPtr driver = conn->privateData; int ret; + if (virConnectDomainEventRegisterEnsureACL(conn) < 0) + return -1; + lxcDriverLock(driver); ret = virDomainEventStateRegister(conn, driver->domainEventState, @@ -1212,6 +1302,9 @@ lxcConnectDomainEventDeregister(virConnectPtr conn, virLXCDriverPtr driver = conn->privateData; int ret; + if (virConnectDomainEventDeregisterEnsureACL(conn) < 0) + return -1; + lxcDriverLock(driver); ret = virDomainEventStateDeregister(conn, driver->domainEventState, @@ -1233,6 +1326,9 @@ lxcConnectDomainEventRegisterAny(virConnectPtr conn, virLXCDriverPtr driver = conn->privateData; int ret; + if (virConnectDomainEventRegisterAnyEnsureACL(conn) < 0) + return -1; + lxcDriverLock(driver); if (virDomainEventStateRegisterID(conn, driver->domainEventState, @@ -1252,6 +1348,9 @@ lxcConnectDomainEventDeregisterAny(virConnectPtr conn, virLXCDriverPtr driver = conn->privateData; int ret; + if (virConnectDomainEventDeregisterAnyEnsureACL(conn) < 0) + return -1; + lxcDriverLock(driver); ret = virDomainEventStateDeregisterID(conn, driver->domainEventState, @@ -1293,6 +1392,9 @@ lxcDomainDestroyFlags(virDomainPtr dom, goto cleanup; } + if (virDomainDestroyFlagsEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (!virDomainObjIsActive(vm)) { virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not running")); @@ -1544,12 +1646,15 @@ static int lxcStateCleanup(void) } -static int lxcConnectGetVersion(virConnectPtr conn ATTRIBUTE_UNUSED, unsigned long *version) +static int lxcConnectGetVersion(virConnectPtr conn, unsigned long *version) { struct utsname ver; uname(&ver); + if (virConnectGetVersionEnsureACL(conn) < 0) + return -1; + if (virParseVersionString(ver.release, version, true) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Unknown release: %s"), ver.release); return -1; @@ -1559,8 +1664,11 @@ static int lxcConnectGetVersion(virConnectPtr conn ATTRIBUTE_UNUSED, unsigned lo } -static char *lxcConnectGetHostname(virConnectPtr conn ATTRIBUTE_UNUSED) +static char *lxcConnectGetHostname(virConnectPtr conn) { + if (virConnectGetHostnameEnsureACL(conn) < 0) + return NULL; + return virGetHostname(); } @@ -1617,6 +1725,9 @@ static char *lxcDomainGetSchedulerType(virDomainPtr dom, } priv = vm->privateData; + if (virDomainGetSchedulerTypeEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (!virCgroupHasController(priv->cgroup, VIR_CGROUP_CONTROLLER_CPU)) { virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("cgroup CPU controller is not mounted")); @@ -1753,6 +1864,9 @@ lxcDomainSetSchedulerParametersFlags(virDomainPtr dom, } priv = vm->privateData; + if (virDomainSetSchedulerParametersFlagsEnsureACL(dom->conn, vm->def, flags) < 0) + goto cleanup; + if (virDomainLiveConfigHelperMethod(driver->caps, driver->xmlopt, vm, &flags, &vmdef) < 0) goto cleanup; @@ -1882,6 +1996,9 @@ lxcDomainGetSchedulerParametersFlags(virDomainPtr dom, } priv = vm->privateData; + if (virDomainGetSchedulerParametersFlagsEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (*nparams > 1) { rc = lxcGetCpuBWStatus(priv->cgroup); if (rc < 0) @@ -1996,6 +2113,9 @@ lxcDomainSetBlkioParameters(virDomainPtr dom, } priv = vm->privateData; + if (virDomainSetBlkioParametersEnsureACL(dom->conn, vm->def, flags) < 0) + goto cleanup; + if (virDomainLiveConfigHelperMethod(driver->caps, driver->xmlopt, vm, &flags, &persistentDef) < 0) goto cleanup; @@ -2088,6 +2208,9 @@ lxcDomainGetBlkioParameters(virDomainPtr dom, } priv = vm->privateData; + if (virDomainGetBlkioParametersEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if ((*nparams) == 0) { /* Current number of blkio parameters supported by cgroups */ *nparams = LXC_NB_BLKIO_PARAM; @@ -2184,6 +2307,9 @@ lxcDomainInterfaceStats(virDomainPtr dom, goto cleanup; } + if (virDomainInterfaceStatsEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (!virDomainObjIsActive(vm)) { virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not running")); @@ -2239,6 +2365,9 @@ static int lxcDomainGetAutostart(virDomainPtr dom, goto cleanup; } + if (virDomainGetAutostartEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + *autostart = vm->autostart; ret = 0; @@ -2266,6 +2395,9 @@ static int lxcDomainSetAutostart(virDomainPtr dom, goto cleanup; } + if (virDomainSetAutostartEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (!vm->persistent) { virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Cannot set autostart for transient domain")); @@ -2427,6 +2559,9 @@ static int lxcDomainSuspend(virDomainPtr dom) goto cleanup; } + if (virDomainSuspendEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (!virDomainObjIsActive(vm)) { virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not running")); @@ -2480,6 +2615,9 @@ static int lxcDomainResume(virDomainPtr dom) priv = vm->privateData; + if (virDomainResumeEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (!virDomainObjIsActive(vm)) { virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not running")); @@ -2537,6 +2675,9 @@ lxcDomainOpenConsole(virDomainPtr dom, goto cleanup; } + if (virDomainOpenConsoleEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (!virDomainObjIsActive(vm)) { virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("domain is not running")); @@ -2617,6 +2758,9 @@ lxcDomainSendProcessSignal(virDomainPtr dom, } priv = vm->privateData; + if (virDomainSendProcessSignalEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (!virDomainObjIsActive(vm)) { virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("domain is not running")); @@ -2672,6 +2816,9 @@ lxcConnectListAllDomains(virConnectPtr conn, virCheckFlags(VIR_CONNECT_LIST_DOMAINS_FILTERS_ALL, -1); + if (virConnectListAllDomainsEnsureACL(conn) < 0) + return -1; + lxcDriverLock(driver); ret = virDomainObjListExport(driver->domains, conn, domains, flags); lxcDriverUnlock(driver); @@ -2708,6 +2855,9 @@ lxcDomainShutdownFlags(virDomainPtr dom, priv = vm->privateData; + if (virDomainShutdownFlagsEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (!virDomainObjIsActive(vm)) { virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not running")); @@ -2797,6 +2947,9 @@ lxcDomainReboot(virDomainPtr dom, priv = vm->privateData; + if (virDomainRebootEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (!virDomainObjIsActive(vm)) { virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not running")); @@ -4153,6 +4306,9 @@ static int lxcDomainAttachDeviceFlags(virDomainPtr dom, goto cleanup; } + if (virDomainAttachDeviceFlagsEnsureACL(dom->conn, vm->def, flags) < 0) + goto cleanup; + if (virDomainObjIsActive(vm)) { if (affect == VIR_DOMAIN_AFFECT_CURRENT) flags |= VIR_DOMAIN_AFFECT_LIVE; @@ -4278,6 +4434,9 @@ static int lxcDomainUpdateDeviceFlags(virDomainPtr dom, goto cleanup; } + if (virDomainUpdateDeviceFlagsEnsureACL(dom->conn, vm->def, flags) < 0) + goto cleanup; + if (virDomainObjIsActive(vm)) { if (affect == VIR_DOMAIN_AFFECT_CURRENT) flags |= VIR_DOMAIN_AFFECT_LIVE; @@ -4387,6 +4546,9 @@ static int lxcDomainDetachDeviceFlags(virDomainPtr dom, goto cleanup; } + if (virDomainDetachDeviceFlagsEnsureACL(dom->conn, vm->def, flags) < 0) + goto cleanup; + if (virDomainObjIsActive(vm)) { if (affect == VIR_DOMAIN_AFFECT_CURRENT) flags |= VIR_DOMAIN_AFFECT_LIVE; @@ -4510,6 +4672,9 @@ static int lxcDomainLxcOpenNamespace(virDomainPtr dom, } priv = vm->privateData; + if (virDomainLxcOpenNamespaceEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (!virDomainObjIsActive(vm)) { virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not running")); @@ -4541,6 +4706,9 @@ lxcConnectGetSysinfo(virConnectPtr conn, unsigned int flags) virCheckFlags(0, NULL); + if (virConnectGetSysinfoEnsureACL(conn) < 0) + return NULL; + if (!driver->hostsysinfo) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("Host SMBIOS information is not available")); @@ -4558,88 +4726,115 @@ lxcConnectGetSysinfo(virConnectPtr conn, unsigned int flags) static int -lxcNodeGetInfo(virConnectPtr conn ATTRIBUTE_UNUSED, +lxcNodeGetInfo(virConnectPtr conn, virNodeInfoPtr nodeinfo) { + if (virNodeGetInfoEnsureACL(conn) < 0) + return -1; + return nodeGetInfo(nodeinfo); } static int -lxcNodeGetCPUStats(virConnectPtr conn ATTRIBUTE_UNUSED, +lxcNodeGetCPUStats(virConnectPtr conn, int cpuNum, virNodeCPUStatsPtr params, int *nparams, unsigned int flags) { + if (virNodeGetCPUStatsEnsureACL(conn) < 0) + return -1; + return nodeGetCPUStats(cpuNum, params, nparams, flags); } static int -lxcNodeGetMemoryStats(virConnectPtr conn ATTRIBUTE_UNUSED, +lxcNodeGetMemoryStats(virConnectPtr conn, int cellNum, virNodeMemoryStatsPtr params, int *nparams, unsigned int flags) { + if (virNodeGetMemoryStatsEnsureACL(conn) < 0) + return -1; + return nodeGetMemoryStats(cellNum, params, nparams, flags); } static int -lxcNodeGetCellsFreeMemory(virConnectPtr conn ATTRIBUTE_UNUSED, +lxcNodeGetCellsFreeMemory(virConnectPtr conn, unsigned long long *freeMems, int startCell, int maxCells) { + if (virNodeGetCellsFreeMemoryEnsureACL(conn) < 0) + return -1; + return nodeGetCellsFreeMemory(freeMems, startCell, maxCells); } static unsigned long long -lxcNodeGetFreeMemory(virConnectPtr conn ATTRIBUTE_UNUSED) +lxcNodeGetFreeMemory(virConnectPtr conn) { + if (virNodeGetFreeMemoryEnsureACL(conn) < 0) + return 0; + return nodeGetFreeMemory(); } static int -lxcNodeGetMemoryParameters(virConnectPtr conn ATTRIBUTE_UNUSED, +lxcNodeGetMemoryParameters(virConnectPtr conn, virTypedParameterPtr params, int *nparams, unsigned int flags) { + if (virNodeGetMemoryParametersEnsureACL(conn) < 0) + return -1; + return nodeGetMemoryParameters(params, nparams, flags); } static int -lxcNodeSetMemoryParameters(virConnectPtr conn ATTRIBUTE_UNUSED, +lxcNodeSetMemoryParameters(virConnectPtr conn, virTypedParameterPtr params, int nparams, unsigned int flags) { + if (virNodeSetMemoryParametersEnsureACL(conn) < 0) + return -1; + return nodeSetMemoryParameters(params, nparams, flags); } static int -lxcNodeGetCPUMap(virConnectPtr conn ATTRIBUTE_UNUSED, +lxcNodeGetCPUMap(virConnectPtr conn, unsigned char **cpumap, unsigned int *online, unsigned int flags) { + if (virNodeGetCPUMapEnsureACL(conn) < 0) + return -1; + return nodeGetCPUMap(cpumap, online, flags); } static int -lxcNodeSuspendForDuration(virConnectPtr conn ATTRIBUTE_UNUSED, +lxcNodeSuspendForDuration(virConnectPtr conn, unsigned int target, unsigned long long duration, unsigned int flags) { + if (virNodeSuspendForDurationEnsureACL(conn) < 0) + return -1; + return nodeSuspendForDuration(target, duration, flags); } -- 1.8.1.4

From: "Daniel P. Berrange" <berrange@redhat.com> Insert calls to the ACL checking APIs in all UML driver entrypoints. Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- src/uml/uml_driver.c | 174 +++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 162 insertions(+), 12 deletions(-) diff --git a/src/uml/uml_driver.c b/src/uml/uml_driver.c index 321be0f..a3b8706 100644 --- a/src/uml/uml_driver.c +++ b/src/uml/uml_driver.c @@ -65,6 +65,7 @@ #include "virprocess.h" #include "viruri.h" #include "virstring.h" +#include "access/viraccessapicheck.h" #define VIR_FROM_THIS VIR_FROM_UML @@ -1235,6 +1236,9 @@ static virDrvOpenStatus umlConnectOpen(virConnectPtr conn, } } + if (virConnectOpenEnsureACL(conn) < 0) + return VIR_DRV_OPEN_ERROR; + conn->privateData = uml_driver; return VIR_DRV_OPEN_SUCCESS; @@ -1252,7 +1256,10 @@ static int umlConnectClose(virConnectPtr conn) { return 0; } -static const char *umlConnectGetType(virConnectPtr conn ATTRIBUTE_UNUSED) { +static const char *umlConnectGetType(virConnectPtr conn) { + if (virConnectGetTypeEnsureACL(conn) < 0) + return NULL; + return "UML"; } @@ -1281,6 +1288,9 @@ static char *umlConnectGetCapabilities(virConnectPtr conn) { struct uml_driver *driver = (struct uml_driver *)conn->privateData; char *xml; + if (virConnectGetCapabilitiesEnsureACL(conn) < 0) + return NULL; + umlDriverLock(driver); if ((xml = virCapabilitiesFormatXML(driver->caps)) == NULL) virReportOOMError(); @@ -1346,6 +1356,9 @@ static virDomainPtr umlDomainLookupByID(virConnectPtr conn, goto cleanup; } + if (virDomainLookupByIDEnsureACL(conn, vm->def) < 0) + goto cleanup; + dom = virGetDomain(conn, vm->def->name, vm->def->uuid); if (dom) dom->id = vm->def->id; @@ -1370,6 +1383,9 @@ static virDomainPtr umlDomainLookupByUUID(virConnectPtr conn, goto cleanup; } + if (virDomainLookupByUUIDEnsureACL(conn, vm->def) < 0) + goto cleanup; + dom = virGetDomain(conn, vm->def->name, vm->def->uuid); if (dom) dom->id = vm->def->id; @@ -1394,6 +1410,9 @@ static virDomainPtr umlDomainLookupByName(virConnectPtr conn, goto cleanup; } + if (virDomainLookupByNameEnsureACL(conn, vm->def) < 0) + goto cleanup; + dom = virGetDomain(conn, vm->def->name, vm->def->uuid); if (dom) dom->id = vm->def->id; @@ -1417,6 +1436,10 @@ static int umlDomainIsActive(virDomainPtr dom) virReportError(VIR_ERR_NO_DOMAIN, NULL); goto cleanup; } + + if (virDomainIsActiveEnsureACL(dom->conn, obj->def) < 0) + goto cleanup; + ret = virDomainObjIsActive(obj); cleanup: @@ -1439,6 +1462,10 @@ static int umlDomainIsPersistent(virDomainPtr dom) virReportError(VIR_ERR_NO_DOMAIN, NULL); goto cleanup; } + + if (virDomainIsPersistentEnsureACL(dom->conn, obj->def) < 0) + goto cleanup; + ret = obj->persistent; cleanup: @@ -1460,6 +1487,10 @@ static int umlDomainIsUpdated(virDomainPtr dom) virReportError(VIR_ERR_NO_DOMAIN, NULL); goto cleanup; } + + if (virDomainIsUpdatedEnsureACL(dom->conn, obj->def) < 0) + goto cleanup; + ret = obj->updated; cleanup: @@ -1473,6 +1504,9 @@ static int umlConnectGetVersion(virConnectPtr conn, unsigned long *version) { struct utsname ut; int ret = -1; + if (virConnectGetVersionEnsureACL(conn) < 0) + return -1; + umlDriverLock(driver); if (driver->umlVersion == 0) { @@ -1494,8 +1528,11 @@ cleanup: } -static char *umlConnectGetHostname(virConnectPtr conn ATTRIBUTE_UNUSED) +static char *umlConnectGetHostname(virConnectPtr conn) { + if (virConnectGetHostnameEnsureACL(conn) < 0) + return NULL; + return virGetHostname(); } @@ -1504,6 +1541,9 @@ static int umlConnectListDomains(virConnectPtr conn, int *ids, int nids) { struct uml_driver *driver = conn->privateData; int n; + if (virConnectListDomainsEnsureACL(conn) < 0) + return -1; + umlDriverLock(driver); n = virDomainObjListGetActiveIDs(driver->domains, ids, nids); umlDriverUnlock(driver); @@ -1514,6 +1554,9 @@ static int umlConnectNumOfDomains(virConnectPtr conn) { struct uml_driver *driver = conn->privateData; int n; + if (virConnectNumOfDomainsEnsureACL(conn) < 0) + return -1; + umlDriverLock(driver); n = virDomainObjListNumOfDomains(driver->domains, 1); umlDriverUnlock(driver); @@ -1536,6 +1579,9 @@ static virDomainPtr umlDomainCreateXML(virConnectPtr conn, const char *xml, VIR_DOMAIN_XML_INACTIVE))) goto cleanup; + if (virDomainCreateXMLEnsureACL(conn, def) < 0) + goto cleanup; + if (!(vm = virDomainObjListAdd(driver->domains, def, driver->xmlopt, VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE, @@ -1588,6 +1634,9 @@ static int umlDomainShutdownFlags(virDomainPtr dom, goto cleanup; } + if (virDomainShutdownFlagsEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + #if 0 if (umlMonitorCommand(driver, vm, "system_powerdown", &info) < 0) { virReportError(VIR_ERR_OPERATION_FAILED, "%s", @@ -1629,6 +1678,9 @@ umlDomainDestroyFlags(virDomainPtr dom, goto cleanup; } + if (virDomainDestroyFlagsEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + umlShutdownVMDaemon(driver, vm, VIR_DOMAIN_SHUTOFF_DESTROYED); virDomainAuditStop(vm, "destroyed"); event = virDomainEventNewFromObj(vm, @@ -1671,7 +1723,11 @@ static char *umlDomainGetOSType(virDomainPtr dom) { goto cleanup; } - ignore_value(VIR_STRDUP(type, vm->def->os.type)); + if (virDomainGetOSTypeEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + + if (VIR_STRDUP(type, vm->def->os.type) < 0) + goto cleanup; cleanup: if (vm) @@ -1699,6 +1755,10 @@ umlDomainGetMaxMemory(virDomainPtr dom) _("no domain with matching uuid '%s'"), uuidstr); goto cleanup; } + + if (virDomainGetMaxMemoryEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + ret = vm->def->mem.max_balloon; cleanup: @@ -1725,6 +1785,9 @@ static int umlDomainSetMaxMemory(virDomainPtr dom, unsigned long newmax) { goto cleanup; } + if (virDomainSetMaxMemoryEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (newmax < vm->def->mem.cur_balloon) { virReportError(VIR_ERR_INVALID_ARG, "%s", _("cannot set max memory lower than current memory")); @@ -1758,6 +1821,9 @@ static int umlDomainSetMemory(virDomainPtr dom, unsigned long newmem) { goto cleanup; } + if (virDomainSetMemoryEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (virDomainObjIsActive(vm)) { virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("cannot set memory of an active domain")); @@ -1795,6 +1861,9 @@ static int umlDomainGetInfo(virDomainPtr dom, goto cleanup; } + if (virDomainGetInfoEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + info->state = virDomainObjGetState(vm, NULL); if (!virDomainObjIsActive(vm)) { @@ -1841,6 +1910,9 @@ umlDomainGetState(virDomainPtr dom, goto cleanup; } + if (virDomainGetStateEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + *state = virDomainObjGetState(vm, reason); ret = 0; @@ -1870,6 +1942,9 @@ static char *umlDomainGetXMLDesc(virDomainPtr dom, goto cleanup; } + if (virDomainGetXMLDescEnsureACL(dom->conn, vm->def, flags) < 0) + goto cleanup; + ret = virDomainDefFormat((flags & VIR_DOMAIN_XML_INACTIVE) && vm->newDef ? vm->newDef : vm->def, flags); @@ -1886,6 +1961,9 @@ static int umlConnectListDefinedDomains(virConnectPtr conn, struct uml_driver *driver = conn->privateData; int n; + if (virConnectListDefinedDomainsEnsureACL(conn) < 0) + return -1; + umlDriverLock(driver); n = virDomainObjListGetInactiveNames(driver->domains, names, nnames); umlDriverUnlock(driver); @@ -1897,6 +1975,9 @@ static int umlConnectNumOfDefinedDomains(virConnectPtr conn) { struct uml_driver *driver = conn->privateData; int n; + if (virConnectNumOfDefinedDomainsEnsureACL(conn) < 0) + return -1; + umlDriverLock(driver); n = virDomainObjListNumOfDomains(driver->domains, 0); umlDriverUnlock(driver); @@ -1922,6 +2003,9 @@ static int umlDomainCreateWithFlags(virDomainPtr dom, unsigned int flags) { goto cleanup; } + if (virDomainCreateWithFlagsEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + ret = umlStartVMDaemon(dom->conn, driver, vm, (flags & VIR_DOMAIN_START_AUTODESTROY)); virDomainAuditStart(vm, "booted", ret >= 0); @@ -1955,6 +2039,9 @@ static virDomainPtr umlDomainDefineXML(virConnectPtr conn, const char *xml) { VIR_DOMAIN_XML_INACTIVE))) goto cleanup; + if (virDomainDefineXMLEnsureACL(conn, def) < 0) + goto cleanup; + if (!(vm = virDomainObjListAdd(driver->domains, def, driver->xmlopt, 0, NULL))) @@ -1998,6 +2085,9 @@ static int umlDomainUndefineFlags(virDomainPtr dom, goto cleanup; } + if (virDomainUndefineFlagsEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (!vm->persistent) { virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("cannot undefine transient domain")); @@ -2098,6 +2188,9 @@ static int umlDomainAttachDevice(virDomainPtr dom, const char *xml) goto cleanup; } + if (virDomainAttachDeviceEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (!virDomainObjIsActive(vm)) { virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("cannot attach device on inactive domain")); @@ -2216,6 +2309,9 @@ static int umlDomainDetachDevice(virDomainPtr dom, const char *xml) { goto cleanup; } + if (virDomainDetachDeviceEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (!virDomainObjIsActive(vm)) { virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("cannot detach device on inactive domain")); @@ -2281,6 +2377,9 @@ static int umlDomainGetAutostart(virDomainPtr dom, goto cleanup; } + if (virDomainGetAutostartEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + *autostart = vm->autostart; ret = 0; @@ -2307,6 +2406,9 @@ static int umlDomainSetAutostart(virDomainPtr dom, goto cleanup; } + if (virDomainSetAutostartEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (!vm->persistent) { virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("cannot set autostart for transient domain")); @@ -2382,6 +2484,9 @@ umlDomainBlockPeek(virDomainPtr dom, goto cleanup; } + if (virDomainBlockPeekEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (!path || path[0] == '\0') { virReportError(VIR_ERR_INVALID_ARG, "%s", _("NULL or empty path")); @@ -2449,6 +2554,9 @@ umlDomainOpenConsole(virDomainPtr dom, goto cleanup; } + if (virDomainOpenConsoleEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (!virDomainObjIsActive(vm)) { virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("domain is not running")); @@ -2505,6 +2613,9 @@ umlConnectDomainEventRegister(virConnectPtr conn, struct uml_driver *driver = conn->privateData; int ret; + if (virConnectDomainEventRegisterEnsureACL(conn) < 0) + return -1; + umlDriverLock(driver); ret = virDomainEventStateRegister(conn, driver->domainEventState, @@ -2521,6 +2632,9 @@ umlConnectDomainEventDeregister(virConnectPtr conn, struct uml_driver *driver = conn->privateData; int ret; + if (virConnectDomainEventDeregisterEnsureACL(conn) < 0) + return -1; + umlDriverLock(driver); ret = virDomainEventStateDeregister(conn, driver->domainEventState, @@ -2541,6 +2655,9 @@ umlConnectDomainEventRegisterAny(virConnectPtr conn, struct uml_driver *driver = conn->privateData; int ret; + if (virConnectDomainEventRegisterAnyEnsureACL(conn) < 0) + return -1; + umlDriverLock(driver); if (virDomainEventStateRegisterID(conn, driver->domainEventState, @@ -2560,6 +2677,9 @@ umlConnectDomainEventDeregisterAny(virConnectPtr conn, struct uml_driver *driver = conn->privateData; int ret; + if (virConnectDomainEventDeregisterAnyEnsureACL(conn) < 0) + return -1; + umlDriverLock(driver); ret = virDomainEventStateDeregisterID(conn, driver->domainEventState, @@ -2586,6 +2706,9 @@ static int umlConnectListAllDomains(virConnectPtr conn, virCheckFlags(VIR_CONNECT_LIST_DOMAINS_FILTERS_ALL, -1); + if (virConnectListAllDomainsEnsureACL(conn) < 0) + return -1; + umlDriverLock(driver); ret = virDomainObjListExport(driver->domains, conn, domains, flags); umlDriverUnlock(driver); @@ -2595,88 +2718,115 @@ static int umlConnectListAllDomains(virConnectPtr conn, static int -umlNodeGetInfo(virConnectPtr conn ATTRIBUTE_UNUSED, +umlNodeGetInfo(virConnectPtr conn, virNodeInfoPtr nodeinfo) { + if (virNodeGetInfoEnsureACL(conn) < 0) + return -1; + return nodeGetInfo(nodeinfo); } static int -umlNodeGetCPUStats(virConnectPtr conn ATTRIBUTE_UNUSED, +umlNodeGetCPUStats(virConnectPtr conn, int cpuNum, virNodeCPUStatsPtr params, int *nparams, unsigned int flags) { + if (virNodeGetCPUStatsEnsureACL(conn) < 0) + return -1; + return nodeGetCPUStats(cpuNum, params, nparams, flags); } static int -umlNodeGetMemoryStats(virConnectPtr conn ATTRIBUTE_UNUSED, +umlNodeGetMemoryStats(virConnectPtr conn, int cellNum, virNodeMemoryStatsPtr params, int *nparams, unsigned int flags) { + if (virNodeGetMemoryStatsEnsureACL(conn) < 0) + return -1; + return nodeGetMemoryStats(cellNum, params, nparams, flags); } static int -umlNodeGetCellsFreeMemory(virConnectPtr conn ATTRIBUTE_UNUSED, +umlNodeGetCellsFreeMemory(virConnectPtr conn, unsigned long long *freeMems, int startCell, int maxCells) { + if (virNodeGetCellsFreeMemoryEnsureACL(conn) < 0) + return -1; + return nodeGetCellsFreeMemory(freeMems, startCell, maxCells); } static unsigned long long -umlNodeGetFreeMemory(virConnectPtr conn ATTRIBUTE_UNUSED) +umlNodeGetFreeMemory(virConnectPtr conn) { + if (virNodeGetFreeMemoryEnsureACL(conn) < 0) + return 0; + return nodeGetFreeMemory(); } static int -umlNodeGetMemoryParameters(virConnectPtr conn ATTRIBUTE_UNUSED, +umlNodeGetMemoryParameters(virConnectPtr conn, virTypedParameterPtr params, int *nparams, unsigned int flags) { + if (virNodeGetMemoryParametersEnsureACL(conn) < 0) + return -1; + return nodeGetMemoryParameters(params, nparams, flags); } static int -umlNodeSetMemoryParameters(virConnectPtr conn ATTRIBUTE_UNUSED, +umlNodeSetMemoryParameters(virConnectPtr conn, virTypedParameterPtr params, int nparams, unsigned int flags) { + if (virNodeSetMemoryParametersEnsureACL(conn) < 0) + return -1; + return nodeSetMemoryParameters(params, nparams, flags); } static int -umlNodeGetCPUMap(virConnectPtr conn ATTRIBUTE_UNUSED, +umlNodeGetCPUMap(virConnectPtr conn, unsigned char **cpumap, unsigned int *online, unsigned int flags) { + if (virNodeGetCPUMapEnsureACL(conn) < 0) + return -1; + return nodeGetCPUMap(cpumap, online, flags); } static int -umlNodeSuspendForDuration(virConnectPtr conn ATTRIBUTE_UNUSED, +umlNodeSuspendForDuration(virConnectPtr conn, unsigned int target, unsigned long long duration, unsigned int flags) { + if (virNodeSuspendForDurationEnsureACL(conn) < 0) + return -1; + return nodeSuspendForDuration(target, duration, flags); } -- 1.8.1.4

From: "Daniel P. Berrange" <berrange@redhat.com> Insert calls to the ACL checking APIs in all Xen driver entrypoints. Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- src/xen/xen_driver.c | 217 +++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 209 insertions(+), 8 deletions(-) diff --git a/src/xen/xen_driver.c b/src/xen/xen_driver.c index a6c87ce..77f1fae 100644 --- a/src/xen/xen_driver.c +++ b/src/xen/xen_driver.c @@ -66,6 +66,7 @@ #include "nodeinfo.h" #include "configmake.h" #include "virstring.h" +#include "access/viraccessapicheck.h" #define VIR_FROM_THIS VIR_FROM_XEN #define XEN_SAVE_DIR LOCALSTATEDIR "/lib/libvirt/xen/save" @@ -398,6 +399,9 @@ xenUnifiedConnectOpen(virConnectPtr conn, virConnectAuthPtr auth, unsigned int f /* We now know the URI is definitely for this driver, so beyond * here, don't return DECLINED, always use ERROR */ + if (virConnectOpenEnsureACL(conn) < 0) + return VIR_DRV_OPEN_ERROR; + /* Allocate per-connection private data. */ if (VIR_ALLOC(priv) < 0) { virReportOOMError(); @@ -544,15 +548,21 @@ unsigned long xenUnifiedVersion(void) static const char * -xenUnifiedConnectGetType(virConnectPtr conn ATTRIBUTE_UNUSED) +xenUnifiedConnectGetType(virConnectPtr conn) { + if (virConnectGetTypeEnsureACL(conn) < 0) + return NULL; + return "Xen"; } /* Which features are supported by this driver? */ static int -xenUnifiedConnectSupportsFeature(virConnectPtr conn ATTRIBUTE_UNUSED, int feature) +xenUnifiedConnectSupportsFeature(virConnectPtr conn, int feature) { + if (virConnectSupportsFeatureEnsureACL(conn) < 0) + return -1; + switch (feature) { case VIR_DRV_FEATURE_MIGRATION_V1: case VIR_DRV_FEATURE_MIGRATION_DIRECT: @@ -565,12 +575,18 @@ xenUnifiedConnectSupportsFeature(virConnectPtr conn ATTRIBUTE_UNUSED, int featur static int xenUnifiedConnectGetVersion(virConnectPtr conn, unsigned long *hvVer) { + if (virConnectGetVersionEnsureACL(conn) < 0) + return -1; + return xenHypervisorGetVersion(conn, hvVer); } -static char *xenUnifiedConnectGetHostname(virConnectPtr conn ATTRIBUTE_UNUSED) +static char *xenUnifiedConnectGetHostname(virConnectPtr conn) { + if (virConnectGetHostnameEnsureACL(conn) < 0) + return NULL; + return virGetHostname(); } @@ -605,6 +621,9 @@ xenUnifiedConnectIsAlive(virConnectPtr conn ATTRIBUTE_UNUSED) int xenUnifiedConnectGetMaxVcpus(virConnectPtr conn, const char *type) { + if (virConnectGetMaxVcpusEnsureACL(conn) < 0) + return -1; + if (type && STRCASENEQ(type, "Xen")) { virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__); return -1; @@ -616,6 +635,9 @@ xenUnifiedConnectGetMaxVcpus(virConnectPtr conn, const char *type) static int xenUnifiedNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info) { + if (virNodeGetInfoEnsureACL(conn) < 0) + return -1; + return xenDaemonNodeGetInfo(conn, info); } @@ -625,6 +647,9 @@ xenUnifiedConnectGetCapabilities(virConnectPtr conn) xenUnifiedPrivatePtr priv = conn->privateData; char *xml; + if (virConnectGetCapabilitiesEnsureACL(conn) < 0) + return NULL; + if (!(xml = virCapabilitiesFormatXML(priv->caps))) { virReportOOMError(); return NULL; @@ -636,12 +661,18 @@ xenUnifiedConnectGetCapabilities(virConnectPtr conn) static int xenUnifiedConnectListDomains(virConnectPtr conn, int *ids, int maxids) { + if (virConnectListDomainsEnsureACL(conn) < 0) + return -1; + return xenStoreListDomains(conn, ids, maxids); } static int xenUnifiedConnectNumOfDomains(virConnectPtr conn) { + if (virConnectNumOfDomainsEnsureACL(conn) < 0) + return -1; + return xenStoreNumOfDomains(conn); } @@ -661,6 +692,9 @@ xenUnifiedDomainCreateXML(virConnectPtr conn, VIR_DOMAIN_XML_INACTIVE))) goto cleanup; + if (virDomainCreateXMLEnsureACL(conn, def) < 0) + goto cleanup; + if (xenDaemonCreateXML(conn, def) < 0) goto cleanup; @@ -682,6 +716,9 @@ xenUnifiedDomainLookupByID(virConnectPtr conn, int id) if (!(def = xenGetDomainDefForID(conn, id))) goto cleanup; + if (virDomainLookupByIDEnsureACL(conn, def) < 0) + goto cleanup; + if (!(ret = virGetDomain(conn, def->name, def->uuid))) goto cleanup; @@ -702,6 +739,9 @@ xenUnifiedDomainLookupByUUID(virConnectPtr conn, if (!(def = xenGetDomainDefForUUID(conn, uuid))) goto cleanup; + if (virDomainLookupByUUIDEnsureACL(conn, def) < 0) + goto cleanup; + if (!(ret = virGetDomain(conn, def->name, def->uuid))) goto cleanup; @@ -722,6 +762,9 @@ xenUnifiedDomainLookupByName(virConnectPtr conn, if (!(def = xenGetDomainDefForName(conn, name))) goto cleanup; + if (virDomainLookupByNameEnsureACL(conn, def) < 0) + goto cleanup; + if (!(ret = virGetDomain(conn, def->name, def->uuid))) goto cleanup; @@ -813,6 +856,9 @@ xenUnifiedDomainSuspend(virDomainPtr dom) if (!(def = xenGetDomainDefForDom(dom))) goto cleanup; + if (virDomainSuspendEnsureACL(dom->conn, def) < 0) + goto cleanup; + ret = xenDaemonDomainSuspend(dom->conn, def); cleanup: @@ -829,6 +875,9 @@ xenUnifiedDomainResume(virDomainPtr dom) if (!(def = xenGetDomainDefForDom(dom))) goto cleanup; + if (virDomainResumeEnsureACL(dom->conn, def) < 0) + goto cleanup; + ret = xenDaemonDomainResume(dom->conn, def); cleanup: @@ -848,6 +897,9 @@ xenUnifiedDomainShutdownFlags(virDomainPtr dom, if (!(def = xenGetDomainDefForDom(dom))) goto cleanup; + if (virDomainShutdownFlagsEnsureACL(dom->conn, def) < 0) + goto cleanup; + ret = xenDaemonDomainShutdown(dom->conn, def); cleanup: @@ -872,6 +924,9 @@ xenUnifiedDomainReboot(virDomainPtr dom, unsigned int flags) if (!(def = xenGetDomainDefForDom(dom))) goto cleanup; + if (virDomainRebootEnsureACL(dom->conn, def) < 0) + goto cleanup; + ret = xenDaemonDomainReboot(dom->conn, def); cleanup: @@ -891,6 +946,9 @@ xenUnifiedDomainDestroyFlags(virDomainPtr dom, if (!(def = xenGetDomainDefForDom(dom))) goto cleanup; + if (virDomainDestroyFlagsEnsureACL(dom->conn, def) < 0) + goto cleanup; + ret = xenDaemonDomainDestroy(dom->conn, def); cleanup: @@ -914,6 +972,9 @@ xenUnifiedDomainGetOSType(virDomainPtr dom) if (!(def = xenGetDomainDefForDom(dom))) goto cleanup; + if (virDomainGetOSTypeEnsureACL(dom->conn, def) < 0) + goto cleanup; + if (def->id < 0) { if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", @@ -942,6 +1003,9 @@ xenUnifiedDomainGetMaxMemory(virDomainPtr dom) if (!(def = xenGetDomainDefForDom(dom))) goto cleanup; + if (virDomainGetMaxMemoryEnsureACL(dom->conn, def) < 0) + goto cleanup; + if (def->id < 0) { if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4) ret = xenXMDomainGetMaxMemory(dom->conn, def); @@ -966,6 +1030,9 @@ xenUnifiedDomainSetMaxMemory(virDomainPtr dom, unsigned long memory) if (!(def = xenGetDomainDefForDom(dom))) goto cleanup; + if (virDomainSetMaxMemoryEnsureACL(dom->conn, def) < 0) + goto cleanup; + if (def->id < 0) { if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4) ret = xenXMDomainSetMaxMemory(dom->conn, def, memory); @@ -990,6 +1057,9 @@ xenUnifiedDomainSetMemory(virDomainPtr dom, unsigned long memory) if (!(def = xenGetDomainDefForDom(dom))) goto cleanup; + if (virDomainSetMemoryEnsureACL(dom->conn, def) < 0) + goto cleanup; + if (def->id < 0 && priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4) ret = xenXMDomainSetMemory(dom->conn, def, memory); else @@ -1010,6 +1080,9 @@ xenUnifiedDomainGetInfo(virDomainPtr dom, virDomainInfoPtr info) if (!(def = xenGetDomainDefForDom(dom))) goto cleanup; + if (virDomainGetInfoEnsureACL(dom->conn, def) < 0) + goto cleanup; + if (def->id < 0) { if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4) ret = xenXMDomainGetInfo(dom->conn, def, info); @@ -1039,6 +1112,9 @@ xenUnifiedDomainGetState(virDomainPtr dom, if (!(def = xenGetDomainDefForDom(dom))) goto cleanup; + if (virDomainGetStateEnsureACL(dom->conn, def) < 0) + goto cleanup; + if (def->id < 0) { if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4) ret = xenXMDomainGetState(dom->conn, def, state, reason); @@ -1071,6 +1147,9 @@ xenUnifiedDomainSaveFlags(virDomainPtr dom, const char *to, const char *dxml, if (!(def = xenGetDomainDefForDom(dom))) goto cleanup; + if (virDomainSaveFlagsEnsureACL(dom->conn, def) < 0) + goto cleanup; + ret = xenDaemonDomainSave(dom->conn, def, to); cleanup: @@ -1112,6 +1191,9 @@ xenUnifiedDomainManagedSave(virDomainPtr dom, unsigned int flags) if (!(def = xenGetDomainDefForDom(dom))) goto cleanup; + if (virDomainManagedSaveEnsureACL(dom->conn, def) < 0) + goto cleanup; + if (!(name = xenUnifiedDomainManagedSavePath(priv, def))) goto cleanup; @@ -1136,6 +1218,9 @@ xenUnifiedDomainHasManagedSaveImage(virDomainPtr dom, unsigned int flags) if (!(def = xenGetDomainDefForDom(dom))) goto cleanup; + if (virDomainHasManagedSaveImageEnsureACL(dom->conn, def) < 0) + goto cleanup; + if (!(name = xenUnifiedDomainManagedSavePath(priv, def))) goto cleanup; @@ -1160,6 +1245,9 @@ xenUnifiedDomainManagedSaveRemove(virDomainPtr dom, unsigned int flags) if (!(def = xenGetDomainDefForDom(dom))) goto cleanup; + if (virDomainManagedSaveRemoveEnsureACL(dom->conn, def) < 0) + goto cleanup; + if (!(name = xenUnifiedDomainManagedSavePath(priv, def))) goto cleanup; @@ -1201,6 +1289,9 @@ xenUnifiedDomainCoreDump(virDomainPtr dom, const char *to, unsigned int flags) if (!(def = xenGetDomainDefForDom(dom))) goto cleanup; + if (virDomainCoreDumpEnsureACL(dom->conn, def) < 0) + goto cleanup; + ret = xenDaemonDomainCoreDump(dom->conn, def, to, flags); cleanup: @@ -1238,6 +1329,9 @@ xenUnifiedDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus, if (!(def = xenGetDomainDefForDom(dom))) goto cleanup; + if (virDomainSetVcpusFlagsEnsureACL(dom->conn, def, flags) < 0) + goto cleanup; + /* Try non-hypervisor methods first, then hypervisor direct method * as a last resort. */ @@ -1277,6 +1371,9 @@ xenUnifiedDomainPinVcpu(virDomainPtr dom, unsigned int vcpu, if (!(def = xenGetDomainDefForDom(dom))) goto cleanup; + if (virDomainPinVcpuEnsureACL(dom->conn, def) < 0) + goto cleanup; + if (dom->id < 0) { if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4) ret = xenXMDomainPinVcpu(dom->conn, def, vcpu, cpumap, maplen); @@ -1303,6 +1400,9 @@ xenUnifiedDomainGetVcpus(virDomainPtr dom, if (!(def = xenGetDomainDefForDom(dom))) goto cleanup; + if (virDomainGetVcpusEnsureACL(dom->conn, def) < 0) + goto cleanup; + if (dom->id < 0) { if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", @@ -1334,6 +1434,9 @@ xenUnifiedDomainGetVcpusFlags(virDomainPtr dom, unsigned int flags) if (!(def = xenGetDomainDefForDom(dom))) goto cleanup; + if (virDomainGetVcpusFlagsEnsureACL(dom->conn, def) < 0) + goto cleanup; + if (dom->id < 0) { if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4) ret = xenXMDomainGetVcpusFlags(dom->conn, def, flags); @@ -1369,6 +1472,9 @@ xenUnifiedDomainGetXMLDesc(virDomainPtr dom, unsigned int flags) if (!(minidef = xenGetDomainDefForDom(dom))) goto cleanup; + if (virDomainGetXMLDescEnsureACL(dom->conn, minidef, flags) < 0) + goto cleanup; + if (dom->id < 0 && priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4) { def = xenXMDomainGetXMLDesc(dom->conn, minidef); } else { @@ -1406,6 +1512,9 @@ xenUnifiedConnectDomainXMLFromNative(virConnectPtr conn, virCheckFlags(0, NULL); + if (virConnectDomainXMLFromNativeEnsureACL(conn) < 0) + return NULL; + if (STRNEQ(format, XEN_CONFIG_FORMAT_XM) && STRNEQ(format, XEN_CONFIG_FORMAT_SEXPR)) { virReportError(VIR_ERR_INVALID_ARG, @@ -1455,6 +1564,9 @@ xenUnifiedConnectDomainXMLToNative(virConnectPtr conn, virCheckFlags(0, NULL); + if (virConnectDomainXMLToNativeEnsureACL(conn) < 0) + return NULL; + if (STRNEQ(format, XEN_CONFIG_FORMAT_XM) && STRNEQ(format, XEN_CONFIG_FORMAT_SEXPR)) { virReportError(VIR_ERR_INVALID_ARG, @@ -1527,6 +1639,9 @@ xenUnifiedDomainMigratePerform(virDomainPtr dom, if (!(def = xenGetDomainDefForDom(dom))) goto cleanup; + if (virDomainMigratePerformEnsureACL(dom->conn, def) < 0) + goto cleanup; + ret = xenDaemonDomainMigratePerform(dom->conn, def, cookie, cookielen, uri, flags, dname, resource); @@ -1554,6 +1669,9 @@ xenUnifiedDomainMigrateFinish(virConnectPtr dconn, if (!(minidef = xenGetDomainDefForName(dconn, dname))) goto cleanup; + if (virDomainMigrateFinishEnsureACL(dconn, minidef) < 0) + goto cleanup; + if (flags & VIR_MIGRATE_PERSIST_DEST) { if (!(def = xenDaemonDomainGetXMLDesc(dconn, minidef, NULL))) goto cleanup; @@ -1583,6 +1701,9 @@ xenUnifiedConnectListDefinedDomains(virConnectPtr conn, char **const names, { xenUnifiedPrivatePtr priv = conn->privateData; + if (virConnectListDefinedDomainsEnsureACL(conn) < 0) + return -1; + if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4) { return xenXMListDefinedDomains(conn, names, maxnames); } else { @@ -1595,6 +1716,9 @@ xenUnifiedConnectNumOfDefinedDomains(virConnectPtr conn) { xenUnifiedPrivatePtr priv = conn->privateData; + if (virConnectNumOfDefinedDomainsEnsureACL(conn) < 0) + return -1; + if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4) { return xenXMNumOfDefinedDomains(conn); } else { @@ -1615,6 +1739,9 @@ xenUnifiedDomainCreateWithFlags(virDomainPtr dom, unsigned int flags) if (!(def = xenGetDomainDefForDom(dom))) goto cleanup; + if (virDomainCreateWithFlagsEnsureACL(dom->conn, def) < 0) + goto cleanup; + if (!(name = xenUnifiedDomainManagedSavePath(priv, def))) goto cleanup; @@ -1657,6 +1784,9 @@ xenUnifiedDomainDefineXML(virConnectPtr conn, const char *xml) VIR_DOMAIN_XML_INACTIVE))) goto cleanup; + if (virDomainDefineXMLEnsureACL(conn, def) < 0) + goto cleanup; + if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4) { if (xenXMDomainDefineXML(conn, def) < 0) goto cleanup; @@ -1687,6 +1817,9 @@ xenUnifiedDomainUndefineFlags(virDomainPtr dom, unsigned int flags) if (!(def = xenGetDomainDefForDom(dom))) goto cleanup; + if (virDomainUndefineFlagsEnsureACL(dom->conn, def) < 0) + goto cleanup; + if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4) ret = xenXMDomainUndefine(dom->conn, def); else @@ -1721,6 +1854,9 @@ xenUnifiedDomainAttachDevice(virDomainPtr dom, const char *xml) if (!(def = xenGetDomainDefForDom(dom))) goto cleanup; + if (virDomainAttachDeviceEnsureACL(dom->conn, def) < 0) + goto cleanup; + if (dom->id < 0 && priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4) ret = xenXMDomainAttachDeviceFlags(dom->conn, def, xml, flags); else @@ -1742,6 +1878,9 @@ xenUnifiedDomainAttachDeviceFlags(virDomainPtr dom, const char *xml, if (!(def = xenGetDomainDefForDom(dom))) goto cleanup; + if (virDomainAttachDeviceFlagsEnsureACL(dom->conn, def, flags) < 0) + goto cleanup; + if (dom->id < 0 && priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4) ret = xenXMDomainAttachDeviceFlags(dom->conn, def, xml, flags); else @@ -1771,6 +1910,9 @@ xenUnifiedDomainDetachDevice(virDomainPtr dom, const char *xml) if (!(def = xenGetDomainDefForDom(dom))) goto cleanup; + if (virDomainDetachDeviceEnsureACL(dom->conn, def) < 0) + goto cleanup; + if (dom->id < 0 && priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4) ret = xenXMDomainDetachDeviceFlags(dom->conn, def, xml, flags); else @@ -1792,6 +1934,9 @@ xenUnifiedDomainDetachDeviceFlags(virDomainPtr dom, const char *xml, if (!(def = xenGetDomainDefForDom(dom))) goto cleanup; + if (virDomainDetachDeviceFlagsEnsureACL(dom->conn, def, flags) < 0) + goto cleanup; + if (dom->id < 0 && priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4) ret = xenXMDomainDetachDeviceFlags(dom->conn, def, xml, flags); else @@ -1812,6 +1957,9 @@ xenUnifiedDomainUpdateDeviceFlags(virDomainPtr dom, const char *xml, if (!(def = xenGetDomainDefForDom(dom))) goto cleanup; + if (virDomainUpdateDeviceFlagsEnsureACL(dom->conn, def, flags) < 0) + goto cleanup; + ret = xenDaemonUpdateDeviceFlags(dom->conn, def, xml, flags); cleanup: @@ -1829,6 +1977,9 @@ xenUnifiedDomainGetAutostart(virDomainPtr dom, int *autostart) if (!(def = xenGetDomainDefForDom(dom))) goto cleanup; + if (virDomainGetAutostartEnsureACL(dom->conn, def) < 0) + goto cleanup; + if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4) ret = xenXMDomainGetAutostart(def, autostart); else @@ -1849,6 +2000,9 @@ xenUnifiedDomainSetAutostart(virDomainPtr dom, int autostart) if (!(def = xenGetDomainDefForDom(dom))) goto cleanup; + if (virDomainSetAutostartEnsureACL(dom->conn, def) < 0) + goto cleanup; + if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4) ret = xenXMDomainSetAutostart(def, autostart); else @@ -1869,6 +2023,9 @@ xenUnifiedDomainGetSchedulerType(virDomainPtr dom, int *nparams) if (!(def = xenGetDomainDefForDom(dom))) goto cleanup; + if (virDomainGetSchedulerTypeEnsureACL(dom->conn, def) < 0) + goto cleanup; + if (dom->id < 0) { if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", @@ -1900,6 +2057,9 @@ xenUnifiedDomainGetSchedulerParametersFlags(virDomainPtr dom, if (!(def = xenGetDomainDefForDom(dom))) goto cleanup; + if (virDomainGetSchedulerParametersEnsureACL(dom->conn, def) < 0) + goto cleanup; + if (dom->id < 0) { if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", @@ -1940,6 +2100,9 @@ xenUnifiedDomainSetSchedulerParametersFlags(virDomainPtr dom, if (!(def = xenGetDomainDefForDom(dom))) goto cleanup; + if (virDomainSetSchedulerParametersFlagsEnsureACL(dom->conn, def, flags) < 0) + goto cleanup; + if (dom->id < 0) { if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", @@ -1975,6 +2138,9 @@ xenUnifiedDomainBlockStats(virDomainPtr dom, const char *path, if (!(def = xenGetDomainDefForDom(dom))) goto cleanup; + if (virDomainBlockStatsEnsureACL(dom->conn, def) < 0) + goto cleanup; + ret = xenHypervisorDomainBlockStats(dom->conn, def, path, stats); cleanup: @@ -1992,6 +2158,9 @@ xenUnifiedDomainInterfaceStats(virDomainPtr dom, const char *path, if (!(def = xenGetDomainDefForDom(dom))) goto cleanup; + if (virDomainInterfaceStatsEnsureACL(dom->conn, def) < 0) + goto cleanup; + ret = xenHypervisorDomainInterfaceStats(def, path, stats); cleanup: @@ -2013,6 +2182,9 @@ xenUnifiedDomainBlockPeek(virDomainPtr dom, const char *path, if (!(def = xenGetDomainDefForDom(dom))) goto cleanup; + if (virDomainBlockPeekEnsureACL(dom->conn, def) < 0) + goto cleanup; + if (dom->id < 0 && priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4) ret = xenXMDomainBlockPeek(dom->conn, def, path, offset, size, buffer); else @@ -2027,6 +2199,9 @@ static int xenUnifiedNodeGetCellsFreeMemory(virConnectPtr conn, unsigned long long *freeMems, int startCell, int maxCells) { + if (virNodeGetCellsFreeMemoryEnsureACL(conn) < 0) + return 0; + return xenHypervisorNodeGetCellsFreeMemory(conn, freeMems, startCell, maxCells); } @@ -2036,6 +2211,9 @@ xenUnifiedNodeGetFreeMemory(virConnectPtr conn) { unsigned long long freeMem = 0; + if (virNodeGetFreeMemoryEnsureACL(conn) < 0) + return 0; + if (xenHypervisorNodeGetCellsFreeMemory(conn, &freeMem, -1, 1) < 0) return 0; return freeMem; @@ -2049,8 +2227,11 @@ xenUnifiedConnectDomainEventRegister(virConnectPtr conn, virFreeCallback freefunc) { xenUnifiedPrivatePtr priv = conn->privateData; - int ret; + + if (virConnectDomainEventRegisterEnsureACL(conn) < 0) + return -1; + xenUnifiedLock(priv); if (priv->xsWatch == -1) { @@ -2073,6 +2254,10 @@ xenUnifiedConnectDomainEventDeregister(virConnectPtr conn, { int ret; xenUnifiedPrivatePtr priv = conn->privateData; + + if (virConnectDomainEventDeregisterEnsureACL(conn) < 0) + return -1; + xenUnifiedLock(priv); if (priv->xsWatch == -1) { @@ -2099,8 +2284,11 @@ xenUnifiedConnectDomainEventRegisterAny(virConnectPtr conn, virFreeCallback freefunc) { xenUnifiedPrivatePtr priv = conn->privateData; - int ret; + + if (virConnectDomainEventRegisterAnyEnsureACL(conn) < 0) + return -1; + xenUnifiedLock(priv); if (priv->xsWatch == -1) { @@ -2124,6 +2312,10 @@ xenUnifiedConnectDomainEventDeregisterAny(virConnectPtr conn, { int ret; xenUnifiedPrivatePtr priv = conn->privateData; + + if (virConnectDomainEventDeregisterAnyEnsureACL(conn) < 0) + return -1; + xenUnifiedLock(priv); if (priv->xsWatch == -1) { @@ -2399,31 +2591,40 @@ cleanup: } static int -xenUnifiedNodeGetMemoryParameters(virConnectPtr conn ATTRIBUTE_UNUSED, +xenUnifiedNodeGetMemoryParameters(virConnectPtr conn, virTypedParameterPtr params, int *nparams, unsigned int flags) { + if (virNodeGetMemoryParametersEnsureACL(conn) < 0) + return -1; + return nodeGetMemoryParameters(params, nparams, flags); } static int -xenUnifiedNodeSetMemoryParameters(virConnectPtr conn ATTRIBUTE_UNUSED, +xenUnifiedNodeSetMemoryParameters(virConnectPtr conn, virTypedParameterPtr params, int nparams, unsigned int flags) { + if (virNodeSetMemoryParametersEnsureACL(conn) < 0) + return -1; + return nodeSetMemoryParameters(params, nparams, flags); } static int -xenUnifiedNodeSuspendForDuration(virConnectPtr conn ATTRIBUTE_UNUSED, +xenUnifiedNodeSuspendForDuration(virConnectPtr conn, unsigned int target, unsigned long long duration, unsigned int flags) { + if (virNodeSuspendForDurationEnsureACL(conn) < 0) + return -1; + return nodeSuspendForDuration(target, duration, flags); } -- 1.8.1.4

From: "Daniel P. Berrange" <berrange@redhat.com> Insert calls to the ACL checking APIs in all libxl driver entrypoints. Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- src/libxl/libxl_driver.c | 187 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 184 insertions(+), 3 deletions(-) diff --git a/src/libxl/libxl_driver.c b/src/libxl/libxl_driver.c index 99d2dc4..0bbe8a1 100644 --- a/src/libxl/libxl_driver.c +++ b/src/libxl/libxl_driver.c @@ -45,6 +45,7 @@ #include "virtypedparam.h" #include "viruri.h" #include "virstring.h" +#include "access/viraccessapicheck.h" #define VIR_FROM_THIS VIR_FROM_LIBXL @@ -1382,6 +1383,9 @@ libxlConnectOpen(virConnectPtr conn, } } + if (virConnectOpenEnsureACL(conn) < 0) + return VIR_DRV_OPEN_ERROR; + conn->privateData = libxl_driver; return VIR_DRV_OPEN_SUCCESS; @@ -1395,8 +1399,11 @@ libxlConnectClose(virConnectPtr conn ATTRIBUTE_UNUSED) } static const char * -libxlConnectGetType(virConnectPtr conn ATTRIBUTE_UNUSED) +libxlConnectGetType(virConnectPtr conn) { + if (virConnectGetTypeEnsureACL(conn) < 0) + return NULL; + return "xenlight"; } @@ -1405,6 +1412,9 @@ libxlConnectGetVersion(virConnectPtr conn, unsigned long *version) { libxlDriverPrivatePtr driver = conn->privateData; + if (virConnectGetVersionEnsureACL(conn) < 0) + return 0; + libxlDriverLock(driver); *version = driver->version; libxlDriverUnlock(driver); @@ -1412,8 +1422,11 @@ libxlConnectGetVersion(virConnectPtr conn, unsigned long *version) } -static char *libxlConnectGetHostname(virConnectPtr conn ATTRIBUTE_UNUSED) +static char *libxlConnectGetHostname(virConnectPtr conn) { + if (virConnectGetHostnameEnsureACL(conn) < 0) + return NULL; + return virGetHostname(); } @@ -1424,6 +1437,9 @@ libxlConnectGetMaxVcpus(virConnectPtr conn, const char *type ATTRIBUTE_UNUSED) int ret; libxlDriverPrivatePtr driver = conn->privateData; + if (virConnectGetMaxVcpusEnsureACL(conn) < 0) + return -1; + ret = libxl_get_max_cpus(driver->ctx); /* libxl_get_max_cpus() will return 0 if there were any failures, e.g. xc_physinfo() failing */ @@ -1436,6 +1452,9 @@ libxlConnectGetMaxVcpus(virConnectPtr conn, const char *type ATTRIBUTE_UNUSED) static int libxlNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info) { + if (virNodeGetInfoEnsureACL(conn) < 0) + return -1; + return libxlDoNodeGetInfo(conn->privateData, info); } @@ -1445,6 +1464,9 @@ libxlConnectGetCapabilities(virConnectPtr conn) libxlDriverPrivatePtr driver = conn->privateData; char *xml; + if (virConnectGetCapabilitiesEnsureACL(conn) < 0) + return NULL; + libxlDriverLock(driver); if ((xml = virCapabilitiesFormatXML(driver->caps)) == NULL) virReportOOMError(); @@ -1459,6 +1481,9 @@ libxlConnectListDomains(virConnectPtr conn, int *ids, int nids) libxlDriverPrivatePtr driver = conn->privateData; int n; + if (virConnectListDomainsEnsureACL(conn) < 0) + return -1; + libxlDriverLock(driver); n = virDomainObjListGetActiveIDs(driver->domains, ids, nids); libxlDriverUnlock(driver); @@ -1472,6 +1497,9 @@ libxlConnectNumOfDomains(virConnectPtr conn) libxlDriverPrivatePtr driver = conn->privateData; int n; + if (virConnectNumOfDomainsEnsureACL(conn) < 0) + return -1; + libxlDriverLock(driver); n = virDomainObjListNumOfDomains(driver->domains, 1); libxlDriverUnlock(driver); @@ -1496,6 +1524,9 @@ libxlDomainCreateXML(virConnectPtr conn, const char *xml, VIR_DOMAIN_XML_INACTIVE))) goto cleanup; + if (virDomainCreateXMLEnsureACL(conn, def) < 0) + goto cleanup; + if (!(vm = virDomainObjListAdd(driver->domains, def, driver->xmlopt, VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE, @@ -1538,6 +1569,9 @@ libxlDomainLookupByID(virConnectPtr conn, int id) goto cleanup; } + if (virDomainLookupByIDEnsureACL(conn, vm->def) < 0) + goto cleanup; + dom = virGetDomain(conn, vm->def->name, vm->def->uuid); if (dom) dom->id = vm->def->id; @@ -1564,6 +1598,9 @@ libxlDomainLookupByUUID(virConnectPtr conn, const unsigned char *uuid) goto cleanup; } + if (virDomainLookupByUUIDEnsureACL(conn, vm->def) < 0) + goto cleanup; + dom = virGetDomain(conn, vm->def->name, vm->def->uuid); if (dom) dom->id = vm->def->id; @@ -1590,6 +1627,9 @@ libxlDomainLookupByName(virConnectPtr conn, const char *name) goto cleanup; } + if (virDomainLookupByNameEnsureACL(conn, vm->def) < 0) + goto cleanup; + dom = virGetDomain(conn, vm->def->name, vm->def->uuid); if (dom) dom->id = vm->def->id; @@ -1620,6 +1660,10 @@ libxlDomainSuspend(virDomainPtr dom) _("No domain with matching uuid '%s'"), uuidstr); goto cleanup; } + + if (virDomainSuspendEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (!virDomainObjIsActive(vm)) { virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not running")); goto cleanup; @@ -1679,6 +1723,9 @@ libxlDomainResume(virDomainPtr dom) goto cleanup; } + if (virDomainResumeEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (!virDomainObjIsActive(vm)) { virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not running")); goto cleanup; @@ -1737,6 +1784,9 @@ libxlDomainShutdownFlags(virDomainPtr dom, unsigned int flags) goto cleanup; } + if (virDomainShutdownFlagsEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (!virDomainObjIsActive(vm)) { virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not running")); @@ -1790,6 +1840,9 @@ libxlDomainReboot(virDomainPtr dom, unsigned int flags) goto cleanup; } + if (virDomainRebootEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (!virDomainObjIsActive(vm)) { virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not running")); @@ -1833,6 +1886,9 @@ libxlDomainDestroyFlags(virDomainPtr dom, goto cleanup; } + if (virDomainDestroyFlagsEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (!virDomainObjIsActive(vm)) { virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not running")); @@ -1888,7 +1944,11 @@ libxlDomainGetOSType(virDomainPtr dom) goto cleanup; } - ignore_value(VIR_STRDUP(type, vm->def->os.type)); + if (virDomainGetOSTypeEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + + if (VIR_STRDUP(type, vm->def->os.type) < 0) + goto cleanup; cleanup: if (vm) @@ -1911,6 +1971,10 @@ libxlDomainGetMaxMemory(virDomainPtr dom) virReportError(VIR_ERR_NO_DOMAIN, "%s", _("no domain with matching uuid")); goto cleanup; } + + if (virDomainGetMaxMemoryEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + ret = vm->def->mem.max_balloon; cleanup: @@ -1943,6 +2007,9 @@ libxlDomainSetMemoryFlags(virDomainPtr dom, unsigned long newmem, goto cleanup; } + if (virDomainSetMemoryFlagsEnsureACL(dom->conn, vm->def, flags) < 0) + goto cleanup; + isActive = virDomainObjIsActive(vm); if (flags == VIR_DOMAIN_MEM_CURRENT) { @@ -2065,6 +2132,9 @@ libxlDomainGetInfo(virDomainPtr dom, virDomainInfoPtr info) goto cleanup; } + if (virDomainGetInfoEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (!virDomainObjIsActive(vm)) { info->cpuTime = 0; info->memory = vm->def->mem.cur_balloon; @@ -2112,6 +2182,9 @@ libxlDomainGetState(virDomainPtr dom, goto cleanup; } + if (virDomainGetStateEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + *state = virDomainObjGetState(vm, reason); ret = 0; @@ -2224,6 +2297,9 @@ libxlDomainSaveFlags(virDomainPtr dom, const char *to, const char *dxml, goto cleanup; } + if (virDomainSaveFlagsEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (!virDomainObjIsActive(vm)) { virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not running")); goto cleanup; @@ -2276,6 +2352,9 @@ libxlDomainRestoreFlags(virConnectPtr conn, const char *from, if (fd < 0) goto cleanup; + if (virDomainRestoreFlagsEnsureACL(conn, def) < 0) + goto cleanup; + if (!(vm = virDomainObjListAdd(driver->domains, def, driver->xmlopt, VIR_DOMAIN_OBJ_LIST_ADD_LIVE | @@ -2331,6 +2410,9 @@ libxlDomainCoreDump(virDomainPtr dom, const char *to, unsigned int flags) goto cleanup; } + if (virDomainCoreDumpEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (!virDomainObjIsActive(vm)) { virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not running")); goto cleanup; @@ -2421,6 +2503,9 @@ libxlDomainManagedSave(virDomainPtr dom, unsigned int flags) goto cleanup; } + if (virDomainManagedSaveEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (!virDomainObjIsActive(vm)) { virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not running")); goto cleanup; @@ -2496,6 +2581,9 @@ libxlDomainHasManagedSaveImage(virDomainPtr dom, unsigned int flags) goto cleanup; } + if (virDomainHasManagedSaveImageEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + ret = vm->hasManagedSave; cleanup: @@ -2525,6 +2613,9 @@ libxlDomainManagedSaveRemove(virDomainPtr dom, unsigned int flags) goto cleanup; } + if (virDomainManagedSaveRemoveEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + name = libxlDomainManagedSavePath(driver, vm); if (name == NULL) goto cleanup; @@ -2583,6 +2674,9 @@ libxlDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus, goto cleanup; } + if (virDomainSetVcpusFlagsEnsureACL(dom->conn, vm->def, flags) < 0) + goto cleanup; + if (!virDomainObjIsActive(vm) && (flags & VIR_DOMAIN_VCPU_LIVE)) { virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("cannot set vcpus on an inactive domain")); @@ -2702,6 +2796,9 @@ libxlDomainGetVcpusFlags(virDomainPtr dom, unsigned int flags) goto cleanup; } + if (virDomainGetVcpusFlagsEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + active = virDomainObjIsActive(vm); if ((flags & (VIR_DOMAIN_VCPU_LIVE | VIR_DOMAIN_VCPU_CONFIG)) == 0) { @@ -2759,6 +2856,9 @@ libxlDomainPinVcpu(virDomainPtr dom, unsigned int vcpu, unsigned char *cpumap, goto cleanup; } + if (virDomainPinVcpuEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (!virDomainObjIsActive(vm)) { virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("cannot pin vcpus on an inactive domain")); @@ -2826,6 +2926,9 @@ libxlDomainGetVcpus(virDomainPtr dom, virVcpuInfoPtr info, int maxinfo, goto cleanup; } + if (virDomainGetVcpusEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (!virDomainObjIsActive(vm)) { virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not running")); goto cleanup; @@ -2890,6 +2993,9 @@ libxlDomainGetXMLDesc(virDomainPtr dom, unsigned int flags) goto cleanup; } + if (virDomainGetXMLDescEnsureACL(dom->conn, vm->def, flags) < 0) + goto cleanup; + ret = virDomainDefFormat(vm->def, flags); cleanup: @@ -2911,6 +3017,9 @@ libxlConnectDomainXMLFromNative(virConnectPtr conn, const char * nativeFormat, virCheckFlags(0, NULL); + if (virConnectDomainXMLFromNativeEnsureACL(conn) < 0) + goto cleanup; + if (STRNEQ(nativeFormat, LIBXL_CONFIG_FORMAT_XM)) { virReportError(VIR_ERR_INVALID_ARG, _("unsupported config type %s"), nativeFormat); @@ -2954,6 +3063,9 @@ libxlConnectDomainXMLToNative(virConnectPtr conn, const char * nativeFormat, virCheckFlags(0, NULL); + if (virConnectDomainXMLToNativeEnsureACL(conn) < 0) + goto cleanup; + if (STRNEQ(nativeFormat, LIBXL_CONFIG_FORMAT_XM)) { virReportError(VIR_ERR_INVALID_ARG, _("unsupported config type %s"), nativeFormat); @@ -2997,6 +3109,9 @@ libxlConnectListDefinedDomains(virConnectPtr conn, libxlDriverPrivatePtr driver = conn->privateData; int n; + if (virConnectListDefinedDomainsEnsureACL(conn) < 0) + return -1; + libxlDriverLock(driver); n = virDomainObjListGetInactiveNames(driver->domains, names, nnames); libxlDriverUnlock(driver); @@ -3009,6 +3124,9 @@ libxlConnectNumOfDefinedDomains(virConnectPtr conn) libxlDriverPrivatePtr driver = conn->privateData; int n; + if (virConnectNumOfDefinedDomainsEnsureACL(conn) < 0) + return -1; + libxlDriverLock(driver); n = virDomainObjListNumOfDomains(driver->domains, 0); libxlDriverUnlock(driver); @@ -3036,6 +3154,9 @@ libxlDomainCreateWithFlags(virDomainPtr dom, goto cleanup; } + if (virDomainCreateWithFlagsEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (virDomainObjIsActive(vm)) { virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is already running")); @@ -3073,6 +3194,9 @@ libxlDomainDefineXML(virConnectPtr conn, const char *xml) VIR_DOMAIN_XML_INACTIVE))) goto cleanup; + if (virDomainDefineXMLEnsureACL(conn, def) < 0) + goto cleanup; + if (!(vm = virDomainObjListAdd(driver->domains, def, driver->xmlopt, 0, @@ -3132,6 +3256,9 @@ libxlDomainUndefineFlags(virDomainPtr dom, goto cleanup; } + if (virDomainUndefineFlagsEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (!vm->persistent) { virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("cannot undefine transient domain")); @@ -3561,6 +3688,9 @@ libxlDomainAttachDeviceFlags(virDomainPtr dom, const char *xml, goto cleanup; } + if (virDomainAttachDeviceFlagsEnsureACL(dom->conn, vm->def, flags) < 0) + goto cleanup; + if (virDomainObjIsActive(vm)) { if (flags == VIR_DOMAIN_DEVICE_MODIFY_CURRENT) flags |= VIR_DOMAIN_DEVICE_MODIFY_LIVE; @@ -3666,6 +3796,9 @@ libxlDomainDetachDeviceFlags(virDomainPtr dom, const char *xml, goto cleanup; } + if (virDomainDetachDeviceFlagsEnsureACL(dom->conn, vm->def, flags) < 0) + goto cleanup; + if (virDomainObjIsActive(vm)) { if (flags == VIR_DOMAIN_DEVICE_MODIFY_CURRENT) flags |= VIR_DOMAIN_DEVICE_MODIFY_LIVE; @@ -3771,6 +3904,9 @@ libxlDomainUpdateDeviceFlags(virDomainPtr dom, const char *xml, goto cleanup; } + if (virDomainUpdateDeviceFlagsEnsureACL(dom->conn, vm->def, flags) < 0) + goto cleanup; + if (virDomainObjIsActive(vm)) { if (flags == VIR_DOMAIN_DEVICE_MODIFY_CURRENT) flags |= VIR_DOMAIN_DEVICE_MODIFY_LIVE; @@ -3854,6 +3990,9 @@ libxlNodeGetFreeMemory(virConnectPtr conn) const libxl_version_info* ver_info; libxlDriverPrivatePtr driver = conn->privateData; + if (virNodeGetFreeMemoryEnsureACL(conn) < 0) + return 0; + if (libxl_get_physinfo(driver->ctx, &phy_info)) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("libxl_get_physinfo_info failed")); @@ -3877,6 +4016,9 @@ libxlConnectDomainEventRegister(virConnectPtr conn, libxlDriverPrivatePtr driver = conn->privateData; int ret; + if (virConnectDomainEventRegisterEnsureACL(conn) < 0) + return -1; + libxlDriverLock(driver); ret = virDomainEventStateRegister(conn, driver->domainEventState, @@ -3894,6 +4036,9 @@ libxlConnectDomainEventDeregister(virConnectPtr conn, libxlDriverPrivatePtr driver = conn->privateData; int ret; + if (virConnectDomainEventDeregisterEnsureACL(conn) < 0) + return -1; + libxlDriverLock(driver); ret = virDomainEventStateDeregister(conn, driver->domainEventState, @@ -3922,6 +4067,9 @@ libxlDomainGetAutostart(virDomainPtr dom, int *autostart) goto cleanup; } + if (virDomainGetAutostartEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + *autostart = vm->autostart; ret = 0; @@ -3950,6 +4098,9 @@ libxlDomainSetAutostart(virDomainPtr dom, int autostart) goto cleanup; } + if (virDomainSetAutostartEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (!vm->persistent) { virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("cannot set autostart for transient domain")); @@ -4019,6 +4170,9 @@ libxlDomainGetSchedulerType(virDomainPtr dom, int *nparams) goto cleanup; } + if (virDomainGetSchedulerTypeEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (!virDomainObjIsActive(vm)) { virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not running")); goto cleanup; @@ -4084,6 +4238,9 @@ libxlDomainGetSchedulerParametersFlags(virDomainPtr dom, goto cleanup; } + if (virDomainGetSchedulerParametersFlagsEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + if (!virDomainObjIsActive(vm)) { virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not running")); @@ -4166,6 +4323,9 @@ libxlDomainSetSchedulerParametersFlags(virDomainPtr dom, goto cleanup; } + if (virDomainSetSchedulerParametersFlagsEnsureACL(dom->conn, vm->def, flags) < 0) + goto cleanup; + if (!virDomainObjIsActive(vm)) { virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not running")); goto cleanup; @@ -4234,6 +4394,10 @@ libxlDomainIsActive(virDomainPtr dom) virReportError(VIR_ERR_NO_DOMAIN, NULL); goto cleanup; } + + if (virDomainIsActiveEnsureACL(dom->conn, obj->def) < 0) + goto cleanup; + ret = virDomainObjIsActive(obj); cleanup: @@ -4256,6 +4420,10 @@ libxlDomainIsPersistent(virDomainPtr dom) virReportError(VIR_ERR_NO_DOMAIN, NULL); goto cleanup; } + + if (virDomainIsPersistentEnsureACL(dom->conn, obj->def) < 0) + goto cleanup; + ret = obj->persistent; cleanup: @@ -4278,6 +4446,10 @@ libxlDomainIsUpdated(virDomainPtr dom) virReportError(VIR_ERR_NO_DOMAIN, NULL); goto cleanup; } + + if (virDomainIsUpdatedEnsureACL(dom->conn, vm->def) < 0) + goto cleanup; + ret = vm->updated; cleanup: @@ -4294,6 +4466,9 @@ libxlConnectDomainEventRegisterAny(virConnectPtr conn, virDomainPtr dom, int eve libxlDriverPrivatePtr driver = conn->privateData; int ret; + if (virConnectDomainEventRegisterAnyEnsureACL(conn) < 0) + return -1; + libxlDriverLock(driver); if (virDomainEventStateRegisterID(conn, driver->domainEventState, @@ -4312,6 +4487,9 @@ libxlConnectDomainEventDeregisterAny(virConnectPtr conn, int callbackID) libxlDriverPrivatePtr driver = conn->privateData; int ret; + if (virConnectDomainEventDeregisterAnyEnsureACL(conn) < 0) + return -1; + libxlDriverLock(driver); ret = virDomainEventStateDeregisterID(conn, driver->domainEventState, @@ -4338,6 +4516,9 @@ libxlConnectListAllDomains(virConnectPtr conn, virCheckFlags(VIR_CONNECT_LIST_DOMAINS_FILTERS_ALL, -1); + if (virConnectListAllDomainsEnsureACL(conn) < 0) + return -1; + libxlDriverLock(driver); ret = virDomainObjListExport(driver->domains, conn, domains, flags); libxlDriverUnlock(driver); -- 1.8.1.4

From: "Daniel P. Berrange" <berrange@redhat.com> Insert calls to the ACL checking APIs in all storage driver entrypoints. Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- src/storage/storage_driver.c | 155 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 151 insertions(+), 4 deletions(-) diff --git a/src/storage/storage_driver.c b/src/storage/storage_driver.c index 990f0b1..edbd94d 100644 --- a/src/storage/storage_driver.c +++ b/src/storage/storage_driver.c @@ -48,6 +48,7 @@ #include "fdstream.h" #include "configmake.h" #include "virstring.h" +#include "access/viraccessapicheck.h" #define VIR_FROM_THIS VIR_FROM_STORAGE @@ -248,6 +249,9 @@ storagePoolLookupByUUID(virConnectPtr conn, goto cleanup; } + if (virStoragePoolLookupByUUIDEnsureACL(conn, pool->def) < 0) + goto cleanup; + ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid, NULL, NULL); @@ -274,6 +278,9 @@ storagePoolLookupByName(virConnectPtr conn, goto cleanup; } + if (virStoragePoolLookupByNameEnsureACL(conn, pool->def) < 0) + goto cleanup; + ret = virGetStoragePool(conn, pool->def->name, pool->def->uuid, NULL, NULL); @@ -285,7 +292,30 @@ cleanup: static virStoragePoolPtr storagePoolLookupByVolume(virStorageVolPtr vol) { - return storagePoolLookupByName(vol->conn, vol->pool); + virStorageDriverStatePtr driver = vol->conn->storagePrivateData; + virStoragePoolObjPtr pool; + virStoragePoolPtr ret = NULL; + + storageDriverLock(driver); + pool = virStoragePoolObjFindByName(&driver->pools, vol->pool); + storageDriverUnlock(driver); + + if (!pool) { + virReportError(VIR_ERR_NO_STORAGE_POOL, + _("no storage pool with matching name '%s'"), vol->pool); + goto cleanup; + } + + if (virStoragePoolLookupByVolumeEnsureACL(vol->conn, pool->def) < 0) + goto cleanup; + + ret = virGetStoragePool(vol->conn, pool->def->name, pool->def->uuid, + NULL, NULL); + +cleanup: + if (pool) + virStoragePoolObjUnlock(pool); + return ret; } static virDrvOpenStatus @@ -313,6 +343,9 @@ storageConnectNumOfStoragePools(virConnectPtr conn) { virStorageDriverStatePtr driver = conn->storagePrivateData; unsigned int i, nactive = 0; + if (virConnectNumOfStoragePoolsEnsureACL(conn) < 0) + return -1; + storageDriverLock(driver); for (i = 0 ; i < driver->pools.count ; i++) { virStoragePoolObjLock(driver->pools.objs[i]); @@ -332,6 +365,9 @@ storageConnectListStoragePools(virConnectPtr conn, virStorageDriverStatePtr driver = conn->storagePrivateData; int got = 0, i; + if (virConnectListStoragePoolsEnsureACL(conn) < 0) + return -1; + storageDriverLock(driver); for (i = 0 ; i < driver->pools.count && got < nnames ; i++) { virStoragePoolObjLock(driver->pools.objs[i]); @@ -361,6 +397,9 @@ storageConnectNumOfDefinedStoragePools(virConnectPtr conn) { virStorageDriverStatePtr driver = conn->storagePrivateData; unsigned int i, nactive = 0; + if (virConnectNumOfDefinedStoragePoolsEnsureACL(conn) < 0) + return -1; + storageDriverLock(driver); for (i = 0 ; i < driver->pools.count ; i++) { virStoragePoolObjLock(driver->pools.objs[i]); @@ -380,6 +419,9 @@ storageConnectListDefinedStoragePools(virConnectPtr conn, virStorageDriverStatePtr driver = conn->storagePrivateData; int got = 0, i; + if (virConnectListDefinedStoragePoolsEnsureACL(conn) < 0) + return -1; + storageDriverLock(driver); for (i = 0 ; i < driver->pools.count && got < nnames ; i++) { virStoragePoolObjLock(driver->pools.objs[i]); @@ -417,6 +459,9 @@ storageConnectFindStoragePoolSources(virConnectPtr conn, virStorageBackendPtr backend; char *ret = NULL; + if (virConnectFindStoragePoolSourcesEnsureACL(conn) < 0) + return NULL; + backend_type = virStoragePoolTypeFromString(type); if (backend_type < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, @@ -455,6 +500,10 @@ static int storagePoolIsActive(virStoragePoolPtr pool) virReportError(VIR_ERR_NO_STORAGE_POOL, NULL); goto cleanup; } + + if (virStoragePoolIsActiveEnsureACL(pool->conn, obj->def) < 0) + goto cleanup; + ret = virStoragePoolObjIsActive(obj); cleanup: @@ -476,6 +525,10 @@ static int storagePoolIsPersistent(virStoragePoolPtr pool) virReportError(VIR_ERR_NO_STORAGE_POOL, NULL); goto cleanup; } + + if (virStoragePoolIsPersistentEnsureACL(pool->conn, obj->def) < 0) + goto cleanup; + ret = obj->configFile ? 1 : 0; cleanup: @@ -502,6 +555,9 @@ storagePoolCreateXML(virConnectPtr conn, if (!(def = virStoragePoolDefParseString(xml))) goto cleanup; + if (virStoragePoolCreateXMLEnsureACL(conn, def) < 0) + goto cleanup; + if (virStoragePoolObjIsDuplicate(&driver->pools, def, 1) < 0) goto cleanup; @@ -559,6 +615,9 @@ storagePoolDefineXML(virConnectPtr conn, if (!(def = virStoragePoolDefParseString(xml))) goto cleanup; + if (virStoragePoolDefineXMLEnsureACL(conn, def) < 0) + goto cleanup; + if (virStoragePoolObjIsDuplicate(&driver->pools, def, 0) < 0) goto cleanup; @@ -604,6 +663,9 @@ storagePoolUndefine(virStoragePoolPtr obj) { goto cleanup; } + if (virStoragePoolUndefineEnsureACL(obj->conn, pool->def) < 0) + goto cleanup; + if (virStoragePoolObjIsActive(pool)) { virReportError(VIR_ERR_OPERATION_INVALID, _("storage pool '%s' is still active"), @@ -663,6 +725,9 @@ storagePoolCreate(virStoragePoolPtr obj, goto cleanup; } + if (virStoragePoolCreateEnsureACL(obj->conn, pool->def) < 0) + goto cleanup; + if ((backend = virStorageBackendForType(pool->def->type)) == NULL) goto cleanup; @@ -710,6 +775,9 @@ storagePoolBuild(virStoragePoolPtr obj, goto cleanup; } + if (virStoragePoolBuildEnsureACL(obj->conn, pool->def) < 0) + goto cleanup; + if ((backend = virStorageBackendForType(pool->def->type)) == NULL) goto cleanup; @@ -748,6 +816,9 @@ storagePoolDestroy(virStoragePoolPtr obj) { goto cleanup; } + if (virStoragePoolDestroyEnsureACL(obj->conn, pool->def) < 0) + goto cleanup; + if ((backend = virStorageBackendForType(pool->def->type)) == NULL) goto cleanup; @@ -808,6 +879,9 @@ storagePoolDelete(virStoragePoolPtr obj, goto cleanup; } + if (virStoragePoolDeleteEnsureACL(obj->conn, pool->def) < 0) + goto cleanup; + if ((backend = virStorageBackendForType(pool->def->type)) == NULL) goto cleanup; @@ -862,6 +936,9 @@ storagePoolRefresh(virStoragePoolPtr obj, goto cleanup; } + if (virStoragePoolRefreshEnsureACL(obj->conn, pool->def) < 0) + goto cleanup; + if ((backend = virStorageBackendForType(pool->def->type)) == NULL) goto cleanup; @@ -918,6 +995,9 @@ storagePoolGetInfo(virStoragePoolPtr obj, goto cleanup; } + if (virStoragePoolGetInfoEnsureACL(obj->conn, pool->def) < 0) + goto cleanup; + if (virStorageBackendForType(pool->def->type) == NULL) goto cleanup; @@ -958,6 +1038,9 @@ storagePoolGetXMLDesc(virStoragePoolPtr obj, goto cleanup; } + if (virStoragePoolGetXMLDescEnsureACL(obj->conn, pool->def) < 0) + goto cleanup; + if ((flags & VIR_STORAGE_XML_INACTIVE) && pool->newDef) def = pool->newDef; else @@ -988,6 +1071,9 @@ storagePoolGetAutostart(virStoragePoolPtr obj, goto cleanup; } + if (virStoragePoolGetAutostartEnsureACL(obj->conn, pool->def) < 0) + goto cleanup; + if (!pool->configFile) { *autostart = 0; } else { @@ -1017,6 +1103,9 @@ storagePoolSetAutostart(virStoragePoolPtr obj, goto cleanup; } + if (virStoragePoolSetAutostartEnsureACL(obj->conn, pool->def) < 0) + goto cleanup; + if (!pool->configFile) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("pool has no config file")); @@ -1077,6 +1166,9 @@ storagePoolNumOfVolumes(virStoragePoolPtr obj) { goto cleanup; } + if (virStoragePoolNumOfVolumesEnsureACL(obj->conn, pool->def) < 0) + goto cleanup; + if (!virStoragePoolObjIsActive(pool)) { virReportError(VIR_ERR_OPERATION_INVALID, _("storage pool '%s' is not active"), pool->def->name); @@ -1110,6 +1202,9 @@ storagePoolListVolumes(virStoragePoolPtr obj, goto cleanup; } + if (virStoragePoolListVolumesEnsureACL(obj->conn, pool->def) < 0) + goto cleanup; + if (!virStoragePoolObjIsActive(pool)) { virReportError(VIR_ERR_OPERATION_INVALID, _("storage pool '%s' is not active"), pool->def->name); @@ -1161,6 +1256,9 @@ storagePoolListAllVolumes(virStoragePoolPtr pool, goto cleanup; } + if (virStoragePoolListAllVolumesEnsureACL(pool->conn, obj->def) < 0) + goto cleanup; + if (!virStoragePoolObjIsActive(obj)) { virReportError(VIR_ERR_OPERATION_INVALID, _("storage pool '%s' is not active"), obj->def->name); @@ -1239,6 +1337,9 @@ storageVolLookupByName(virStoragePoolPtr obj, goto cleanup; } + if (virStorageVolLookupByNameEnsureACL(obj->conn, pool->def, vol) < 0) + goto cleanup; + ret = virGetStorageVol(obj->conn, pool->def->name, vol->name, vol->key, NULL, NULL); @@ -1263,21 +1364,27 @@ storageVolLookupByKey(virConnectPtr conn, virStorageVolDefPtr vol = virStorageVolDefFindByKey(driver->pools.objs[i], key); - if (vol) + if (vol) { + if (virStorageVolLookupByKeyEnsureACL(conn, driver->pools.objs[i]->def, vol) < 0) + goto cleanup; + ret = virGetStorageVol(conn, driver->pools.objs[i]->def->name, vol->name, vol->key, NULL, NULL); + goto cleanup; + } } virStoragePoolObjUnlock(driver->pools.objs[i]); } - storageDriverUnlock(driver); if (!ret) virReportError(VIR_ERR_NO_STORAGE_VOL, _("no storage vol with matching key %s"), key); +cleanup: + storageDriverUnlock(driver); return ret; } @@ -1317,12 +1424,17 @@ storageVolLookupByPath(virConnectPtr conn, stable_path); VIR_FREE(stable_path); - if (vol) + if (vol) { + if (virStorageVolLookupByPathEnsureACL(conn, driver->pools.objs[i]->def, vol) < 0) + goto cleanup; + ret = virGetStorageVol(conn, driver->pools.objs[i]->def->name, vol->name, vol->key, NULL, NULL); + goto cleanup; + } } virStoragePoolObjUnlock(driver->pools.objs[i]); } @@ -1331,6 +1443,7 @@ storageVolLookupByPath(virConnectPtr conn, virReportError(VIR_ERR_NO_STORAGE_VOL, _("no storage vol with matching path %s"), path); +cleanup: VIR_FREE(cleanpath); storageDriverUnlock(driver); return ret; @@ -1374,6 +1487,9 @@ storageVolCreateXML(virStoragePoolPtr obj, if (voldef == NULL) goto cleanup; + if (virStorageVolCreateXMLEnsureACL(obj->conn, pool->def, voldef) < 0) + goto cleanup; + if (virStorageVolDefFindByName(pool, voldef->name)) { virReportError(VIR_ERR_NO_STORAGE_VOL, _("storage vol '%s' already exists"), voldef->name); @@ -1525,6 +1641,9 @@ storageVolCreateXMLFrom(virStoragePoolPtr obj, if (newvol == NULL) goto cleanup; + if (virStorageVolCreateXMLFromEnsureACL(obj->conn, pool->def, newvol) < 0) + goto cleanup; + if (virStorageVolDefFindByName(pool, newvol->name)) { virReportError(VIR_ERR_INTERNAL_ERROR, _("storage volume name '%s' already in use."), @@ -1666,6 +1785,9 @@ storageVolDownload(virStorageVolPtr obj, goto out; } + if (virStorageVolDownloadEnsureACL(obj->conn, pool->def, vol) < 0) + goto out; + if (vol->building) { virReportError(VIR_ERR_OPERATION_INVALID, _("volume '%s' is still being allocated."), @@ -1729,6 +1851,9 @@ storageVolUpload(virStorageVolPtr obj, goto out; } + if (virStorageVolUploadEnsureACL(obj->conn, pool->def, vol) < 0) + goto out; + if (vol->building) { virReportError(VIR_ERR_OPERATION_INVALID, _("volume '%s' is still being allocated."), @@ -1796,6 +1921,9 @@ storageVolResize(virStorageVolPtr obj, goto out; } + if (virStorageVolResizeEnsureACL(obj->conn, pool->def, vol) < 0) + goto out; + if (vol->building) { virReportError(VIR_ERR_OPERATION_INVALID, _("volume '%s' is still being allocated."), @@ -2088,6 +2216,9 @@ storageVolWipePattern(virStorageVolPtr obj, goto out; } + if (virStorageVolWipePatternEnsureACL(obj->conn, pool->def, vol) < 0) + goto out; + if (vol->building) { virReportError(VIR_ERR_OPERATION_INVALID, _("volume '%s' is still being allocated."), @@ -2156,6 +2287,9 @@ storageVolDelete(virStorageVolPtr obj, goto cleanup; } + if (virStorageVolDeleteEnsureACL(obj->conn, pool->def, vol) < 0) + goto cleanup; + if (vol->building) { virReportError(VIR_ERR_OPERATION_INVALID, _("volume '%s' is still being allocated."), @@ -2235,6 +2369,9 @@ storageVolGetInfo(virStorageVolPtr obj, goto cleanup; } + if (virStorageVolGetInfoEnsureACL(obj->conn, pool->def, vol) < 0) + goto cleanup; + if ((backend = virStorageBackendForType(pool->def->type)) == NULL) goto cleanup; @@ -2292,6 +2429,9 @@ storageVolGetXMLDesc(virStorageVolPtr obj, goto cleanup; } + if (virStorageVolGetXMLDescEnsureACL(obj->conn, pool->def, vol) < 0) + goto cleanup; + if ((backend = virStorageBackendForType(pool->def->type)) == NULL) goto cleanup; @@ -2340,6 +2480,9 @@ storageVolGetPath(virStorageVolPtr obj) { goto cleanup; } + if (virStorageVolGetPathEnsureACL(obj->conn, pool->def, vol) < 0) + goto cleanup; + ret = strdup(vol->target.path); if (ret == NULL) virReportOOMError(); @@ -2360,10 +2503,14 @@ storageConnectListAllStoragePools(virConnectPtr conn, virCheckFlags(VIR_CONNECT_LIST_STORAGE_POOLS_FILTERS_ALL, -1); + if (virConnectListAllStoragePoolsEnsureACL(conn) < 0) + goto cleanup; + storageDriverLock(driver); ret = virStoragePoolList(conn, driver->pools, pools, flags); storageDriverUnlock(driver); +cleanup: return ret; } -- 1.8.1.4

From: "Daniel P. Berrange" <berrange@redhat.com> Insert calls to the ACL checking APIs in all network driver entrypoints. Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- src/network/bridge_driver.c | 61 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/src/network/bridge_driver.c b/src/network/bridge_driver.c index 99c1316..76966df 100644 --- a/src/network/bridge_driver.c +++ b/src/network/bridge_driver.c @@ -65,6 +65,7 @@ #include "virdbus.h" #include "virfile.h" #include "virstring.h" +#include "access/viraccessapicheck.h" #define VIR_FROM_THIS VIR_FROM_NETWORK @@ -2769,6 +2770,9 @@ static virNetworkPtr networkLookupByUUID(virConnectPtr conn, goto cleanup; } + if (virNetworkLookupByUUIDEnsureACL(conn, network->def) < 0) + goto cleanup; + ret = virGetNetwork(conn, network->def->name, network->def->uuid); cleanup: @@ -2792,6 +2796,9 @@ static virNetworkPtr networkLookupByName(virConnectPtr conn, goto cleanup; } + if (virNetworkLookupByNameEnsureACL(conn, network->def) < 0) + goto cleanup; + ret = virGetNetwork(conn, network->def->name, network->def->uuid); cleanup: @@ -2822,6 +2829,9 @@ static int networkConnectNumOfNetworks(virConnectPtr conn) { int nactive = 0, i; struct network_driver *driver = conn->networkPrivateData; + if (virConnectNumOfNetworksEnsureACL(conn) < 0) + return -1; + networkDriverLock(driver); for (i = 0 ; i < driver->networks.count ; i++) { virNetworkObjLock(driver->networks.objs[i]); @@ -2838,6 +2848,9 @@ static int networkConnectListNetworks(virConnectPtr conn, char **const names, in struct network_driver *driver = conn->networkPrivateData; int got = 0, i; + if (virConnectListNetworksEnsureACL(conn) < 0) + return -1; + networkDriverLock(driver); for (i = 0 ; i < driver->networks.count && got < nnames ; i++) { virNetworkObjLock(driver->networks.objs[i]); @@ -2865,6 +2878,9 @@ static int networkConnectNumOfDefinedNetworks(virConnectPtr conn) { int ninactive = 0, i; struct network_driver *driver = conn->networkPrivateData; + if (virConnectNumOfDefinedNetworksEnsureACL(conn) < 0) + return -1; + networkDriverLock(driver); for (i = 0 ; i < driver->networks.count ; i++) { virNetworkObjLock(driver->networks.objs[i]); @@ -2881,6 +2897,9 @@ static int networkConnectListDefinedNetworks(virConnectPtr conn, char **const na struct network_driver *driver = conn->networkPrivateData; int got = 0, i; + if (virConnectListDefinedNetworksEnsureACL(conn) < 0) + return -1; + networkDriverLock(driver); for (i = 0 ; i < driver->networks.count && got < nnames ; i++) { virNetworkObjLock(driver->networks.objs[i]); @@ -2913,10 +2932,14 @@ networkConnectListAllNetworks(virConnectPtr conn, virCheckFlags(VIR_CONNECT_LIST_NETWORKS_FILTERS_ALL, -1); + if (virConnectListAllNetworksEnsureACL(conn) < 0) + goto cleanup; + networkDriverLock(driver); ret = virNetworkList(conn, driver->networks, nets, flags); networkDriverUnlock(driver); +cleanup: return ret; } @@ -2933,6 +2956,10 @@ static int networkIsActive(virNetworkPtr net) virReportError(VIR_ERR_NO_NETWORK, NULL); goto cleanup; } + + if (virNetworkIsActiveEnsureACL(net->conn, obj->def) < 0) + goto cleanup; + ret = virNetworkObjIsActive(obj); cleanup: @@ -2954,6 +2981,10 @@ static int networkIsPersistent(virNetworkPtr net) virReportError(VIR_ERR_NO_NETWORK, NULL); goto cleanup; } + + if (virNetworkIsPersistentEnsureACL(net->conn, obj->def) < 0) + goto cleanup; + ret = obj->persistent; cleanup: @@ -3121,6 +3152,9 @@ static virNetworkPtr networkCreateXML(virConnectPtr conn, const char *xml) { if (!(def = virNetworkDefParseString(xml))) goto cleanup; + if (virNetworkCreateXMLEnsureACL(conn, def) < 0) + goto cleanup; + if (networkValidate(driver, def, true) < 0) goto cleanup; @@ -3161,6 +3195,9 @@ static virNetworkPtr networkDefineXML(virConnectPtr conn, const char *xml) { if (!(def = virNetworkDefParseString(xml))) goto cleanup; + if (virNetworkDefineXMLEnsureACL(conn, def) < 0) + goto cleanup; + if (networkValidate(driver, def, false) < 0) goto cleanup; @@ -3219,6 +3256,9 @@ networkUndefine(virNetworkPtr net) { goto cleanup; } + if (virNetworkUndefineEnsureACL(net->conn, network->def) < 0) + goto cleanup; + if (virNetworkObjIsActive(network)) active = true; @@ -3279,6 +3319,9 @@ networkUpdate(virNetworkPtr net, goto cleanup; } + if (virNetworkUpdateEnsureACL(net->conn, network->def, flags) < 0) + goto cleanup; + /* see if we are listening for dhcp pre-modification */ for (ii = 0; (ipdef = virNetworkDefGetIpByIndex(network->def, AF_INET, ii)); @@ -3414,6 +3457,9 @@ static int networkCreate(virNetworkPtr net) { goto cleanup; } + if (virNetworkCreateEnsureACL(net->conn, network->def) < 0) + goto cleanup; + ret = networkStartNetwork(driver, network); cleanup: @@ -3437,6 +3483,9 @@ static int networkDestroy(virNetworkPtr net) { goto cleanup; } + if (virNetworkDestroyEnsureACL(net->conn, network->def) < 0) + goto cleanup; + if (!virNetworkObjIsActive(network)) { virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("network is not active")); @@ -3482,6 +3531,9 @@ static char *networkGetXMLDesc(virNetworkPtr net, goto cleanup; } + if (virNetworkGetXMLDescEnsureACL(net->conn, network->def) < 0) + goto cleanup; + if ((flags & VIR_NETWORK_XML_INACTIVE) && network->newDef) def = network->newDef; else @@ -3510,6 +3562,9 @@ static char *networkGetBridgeName(virNetworkPtr net) { goto cleanup; } + if (virNetworkGetBridgeNameEnsureACL(net->conn, network->def) < 0) + goto cleanup; + if (!(network->def->bridge)) { virReportError(VIR_ERR_INTERNAL_ERROR, _("network '%s' does not have a bridge name."), @@ -3540,6 +3595,9 @@ static int networkGetAutostart(virNetworkPtr net, goto cleanup; } + if (virNetworkGetAutostartEnsureACL(net->conn, network->def) < 0) + goto cleanup; + *autostart = network->autostart; ret = 0; @@ -3565,6 +3623,9 @@ static int networkSetAutostart(virNetworkPtr net, goto cleanup; } + if (virNetworkSetAutostartEnsureACL(net->conn, network->def) < 0) + goto cleanup; + if (!network->persistent) { virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("cannot set autostart for transient network")); -- 1.8.1.4

From: "Daniel P. Berrange" <berrange@redhat.com> Insert calls to the ACL checking APIs in all interface driver entrypoints. Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- src/interface/interface_backend_netcf.c | 114 ++++++++++++++++++++++++++++++++ src/interface/interface_backend_udev.c | 85 +++++++++++++++++++++--- 2 files changed, 191 insertions(+), 8 deletions(-) diff --git a/src/interface/interface_backend_netcf.c b/src/interface/interface_backend_netcf.c index cbba4fd..4707e3e 100644 --- a/src/interface/interface_backend_netcf.c +++ b/src/interface/interface_backend_netcf.c @@ -31,6 +31,7 @@ #include "interface_conf.h" #include "viralloc.h" #include "virlog.h" +#include "access/viraccessapicheck.h" #define VIR_FROM_THIS VIR_FROM_INTERFACE @@ -52,6 +53,36 @@ static void interfaceDriverUnlock(struct interface_driver *driver) virMutexUnlock(&driver->lock); } +/* + * Get a minimal virInterfaceDef containing enough metadata + * for access control checks to be performed. Currently + * this implies existance of name and mac address attributes + */ +static virInterfaceDef * ATTRIBUTE_NONNULL(1) +netcfGetMinimalDefForDevice(struct netcf_if *iface) +{ + virInterfaceDef *def; + + /* Allocate our interface definition structure */ + if (VIR_ALLOC(def) < 0) { + virReportOOMError(); + return NULL; + } + + if (VIR_STRDUP(def->name, ncf_if_name(iface)) < 0) + goto cleanup; + + if (VIR_STRDUP(def->mac, ncf_if_mac_string(iface)) < 0) + goto cleanup; + + return def; + +cleanup: + virInterfaceDefFree(def); + return NULL; +} + + static int netcf_to_vir_err(int netcf_errcode) { switch (netcf_errcode) @@ -182,6 +213,9 @@ static int netcfConnectNumOfInterfaces(virConnectPtr conn) int count; struct interface_driver *driver = conn->interfacePrivateData; + if (virConnectNumOfInterfacesEnsureACL(conn) < 0) + return -1; + interfaceDriverLock(driver); count = ncf_num_of_interfaces(driver->netcf, NETCF_IFACE_ACTIVE); if (count < 0) { @@ -201,6 +235,9 @@ static int netcfConnectListInterfaces(virConnectPtr conn, char **const names, in struct interface_driver *driver = conn->interfacePrivateData; int count; + if (virConnectListInterfacesEnsureACL(conn) < 0) + return -1; + interfaceDriverLock(driver); count = ncf_list_interfaces(driver->netcf, nnames, names, NETCF_IFACE_ACTIVE); @@ -223,6 +260,9 @@ static int netcfConnectNumOfDefinedInterfaces(virConnectPtr conn) int count; struct interface_driver *driver = conn->interfacePrivateData; + if (virConnectNumOfDefinedInterfacesEnsureACL(conn) < 0) + return -1; + interfaceDriverLock(driver); count = ncf_num_of_interfaces(driver->netcf, NETCF_IFACE_INACTIVE); if (count < 0) { @@ -243,6 +283,9 @@ static int netcfConnectListDefinedInterfaces(virConnectPtr conn, char **const na struct interface_driver *driver = conn->interfacePrivateData; int count; + if (virConnectListDefinedInterfacesEnsureACL(conn) < 0) + return -1; + interfaceDriverLock(driver); count = ncf_list_interfaces(driver->netcf, nnames, names, NETCF_IFACE_INACTIVE); @@ -279,6 +322,9 @@ netcfConnectListAllInterfaces(virConnectPtr conn, virCheckFlags(VIR_CONNECT_LIST_INTERFACES_ACTIVE | VIR_CONNECT_LIST_INTERFACES_INACTIVE, -1); + if (virConnectListAllInterfacesEnsureACL(conn) < 0) + return -1; + interfaceDriverLock(driver); /* List all interfaces, in case of we might support new filter flags @@ -413,6 +459,7 @@ static virInterfacePtr netcfInterfaceLookupByName(virConnectPtr conn, struct interface_driver *driver = conn->interfacePrivateData; struct netcf_if *iface; virInterfacePtr ret = NULL; + virInterfaceDefPtr def = NULL; interfaceDriverLock(driver); iface = ncf_lookup_by_name(driver->netcf, name); @@ -431,10 +478,17 @@ static virInterfacePtr netcfInterfaceLookupByName(virConnectPtr conn, goto cleanup; } + if (!(def = netcfGetMinimalDefForDevice(iface))) + goto cleanup; + + if (virInterfaceLookupByNameEnsureACL(conn, def) < 0) + goto cleanup; + ret = virGetInterface(conn, ncf_if_name(iface), ncf_if_mac_string(iface)); cleanup: ncf_if_free(iface); + virInterfaceDefFree(def); interfaceDriverUnlock(driver); return ret; } @@ -446,6 +500,7 @@ static virInterfacePtr netcfInterfaceLookupByMACString(virConnectPtr conn, struct netcf_if *iface; int niface; virInterfacePtr ret = NULL; + virInterfaceDefPtr def = NULL; interfaceDriverLock(driver); niface = ncf_lookup_by_mac_string(driver->netcf, macstr, 1, &iface); @@ -471,10 +526,18 @@ static virInterfacePtr netcfInterfaceLookupByMACString(virConnectPtr conn, goto cleanup; } + + if (!(def = netcfGetMinimalDefForDevice(iface))) + goto cleanup; + + if (virInterfaceLookupByMACStringEnsureACL(conn, def) < 0) + goto cleanup; + ret = virGetInterface(conn, ncf_if_name(iface), ncf_if_mac_string(iface)); cleanup: ncf_if_free(iface); + virInterfaceDefFree(def); interfaceDriverUnlock(driver); return ret; } @@ -519,6 +582,9 @@ static char *netcfInterfaceGetXMLDesc(virInterfacePtr ifinfo, goto cleanup; } + if (virInterfaceGetXMLDescEnsureACL(ifinfo->conn, ifacedef) < 0) + goto cleanup; + ret = virInterfaceDefFormat(ifacedef); if (!ret) { /* error was already reported */ @@ -553,6 +619,9 @@ static virInterfacePtr netcfInterfaceDefineXML(virConnectPtr conn, goto cleanup; } + if (virInterfaceDefineXMLEnsureACL(conn, ifacedef) < 0) + goto cleanup; + xmlstr = virInterfaceDefFormat(ifacedef); if (!xmlstr) { /* error was already reported */ @@ -583,6 +652,7 @@ cleanup: static int netcfInterfaceUndefine(virInterfacePtr ifinfo) { struct interface_driver *driver = ifinfo->conn->interfacePrivateData; struct netcf_if *iface = NULL; + virInterfaceDefPtr def = NULL; int ret = -1; interfaceDriverLock(driver); @@ -593,6 +663,13 @@ static int netcfInterfaceUndefine(virInterfacePtr ifinfo) { goto cleanup; } + + if (!(def = netcfGetMinimalDefForDevice(iface))) + goto cleanup; + + if (virInterfaceUndefineEnsureACL(ifinfo->conn, def) < 0) + goto cleanup; + ret = ncf_if_undefine(iface); if (ret < 0) { const char *errmsg, *details; @@ -606,6 +683,7 @@ static int netcfInterfaceUndefine(virInterfacePtr ifinfo) { cleanup: ncf_if_free(iface); + virInterfaceDefFree(def); interfaceDriverUnlock(driver); return ret; } @@ -615,6 +693,7 @@ static int netcfInterfaceCreate(virInterfacePtr ifinfo, { struct interface_driver *driver = ifinfo->conn->interfacePrivateData; struct netcf_if *iface = NULL; + virInterfaceDefPtr def = NULL; int ret = -1; virCheckFlags(0, -1); @@ -627,6 +706,13 @@ static int netcfInterfaceCreate(virInterfacePtr ifinfo, goto cleanup; } + + if (!(def = netcfGetMinimalDefForDevice(iface))) + goto cleanup; + + if (virInterfaceCreateEnsureACL(ifinfo->conn, def) < 0) + goto cleanup; + ret = ncf_if_up(iface); if (ret < 0) { const char *errmsg, *details; @@ -640,6 +726,7 @@ static int netcfInterfaceCreate(virInterfacePtr ifinfo, cleanup: ncf_if_free(iface); + virInterfaceDefFree(def); interfaceDriverUnlock(driver); return ret; } @@ -649,6 +736,7 @@ static int netcfInterfaceDestroy(virInterfacePtr ifinfo, { struct interface_driver *driver = ifinfo->conn->interfacePrivateData; struct netcf_if *iface = NULL; + virInterfaceDefPtr def = NULL; int ret = -1; virCheckFlags(0, -1); @@ -661,6 +749,13 @@ static int netcfInterfaceDestroy(virInterfacePtr ifinfo, goto cleanup; } + + if (!(def = netcfGetMinimalDefForDevice(iface))) + goto cleanup; + + if (virInterfaceDestroyEnsureACL(ifinfo->conn, def) < 0) + goto cleanup; + ret = ncf_if_down(iface); if (ret < 0) { const char *errmsg, *details; @@ -674,6 +769,7 @@ static int netcfInterfaceDestroy(virInterfacePtr ifinfo, cleanup: ncf_if_free(iface); + virInterfaceDefFree(def); interfaceDriverUnlock(driver); return ret; } @@ -683,6 +779,7 @@ static int netcfInterfaceIsActive(virInterfacePtr ifinfo) struct interface_driver *driver = ifinfo->conn->interfacePrivateData; struct netcf_if *iface = NULL; unsigned int flags = 0; + virInterfaceDefPtr def = NULL; int ret = -1; interfaceDriverLock(driver); @@ -693,6 +790,13 @@ static int netcfInterfaceIsActive(virInterfacePtr ifinfo) goto cleanup; } + + if (!(def = netcfGetMinimalDefForDevice(iface))) + goto cleanup; + + if (virInterfaceIsActiveEnsureACL(ifinfo->conn, def) < 0) + goto cleanup; + if (ncf_if_status(iface, &flags) < 0) { const char *errmsg, *details; int errcode = ncf_error(driver->netcf, &errmsg, &details); @@ -707,6 +811,7 @@ static int netcfInterfaceIsActive(virInterfacePtr ifinfo) cleanup: ncf_if_free(iface); + virInterfaceDefFree(def); interfaceDriverUnlock(driver); return ret; } @@ -719,6 +824,9 @@ static int netcfInterfaceChangeBegin(virConnectPtr conn, unsigned int flags) virCheckFlags(0, -1); /* currently flags must be 0 */ + if (virInterfaceChangeBeginEnsureACL(conn) < 0) + return -1; + interfaceDriverLock(driver); ret = ncf_change_begin(driver->netcf, 0); @@ -742,6 +850,9 @@ static int netcfInterfaceChangeCommit(virConnectPtr conn, unsigned int flags) virCheckFlags(0, -1); /* currently flags must be 0 */ + if (virInterfaceChangeCommitEnsureACL(conn) < 0) + return -1; + interfaceDriverLock(driver); ret = ncf_change_commit(driver->netcf, 0); @@ -765,6 +876,9 @@ static int netcfInterfaceChangeRollback(virConnectPtr conn, unsigned int flags) virCheckFlags(0, -1); /* currently flags must be 0 */ + if (virInterfaceChangeRollbackEnsureACL(conn) < 0) + return -1; + interfaceDriverLock(driver); ret = ncf_change_rollback(driver->netcf, 0); diff --git a/src/interface/interface_backend_udev.c b/src/interface/interface_backend_udev.c index f9a179f..a6e7bd5 100644 --- a/src/interface/interface_backend_udev.c +++ b/src/interface/interface_backend_udev.c @@ -31,6 +31,7 @@ #include "interface_conf.h" #include "viralloc.h" #include "virstring.h" +#include "access/viraccessapicheck.h" #define VIR_FROM_THIS VIR_FROM_INTERFACE @@ -61,6 +62,36 @@ virUdevStatusString(virUdevStatus status) return ""; } +/* + * Get a minimal virInterfaceDef containing enough metadata + * for access control checks to be performed. Currently + * this implies existance of name and mac address attributes + */ +static virInterfaceDef * ATTRIBUTE_NONNULL(1) +udevGetMinimalDefForDevice(struct udev_device *dev) +{ + virInterfaceDef *def; + + /* Allocate our interface definition structure */ + if (VIR_ALLOC(def) < 0) { + virReportOOMError(); + return NULL; + } + + if (VIR_STRDUP(def->name, udev_device_get_sysname(dev)) < 0) + goto cleanup; + + if (VIR_STRDUP(def->mac, udev_device_get_sysattr_value(dev, "address")) < 0) + goto cleanup; + + return def; + +cleanup: + virInterfaceDefFree(def); + return NULL; +} + + static struct udev_enumerate * ATTRIBUTE_NONNULL(1) udevGetDevices(struct udev *udev, virUdevStatus status) { @@ -255,6 +286,9 @@ error: static int udevConnectNumOfInterfaces(virConnectPtr conn) { + if (virConnectNumOfInterfacesEnsureACL(conn) < 0) + return -1; + return udevNumOfInterfacesByStatus(conn, VIR_UDEV_IFACE_ACTIVE); } @@ -263,6 +297,9 @@ udevConnectListInterfaces(virConnectPtr conn, char **const names, int names_len) { + if (virConnectListInterfacesEnsureACL(conn) < 0) + return -1; + return udevListInterfacesByStatus(conn, names, names_len, VIR_UDEV_IFACE_ACTIVE); } @@ -270,6 +307,9 @@ udevConnectListInterfaces(virConnectPtr conn, static int udevConnectNumOfDefinedInterfaces(virConnectPtr conn) { + if (virConnectNumOfDefinedInterfacesEnsureACL(conn) < 0) + return -1; + return udevNumOfInterfacesByStatus(conn, VIR_UDEV_IFACE_INACTIVE); } @@ -278,6 +318,9 @@ udevConnectListDefinedInterfaces(virConnectPtr conn, char **const names, int names_len) { + if (virConnectListDefinedInterfacesEnsureACL(conn) < 0) + return -1; + return udevListInterfacesByStatus(conn, names, names_len, VIR_UDEV_IFACE_INACTIVE); } @@ -302,6 +345,9 @@ udevConnectListAllInterfaces(virConnectPtr conn, virCheckFlags(VIR_CONNECT_LIST_INTERFACES_ACTIVE | VIR_CONNECT_LIST_INTERFACES_INACTIVE, -1); + if (virConnectListAllInterfacesEnsureACL(conn) < 0) + return -1; + /* Grab a udev reference */ udev = udev_ref(driverState->udev); @@ -413,8 +459,8 @@ udevInterfaceLookupByName(virConnectPtr conn, const char *name) struct udev_iface_driver *driverState = conn->interfacePrivateData; struct udev *udev = udev_ref(driverState->udev); struct udev_device *dev; - const char *macaddr; virInterfacePtr ret = NULL; + virInterfaceDefPtr def = NULL; /* get a device reference based on the device name */ dev = udev_device_new_from_subsystem_sysname(udev, "net", name); @@ -425,12 +471,18 @@ udevInterfaceLookupByName(virConnectPtr conn, const char *name) goto cleanup; } - macaddr = udev_device_get_sysattr_value(dev, "address"); - ret = virGetInterface(conn, name, macaddr); + if (!(def = udevGetMinimalDefForDevice(dev))) + goto err; + + if (virInterfaceLookupByNameEnsureACL(conn, def) < 0) + goto err; + + ret = virGetInterface(conn, def->name, def->mac); udev_device_unref(dev); cleanup: udev_unref(udev); + virInterfaceDefFree(def); return ret; } @@ -443,7 +495,7 @@ udevInterfaceLookupByMACString(virConnectPtr conn, const char *macstr) struct udev_enumerate *enumerate = NULL; struct udev_list_entry *dev_entry; struct udev_device *dev; - const char *name; + virInterfaceDefPtr def = NULL; virInterfacePtr ret = NULL; enumerate = udevGetDevices(udev, VIR_UDEV_IFACE_ALL); @@ -481,14 +533,21 @@ udevInterfaceLookupByMACString(virConnectPtr conn, const char *macstr) } dev = udev_device_new_from_syspath(udev, udev_list_entry_get_name(dev_entry)); - name = udev_device_get_sysname(dev); - ret = virGetInterface(conn, name, macstr); + + if (!(def = udevGetMinimalDefForDevice(dev))) + goto err; + + if (virInterfaceLookupByMACStringEnsureACL(conn, def) < 0) + goto err; + + ret = virGetInterface(conn, def->name, def->mac); udev_device_unref(dev); cleanup: if (enumerate) udev_enumerate_unref(enumerate); udev_unref(udev); + virInterfaceDefFree(def); return ret; } @@ -1045,6 +1104,9 @@ udevInterfaceGetXMLDesc(virInterfacePtr ifinfo, if (!ifacedef) goto cleanup; + if (virInterfaceGetXMLDescEnsureACL(ifinfo->conn, ifacedef) < 0) + goto err; + xmlstr = virInterfaceDefFormat(ifacedef); virInterfaceDefFree(ifacedef); @@ -1062,7 +1124,8 @@ udevInterfaceIsActive(virInterfacePtr ifinfo) struct udev_iface_driver *driverState = ifinfo->conn->interfacePrivateData; struct udev *udev = udev_ref(driverState->udev); struct udev_device *dev; - int status; + virInterfaceDefPtr def = NULL; + int status = -1; dev = udev_device_new_from_subsystem_sysname(udev, "net", ifinfo->name); @@ -1070,10 +1133,15 @@ udevInterfaceIsActive(virInterfacePtr ifinfo) virReportError(VIR_ERR_NO_INTERFACE, _("couldn't find interface named '%s'"), ifinfo->name); - status = -1; goto cleanup; } + if (!(def = udevGetMinimalDefForDevice(dev))) + goto cleanup; + + if (virInterfaceIsActiveEnsureACL(ifinfo->conn, def) < 0) + goto cleanup; + /* Check if it's active or not */ status = STREQ(udev_device_get_sysattr_value(dev, "operstate"), "up"); @@ -1081,6 +1149,7 @@ udevInterfaceIsActive(virInterfacePtr ifinfo) cleanup: udev_unref(udev); + virInterfaceDefFree(def); return status; } -- 1.8.1.4

From: "Daniel P. Berrange" <berrange@redhat.com> Insert calls to the ACL checking APIs in all node device driver entrypoints. Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- src/node_device/node_device_driver.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/src/node_device/node_device_driver.c b/src/node_device/node_device_driver.c index c596901..377d5a9 100644 --- a/src/node_device/node_device_driver.c +++ b/src/node_device/node_device_driver.c @@ -37,6 +37,8 @@ #include "node_device_conf.h" #include "node_device_hal.h" #include "node_device_driver.h" +#include "virutil.h" +#include "access/viraccessapicheck.h" #define VIR_FROM_THIS VIR_FROM_NODEDEV @@ -125,6 +127,9 @@ nodeNumOfDevices(virConnectPtr conn, int ndevs = 0; unsigned int i; + if (virNodeNumOfDevicesEnsureACL(conn) < 0) + return -1; + virCheckFlags(0, -1); nodeDeviceLock(driver); @@ -150,6 +155,9 @@ nodeListDevices(virConnectPtr conn, int ndevs = 0; unsigned int i; + if (virNodeListDevicesEnsureACL(conn) < 0) + return -1; + virCheckFlags(0, -1); nodeDeviceLock(driver); @@ -186,6 +194,9 @@ nodeConnectListAllNodeDevices(virConnectPtr conn, virCheckFlags(VIR_CONNECT_LIST_NODE_DEVICES_FILTERS_CAP, -1); + if (virConnectListAllNodeDevicesEnsureACL(conn) < 0) + return -1; + nodeDeviceLock(driver); ret = virNodeDeviceList(conn, driver->devs, devices, flags); nodeDeviceUnlock(driver); @@ -208,6 +219,9 @@ nodeDeviceLookupByName(virConnectPtr conn, const char *name) goto cleanup; } + if (virNodeDeviceLookupByNameEnsureACL(conn, obj->def) < 0) + goto cleanup; + ret = virGetNodeDevice(conn, name); cleanup: @@ -246,6 +260,10 @@ nodeDeviceLookupSCSIHostByWWN(virConnectPtr conn, VIR_NODE_DEV_CAP_FLAG_HBA_FC_HOST) { if (STREQ(cap->data.scsi_host.wwnn, wwnn) && STREQ(cap->data.scsi_host.wwpn, wwpn)) { + + if (virNodeDeviceLookupSCSIHostByWWNEnsureACL(conn, obj->def) < 0) + goto out; + dev = virGetNodeDevice(conn, obj->def->name); virNodeDeviceObjUnlock(obj); goto out; @@ -285,6 +303,9 @@ nodeDeviceGetXMLDesc(virNodeDevicePtr dev, goto cleanup; } + if (virNodeDeviceGetXMLDescEnsureACL(dev->conn, obj->def) < 0) + goto cleanup; + update_driver_name(obj); update_caps(obj); @@ -315,6 +336,9 @@ nodeDeviceGetParent(virNodeDevicePtr dev) goto cleanup; } + if (virNodeDeviceGetParentEnsureACL(dev->conn, obj->def) < 0) + goto cleanup; + if (obj->def->parent) { if (VIR_STRDUP(ret, obj->def->parent) < 0) goto cleanup; @@ -350,6 +374,9 @@ nodeDeviceNumOfCaps(virNodeDevicePtr dev) goto cleanup; } + if (virNodeDeviceNumOfCapsEnsureACL(dev->conn, obj->def) < 0) + goto cleanup; + for (caps = obj->def->caps; caps; caps = caps->next) ++ncaps; ret = ncaps; @@ -381,6 +408,9 @@ nodeDeviceListCaps(virNodeDevicePtr dev, char **const names, int maxnames) goto cleanup; } + if (virNodeDeviceListCapsEnsureACL(dev->conn, obj->def) < 0) + goto cleanup; + for (caps = obj->def->caps; caps && ncaps < maxnames; caps = caps->next) { if (VIR_STRDUP(names[ncaps], virNodeDevCapTypeToString(caps->type)) < 0) goto cleanup; @@ -488,6 +518,9 @@ nodeDeviceCreateXML(virConnectPtr conn, goto cleanup; } + if (virNodeDeviceCreateXMLEnsureACL(conn, def) < 0) + goto cleanup; + if (virNodeDeviceGetWWNs(def, &wwnn, &wwpn) == -1) { goto cleanup; } @@ -541,6 +574,9 @@ nodeDeviceDestroy(virNodeDevicePtr dev) goto out; } + if (virNodeDeviceDestroyEnsureACL(dev->conn, obj->def) < 0) + goto out; + if (virNodeDeviceGetWWNs(obj->def, &wwnn, &wwpn) == -1) { goto out; } -- 1.8.1.4

From: "Daniel P. Berrange" <berrange@redhat.com> Insert calls to the ACL checking APIs in all nwfilter driver entrypoints. Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- src/nwfilter/nwfilter_driver.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/nwfilter/nwfilter_driver.c b/src/nwfilter/nwfilter_driver.c index 64ea251..14c97a5 100644 --- a/src/nwfilter/nwfilter_driver.c +++ b/src/nwfilter/nwfilter_driver.c @@ -42,6 +42,7 @@ #include "nwfilter_gentech_driver.h" #include "configmake.h" #include "virstring.h" +#include "access/viraccessapicheck.h" #include "nwfilter_ipaddrmap.h" #include "nwfilter_dhcpsnoop.h" @@ -380,6 +381,9 @@ nwfilterLookupByUUID(virConnectPtr conn, goto cleanup; } + if (virNWFilterLookupByUUIDEnsureACL(conn, nwfilter->def) < 0) + goto cleanup; + ret = virGetNWFilter(conn, nwfilter->def->name, nwfilter->def->uuid); cleanup: @@ -406,6 +410,9 @@ nwfilterLookupByName(virConnectPtr conn, goto cleanup; } + if (virNWFilterLookupByNameEnsureACL(conn, nwfilter->def) < 0) + goto cleanup; + ret = virGetNWFilter(conn, nwfilter->def->name, nwfilter->def->uuid); cleanup: @@ -440,6 +447,10 @@ nwfilterClose(virConnectPtr conn) { static int nwfilterConnectNumOfNWFilters(virConnectPtr conn) { virNWFilterDriverStatePtr driver = conn->nwfilterPrivateData; + + if (virConnectNumOfNWFiltersEnsureACL(conn) < 0) + return -1; + return driver->nwfilters.count; } @@ -451,6 +462,9 @@ nwfilterConnectListNWFilters(virConnectPtr conn, virNWFilterDriverStatePtr driver = conn->nwfilterPrivateData; int got = 0, i; + if (virConnectListNWFiltersEnsureACL(conn) < 0) + return -1; + nwfilterDriverLock(driver); for (i = 0 ; i < driver->nwfilters.count && got < nnames ; i++) { virNWFilterObjLock(driver->nwfilters.objs[i]); @@ -487,6 +501,9 @@ nwfilterConnectListAllNWFilters(virConnectPtr conn, virCheckFlags(0, -1); + if (virConnectListAllNWFiltersEnsureACL(conn) < 0) + return -1; + nwfilterDriverLock(driver); if (!filters) { @@ -543,6 +560,9 @@ nwfilterDefineXML(virConnectPtr conn, if (!(def = virNWFilterDefParseString(conn, xml))) goto cleanup; + if (virNWFilterDefineXMLEnsureACL(conn, def) < 0) + goto cleanup; + if (!(nwfilter = virNWFilterObjAssignDef(conn, &driver->nwfilters, def))) goto cleanup; @@ -584,6 +604,9 @@ nwfilterUndefine(virNWFilterPtr obj) { goto cleanup; } + if (virNWFilterUndefineEnsureACL(obj->conn, nwfilter->def) < 0) + goto cleanup; + if (virNWFilterTestUnassignDef(obj->conn, nwfilter) < 0) { virReportError(VIR_ERR_OPERATION_INVALID, "%s", @@ -632,6 +655,9 @@ nwfilterGetXMLDesc(virNWFilterPtr obj, goto cleanup; } + if (virNWFilterGetXMLDescEnsureACL(obj->conn, nwfilter->def) < 0) + goto cleanup; + ret = virNWFilterDefFormat(nwfilter->def); cleanup: -- 1.8.1.4

From: "Daniel P. Berrange" <berrange@redhat.com> Insert calls to the ACL checking APIs in all secrets driver entrypoints. Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- src/secret/secret_driver.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/src/secret/secret_driver.c b/src/secret/secret_driver.c index 5d1739f..b73dc51 100644 --- a/src/secret/secret_driver.c +++ b/src/secret/secret_driver.c @@ -42,6 +42,7 @@ #include "virfile.h" #include "configmake.h" #include "virstring.h" +#include "access/viraccessapicheck.h" #define VIR_FROM_THIS VIR_FROM_SECRET @@ -559,6 +560,9 @@ secretConnectNumOfSecrets(virConnectPtr conn) int i; virSecretEntryPtr secret; + if (virConnectNumOfSecretsEnsureACL(conn) < 0) + return -1; + secretDriverLock(driver); i = 0; @@ -578,6 +582,9 @@ secretConnectListSecrets(virConnectPtr conn, char **uuids, int maxuuids) memset(uuids, 0, maxuuids * sizeof(*uuids)); + if (virConnectListSecretsEnsureACL(conn) < 0) + return -1; + secretDriverLock(driver); i = 0; @@ -643,6 +650,9 @@ secretConnectListAllSecrets(virConnectPtr conn, virCheckFlags(VIR_CONNECT_LIST_SECRETS_FILTERS_ALL, -1); + if (virConnectListAllSecretsEnsureACL(conn) < 0) + return -1; + secretDriverLock(driver); for (entry = driver->secrets; entry != NULL; entry = entry->next) @@ -725,6 +735,9 @@ secretLookupByUUID(virConnectPtr conn, const unsigned char *uuid) goto cleanup; } + if (virSecretLookupByUUIDEnsureACL(conn, secret->def) < 0) + goto cleanup; + ret = virGetSecret(conn, secret->def->uuid, secret->def->usage_type, @@ -752,6 +765,9 @@ secretLookupByUsage(virConnectPtr conn, int usageType, const char *usageID) goto cleanup; } + if (virSecretLookupByUsageEnsureACL(conn, secret->def) < 0) + goto cleanup; + ret = virGetSecret(conn, secret->def->uuid, secret->def->usage_type, @@ -781,6 +797,9 @@ secretDefineXML(virConnectPtr conn, const char *xml, secretDriverLock(driver); + if (virSecretDefineXMLEnsureACL(conn, new_attrs) < 0) + goto cleanup; + secret = secretFindByUUID(driver, new_attrs->uuid); if (secret == NULL) { /* No existing secret with same UUID, try look for matching usage instead */ @@ -897,6 +916,9 @@ secretGetXMLDesc(virSecretPtr obj, unsigned int flags) goto cleanup; } + if (virSecretGetXMLDescEnsureACL(obj->conn, secret->def) < 0) + goto cleanup; + ret = virSecretDefFormat(secret->def); cleanup: @@ -933,6 +955,9 @@ secretSetValue(virSecretPtr obj, const unsigned char *value, goto cleanup; } + if (virSecretSetValueEnsureACL(obj->conn, secret->def) < 0) + goto cleanup; + old_value = secret->value; old_value_size = secret->value_size; @@ -988,6 +1013,9 @@ secretGetValue(virSecretPtr obj, size_t *value_size, unsigned int flags, goto cleanup; } + if (virSecretGetValueEnsureACL(obj->conn, secret->def) < 0) + goto cleanup; + if (secret->value == NULL) { char uuidstr[VIR_UUID_STRING_BUFLEN]; virUUIDFormat(obj->uuid, uuidstr); @@ -1034,6 +1062,9 @@ secretUndefine(virSecretPtr obj) goto cleanup; } + if (virSecretUndefineEnsureACL(obj->conn, secret->def) < 0) + goto cleanup; + if (!secret->def->ephemeral && secretDeleteSaved(driver, secret) < 0) goto cleanup; -- 1.8.1.4

From: "Daniel P. Berrange" <berrange@redhat.com> Add a script which parses the driver API code and validates that every API registered in a virNNNDriverPtr table contains an ACL check matching the API name. Signed-off-by: Daniel P. Berrange <berrange@redhat.com> --- src/Makefile.am | 22 +++++++- src/check-aclrules.pl | 144 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 164 insertions(+), 2 deletions(-) create mode 100644 src/check-aclrules.pl diff --git a/src/Makefile.am b/src/Makefile.am index 93af8fd..29fe5e9 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -462,15 +462,33 @@ DRIVER_SOURCE_FILES = \ $(XENAPI_DRIVER_SOURCES) \ $(NULL) +STATEFUL_DRIVER_SOURCE_FILES = \ + $(INTERFACE_DRIVER_SOURCES) \ + $(LIBXL_DRIVER_SOURCES) \ + $(LXC_DRIVER_SOURCES) \ + $(NETWORK_DRIVER_SOURCES) \ + $(NODE_DEVICE_DRIVER_SOURCES) \ + $(NWFILTER_DRIVER_SOURCES) \ + $(QEMU_DRIVER_SOURCES) \ + $(SECRET_DRIVER_SOURCES) \ + $(STORAGE_DRIVER_SOURCES) \ + $(UML_DRIVER_SOURCES) \ + $(XEN_DRIVER_SOURCES) \ + $(NULL) + check-driverimpls: $(AM_V_GEN)$(PERL) $(srcdir)/check-driverimpls.pl \ $(DRIVER_SOURCE_FILES) -EXTRA_DIST += check-driverimpls.pl +check-aclrules: + $(AM_V_GEN)$(PERL) $(srcdir)/check-aclrules.pl \ + $(STATEFUL_DRIVER_SOURCE_FILES) + +EXTRA_DIST += check-driverimpls.pl check-aclrules.pl check-local: check-protocol check-symfile check-symsorting \ - check-drivername check-driverimpls + check-drivername check-driverimpls check-aclrules .PHONY: check-protocol $(PROTOCOL_STRUCTS:structs=struct) # Mock driver, covering domains, storage, networks, etc diff --git a/src/check-aclrules.pl b/src/check-aclrules.pl new file mode 100644 index 0000000..62da2b7 --- /dev/null +++ b/src/check-aclrules.pl @@ -0,0 +1,144 @@ +#!/usr/bin/perl +# +# Copyright (C) 2013 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 +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library. If not, see +# <http://www.gnu.org/licenses/>. +# +# This script validates that the driver implementation of any +# public APIs contain ACL checks. +# +# As the script reads each source file, it attempts to identify +# top level function names. +# +# When reading the body of the functions, it looks for anything +# that looks like an API called named XXXEnsureACL. It will +# validate that the XXX prefix matches the name of the function +# it occurs in. +# +# When it later finds the virDriverPtr table, for each entry +# point listed, it will validate if there was a previously +# detected EnsureACL call recorded. +# +use strict; +use warnings; + +my $status = 0; + +my $brace = 0; +my $maybefunc; +my $intable = 0; +my $table; + +my %acls; + +my %whitelist = ( + "connectClose" => 1, + "connectIsEncrypted" => 1, + "connectIsSecure" => 1, + "connectIsAlive" => 1, + "networkOpen" => 1, + "networkClose" => 1, + "nwfilterOpen" => 1, + "nwfilterClose" => 1, + "secretOpen" => 1, + "secretClose" => 1, + "storageOpen" => 1, + "storageClose" => 1, + "interfaceOpen" => 1, + "interfaceClose" => 1, + ); + +my $lastfile; + +while (<>) { + if (!defined $lastfile || + $lastfile ne $ARGV) { + %acls = (); + $brace = 0; + $maybefunc = undef; + $lastfile = $ARGV; + } + if ($brace == 0) { + # Looks for anything which appears to be a function + # body name. Doesn't matter if we pick up bogus stuff + # here, as long as we don't miss valid stuff + if (m,\b(\w+)\(,) { + $maybefunc = $1; + } + } elsif ($brace > 0) { + if (m,(\w+)EnsureACL,) { + # Record the fact that maybefunc contains an + # ACL call, and make sure it is the right call! + my $func = $1; + $func =~ s/^vir//; + if (!defined $maybefunc) { + print "$ARGV:$. Unexpected check '$func' outside function\n"; + $status = 1; + } else { + unless ($maybefunc =~ /$func$/i) { + print "$ARGV:$. Mismatch check 'vir${func}EnsureACL' for function '$maybefunc'\n"; + $status = 1; + } + } + $acls{$maybefunc} = 1; + } elsif (m,\b(\w+)\(,) { + # Handles case where we replaced an API with a new + # one which adds new parameters, and we're left with + # a simple stub calling the new API. + my $callfunc = $1; + if (exists $acls{$callfunc}) { + $acls{$maybefunc} = 1; + } + } + } + + # Pass the vir*DriverPtr tables and make sure that + # every func listed there, has an impl which calls + # an ACL function + if ($intable) { + if (/\}/) { + $intable = 0; + $table = undef; + } elsif (/\.(\w+)\s*=\s*(\w+),?/) { + my $api = $1; + my $impl = $2; + + if ($api ne "no" && + $api ne "name" && + $table ne "virStateDriver" && + !exists $acls{$impl} && + !exists $whitelist{$api}) { + print "$ARGV:$. Missing ACL check in function '$impl' for '$api'\n"; + $status = 1; + } + } + } elsif (/^(?:static\s+)?(vir(?:\w+)?Driver)\s+/) { + if ($1 ne "virNWFilterCallbackDriver" && + $1 ne "virNWFilterTechDriver" && + $1 ne "virDomainConfNWFilterDriver") { + $intable = 1; + $table = $1; + } + } + + + my $count; + $count = s/{//g; + $brace += $count; + $count = s/}//g; + $brace -= $count; +} + +exit $status; -- 1.8.1.4

On 09.05.2013 15:26, Daniel P. Berrange wrote:
From: "Daniel P. Berrange" <berrange@redhat.com>
This series (which depends on the Xen refactoring patches) adds support for access control checks on all APIs that run inside libvirtd.
The first patch defines the basic objects which can be checked and the permissions associated with each object. In addition it provides the basic internal (pluggable) API for access control checks
Later there are policykit and selinux drivers for the access control framework. Neither of these is currently optimal but they have basic functionality working
To ensure that we don't forget access control checks when adding new APIs, we maintain metadata in the remote_protocol.x file against each method declaring what access control check must be done.
There are actually two checks possible. The first check is against the object being used. The optional second check is against the objects being returned (if any). The latter is used to filter what can be seen when asking for a list of objects (eg 'virsh list' gets filtered)
Again to ensure accurate checks, we automate the generation of methods for applying access control checks to each API. These helper methods are named to match the public API names. The last patch ensures that every method listed in the virXXXXDriverPtr tables has a call to an access control helper with the same name as the public API.
And of course there are the patches which actually add the access control checks.
Still todo
- Not all Xen methods have access control checks yet. This causes the test case in the last patch to report failures
- Have not wired up the checks for filtering the returned objects in any driver yet
- The polkit driver is inefficient since it spawns pkcheck for each check. We need to talk to DBus directly since ACL checks will be very frequent and need to be lightweight
- The SELinux driver is validating against the label of libvirtd. We need to validate against the label of the virDomainDefPtr security model or some equivalent for other objects.
- Need to write a generic RBAC access control impl. It was hoped that new polkit would make this obsolete. Polkit is still unable to do access control checks for non-local users though eg it can't validate against SASL usernames or x509 certs.
Daniel P. Berrange (19): Define basic internal API for access control Set conn->driver before running driver connectOpen method Setup default access control manager in libvirtd Add a policy kit access control driver Add an SELinux access control driver Add ACL annotations to all RPC messages Auto-generate helpers for checking access control rules Add ACL checks into the QEMU driver Add ACL checks into the LXC driver Add ACL checks into the UML driver Add ACL checks into the Xen driver Add ACL checks into the libxl driver Add ACL checks into the storage driver Add ACL checks into the network driver Add ACL checks into the interface driver Add ACL checks into the node device driver Add ACL checks into the nwfilter driver Add ACL checks into the secrets driver Add validation that all APIs contain ACL checks
.gitignore | 10 + daemon/Makefile.am | 1 + daemon/libvirtd-config.c | 4 + daemon/libvirtd-config.h | 2 + daemon/libvirtd.aug | 1 + daemon/libvirtd.c | 27 ++ daemon/libvirtd.conf | 9 + daemon/test_libvirtd.aug.in | 4 + include/libvirt/virterror.h | 4 + m4/virt-compile-warnings.m4 | 1 + m4/virt-selinux.m4 | 2 + po/POTFILES.in | 3 + src/Makefile.am | 128 +++++- src/access/genpolkit.pl | 119 ++++++ src/access/viraccessdriver.h | 89 ++++ src/access/viraccessdrivernop.c | 118 ++++++ src/access/viraccessdrivernop.h | 28 ++ src/access/viraccessdriverpolkit.c | 399 ++++++++++++++++++ src/access/viraccessdriverpolkit.h | 28 ++ src/access/viraccessdriverselinux.c | 565 +++++++++++++++++++++++++ src/access/viraccessdriverselinux.h | 28 ++ src/access/viraccessdriverstack.c | 285 +++++++++++++ src/access/viraccessdriverstack.h | 32 ++ src/access/viraccessmanager.c | 352 ++++++++++++++++ src/access/viraccessmanager.h | 91 ++++ src/access/viraccessperm.c | 84 ++++ src/access/viraccessperm.h | 647 +++++++++++++++++++++++++++++ src/check-aclrules.pl | 144 +++++++ src/interface/interface_backend_netcf.c | 114 +++++ src/interface/interface_backend_udev.c | 85 +++- src/internal.h | 4 + src/libvirt.c | 11 +- src/libvirt_private.syms | 37 ++ src/libxl/libxl_driver.c | 187 ++++++++- src/locking/lock_protocol.x | 8 + src/lxc/lxc_driver.c | 219 +++++++++- src/network/bridge_driver.c | 61 +++ src/node_device/node_device_driver.c | 36 ++ src/nwfilter/nwfilter_driver.c | 26 ++ src/qemu/qemu_driver.c | 716 ++++++++++++++++++++++++++++---- src/remote/lxc_protocol.x | 1 + src/remote/qemu_protocol.x | 4 + src/remote/remote_protocol.x | 406 ++++++++++++++++++ src/rpc/gendispatch.pl | 212 +++++++++- src/secret/secret_driver.c | 31 ++ src/storage/storage_driver.c | 155 ++++++- src/uml/uml_driver.c | 174 +++++++- src/util/virerror.c | 8 + src/util/virlog.c | 3 +- src/util/virlog.h | 1 + src/xen/xen_driver.c | 217 +++++++++- 51 files changed, 5785 insertions(+), 136 deletions(-) create mode 100755 src/access/genpolkit.pl create mode 100644 src/access/viraccessdriver.h create mode 100644 src/access/viraccessdrivernop.c create mode 100644 src/access/viraccessdrivernop.h create mode 100644 src/access/viraccessdriverpolkit.c create mode 100644 src/access/viraccessdriverpolkit.h create mode 100644 src/access/viraccessdriverselinux.c create mode 100644 src/access/viraccessdriverselinux.h create mode 100644 src/access/viraccessdriverstack.c create mode 100644 src/access/viraccessdriverstack.h create mode 100644 src/access/viraccessmanager.c create mode 100644 src/access/viraccessmanager.h create mode 100644 src/access/viraccessperm.c create mode 100644 src/access/viraccessperm.h create mode 100644 src/check-aclrules.pl
I wanted to review this. But seems like patches don't apply cleanly. Can you rebase and repost? Michal

On 06/20/2013 11:00 AM, Michal Privoznik wrote:
I wanted to review this. But seems like patches don't apply cleanly. Can you rebase and repost?
Michal
See '[libvirt] [PATCH 00/19] Fine grained access control for libvirt APIs' posted yesterday: https://www.redhat.com/archives/libvir-list/2013-June/msg00753.html Jan
participants (3)
-
Daniel P. Berrange
-
Ján Tomko
-
Michal Privoznik