Refactor the security drivers to simplify usage
The current security driver usage requires horrible code like
if (driver->securityDriver &&
driver->securityDriver->domainSetSecurityHostdevLabel &&
driver->securityDriver->domainSetSecurityHostdevLabel(driver->securityDriver,
vm, hostdev) < 0)
This pair of checks for NULL clutters up the code, making the driver
calls 2 lines longer than they really need to be. The goal of the
patchset is to change the calling convention to simply
if (virSecurityManagerSetHostdevLabel(driver->securityDriver,
vm, hostdev) < 0)
The first check for 'driver->securityDriver' being NULL is removed
by introducing a 'no op' security driver that will always be present
if no real driver is enabled. This guarentees driver->securityDriver
!= NULL.
The second check for 'driver->securityDriver->domainSetSecurityHostdevLabel'
being non-NULL is hidden in a new abstraction called virSecurityManager.
This separates the driver callbacks, from main internal API. The addition
of a virSecurityManager object, that is separate from the virSecurityDriver
struct also allows for security drivers to carry state / configuration
information directly. Thus the DAC/Stack drivers from src/qemu which
used to pull config from 'struct qemud_driver' can now be moved into
the 'src/security' directory and store their config directly.
* src/qemu/qemu_conf.h, src/qemu/qemu_driver.c: Update to
use new virSecurityManager APIs
* src/qemu/qemu_security_dac.c, src/qemu/qemu_security_dac.h
src/qemu/qemu_security_stacked.c, src/qemu/qemu_security_stacked.h:
Move into src/security directory
* src/security/security_stack.c, src/security/security_stack.h,
src/security/security_dac.c, src/security/security_dac.h: Generic
versions of previous QEMU specific drivers
* src/security/security_apparmor.c, src/security/security_apparmor.h,
src/security/security_driver.c, src/security/security_driver.h,
src/security/security_selinux.c, src/security/security_selinux.h:
Update to take virSecurityManagerPtr object as the first param
in all callbacks
* src/security/security_nop.c, src/security/security_nop.h: Stub
implementation of all security driver APIs.
* src/security/security_manager.h, src/security/security_manager.c:
New internal API for invoking security drivers
* src/libvirt.c: Add missing debug for security APIs
2010-11-17 20:26:30 +00:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2010-2011 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, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
*
|
|
|
|
* POSIX DAC security driver
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <config.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
|
|
|
|
#include "security_dac.h"
|
|
|
|
#include "virterror_internal.h"
|
|
|
|
#include "util.h"
|
|
|
|
#include "memory.h"
|
|
|
|
#include "logging.h"
|
|
|
|
#include "pci.h"
|
|
|
|
#include "hostusb.h"
|
|
|
|
#include "storage_file.h"
|
|
|
|
|
|
|
|
#define VIR_FROM_THIS VIR_FROM_SECURITY
|
|
|
|
|
|
|
|
typedef struct _virSecurityDACData virSecurityDACData;
|
|
|
|
typedef virSecurityDACData *virSecurityDACDataPtr;
|
|
|
|
|
|
|
|
struct _virSecurityDACData {
|
|
|
|
uid_t user;
|
|
|
|
gid_t group;
|
|
|
|
bool dynamicOwnership;
|
|
|
|
};
|
|
|
|
|
|
|
|
void virSecurityDACSetUser(virSecurityManagerPtr mgr,
|
|
|
|
uid_t user)
|
|
|
|
{
|
|
|
|
virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
|
|
|
|
priv->user = user;
|
|
|
|
}
|
|
|
|
|
|
|
|
void virSecurityDACSetGroup(virSecurityManagerPtr mgr,
|
|
|
|
gid_t group)
|
|
|
|
{
|
|
|
|
virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
|
|
|
|
priv->group = group;
|
|
|
|
}
|
|
|
|
|
|
|
|
void virSecurityDACSetDynamicOwnership(virSecurityManagerPtr mgr,
|
|
|
|
bool dynamicOwnership)
|
|
|
|
{
|
|
|
|
virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
|
|
|
|
priv->dynamicOwnership = dynamicOwnership;
|
|
|
|
}
|
|
|
|
|
|
|
|
static virSecurityDriverStatus
|
|
|
|
virSecurityDACProbe(void)
|
|
|
|
{
|
|
|
|
return SECURITY_DRIVER_ENABLE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
virSecurityDACOpen(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
virSecurityDACClose(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static const char * virSecurityDACGetModel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
return "dac";
|
|
|
|
}
|
|
|
|
|
|
|
|
static const char * virSecurityDACGetDOI(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
return "0";
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
virSecurityDACSetOwnership(const char *path, int uid, int gid)
|
|
|
|
{
|
|
|
|
VIR_INFO("Setting DAC user and group on '%s' to '%d:%d'", path, uid, gid);
|
|
|
|
|
|
|
|
if (chown(path, uid, gid) < 0) {
|
|
|
|
struct stat sb;
|
|
|
|
int chown_errno = errno;
|
|
|
|
|
|
|
|
if (stat(path, &sb) >= 0) {
|
|
|
|
if (sb.st_uid == uid &&
|
|
|
|
sb.st_gid == gid) {
|
|
|
|
/* It's alright, there's nothing to change anyway. */
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (chown_errno == EOPNOTSUPP) {
|
|
|
|
VIR_INFO("Setting user and group to '%d:%d' on '%s' not supported by filesystem",
|
|
|
|
uid, gid, path);
|
|
|
|
} else if (chown_errno == EPERM) {
|
|
|
|
VIR_INFO("Setting user and group to '%d:%d' on '%s' not permitted",
|
|
|
|
uid, gid, path);
|
|
|
|
} else if (chown_errno == EROFS) {
|
|
|
|
VIR_INFO("Setting user and group to '%d:%d' on '%s' not possible on readonly filesystem",
|
|
|
|
uid, gid, path);
|
|
|
|
} else {
|
|
|
|
virReportSystemError(chown_errno,
|
|
|
|
_("unable to set user and group to '%d:%d' on '%s'"),
|
|
|
|
uid, gid, path);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
virSecurityDACRestoreSecurityFileLabel(const char *path)
|
|
|
|
{
|
|
|
|
struct stat buf;
|
|
|
|
int rc = -1;
|
|
|
|
char *newpath = NULL;
|
|
|
|
|
|
|
|
VIR_INFO("Restoring DAC user and group on '%s'", path);
|
|
|
|
|
|
|
|
if (virFileResolveLink(path, &newpath) < 0) {
|
|
|
|
virReportSystemError(errno,
|
|
|
|
_("cannot resolve symlink %s"), path);
|
|
|
|
goto err;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (stat(newpath, &buf) != 0)
|
|
|
|
goto err;
|
|
|
|
|
|
|
|
/* XXX record previous ownership */
|
|
|
|
rc = virSecurityDACSetOwnership(newpath, 0, 0);
|
|
|
|
|
|
|
|
err:
|
|
|
|
VIR_FREE(newpath);
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
virSecurityDACSetSecurityFileLabel(virDomainDiskDefPtr disk ATTRIBUTE_UNUSED,
|
|
|
|
const char *path,
|
|
|
|
size_t depth ATTRIBUTE_UNUSED,
|
|
|
|
void *opaque)
|
|
|
|
{
|
|
|
|
virSecurityManagerPtr mgr = opaque;
|
|
|
|
virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
|
|
|
|
|
|
|
|
return virSecurityDACSetOwnership(path, priv->user, priv->group);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
virSecurityDACSetSecurityImageLabel(virSecurityManagerPtr mgr,
|
|
|
|
virDomainObjPtr vm ATTRIBUTE_UNUSED,
|
|
|
|
virDomainDiskDefPtr disk)
|
|
|
|
|
|
|
|
{
|
|
|
|
virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
|
|
|
|
|
|
|
|
if (!priv->dynamicOwnership)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return virDomainDiskDefForeachPath(disk,
|
|
|
|
virSecurityManagerGetAllowDiskFormatProbing(mgr),
|
|
|
|
false,
|
|
|
|
virSecurityDACSetSecurityFileLabel,
|
|
|
|
mgr);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
virSecurityDACRestoreSecurityImageLabelInt(virSecurityManagerPtr mgr,
|
|
|
|
virDomainObjPtr vm ATTRIBUTE_UNUSED,
|
|
|
|
virDomainDiskDefPtr disk,
|
|
|
|
int migrated)
|
|
|
|
{
|
|
|
|
virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
|
|
|
|
|
|
|
|
if (!priv->dynamicOwnership)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
/* Don't restore labels on readoly/shared disks, because
|
|
|
|
* other VMs may still be accessing these
|
|
|
|
* Alternatively we could iterate over all running
|
|
|
|
* domains and try to figure out if it is in use, but
|
|
|
|
* this would not work for clustered filesystems, since
|
|
|
|
* we can't see running VMs using the file on other nodes
|
|
|
|
* Safest bet is thus to skip the restore step.
|
|
|
|
*/
|
|
|
|
if (disk->readonly || disk->shared)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (!disk->src)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
/* If we have a shared FS & doing migrated, we must not
|
|
|
|
* change ownership, because that kills access on the
|
|
|
|
* destination host which is sub-optimal for the guest
|
|
|
|
* VM's I/O attempts :-)
|
|
|
|
*/
|
|
|
|
if (migrated) {
|
|
|
|
int rc = virStorageFileIsSharedFS(disk->src);
|
|
|
|
if (rc < 0)
|
|
|
|
return -1;
|
|
|
|
if (rc == 1) {
|
|
|
|
VIR_DEBUG("Skipping image label restore on %s because FS is shared",
|
|
|
|
disk->src);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return virSecurityDACRestoreSecurityFileLabel(disk->src);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
virSecurityDACRestoreSecurityImageLabel(virSecurityManagerPtr mgr,
|
|
|
|
virDomainObjPtr vm,
|
|
|
|
virDomainDiskDefPtr disk)
|
|
|
|
{
|
|
|
|
return virSecurityDACRestoreSecurityImageLabelInt(mgr, vm, disk, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
virSecurityDACSetSecurityPCILabel(pciDevice *dev ATTRIBUTE_UNUSED,
|
|
|
|
const char *file,
|
|
|
|
void *opaque)
|
|
|
|
{
|
|
|
|
virSecurityManagerPtr mgr = opaque;
|
|
|
|
virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
|
|
|
|
|
|
|
|
return virSecurityDACSetOwnership(file, priv->user, priv->group);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
virSecurityDACSetSecurityUSBLabel(usbDevice *dev ATTRIBUTE_UNUSED,
|
|
|
|
const char *file,
|
|
|
|
void *opaque)
|
|
|
|
{
|
|
|
|
virSecurityManagerPtr mgr = opaque;
|
|
|
|
virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
|
|
|
|
|
|
|
|
return virSecurityDACSetOwnership(file, priv->user, priv->group);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
virSecurityDACSetSecurityHostdevLabel(virSecurityManagerPtr mgr,
|
|
|
|
virDomainObjPtr vm ATTRIBUTE_UNUSED,
|
|
|
|
virDomainHostdevDefPtr dev)
|
|
|
|
{
|
|
|
|
virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
if (!priv->dynamicOwnership)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (dev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
switch (dev->source.subsys.type) {
|
|
|
|
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB: {
|
|
|
|
usbDevice *usb = usbGetDevice(dev->source.subsys.u.usb.bus,
|
|
|
|
dev->source.subsys.u.usb.device);
|
|
|
|
|
|
|
|
if (!usb)
|
|
|
|
goto done;
|
|
|
|
|
|
|
|
ret = usbDeviceFileIterate(usb, virSecurityDACSetSecurityUSBLabel, mgr);
|
|
|
|
usbFreeDevice(usb);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI: {
|
|
|
|
pciDevice *pci = pciGetDevice(dev->source.subsys.u.pci.domain,
|
|
|
|
dev->source.subsys.u.pci.bus,
|
|
|
|
dev->source.subsys.u.pci.slot,
|
|
|
|
dev->source.subsys.u.pci.function);
|
|
|
|
|
|
|
|
if (!pci)
|
|
|
|
goto done;
|
|
|
|
|
|
|
|
ret = pciDeviceFileIterate(pci, virSecurityDACSetSecurityPCILabel, mgr);
|
|
|
|
pciFreeDevice(pci);
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
ret = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
done:
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
virSecurityDACRestoreSecurityPCILabel(pciDevice *dev ATTRIBUTE_UNUSED,
|
|
|
|
const char *file,
|
|
|
|
void *opaque ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
return virSecurityDACRestoreSecurityFileLabel(file);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
virSecurityDACRestoreSecurityUSBLabel(usbDevice *dev ATTRIBUTE_UNUSED,
|
|
|
|
const char *file,
|
|
|
|
void *opaque ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
return virSecurityDACRestoreSecurityFileLabel(file);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
virSecurityDACRestoreSecurityHostdevLabel(virSecurityManagerPtr mgr,
|
|
|
|
virDomainObjPtr vm ATTRIBUTE_UNUSED,
|
|
|
|
virDomainHostdevDefPtr dev)
|
|
|
|
|
|
|
|
{
|
|
|
|
virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
if (!priv->dynamicOwnership)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (dev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
switch (dev->source.subsys.type) {
|
|
|
|
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB: {
|
|
|
|
usbDevice *usb = usbGetDevice(dev->source.subsys.u.usb.bus,
|
|
|
|
dev->source.subsys.u.usb.device);
|
|
|
|
|
|
|
|
if (!usb)
|
|
|
|
goto done;
|
|
|
|
|
|
|
|
ret = usbDeviceFileIterate(usb, virSecurityDACRestoreSecurityUSBLabel, mgr);
|
|
|
|
usbFreeDevice(usb);
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI: {
|
|
|
|
pciDevice *pci = pciGetDevice(dev->source.subsys.u.pci.domain,
|
|
|
|
dev->source.subsys.u.pci.bus,
|
|
|
|
dev->source.subsys.u.pci.slot,
|
|
|
|
dev->source.subsys.u.pci.function);
|
|
|
|
|
|
|
|
if (!pci)
|
|
|
|
goto done;
|
|
|
|
|
|
|
|
ret = pciDeviceFileIterate(pci, virSecurityDACRestoreSecurityPCILabel, mgr);
|
|
|
|
pciFreeDevice(pci);
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
ret = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
done:
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
virSecurityDACSetChardevLabel(virSecurityManagerPtr mgr,
|
domain_conf: split source data out from ChrDef
This opens up the possibility of reusing the smaller ChrSourceDef
for both qemu monitor and a passthrough smartcard device.
* src/conf/domain_conf.h (_virDomainChrDef): Factor host
details...
(_virDomainChrSourceDef): ...into new struct.
(virDomainChrSourceDefFree): New prototype.
* src/conf/domain_conf.c (virDomainChrDefFree)
(virDomainChrDefParseXML, virDomainChrDefFormat): Split...
(virDomainChrSourceDefClear, virDomainChrSourceDefFree)
(virDomainChrSourceDefParseXML, virDomainChrSourceDefFormat):
...into new functions.
(virDomainChrDefParseTargetXML): Update clients to reflect type
split.
* src/vmx/vmx.c (virVMXParseSerial, virVMXParseParallel)
(virVMXFormatSerial, virVMXFormatParallel): Likewise.
* src/xen/xen_driver.c (xenUnifiedDomainOpenConsole): Likewise.
* src/xen/xend_internal.c (xenDaemonParseSxprChar)
(xenDaemonFormatSxprChr): Likewise.
* src/vbox/vbox_tmpl.c (vboxDomainDumpXML, vboxAttachSerial)
(vboxAttachParallel): Likewise.
* src/security/security_dac.c (virSecurityDACSetChardevLabel)
(virSecurityDACSetChardevCallback)
(virSecurityDACRestoreChardevLabel)
(virSecurityDACRestoreChardevCallback): Likewise.
* src/security/security_selinux.c (SELinuxSetSecurityChardevLabel)
(SELinuxSetSecurityChardevCallback)
(SELinuxRestoreSecurityChardevLabel)
(SELinuxSetSecurityChardevCallback): Likewise.
* src/security/virt-aa-helper.c (get_files): Likewise.
* src/lxc/lxc_driver.c (lxcVmStart, lxcDomainOpenConsole):
Likewise.
* src/uml/uml_conf.c (umlBuildCommandLineChr): Likewise.
* src/uml/uml_driver.c (umlIdentifyOneChrPTY, umlIdentifyChrPTY)
(umlDomainOpenConsole): Likewise.
* src/qemu/qemu_command.c (qemuBuildChrChardevStr)
(qemuBuildChrArgStr, qemuBuildCommandLine)
(qemuParseCommandLineChr): Likewise.
* src/qemu/qemu_domain.c (qemuDomainObjPrivateXMLFormat)
(qemuDomainObjPrivateXMLParse): Likewise.
* src/qemu/qemu_cgroup.c (qemuSetupChardevCgroup): Likewise.
* src/qemu/qemu_hotplug.c (qemuDomainAttachNetDevice): Likewise.
* src/qemu/qemu_driver.c (qemudFindCharDevicePTYsMonitor)
(qemudFindCharDevicePTYs, qemuPrepareChardevDevice)
(qemuPrepareMonitorChr, qemudShutdownVMDaemon)
(qemuDomainOpenConsole): Likewise.
* src/qemu/qemu_command.h (qemuBuildChrChardevStr)
(qemuBuildChrArgStr): Delete, now that they are static.
* src/libvirt_private.syms (domain_conf.h): New exports.
* cfg.mk (useless_free_options): Update list.
* tests/qemuxml2argvtest.c (testCompareXMLToArgvFiles): Update
tests.
2011-01-07 22:45:01 +00:00
|
|
|
virDomainChrSourceDefPtr dev)
|
Refactor the security drivers to simplify usage
The current security driver usage requires horrible code like
if (driver->securityDriver &&
driver->securityDriver->domainSetSecurityHostdevLabel &&
driver->securityDriver->domainSetSecurityHostdevLabel(driver->securityDriver,
vm, hostdev) < 0)
This pair of checks for NULL clutters up the code, making the driver
calls 2 lines longer than they really need to be. The goal of the
patchset is to change the calling convention to simply
if (virSecurityManagerSetHostdevLabel(driver->securityDriver,
vm, hostdev) < 0)
The first check for 'driver->securityDriver' being NULL is removed
by introducing a 'no op' security driver that will always be present
if no real driver is enabled. This guarentees driver->securityDriver
!= NULL.
The second check for 'driver->securityDriver->domainSetSecurityHostdevLabel'
being non-NULL is hidden in a new abstraction called virSecurityManager.
This separates the driver callbacks, from main internal API. The addition
of a virSecurityManager object, that is separate from the virSecurityDriver
struct also allows for security drivers to carry state / configuration
information directly. Thus the DAC/Stack drivers from src/qemu which
used to pull config from 'struct qemud_driver' can now be moved into
the 'src/security' directory and store their config directly.
* src/qemu/qemu_conf.h, src/qemu/qemu_driver.c: Update to
use new virSecurityManager APIs
* src/qemu/qemu_security_dac.c, src/qemu/qemu_security_dac.h
src/qemu/qemu_security_stacked.c, src/qemu/qemu_security_stacked.h:
Move into src/security directory
* src/security/security_stack.c, src/security/security_stack.h,
src/security/security_dac.c, src/security/security_dac.h: Generic
versions of previous QEMU specific drivers
* src/security/security_apparmor.c, src/security/security_apparmor.h,
src/security/security_driver.c, src/security/security_driver.h,
src/security/security_selinux.c, src/security/security_selinux.h:
Update to take virSecurityManagerPtr object as the first param
in all callbacks
* src/security/security_nop.c, src/security/security_nop.h: Stub
implementation of all security driver APIs.
* src/security/security_manager.h, src/security/security_manager.c:
New internal API for invoking security drivers
* src/libvirt.c: Add missing debug for security APIs
2010-11-17 20:26:30 +00:00
|
|
|
|
|
|
|
{
|
|
|
|
virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
|
|
|
|
char *in = NULL, *out = NULL;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
switch (dev->type) {
|
|
|
|
case VIR_DOMAIN_CHR_TYPE_DEV:
|
|
|
|
case VIR_DOMAIN_CHR_TYPE_FILE:
|
|
|
|
ret = virSecurityDACSetOwnership(dev->data.file.path, priv->user, priv->group);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_CHR_TYPE_PIPE:
|
|
|
|
if ((virAsprintf(&in, "%s.in", dev->data.file.path) < 0) ||
|
|
|
|
(virAsprintf(&out, "%s.out", dev->data.file.path) < 0)) {
|
|
|
|
virReportOOMError();
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
if ((virSecurityDACSetOwnership(in, priv->user, priv->group) < 0) ||
|
|
|
|
(virSecurityDACSetOwnership(out, priv->user, priv->group) < 0))
|
|
|
|
goto done;
|
|
|
|
ret = 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
ret = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
done:
|
|
|
|
VIR_FREE(in);
|
|
|
|
VIR_FREE(out);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
virSecurityDACRestoreChardevLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
|
domain_conf: split source data out from ChrDef
This opens up the possibility of reusing the smaller ChrSourceDef
for both qemu monitor and a passthrough smartcard device.
* src/conf/domain_conf.h (_virDomainChrDef): Factor host
details...
(_virDomainChrSourceDef): ...into new struct.
(virDomainChrSourceDefFree): New prototype.
* src/conf/domain_conf.c (virDomainChrDefFree)
(virDomainChrDefParseXML, virDomainChrDefFormat): Split...
(virDomainChrSourceDefClear, virDomainChrSourceDefFree)
(virDomainChrSourceDefParseXML, virDomainChrSourceDefFormat):
...into new functions.
(virDomainChrDefParseTargetXML): Update clients to reflect type
split.
* src/vmx/vmx.c (virVMXParseSerial, virVMXParseParallel)
(virVMXFormatSerial, virVMXFormatParallel): Likewise.
* src/xen/xen_driver.c (xenUnifiedDomainOpenConsole): Likewise.
* src/xen/xend_internal.c (xenDaemonParseSxprChar)
(xenDaemonFormatSxprChr): Likewise.
* src/vbox/vbox_tmpl.c (vboxDomainDumpXML, vboxAttachSerial)
(vboxAttachParallel): Likewise.
* src/security/security_dac.c (virSecurityDACSetChardevLabel)
(virSecurityDACSetChardevCallback)
(virSecurityDACRestoreChardevLabel)
(virSecurityDACRestoreChardevCallback): Likewise.
* src/security/security_selinux.c (SELinuxSetSecurityChardevLabel)
(SELinuxSetSecurityChardevCallback)
(SELinuxRestoreSecurityChardevLabel)
(SELinuxSetSecurityChardevCallback): Likewise.
* src/security/virt-aa-helper.c (get_files): Likewise.
* src/lxc/lxc_driver.c (lxcVmStart, lxcDomainOpenConsole):
Likewise.
* src/uml/uml_conf.c (umlBuildCommandLineChr): Likewise.
* src/uml/uml_driver.c (umlIdentifyOneChrPTY, umlIdentifyChrPTY)
(umlDomainOpenConsole): Likewise.
* src/qemu/qemu_command.c (qemuBuildChrChardevStr)
(qemuBuildChrArgStr, qemuBuildCommandLine)
(qemuParseCommandLineChr): Likewise.
* src/qemu/qemu_domain.c (qemuDomainObjPrivateXMLFormat)
(qemuDomainObjPrivateXMLParse): Likewise.
* src/qemu/qemu_cgroup.c (qemuSetupChardevCgroup): Likewise.
* src/qemu/qemu_hotplug.c (qemuDomainAttachNetDevice): Likewise.
* src/qemu/qemu_driver.c (qemudFindCharDevicePTYsMonitor)
(qemudFindCharDevicePTYs, qemuPrepareChardevDevice)
(qemuPrepareMonitorChr, qemudShutdownVMDaemon)
(qemuDomainOpenConsole): Likewise.
* src/qemu/qemu_command.h (qemuBuildChrChardevStr)
(qemuBuildChrArgStr): Delete, now that they are static.
* src/libvirt_private.syms (domain_conf.h): New exports.
* cfg.mk (useless_free_options): Update list.
* tests/qemuxml2argvtest.c (testCompareXMLToArgvFiles): Update
tests.
2011-01-07 22:45:01 +00:00
|
|
|
virDomainChrSourceDefPtr dev)
|
Refactor the security drivers to simplify usage
The current security driver usage requires horrible code like
if (driver->securityDriver &&
driver->securityDriver->domainSetSecurityHostdevLabel &&
driver->securityDriver->domainSetSecurityHostdevLabel(driver->securityDriver,
vm, hostdev) < 0)
This pair of checks for NULL clutters up the code, making the driver
calls 2 lines longer than they really need to be. The goal of the
patchset is to change the calling convention to simply
if (virSecurityManagerSetHostdevLabel(driver->securityDriver,
vm, hostdev) < 0)
The first check for 'driver->securityDriver' being NULL is removed
by introducing a 'no op' security driver that will always be present
if no real driver is enabled. This guarentees driver->securityDriver
!= NULL.
The second check for 'driver->securityDriver->domainSetSecurityHostdevLabel'
being non-NULL is hidden in a new abstraction called virSecurityManager.
This separates the driver callbacks, from main internal API. The addition
of a virSecurityManager object, that is separate from the virSecurityDriver
struct also allows for security drivers to carry state / configuration
information directly. Thus the DAC/Stack drivers from src/qemu which
used to pull config from 'struct qemud_driver' can now be moved into
the 'src/security' directory and store their config directly.
* src/qemu/qemu_conf.h, src/qemu/qemu_driver.c: Update to
use new virSecurityManager APIs
* src/qemu/qemu_security_dac.c, src/qemu/qemu_security_dac.h
src/qemu/qemu_security_stacked.c, src/qemu/qemu_security_stacked.h:
Move into src/security directory
* src/security/security_stack.c, src/security/security_stack.h,
src/security/security_dac.c, src/security/security_dac.h: Generic
versions of previous QEMU specific drivers
* src/security/security_apparmor.c, src/security/security_apparmor.h,
src/security/security_driver.c, src/security/security_driver.h,
src/security/security_selinux.c, src/security/security_selinux.h:
Update to take virSecurityManagerPtr object as the first param
in all callbacks
* src/security/security_nop.c, src/security/security_nop.h: Stub
implementation of all security driver APIs.
* src/security/security_manager.h, src/security/security_manager.c:
New internal API for invoking security drivers
* src/libvirt.c: Add missing debug for security APIs
2010-11-17 20:26:30 +00:00
|
|
|
{
|
|
|
|
char *in = NULL, *out = NULL;
|
|
|
|
int ret = -1;
|
|
|
|
|
|
|
|
switch (dev->type) {
|
|
|
|
case VIR_DOMAIN_CHR_TYPE_DEV:
|
|
|
|
case VIR_DOMAIN_CHR_TYPE_FILE:
|
|
|
|
ret = virSecurityDACRestoreSecurityFileLabel(dev->data.file.path);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_CHR_TYPE_PIPE:
|
|
|
|
if ((virAsprintf(&out, "%s.out", dev->data.file.path) < 0) ||
|
|
|
|
(virAsprintf(&in, "%s.in", dev->data.file.path) < 0)) {
|
|
|
|
virReportOOMError();
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
if ((virSecurityDACRestoreSecurityFileLabel(out) < 0) ||
|
|
|
|
(virSecurityDACRestoreSecurityFileLabel(in) < 0))
|
|
|
|
goto done;
|
|
|
|
ret = 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
ret = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
done:
|
|
|
|
VIR_FREE(in);
|
|
|
|
VIR_FREE(out);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
virSecurityDACRestoreChardevCallback(virDomainDefPtr def ATTRIBUTE_UNUSED,
|
|
|
|
virDomainChrDefPtr dev,
|
|
|
|
void *opaque)
|
|
|
|
{
|
|
|
|
virSecurityManagerPtr mgr = opaque;
|
|
|
|
|
domain_conf: split source data out from ChrDef
This opens up the possibility of reusing the smaller ChrSourceDef
for both qemu monitor and a passthrough smartcard device.
* src/conf/domain_conf.h (_virDomainChrDef): Factor host
details...
(_virDomainChrSourceDef): ...into new struct.
(virDomainChrSourceDefFree): New prototype.
* src/conf/domain_conf.c (virDomainChrDefFree)
(virDomainChrDefParseXML, virDomainChrDefFormat): Split...
(virDomainChrSourceDefClear, virDomainChrSourceDefFree)
(virDomainChrSourceDefParseXML, virDomainChrSourceDefFormat):
...into new functions.
(virDomainChrDefParseTargetXML): Update clients to reflect type
split.
* src/vmx/vmx.c (virVMXParseSerial, virVMXParseParallel)
(virVMXFormatSerial, virVMXFormatParallel): Likewise.
* src/xen/xen_driver.c (xenUnifiedDomainOpenConsole): Likewise.
* src/xen/xend_internal.c (xenDaemonParseSxprChar)
(xenDaemonFormatSxprChr): Likewise.
* src/vbox/vbox_tmpl.c (vboxDomainDumpXML, vboxAttachSerial)
(vboxAttachParallel): Likewise.
* src/security/security_dac.c (virSecurityDACSetChardevLabel)
(virSecurityDACSetChardevCallback)
(virSecurityDACRestoreChardevLabel)
(virSecurityDACRestoreChardevCallback): Likewise.
* src/security/security_selinux.c (SELinuxSetSecurityChardevLabel)
(SELinuxSetSecurityChardevCallback)
(SELinuxRestoreSecurityChardevLabel)
(SELinuxSetSecurityChardevCallback): Likewise.
* src/security/virt-aa-helper.c (get_files): Likewise.
* src/lxc/lxc_driver.c (lxcVmStart, lxcDomainOpenConsole):
Likewise.
* src/uml/uml_conf.c (umlBuildCommandLineChr): Likewise.
* src/uml/uml_driver.c (umlIdentifyOneChrPTY, umlIdentifyChrPTY)
(umlDomainOpenConsole): Likewise.
* src/qemu/qemu_command.c (qemuBuildChrChardevStr)
(qemuBuildChrArgStr, qemuBuildCommandLine)
(qemuParseCommandLineChr): Likewise.
* src/qemu/qemu_domain.c (qemuDomainObjPrivateXMLFormat)
(qemuDomainObjPrivateXMLParse): Likewise.
* src/qemu/qemu_cgroup.c (qemuSetupChardevCgroup): Likewise.
* src/qemu/qemu_hotplug.c (qemuDomainAttachNetDevice): Likewise.
* src/qemu/qemu_driver.c (qemudFindCharDevicePTYsMonitor)
(qemudFindCharDevicePTYs, qemuPrepareChardevDevice)
(qemuPrepareMonitorChr, qemudShutdownVMDaemon)
(qemuDomainOpenConsole): Likewise.
* src/qemu/qemu_command.h (qemuBuildChrChardevStr)
(qemuBuildChrArgStr): Delete, now that they are static.
* src/libvirt_private.syms (domain_conf.h): New exports.
* cfg.mk (useless_free_options): Update list.
* tests/qemuxml2argvtest.c (testCompareXMLToArgvFiles): Update
tests.
2011-01-07 22:45:01 +00:00
|
|
|
return virSecurityDACRestoreChardevLabel(mgr, &dev->source);
|
Refactor the security drivers to simplify usage
The current security driver usage requires horrible code like
if (driver->securityDriver &&
driver->securityDriver->domainSetSecurityHostdevLabel &&
driver->securityDriver->domainSetSecurityHostdevLabel(driver->securityDriver,
vm, hostdev) < 0)
This pair of checks for NULL clutters up the code, making the driver
calls 2 lines longer than they really need to be. The goal of the
patchset is to change the calling convention to simply
if (virSecurityManagerSetHostdevLabel(driver->securityDriver,
vm, hostdev) < 0)
The first check for 'driver->securityDriver' being NULL is removed
by introducing a 'no op' security driver that will always be present
if no real driver is enabled. This guarentees driver->securityDriver
!= NULL.
The second check for 'driver->securityDriver->domainSetSecurityHostdevLabel'
being non-NULL is hidden in a new abstraction called virSecurityManager.
This separates the driver callbacks, from main internal API. The addition
of a virSecurityManager object, that is separate from the virSecurityDriver
struct also allows for security drivers to carry state / configuration
information directly. Thus the DAC/Stack drivers from src/qemu which
used to pull config from 'struct qemud_driver' can now be moved into
the 'src/security' directory and store their config directly.
* src/qemu/qemu_conf.h, src/qemu/qemu_driver.c: Update to
use new virSecurityManager APIs
* src/qemu/qemu_security_dac.c, src/qemu/qemu_security_dac.h
src/qemu/qemu_security_stacked.c, src/qemu/qemu_security_stacked.h:
Move into src/security directory
* src/security/security_stack.c, src/security/security_stack.h,
src/security/security_dac.c, src/security/security_dac.h: Generic
versions of previous QEMU specific drivers
* src/security/security_apparmor.c, src/security/security_apparmor.h,
src/security/security_driver.c, src/security/security_driver.h,
src/security/security_selinux.c, src/security/security_selinux.h:
Update to take virSecurityManagerPtr object as the first param
in all callbacks
* src/security/security_nop.c, src/security/security_nop.h: Stub
implementation of all security driver APIs.
* src/security/security_manager.h, src/security/security_manager.c:
New internal API for invoking security drivers
* src/libvirt.c: Add missing debug for security APIs
2010-11-17 20:26:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
virSecurityDACRestoreSecurityAllLabel(virSecurityManagerPtr mgr,
|
|
|
|
virDomainObjPtr vm,
|
|
|
|
int migrated)
|
|
|
|
{
|
|
|
|
virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
|
|
|
|
int i;
|
|
|
|
int rc = 0;
|
|
|
|
|
|
|
|
if (!priv->dynamicOwnership)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
|
|
VIR_DEBUG("Restoring security label on %s migrated=%d",
|
|
|
|
vm->def->name, migrated);
|
|
|
|
|
|
|
|
for (i = 0 ; i < vm->def->nhostdevs ; i++) {
|
|
|
|
if (virSecurityDACRestoreSecurityHostdevLabel(mgr,
|
|
|
|
vm,
|
|
|
|
vm->def->hostdevs[i]) < 0)
|
|
|
|
rc = -1;
|
|
|
|
}
|
|
|
|
for (i = 0 ; i < vm->def->ndisks ; i++) {
|
|
|
|
if (virSecurityDACRestoreSecurityImageLabelInt(mgr,
|
|
|
|
vm,
|
|
|
|
vm->def->disks[i],
|
|
|
|
migrated) < 0)
|
|
|
|
rc = -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (virDomainChrDefForeach(vm->def,
|
|
|
|
false,
|
|
|
|
virSecurityDACRestoreChardevCallback,
|
|
|
|
vm) < 0)
|
|
|
|
rc = -1;
|
|
|
|
|
|
|
|
if (vm->def->os.kernel &&
|
|
|
|
virSecurityDACRestoreSecurityFileLabel(vm->def->os.kernel) < 0)
|
|
|
|
rc = -1;
|
|
|
|
|
|
|
|
if (vm->def->os.initrd &&
|
|
|
|
virSecurityDACRestoreSecurityFileLabel(vm->def->os.initrd) < 0)
|
|
|
|
rc = -1;
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
virSecurityDACSetChardevCallback(virDomainDefPtr def ATTRIBUTE_UNUSED,
|
|
|
|
virDomainChrDefPtr dev,
|
|
|
|
void *opaque)
|
|
|
|
{
|
|
|
|
virSecurityManagerPtr mgr = opaque;
|
|
|
|
|
domain_conf: split source data out from ChrDef
This opens up the possibility of reusing the smaller ChrSourceDef
for both qemu monitor and a passthrough smartcard device.
* src/conf/domain_conf.h (_virDomainChrDef): Factor host
details...
(_virDomainChrSourceDef): ...into new struct.
(virDomainChrSourceDefFree): New prototype.
* src/conf/domain_conf.c (virDomainChrDefFree)
(virDomainChrDefParseXML, virDomainChrDefFormat): Split...
(virDomainChrSourceDefClear, virDomainChrSourceDefFree)
(virDomainChrSourceDefParseXML, virDomainChrSourceDefFormat):
...into new functions.
(virDomainChrDefParseTargetXML): Update clients to reflect type
split.
* src/vmx/vmx.c (virVMXParseSerial, virVMXParseParallel)
(virVMXFormatSerial, virVMXFormatParallel): Likewise.
* src/xen/xen_driver.c (xenUnifiedDomainOpenConsole): Likewise.
* src/xen/xend_internal.c (xenDaemonParseSxprChar)
(xenDaemonFormatSxprChr): Likewise.
* src/vbox/vbox_tmpl.c (vboxDomainDumpXML, vboxAttachSerial)
(vboxAttachParallel): Likewise.
* src/security/security_dac.c (virSecurityDACSetChardevLabel)
(virSecurityDACSetChardevCallback)
(virSecurityDACRestoreChardevLabel)
(virSecurityDACRestoreChardevCallback): Likewise.
* src/security/security_selinux.c (SELinuxSetSecurityChardevLabel)
(SELinuxSetSecurityChardevCallback)
(SELinuxRestoreSecurityChardevLabel)
(SELinuxSetSecurityChardevCallback): Likewise.
* src/security/virt-aa-helper.c (get_files): Likewise.
* src/lxc/lxc_driver.c (lxcVmStart, lxcDomainOpenConsole):
Likewise.
* src/uml/uml_conf.c (umlBuildCommandLineChr): Likewise.
* src/uml/uml_driver.c (umlIdentifyOneChrPTY, umlIdentifyChrPTY)
(umlDomainOpenConsole): Likewise.
* src/qemu/qemu_command.c (qemuBuildChrChardevStr)
(qemuBuildChrArgStr, qemuBuildCommandLine)
(qemuParseCommandLineChr): Likewise.
* src/qemu/qemu_domain.c (qemuDomainObjPrivateXMLFormat)
(qemuDomainObjPrivateXMLParse): Likewise.
* src/qemu/qemu_cgroup.c (qemuSetupChardevCgroup): Likewise.
* src/qemu/qemu_hotplug.c (qemuDomainAttachNetDevice): Likewise.
* src/qemu/qemu_driver.c (qemudFindCharDevicePTYsMonitor)
(qemudFindCharDevicePTYs, qemuPrepareChardevDevice)
(qemuPrepareMonitorChr, qemudShutdownVMDaemon)
(qemuDomainOpenConsole): Likewise.
* src/qemu/qemu_command.h (qemuBuildChrChardevStr)
(qemuBuildChrArgStr): Delete, now that they are static.
* src/libvirt_private.syms (domain_conf.h): New exports.
* cfg.mk (useless_free_options): Update list.
* tests/qemuxml2argvtest.c (testCompareXMLToArgvFiles): Update
tests.
2011-01-07 22:45:01 +00:00
|
|
|
return virSecurityDACSetChardevLabel(mgr, &dev->source);
|
Refactor the security drivers to simplify usage
The current security driver usage requires horrible code like
if (driver->securityDriver &&
driver->securityDriver->domainSetSecurityHostdevLabel &&
driver->securityDriver->domainSetSecurityHostdevLabel(driver->securityDriver,
vm, hostdev) < 0)
This pair of checks for NULL clutters up the code, making the driver
calls 2 lines longer than they really need to be. The goal of the
patchset is to change the calling convention to simply
if (virSecurityManagerSetHostdevLabel(driver->securityDriver,
vm, hostdev) < 0)
The first check for 'driver->securityDriver' being NULL is removed
by introducing a 'no op' security driver that will always be present
if no real driver is enabled. This guarentees driver->securityDriver
!= NULL.
The second check for 'driver->securityDriver->domainSetSecurityHostdevLabel'
being non-NULL is hidden in a new abstraction called virSecurityManager.
This separates the driver callbacks, from main internal API. The addition
of a virSecurityManager object, that is separate from the virSecurityDriver
struct also allows for security drivers to carry state / configuration
information directly. Thus the DAC/Stack drivers from src/qemu which
used to pull config from 'struct qemud_driver' can now be moved into
the 'src/security' directory and store their config directly.
* src/qemu/qemu_conf.h, src/qemu/qemu_driver.c: Update to
use new virSecurityManager APIs
* src/qemu/qemu_security_dac.c, src/qemu/qemu_security_dac.h
src/qemu/qemu_security_stacked.c, src/qemu/qemu_security_stacked.h:
Move into src/security directory
* src/security/security_stack.c, src/security/security_stack.h,
src/security/security_dac.c, src/security/security_dac.h: Generic
versions of previous QEMU specific drivers
* src/security/security_apparmor.c, src/security/security_apparmor.h,
src/security/security_driver.c, src/security/security_driver.h,
src/security/security_selinux.c, src/security/security_selinux.h:
Update to take virSecurityManagerPtr object as the first param
in all callbacks
* src/security/security_nop.c, src/security/security_nop.h: Stub
implementation of all security driver APIs.
* src/security/security_manager.h, src/security/security_manager.c:
New internal API for invoking security drivers
* src/libvirt.c: Add missing debug for security APIs
2010-11-17 20:26:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
virSecurityDACSetSecurityAllLabel(virSecurityManagerPtr mgr,
|
|
|
|
virDomainObjPtr vm,
|
|
|
|
const char *stdin_path ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (!priv->dynamicOwnership)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
for (i = 0 ; i < vm->def->ndisks ; i++) {
|
|
|
|
/* XXX fixme - we need to recursively label the entire tree :-( */
|
|
|
|
if (vm->def->disks[i]->type == VIR_DOMAIN_DISK_TYPE_DIR)
|
|
|
|
continue;
|
|
|
|
if (virSecurityDACSetSecurityImageLabel(mgr,
|
|
|
|
vm,
|
|
|
|
vm->def->disks[i]) < 0)
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
for (i = 0 ; i < vm->def->nhostdevs ; i++) {
|
|
|
|
if (virSecurityDACSetSecurityHostdevLabel(mgr,
|
|
|
|
vm,
|
|
|
|
vm->def->hostdevs[i]) < 0)
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (virDomainChrDefForeach(vm->def,
|
|
|
|
true,
|
|
|
|
virSecurityDACSetChardevCallback,
|
|
|
|
vm) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (vm->def->os.kernel &&
|
|
|
|
virSecurityDACSetOwnership(vm->def->os.kernel,
|
|
|
|
priv->user,
|
|
|
|
priv->group) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if (vm->def->os.initrd &&
|
|
|
|
virSecurityDACSetOwnership(vm->def->os.initrd,
|
|
|
|
priv->user,
|
|
|
|
priv->group) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
virSecurityDACSetSavedStateLabel(virSecurityManagerPtr mgr,
|
|
|
|
virDomainObjPtr vm ATTRIBUTE_UNUSED,
|
|
|
|
const char *savefile)
|
|
|
|
{
|
|
|
|
virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
|
|
|
|
|
|
|
|
return virSecurityDACSetOwnership(savefile, priv->user, priv->group);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
virSecurityDACRestoreSavedStateLabel(virSecurityManagerPtr mgr,
|
|
|
|
virDomainObjPtr vm ATTRIBUTE_UNUSED,
|
|
|
|
const char *savefile)
|
|
|
|
{
|
|
|
|
virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
|
|
|
|
|
|
|
|
if (!priv->dynamicOwnership)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return virSecurityDACRestoreSecurityFileLabel(savefile);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
virSecurityDACSetProcessLabel(virSecurityManagerPtr mgr,
|
|
|
|
virDomainObjPtr vm ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
virSecurityDACDataPtr priv = virSecurityManagerGetPrivateData(mgr);
|
|
|
|
|
|
|
|
DEBUG("Dropping privileges of VM to %d:%d", priv->user, priv->group);
|
|
|
|
|
|
|
|
if (virSetUIDGID(priv->user, priv->group) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
virSecurityDACVerify(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
|
|
|
|
virDomainDefPtr def ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
virSecurityDACGenLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
|
|
|
|
virDomainObjPtr vm ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
virSecurityDACReleaseLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
|
|
|
|
virDomainObjPtr vm ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
virSecurityDACReserveLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
|
|
|
|
virDomainObjPtr vm ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
virSecurityDACGetProcessLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
|
|
|
|
virDomainObjPtr vm ATTRIBUTE_UNUSED,
|
|
|
|
virSecurityLabelPtr seclabel ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
virSecurityDACSetSocketLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
|
|
|
|
virDomainObjPtr vm ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
virSecurityDACClearSocketLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
|
|
|
|
virDomainObjPtr vm ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-01-23 21:02:42 +00:00
|
|
|
static int
|
|
|
|
virSecurityDACSetFDLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
|
|
|
|
virDomainObjPtr vm ATTRIBUTE_UNUSED,
|
|
|
|
int fd ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
Refactor the security drivers to simplify usage
The current security driver usage requires horrible code like
if (driver->securityDriver &&
driver->securityDriver->domainSetSecurityHostdevLabel &&
driver->securityDriver->domainSetSecurityHostdevLabel(driver->securityDriver,
vm, hostdev) < 0)
This pair of checks for NULL clutters up the code, making the driver
calls 2 lines longer than they really need to be. The goal of the
patchset is to change the calling convention to simply
if (virSecurityManagerSetHostdevLabel(driver->securityDriver,
vm, hostdev) < 0)
The first check for 'driver->securityDriver' being NULL is removed
by introducing a 'no op' security driver that will always be present
if no real driver is enabled. This guarentees driver->securityDriver
!= NULL.
The second check for 'driver->securityDriver->domainSetSecurityHostdevLabel'
being non-NULL is hidden in a new abstraction called virSecurityManager.
This separates the driver callbacks, from main internal API. The addition
of a virSecurityManager object, that is separate from the virSecurityDriver
struct also allows for security drivers to carry state / configuration
information directly. Thus the DAC/Stack drivers from src/qemu which
used to pull config from 'struct qemud_driver' can now be moved into
the 'src/security' directory and store their config directly.
* src/qemu/qemu_conf.h, src/qemu/qemu_driver.c: Update to
use new virSecurityManager APIs
* src/qemu/qemu_security_dac.c, src/qemu/qemu_security_dac.h
src/qemu/qemu_security_stacked.c, src/qemu/qemu_security_stacked.h:
Move into src/security directory
* src/security/security_stack.c, src/security/security_stack.h,
src/security/security_dac.c, src/security/security_dac.h: Generic
versions of previous QEMU specific drivers
* src/security/security_apparmor.c, src/security/security_apparmor.h,
src/security/security_driver.c, src/security/security_driver.h,
src/security/security_selinux.c, src/security/security_selinux.h:
Update to take virSecurityManagerPtr object as the first param
in all callbacks
* src/security/security_nop.c, src/security/security_nop.h: Stub
implementation of all security driver APIs.
* src/security/security_manager.h, src/security/security_manager.c:
New internal API for invoking security drivers
* src/libvirt.c: Add missing debug for security APIs
2010-11-17 20:26:30 +00:00
|
|
|
|
|
|
|
virSecurityDriver virSecurityDriverDAC = {
|
|
|
|
sizeof(virSecurityDACData),
|
|
|
|
"virDAC",
|
|
|
|
|
|
|
|
virSecurityDACProbe,
|
|
|
|
virSecurityDACOpen,
|
|
|
|
virSecurityDACClose,
|
|
|
|
|
|
|
|
virSecurityDACGetModel,
|
|
|
|
virSecurityDACGetDOI,
|
|
|
|
|
|
|
|
virSecurityDACVerify,
|
|
|
|
|
|
|
|
virSecurityDACSetSecurityImageLabel,
|
|
|
|
virSecurityDACRestoreSecurityImageLabel,
|
|
|
|
|
|
|
|
virSecurityDACSetSocketLabel,
|
|
|
|
virSecurityDACClearSocketLabel,
|
|
|
|
|
|
|
|
virSecurityDACGenLabel,
|
|
|
|
virSecurityDACReserveLabel,
|
|
|
|
virSecurityDACReleaseLabel,
|
|
|
|
|
|
|
|
virSecurityDACGetProcessLabel,
|
|
|
|
virSecurityDACSetProcessLabel,
|
|
|
|
|
|
|
|
virSecurityDACSetSecurityAllLabel,
|
|
|
|
virSecurityDACRestoreSecurityAllLabel,
|
|
|
|
|
|
|
|
virSecurityDACSetSecurityHostdevLabel,
|
|
|
|
virSecurityDACRestoreSecurityHostdevLabel,
|
|
|
|
|
|
|
|
virSecurityDACSetSavedStateLabel,
|
|
|
|
virSecurityDACRestoreSavedStateLabel,
|
2011-01-23 21:02:42 +00:00
|
|
|
|
|
|
|
virSecurityDACSetFDLabel,
|
Refactor the security drivers to simplify usage
The current security driver usage requires horrible code like
if (driver->securityDriver &&
driver->securityDriver->domainSetSecurityHostdevLabel &&
driver->securityDriver->domainSetSecurityHostdevLabel(driver->securityDriver,
vm, hostdev) < 0)
This pair of checks for NULL clutters up the code, making the driver
calls 2 lines longer than they really need to be. The goal of the
patchset is to change the calling convention to simply
if (virSecurityManagerSetHostdevLabel(driver->securityDriver,
vm, hostdev) < 0)
The first check for 'driver->securityDriver' being NULL is removed
by introducing a 'no op' security driver that will always be present
if no real driver is enabled. This guarentees driver->securityDriver
!= NULL.
The second check for 'driver->securityDriver->domainSetSecurityHostdevLabel'
being non-NULL is hidden in a new abstraction called virSecurityManager.
This separates the driver callbacks, from main internal API. The addition
of a virSecurityManager object, that is separate from the virSecurityDriver
struct also allows for security drivers to carry state / configuration
information directly. Thus the DAC/Stack drivers from src/qemu which
used to pull config from 'struct qemud_driver' can now be moved into
the 'src/security' directory and store their config directly.
* src/qemu/qemu_conf.h, src/qemu/qemu_driver.c: Update to
use new virSecurityManager APIs
* src/qemu/qemu_security_dac.c, src/qemu/qemu_security_dac.h
src/qemu/qemu_security_stacked.c, src/qemu/qemu_security_stacked.h:
Move into src/security directory
* src/security/security_stack.c, src/security/security_stack.h,
src/security/security_dac.c, src/security/security_dac.h: Generic
versions of previous QEMU specific drivers
* src/security/security_apparmor.c, src/security/security_apparmor.h,
src/security/security_driver.c, src/security/security_driver.h,
src/security/security_selinux.c, src/security/security_selinux.h:
Update to take virSecurityManagerPtr object as the first param
in all callbacks
* src/security/security_nop.c, src/security/security_nop.h: Stub
implementation of all security driver APIs.
* src/security/security_manager.h, src/security/security_manager.c:
New internal API for invoking security drivers
* src/libvirt.c: Add missing debug for security APIs
2010-11-17 20:26:30 +00:00
|
|
|
};
|