libvirt/src/security/security_stack.c
Daniel P. Berrange d6623003c6 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
2011-01-10 18:10:52 +00:00

402 lines
10 KiB
C

/*
* 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
*
* Stacked security driver
*/
#include <config.h>
#include "security_stack.h"
#include "virterror_internal.h"
#define VIR_FROM_THIS VIR_FROM_SECURITY
typedef struct _virSecurityStackData virSecurityStackData;
typedef virSecurityStackData *virSecurityStackDataPtr;
struct _virSecurityStackData {
virSecurityManagerPtr primary;
virSecurityManagerPtr secondary;
};
void virSecurityStackSetPrimary(virSecurityManagerPtr mgr,
virSecurityManagerPtr primary)
{
virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
priv->primary = primary;
}
void virSecurityStackSetSecondary(virSecurityManagerPtr mgr,
virSecurityManagerPtr secondary)
{
virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
priv->secondary = secondary;
}
static virSecurityDriverStatus
virSecurityStackProbe(void)
{
return SECURITY_DRIVER_ENABLE;
}
static int
virSecurityStackOpen(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED)
{
return 0;
}
static int
virSecurityStackClose(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED)
{
return 0;
}
static const char *
virSecurityStackGetModel(virSecurityManagerPtr mgr)
{
virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
return virSecurityManagerGetModel(priv->primary);
}
static const char *
virSecurityStackGetDOI(virSecurityManagerPtr mgr)
{
virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
return virSecurityManagerGetDOI(priv->primary);
}
static int
virSecurityStackVerify(virSecurityManagerPtr mgr,
virDomainDefPtr def)
{
virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
int rc = 0;
if (virSecurityManagerVerify(priv->primary, def) < 0)
rc = -1;
if (virSecurityManagerVerify(priv->secondary, def) < 0)
rc = -1;
return rc;
}
static int
virSecurityStackGenLabel(virSecurityManagerPtr mgr,
virDomainObjPtr vm)
{
virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
int rc = 0;
if (virSecurityManagerGenLabel(priv->primary, vm) < 0)
rc = -1;
#if 0
/* We don't allow secondary drivers to generate labels.
* This may have to change in the future, but requires
* changes elsewhere in domain_conf.c and capabilities.c
* XML formats first, to allow recording of multiple
* labels
*/
if (virSecurityManagerGenLabel(priv->secondary, vm) < 0)
rc = -1;
#endif
return rc;
}
static int
virSecurityStackReleaseLabel(virSecurityManagerPtr mgr,
virDomainObjPtr vm)
{
virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
int rc = 0;
if (virSecurityManagerReleaseLabel(priv->primary, vm) < 0)
rc = -1;
#if 0
/* XXX See note in GenLabel */
if (virSecurityManagerReleaseLabel(priv->secondary, vm) < 0)
rc = -1;
#endif
return rc;
}
static int
virSecurityStackReserveLabel(virSecurityManagerPtr mgr,
virDomainObjPtr vm)
{
virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
int rc = 0;
if (virSecurityManagerReserveLabel(priv->primary, vm) < 0)
rc = -1;
#if 0
/* XXX See note in GenLabel */
if (virSecurityManagerReserveLabel(priv->secondary, vm) < 0)
rc = -1;
#endif
return rc;
}
static int
virSecurityStackSetSecurityImageLabel(virSecurityManagerPtr mgr,
virDomainObjPtr vm,
virDomainDiskDefPtr disk)
{
virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
int rc = 0;
if (virSecurityManagerSetImageLabel(priv->secondary, vm, disk) < 0)
rc = -1;
if (virSecurityManagerSetImageLabel(priv->primary, vm, disk) < 0)
rc = -1;
return rc;
}
static int
virSecurityStackRestoreSecurityImageLabel(virSecurityManagerPtr mgr,
virDomainObjPtr vm,
virDomainDiskDefPtr disk)
{
virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
int rc = 0;
if (virSecurityManagerRestoreImageLabel(priv->secondary, vm, disk) < 0)
rc = -1;
if (virSecurityManagerRestoreImageLabel(priv->primary, vm, disk) < 0)
rc = -1;
return rc;
}
static int
virSecurityStackSetSecurityHostdevLabel(virSecurityManagerPtr mgr,
virDomainObjPtr vm,
virDomainHostdevDefPtr dev)
{
virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
int rc = 0;
if (virSecurityManagerSetHostdevLabel(priv->secondary, vm, dev) < 0)
rc = -1;
if (virSecurityManagerSetHostdevLabel(priv->primary, vm, dev) < 0)
rc = -1;
return rc;
}
static int
virSecurityStackRestoreSecurityHostdevLabel(virSecurityManagerPtr mgr,
virDomainObjPtr vm,
virDomainHostdevDefPtr dev)
{
virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
int rc = 0;
if (virSecurityManagerRestoreHostdevLabel(priv->secondary, vm, dev) < 0)
rc = -1;
if (virSecurityManagerRestoreHostdevLabel(priv->primary, vm, dev) < 0)
rc = -1;
return rc;
}
static int
virSecurityStackSetSecurityAllLabel(virSecurityManagerPtr mgr,
virDomainObjPtr vm,
const char *stdin_path)
{
virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
int rc = 0;
if (virSecurityManagerSetAllLabel(priv->secondary, vm, stdin_path) < 0)
rc = -1;
if (virSecurityManagerSetAllLabel(priv->primary, vm, stdin_path) < 0)
rc = -1;
return rc;
}
static int
virSecurityStackRestoreSecurityAllLabel(virSecurityManagerPtr mgr,
virDomainObjPtr vm,
int migrated)
{
virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
int rc = 0;
if (virSecurityManagerRestoreAllLabel(priv->secondary, vm, migrated) < 0)
rc = -1;
if (virSecurityManagerRestoreAllLabel(priv->primary, vm, migrated) < 0)
rc = -1;
return rc;
}
static int
virSecurityStackSetSavedStateLabel(virSecurityManagerPtr mgr,
virDomainObjPtr vm,
const char *savefile)
{
virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
int rc = 0;
if (virSecurityManagerSetSavedStateLabel(priv->secondary, vm, savefile) < 0)
rc = -1;
if (virSecurityManagerSetSavedStateLabel(priv->primary, vm, savefile) < 0)
rc = -1;
return rc;
}
static int
virSecurityStackRestoreSavedStateLabel(virSecurityManagerPtr mgr,
virDomainObjPtr vm,
const char *savefile)
{
virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
int rc = 0;
if (virSecurityManagerRestoreSavedStateLabel(priv->secondary, vm, savefile) < 0)
rc = -1;
if (virSecurityManagerRestoreSavedStateLabel(priv->primary, vm, savefile) < 0)
rc = -1;
return rc;
}
static int
virSecurityStackSetProcessLabel(virSecurityManagerPtr mgr,
virDomainObjPtr vm)
{
virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
int rc = 0;
if (virSecurityManagerSetProcessLabel(priv->secondary, vm) < 0)
rc = -1;
if (virSecurityManagerSetProcessLabel(priv->primary, vm) < 0)
rc = -1;
return rc;
}
static int
virSecurityStackGetProcessLabel(virSecurityManagerPtr mgr,
virDomainObjPtr vm,
virSecurityLabelPtr seclabel)
{
virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
int rc = 0;
#if 0
if (virSecurityManagerGetProcessLabel(priv->secondary, vm, seclabel) < 0)
rc = -1;
#endif
if (virSecurityManagerGetProcessLabel(priv->primary, vm, seclabel) < 0)
rc = -1;
return rc;
}
static int
virSecurityStackSetSocketLabel(virSecurityManagerPtr mgr,
virDomainObjPtr vm)
{
virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
int rc = 0;
if (virSecurityManagerSetSocketLabel(priv->secondary, vm) < 0)
rc = -1;
if (virSecurityManagerSetSocketLabel(priv->primary, vm) < 0)
rc = -1;
return rc;
}
static int
virSecurityStackClearSocketLabel(virSecurityManagerPtr mgr,
virDomainObjPtr vm)
{
virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
int rc = 0;
if (virSecurityManagerClearSocketLabel(priv->secondary, vm) < 0)
rc = -1;
if (virSecurityManagerClearSocketLabel(priv->primary, vm) < 0)
rc = -1;
return rc;
}
virSecurityDriver virSecurityDriverStack = {
sizeof(virSecurityStackData),
"stack",
virSecurityStackProbe,
virSecurityStackOpen,
virSecurityStackClose,
virSecurityStackGetModel,
virSecurityStackGetDOI,
virSecurityStackVerify,
virSecurityStackSetSecurityImageLabel,
virSecurityStackRestoreSecurityImageLabel,
virSecurityStackSetSocketLabel,
virSecurityStackClearSocketLabel,
virSecurityStackGenLabel,
virSecurityStackReserveLabel,
virSecurityStackReleaseLabel,
virSecurityStackGetProcessLabel,
virSecurityStackSetProcessLabel,
virSecurityStackSetSecurityAllLabel,
virSecurityStackRestoreSecurityAllLabel,
virSecurityStackSetSecurityHostdevLabel,
virSecurityStackRestoreSecurityHostdevLabel,
virSecurityStackSetSavedStateLabel,
virSecurityStackRestoreSavedStateLabel,
};