libvirt/src/security/security_stack.c
Guannan Ren ae368ebfcc selinux: add security selinux function to label tapfd
BZ:https://bugzilla.redhat.com/show_bug.cgi?id=851981
When using macvtap, a character device gets first created by
kernel with name /dev/tapN, its selinux context is:
system_u:object_r:device_t:s0

Shortly, when udev gets notification when new file is created
in /dev, it will then jump in and relabel this file back to the
expected default context:
system_u:object_r:tun_tap_device_t:s0

There is a time gap happened.
Sometimes, it will have migration failed, AVC error message:
type=AVC msg=audit(1349858424.233:42507): avc:  denied  { read write } for
pid=19926 comm="qemu-kvm" path="/dev/tap33" dev=devtmpfs ino=131524
scontext=unconfined_u:system_r:svirt_t:s0:c598,c908
tcontext=system_u:object_r:device_t:s0 tclass=chr_file

This patch will label the tapfd device before qemu process starts:
system_u:object_r:tun_tap_device_t:MCS(MCS from seclabel->label)
2012-10-15 21:01:07 +08:00

533 lines
15 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, see
* <http://www.gnu.org/licenses/>.
*
* Stacked security driver
*/
#include <config.h>
#include "security_stack.h"
#include "virterror_internal.h"
#include "memory.h"
#define VIR_FROM_THIS VIR_FROM_SECURITY
typedef struct _virSecurityStackData virSecurityStackData;
typedef virSecurityStackData *virSecurityStackDataPtr;
typedef struct _virSecurityStackItem virSecurityStackItem;
typedef virSecurityStackItem* virSecurityStackItemPtr;
struct _virSecurityStackItem {
virSecurityManagerPtr securityManager;
virSecurityStackItemPtr next;
};
struct _virSecurityStackData {
virSecurityStackItemPtr itemsHead;
};
int
virSecurityStackAddNested(virSecurityManagerPtr mgr,
virSecurityManagerPtr nested)
{
virSecurityStackItemPtr item = NULL;
virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
virSecurityStackItemPtr tmp;
tmp = priv->itemsHead;
while (tmp && tmp->next)
tmp = tmp->next;
if (VIR_ALLOC(item) < 0) {
virReportOOMError();
return -1;
}
item->securityManager = nested;
if (tmp)
tmp->next = item;
else
priv->itemsHead = item;
return 0;
}
virSecurityManagerPtr
virSecurityStackGetPrimary(virSecurityManagerPtr mgr)
{
virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
return priv->itemsHead->securityManager;
}
static virSecurityDriverStatus
virSecurityStackProbe(const char *virtDriver ATTRIBUTE_UNUSED)
{
return SECURITY_DRIVER_ENABLE;
}
static int
virSecurityStackOpen(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED)
{
return 0;
}
static int
virSecurityStackClose(virSecurityManagerPtr mgr)
{
virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
virSecurityStackItemPtr next, item = priv->itemsHead;
while (item) {
next = item->next;
virSecurityManagerFree(item->securityManager);
VIR_FREE(item);
item = next;
}
return 0;
}
static const char *
virSecurityStackGetModel(virSecurityManagerPtr mgr)
{
return virSecurityManagerGetModel(virSecurityStackGetPrimary(mgr));
}
static const char *
virSecurityStackGetDOI(virSecurityManagerPtr mgr)
{
return virSecurityManagerGetDOI(virSecurityStackGetPrimary(mgr));
}
static int
virSecurityStackVerify(virSecurityManagerPtr mgr,
virDomainDefPtr def)
{
virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
virSecurityStackItemPtr item = priv->itemsHead;
int rc = 0;
for(; item; item = item->next) {
if (virSecurityManagerVerify(item->securityManager, def) < 0) {
rc = -1;
break;
}
}
return rc;
}
static int
virSecurityStackGenLabel(virSecurityManagerPtr mgr,
virDomainDefPtr vm)
{
int rc = 0;
if (virSecurityManagerGenLabel(virSecurityStackGetPrimary(mgr), vm) < 0)
rc = -1;
// TODO
#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,
virDomainDefPtr vm)
{
int rc = 0;
if (virSecurityManagerReleaseLabel(virSecurityStackGetPrimary(mgr), vm) < 0)
rc = -1;
// TODO
#if 0
/* XXX See note in GenLabel */
if (virSecurityManagerReleaseLabel(priv->secondary, vm) < 0)
rc = -1;
#endif
return rc;
}
static int
virSecurityStackReserveLabel(virSecurityManagerPtr mgr,
virDomainDefPtr vm,
pid_t pid)
{
int rc = 0;
if (virSecurityManagerReserveLabel(virSecurityStackGetPrimary(mgr), vm, pid) < 0)
rc = -1;
// TODO
#if 0
/* XXX See note in GenLabel */
if (virSecurityManagerReserveLabel(priv->secondary, vm, pid) < 0)
rc = -1;
#endif
return rc;
}
static int
virSecurityStackSetSecurityImageLabel(virSecurityManagerPtr mgr,
virDomainDefPtr vm,
virDomainDiskDefPtr disk)
{
virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
virSecurityStackItemPtr item = priv->itemsHead;
int rc = 0;
for (; item; item = item->next) {
if (virSecurityManagerSetImageLabel(item->securityManager, vm, disk) < 0)
rc = -1;
}
return rc;
}
static int
virSecurityStackRestoreSecurityImageLabel(virSecurityManagerPtr mgr,
virDomainDefPtr vm,
virDomainDiskDefPtr disk)
{
virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
virSecurityStackItemPtr item = priv->itemsHead;
int rc = 0;
for (; item; item = item->next) {
if (virSecurityManagerRestoreImageLabel(item->securityManager, vm, disk) < 0)
rc = -1;
}
return rc;
}
static int
virSecurityStackSetSecurityHostdevLabel(virSecurityManagerPtr mgr,
virDomainDefPtr vm,
virDomainHostdevDefPtr dev)
{
virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
virSecurityStackItemPtr item = priv->itemsHead;
int rc = 0;
for (; item; item = item->next) {
if (virSecurityManagerSetHostdevLabel(item->securityManager, vm, dev) < 0)
rc = -1;
}
return rc;
}
static int
virSecurityStackRestoreSecurityHostdevLabel(virSecurityManagerPtr mgr,
virDomainDefPtr vm,
virDomainHostdevDefPtr dev)
{
virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
virSecurityStackItemPtr item = priv->itemsHead;
int rc = 0;
for (; item; item = item->next) {
if (virSecurityManagerRestoreHostdevLabel(item->securityManager, vm, dev) < 0)
rc = -1;
}
return rc;
}
static int
virSecurityStackSetSecurityAllLabel(virSecurityManagerPtr mgr,
virDomainDefPtr vm,
const char *stdin_path)
{
virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
virSecurityStackItemPtr item = priv->itemsHead;
int rc = 0;
for (; item; item = item->next) {
if (virSecurityManagerSetAllLabel(item->securityManager, vm, stdin_path) < 0)
rc = -1;
}
return rc;
}
static int
virSecurityStackRestoreSecurityAllLabel(virSecurityManagerPtr mgr,
virDomainDefPtr vm,
int migrated)
{
virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
virSecurityStackItemPtr item = priv->itemsHead;
int rc = 0;
for (; item; item = item->next) {
if (virSecurityManagerRestoreAllLabel(item->securityManager, vm, migrated) < 0)
rc = -1;
}
return rc;
}
static int
virSecurityStackSetSavedStateLabel(virSecurityManagerPtr mgr,
virDomainDefPtr vm,
const char *savefile)
{
virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
virSecurityStackItemPtr item = priv->itemsHead;
int rc = 0;
for (; item; item = item->next) {
if (virSecurityManagerSetSavedStateLabel(item->securityManager, vm, savefile) < 0)
rc = -1;
}
return rc;
}
static int
virSecurityStackRestoreSavedStateLabel(virSecurityManagerPtr mgr,
virDomainDefPtr vm,
const char *savefile)
{
virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
virSecurityStackItemPtr item = priv->itemsHead;
int rc = 0;
for (; item; item = item->next) {
if (virSecurityManagerRestoreSavedStateLabel(item->securityManager, vm, savefile) < 0)
rc = -1;
}
return rc;
}
static int
virSecurityStackSetProcessLabel(virSecurityManagerPtr mgr,
virDomainDefPtr vm)
{
virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
virSecurityStackItemPtr item = priv->itemsHead;
int rc = 0;
for (; item; item = item->next) {
if (virSecurityManagerSetProcessLabel(item->securityManager, vm) < 0)
rc = -1;
}
return rc;
}
static int
virSecurityStackGetProcessLabel(virSecurityManagerPtr mgr,
virDomainDefPtr vm,
pid_t pid,
virSecurityLabelPtr seclabel)
{
int rc = 0;
// TODO
#if 0
if (virSecurityManagerGetProcessLabel(priv->secondary, vm, pid, seclabel) < 0)
rc = -1;
#endif
if (virSecurityManagerGetProcessLabel(virSecurityStackGetPrimary(mgr), vm, pid, seclabel) < 0)
rc = -1;
return rc;
}
static int
virSecurityStackSetDaemonSocketLabel(virSecurityManagerPtr mgr,
virDomainDefPtr vm)
{
virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
virSecurityStackItemPtr item = priv->itemsHead;
int rc = 0;
for (; item; item = item->next) {
if (virSecurityManagerSetDaemonSocketLabel(item->securityManager, vm) < 0)
rc = -1;
}
return rc;
}
static int
virSecurityStackSetSocketLabel(virSecurityManagerPtr mgr,
virDomainDefPtr vm)
{
virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
virSecurityStackItemPtr item = priv->itemsHead;
int rc = 0;
for (; item; item = item->next) {
if (virSecurityManagerSetSocketLabel(item->securityManager, vm) < 0)
rc = -1;
}
return rc;
}
static int
virSecurityStackClearSocketLabel(virSecurityManagerPtr mgr,
virDomainDefPtr vm)
{
virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
virSecurityStackItemPtr item = priv->itemsHead;
int rc = 0;
for (; item; item = item->next) {
if (virSecurityManagerClearSocketLabel(item->securityManager, vm) < 0)
rc = -1;
}
return rc;
}
static int
virSecurityStackSetImageFDLabel(virSecurityManagerPtr mgr,
virDomainDefPtr vm,
int fd)
{
virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
virSecurityStackItemPtr item = priv->itemsHead;
int rc = 0;
for (; item; item = item->next) {
if (virSecurityManagerSetImageFDLabel(item->securityManager, vm, fd) < 0)
rc = -1;
}
return rc;
}
static int
virSecurityStackSetTapFDLabel(virSecurityManagerPtr mgr,
virDomainDefPtr vm,
int fd)
{
virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
virSecurityStackItemPtr item = priv->itemsHead;
int rc = 0;
for (; item; item = item->next) {
if (virSecurityManagerSetTapFDLabel(item->securityManager, vm, fd) < 0)
rc = -1;
}
return rc;
}
static char *virSecurityStackGetMountOptions(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
virDomainDefPtr vm ATTRIBUTE_UNUSED) {
return NULL;
}
virSecurityManagerPtr*
virSecurityStackGetNested(virSecurityManagerPtr mgr)
{
virSecurityManagerPtr *list = NULL;
virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
virSecurityStackItemPtr item;
int len = 0, i = 0;
for (item = priv->itemsHead; item; item = item->next)
len++;
if (VIR_ALLOC_N(list, len + 1) < 0) {
virReportOOMError();
return NULL;
}
for (item = priv->itemsHead; item; item = item->next, i++)
list[i] = item->securityManager;
list[len] = NULL;
return list;
}
virSecurityDriver virSecurityDriverStack = {
.privateDataLen = sizeof(virSecurityStackData),
.name = "stack",
.probe = virSecurityStackProbe,
.open = virSecurityStackOpen,
.close = virSecurityStackClose,
.getModel = virSecurityStackGetModel,
.getDOI = virSecurityStackGetDOI,
.domainSecurityVerify = virSecurityStackVerify,
.domainSetSecurityImageLabel = virSecurityStackSetSecurityImageLabel,
.domainRestoreSecurityImageLabel = virSecurityStackRestoreSecurityImageLabel,
.domainSetSecurityDaemonSocketLabel = virSecurityStackSetDaemonSocketLabel,
.domainSetSecuritySocketLabel = virSecurityStackSetSocketLabel,
.domainClearSecuritySocketLabel = virSecurityStackClearSocketLabel,
.domainGenSecurityLabel = virSecurityStackGenLabel,
.domainReserveSecurityLabel = virSecurityStackReserveLabel,
.domainReleaseSecurityLabel = virSecurityStackReleaseLabel,
.domainGetSecurityProcessLabel = virSecurityStackGetProcessLabel,
.domainSetSecurityProcessLabel = virSecurityStackSetProcessLabel,
.domainSetSecurityAllLabel = virSecurityStackSetSecurityAllLabel,
.domainRestoreSecurityAllLabel = virSecurityStackRestoreSecurityAllLabel,
.domainSetSecurityHostdevLabel = virSecurityStackSetSecurityHostdevLabel,
.domainRestoreSecurityHostdevLabel = virSecurityStackRestoreSecurityHostdevLabel,
.domainSetSavedStateLabel = virSecurityStackSetSavedStateLabel,
.domainRestoreSavedStateLabel = virSecurityStackRestoreSavedStateLabel,
.domainSetSecurityImageFDLabel = virSecurityStackSetImageFDLabel,
.domainSetSecurityTapFDLabel = virSecurityStackSetTapFDLabel,
.domainGetSecurityMountOptions = virSecurityStackGetMountOptions,
};