2009-03-03 10:06:49 +00:00
|
|
|
/*
|
2014-03-18 19:55:04 +00:00
|
|
|
* Copyright (C) 2008-2014 Red Hat, Inc.
|
2009-03-03 10:06:49 +00:00
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*
|
2012-07-21 10:06:23 +00:00
|
|
|
* 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
|
2012-09-20 22:30:55 +00:00
|
|
|
* License along with this library. If not, see
|
2012-07-21 10:06:23 +00:00
|
|
|
* <http://www.gnu.org/licenses/>.
|
|
|
|
*
|
2009-03-03 10:06:49 +00:00
|
|
|
* Authors:
|
|
|
|
* James Morris <jmorris@namei.org>
|
2009-04-03 10:55:51 +00:00
|
|
|
* Dan Walsh <dwalsh@redhat.com>
|
2009-03-03 10:06:49 +00:00
|
|
|
*
|
|
|
|
* SELinux security driver.
|
|
|
|
*/
|
|
|
|
#include <config.h>
|
|
|
|
#include <selinux/selinux.h>
|
|
|
|
#include <selinux/context.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <fcntl.h>
|
2010-12-15 00:07:52 +00:00
|
|
|
#if HAVE_SELINUX_LABEL_H
|
|
|
|
# include <selinux/label.h>
|
|
|
|
#endif
|
2009-03-03 10:06:49 +00:00
|
|
|
|
2009-09-15 18:06:37 +00:00
|
|
|
#include "security_driver.h"
|
2009-03-03 10:06:49 +00:00
|
|
|
#include "security_selinux.h"
|
2012-12-13 18:21:53 +00:00
|
|
|
#include "virerror.h"
|
2012-12-12 18:06:53 +00:00
|
|
|
#include "viralloc.h"
|
2012-12-12 17:59:27 +00:00
|
|
|
#include "virlog.h"
|
2017-02-03 12:25:57 +00:00
|
|
|
#include "virmdev.h"
|
2012-12-13 14:52:25 +00:00
|
|
|
#include "virpci.h"
|
2012-12-12 17:04:51 +00:00
|
|
|
#include "virusb.h"
|
2013-05-03 18:07:28 +00:00
|
|
|
#include "virscsi.h"
|
2016-11-22 03:58:21 +00:00
|
|
|
#include "virscsivhost.h"
|
2012-12-13 15:25:48 +00:00
|
|
|
#include "virstoragefile.h"
|
2011-07-19 18:32:58 +00:00
|
|
|
#include "virfile.h"
|
2012-05-24 16:22:29 +00:00
|
|
|
#include "virhash.h"
|
2012-01-25 15:17:46 +00:00
|
|
|
#include "virrandom.h"
|
2012-12-12 16:35:35 +00:00
|
|
|
#include "virconf.h"
|
2013-04-12 20:55:46 +00:00
|
|
|
#include "virtpm.h"
|
2013-04-03 10:36:23 +00:00
|
|
|
#include "virstring.h"
|
2009-03-03 15:18:24 +00:00
|
|
|
|
|
|
|
#define VIR_FROM_THIS VIR_FROM_SECURITY
|
|
|
|
|
2014-02-28 12:16:17 +00:00
|
|
|
VIR_LOG_INIT("security.security_selinux");
|
|
|
|
|
2012-05-11 09:43:30 +00:00
|
|
|
#define MAX_CONTEXT 1024
|
|
|
|
|
|
|
|
typedef struct _virSecuritySELinuxData virSecuritySELinuxData;
|
|
|
|
typedef virSecuritySELinuxData *virSecuritySELinuxDataPtr;
|
|
|
|
|
|
|
|
struct _virSecuritySELinuxData {
|
|
|
|
char *domain_context;
|
2012-12-12 11:47:19 +00:00
|
|
|
char *alt_domain_context;
|
2012-05-11 09:43:30 +00:00
|
|
|
char *file_context;
|
|
|
|
char *content_context;
|
2012-05-24 16:22:29 +00:00
|
|
|
virHashTablePtr mcs;
|
2012-11-28 13:54:39 +00:00
|
|
|
bool skipAllLabel;
|
2013-01-23 20:09:04 +00:00
|
|
|
#if HAVE_SELINUX_LABEL_H
|
|
|
|
struct selabel_handle *label_handle;
|
|
|
|
#endif
|
2012-05-11 09:43:30 +00:00
|
|
|
};
|
|
|
|
|
2015-09-10 11:49:18 +00:00
|
|
|
/* Data structure to pass to various callbacks so we have everything we need */
|
|
|
|
typedef struct _virSecuritySELinuxCallbackData virSecuritySELinuxCallbackData;
|
|
|
|
typedef virSecuritySELinuxCallbackData *virSecuritySELinuxCallbackDataPtr;
|
2009-03-03 10:06:49 +00:00
|
|
|
|
2015-09-10 11:49:18 +00:00
|
|
|
struct _virSecuritySELinuxCallbackData {
|
2014-11-26 17:35:46 +00:00
|
|
|
virSecurityManagerPtr mgr;
|
|
|
|
virDomainDefPtr def;
|
|
|
|
};
|
|
|
|
|
2016-12-14 16:11:05 +00:00
|
|
|
typedef struct _virSecuritySELinuxContextItem virSecuritySELinuxContextItem;
|
|
|
|
typedef virSecuritySELinuxContextItem *virSecuritySELinuxContextItemPtr;
|
|
|
|
struct _virSecuritySELinuxContextItem {
|
2017-01-17 11:22:14 +00:00
|
|
|
char *path;
|
|
|
|
char *tcon;
|
2016-12-14 16:11:05 +00:00
|
|
|
bool optional;
|
|
|
|
};
|
|
|
|
|
|
|
|
typedef struct _virSecuritySELinuxContextList virSecuritySELinuxContextList;
|
|
|
|
typedef virSecuritySELinuxContextList *virSecuritySELinuxContextListPtr;
|
|
|
|
struct _virSecuritySELinuxContextList {
|
|
|
|
bool privileged;
|
|
|
|
virSecuritySELinuxContextItemPtr *items;
|
|
|
|
size_t nItems;
|
|
|
|
};
|
|
|
|
|
2015-09-10 11:49:18 +00:00
|
|
|
#define SECURITY_SELINUX_VOID_DOI "0"
|
|
|
|
#define SECURITY_SELINUX_NAME "selinux"
|
|
|
|
|
2013-04-12 20:55:46 +00:00
|
|
|
static int
|
2015-12-09 13:34:34 +00:00
|
|
|
virSecuritySELinuxRestoreTPMFileLabelInt(virSecurityManagerPtr mgr,
|
|
|
|
virDomainDefPtr def,
|
|
|
|
virDomainTPMDefPtr tpm);
|
2013-04-12 20:55:46 +00:00
|
|
|
|
|
|
|
|
2016-12-14 16:11:05 +00:00
|
|
|
virThreadLocal contextList;
|
|
|
|
|
2017-01-17 11:22:14 +00:00
|
|
|
|
|
|
|
static void
|
|
|
|
virSecuritySELinuxContextItemFree(virSecuritySELinuxContextItemPtr item)
|
|
|
|
{
|
|
|
|
if (!item)
|
|
|
|
return;
|
|
|
|
|
|
|
|
VIR_FREE(item->path);
|
|
|
|
VIR_FREE(item->tcon);
|
|
|
|
VIR_FREE(item);
|
|
|
|
}
|
|
|
|
|
2016-12-14 16:11:05 +00:00
|
|
|
static int
|
|
|
|
virSecuritySELinuxContextListAppend(virSecuritySELinuxContextListPtr list,
|
|
|
|
const char *path,
|
|
|
|
const char *tcon,
|
|
|
|
bool optional)
|
|
|
|
{
|
2017-01-17 11:22:14 +00:00
|
|
|
int ret = -1;
|
|
|
|
virSecuritySELinuxContextItemPtr item = NULL;
|
2016-12-14 16:11:05 +00:00
|
|
|
|
|
|
|
if (VIR_ALLOC(item) < 0)
|
|
|
|
return -1;
|
|
|
|
|
2017-01-17 11:22:14 +00:00
|
|
|
if (VIR_STRDUP(item->path, path) < 0 || VIR_STRDUP(item->tcon, tcon) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
2016-12-14 16:11:05 +00:00
|
|
|
item->optional = optional;
|
|
|
|
|
2017-01-17 11:22:14 +00:00
|
|
|
if (VIR_APPEND_ELEMENT(list->items, list->nItems, item) < 0)
|
|
|
|
goto cleanup;
|
2016-12-14 16:11:05 +00:00
|
|
|
|
2017-01-17 11:22:14 +00:00
|
|
|
ret = 0;
|
|
|
|
cleanup:
|
|
|
|
virSecuritySELinuxContextItemFree(item);
|
|
|
|
return ret;
|
2016-12-14 16:11:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
virSecuritySELinuxContextListFree(void *opaque)
|
|
|
|
{
|
|
|
|
virSecuritySELinuxContextListPtr list = opaque;
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
if (!list)
|
|
|
|
return;
|
|
|
|
|
|
|
|
for (i = 0; i < list->nItems; i++)
|
2017-01-17 11:22:14 +00:00
|
|
|
virSecuritySELinuxContextItemFree(list->items[i]);
|
|
|
|
|
2016-12-14 16:11:05 +00:00
|
|
|
VIR_FREE(list);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virSecuritySELinuxTransactionAppend:
|
|
|
|
* @path: Path to chown
|
|
|
|
* @tcon: target context
|
|
|
|
* @optional: true if setting @tcon is optional
|
|
|
|
*
|
|
|
|
* Appends an entry onto transaction list.
|
|
|
|
*
|
|
|
|
* Returns: 1 in case of successful append
|
|
|
|
* 0 if there is no transaction enabled
|
|
|
|
* -1 otherwise.
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
virSecuritySELinuxTransactionAppend(const char *path,
|
|
|
|
const char *tcon,
|
|
|
|
bool optional)
|
|
|
|
{
|
|
|
|
virSecuritySELinuxContextListPtr list;
|
|
|
|
|
|
|
|
list = virThreadLocalGet(&contextList);
|
|
|
|
if (!list)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (virSecuritySELinuxContextListAppend(list, path, tcon, optional) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int virSecuritySELinuxSetFileconHelper(const char *path,
|
|
|
|
const char *tcon,
|
|
|
|
bool optional,
|
|
|
|
bool privileged);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virSecuritySELinuxTransactionRun:
|
|
|
|
* @pid: process pid
|
|
|
|
* @opaque: opaque data
|
|
|
|
*
|
|
|
|
* This is the callback that runs in the same namespace as the domain we are
|
|
|
|
* relabelling. For given transaction (@opaque) it relabels all the paths on
|
|
|
|
* the list.
|
|
|
|
*
|
|
|
|
* Returns: 0 on success
|
|
|
|
* -1 otherwise.
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
virSecuritySELinuxTransactionRun(pid_t pid ATTRIBUTE_UNUSED,
|
|
|
|
void *opaque)
|
|
|
|
{
|
|
|
|
virSecuritySELinuxContextListPtr list = opaque;
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
for (i = 0; i < list->nItems; i++) {
|
|
|
|
virSecuritySELinuxContextItemPtr item = list->items[i];
|
|
|
|
|
|
|
|
/* TODO Implement rollback */
|
|
|
|
if (virSecuritySELinuxSetFileconHelper(item->path,
|
|
|
|
item->tcon,
|
|
|
|
item->optional,
|
|
|
|
list->privileged) < 0)
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-05-24 15:52:18 +00:00
|
|
|
/*
|
|
|
|
* Returns 0 on success, 1 if already reserved, or -1 on fatal error
|
|
|
|
*/
|
2009-03-03 10:06:49 +00:00
|
|
|
static int
|
2012-05-24 16:22:29 +00:00
|
|
|
virSecuritySELinuxMCSAdd(virSecurityManagerPtr mgr,
|
|
|
|
const char *mcs)
|
2009-03-03 10:06:49 +00:00
|
|
|
{
|
2012-05-24 16:22:29 +00:00
|
|
|
virSecuritySELinuxDataPtr data = virSecurityManagerGetPrivateData(mgr);
|
2009-03-03 10:06:49 +00:00
|
|
|
|
2012-05-24 16:22:29 +00:00
|
|
|
if (virHashLookup(data->mcs, mcs))
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
if (virHashAddEntry(data->mcs, mcs, (void*)0x1) < 0)
|
2012-05-24 15:52:18 +00:00
|
|
|
return -1;
|
2012-05-24 16:22:29 +00:00
|
|
|
|
2009-03-03 10:06:49 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-05-24 16:22:29 +00:00
|
|
|
static void
|
|
|
|
virSecuritySELinuxMCSRemove(virSecurityManagerPtr mgr,
|
|
|
|
const char *mcs)
|
2009-03-03 10:06:49 +00:00
|
|
|
{
|
2012-05-24 16:22:29 +00:00
|
|
|
virSecuritySELinuxDataPtr data = virSecurityManagerGetPrivateData(mgr);
|
|
|
|
|
|
|
|
virHashRemoveEntry(data->mcs, mcs);
|
2009-03-03 10:06:49 +00:00
|
|
|
}
|
|
|
|
|
2012-08-09 16:43:12 +00:00
|
|
|
|
|
|
|
static char *
|
2013-03-13 17:41:19 +00:00
|
|
|
virSecuritySELinuxMCSFind(virSecurityManagerPtr mgr,
|
|
|
|
const char *sens,
|
|
|
|
int catMin,
|
|
|
|
int catMax)
|
2012-08-09 16:43:12 +00:00
|
|
|
{
|
|
|
|
virSecuritySELinuxDataPtr data = virSecurityManagerGetPrivateData(mgr);
|
2013-03-13 17:41:19 +00:00
|
|
|
int catRange;
|
2012-08-09 16:43:12 +00:00
|
|
|
char *mcs = NULL;
|
2013-03-13 17:41:19 +00:00
|
|
|
|
|
|
|
/* +1 since virRandomInt range is exclusive of the upper bound */
|
|
|
|
catRange = (catMax - catMin) + 1;
|
|
|
|
|
|
|
|
if (catRange < 8) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Category range c%d-c%d too small"),
|
|
|
|
catMin, catMax);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
VIR_DEBUG("Using sensitivity level '%s' cat min %d max %d range %d",
|
|
|
|
sens, catMin, catMax, catRange);
|
|
|
|
|
|
|
|
for (;;) {
|
|
|
|
int c1 = virRandomInt(catRange);
|
|
|
|
int c2 = virRandomInt(catRange);
|
|
|
|
|
|
|
|
VIR_DEBUG("Try cat %s:c%d,c%d", sens, c1 + catMin, c2 + catMin);
|
|
|
|
|
|
|
|
if (c1 == c2) {
|
2013-07-04 10:15:50 +00:00
|
|
|
if (virAsprintf(&mcs, "%s:c%d", sens, catMin + c1) < 0)
|
2013-03-13 17:41:19 +00:00
|
|
|
return NULL;
|
|
|
|
} else {
|
|
|
|
if (c1 > c2) {
|
|
|
|
int t = c1;
|
|
|
|
c1 = c2;
|
|
|
|
c2 = t;
|
|
|
|
}
|
2013-07-04 10:15:50 +00:00
|
|
|
if (virAsprintf(&mcs, "%s:c%d,c%d", sens, catMin + c1, catMin + c2) < 0)
|
2013-03-13 17:41:19 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (virHashLookup(data->mcs, mcs) == NULL)
|
|
|
|
break;
|
|
|
|
|
|
|
|
VIR_FREE(mcs);
|
|
|
|
}
|
|
|
|
|
|
|
|
return mcs;
|
|
|
|
}
|
|
|
|
|
2013-03-13 17:58:26 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* This needs to cope with several styles of range
|
|
|
|
*
|
2013-06-10 12:37:40 +00:00
|
|
|
* system_u:system_r:virtd_t
|
2013-03-13 17:58:26 +00:00
|
|
|
* system_u:system_r:virtd_t:s0
|
|
|
|
* system_u:system_r:virtd_t:s0-s0
|
|
|
|
* system_u:system_r:virtd_t:s0-s0:c0.c1023
|
|
|
|
*
|
2013-06-10 12:37:40 +00:00
|
|
|
* In the first case we'll assume s0:c0.c1023 and
|
|
|
|
* in the next two cases, we'll assume c0.c1023 for
|
2013-03-13 17:58:26 +00:00
|
|
|
* the category part, since that's what we're really
|
|
|
|
* interested in. This won't work in Enforcing mode,
|
|
|
|
* but will prevent libvirtd breaking in Permissive
|
2014-04-20 20:07:46 +00:00
|
|
|
* mode when run with a weird process label.
|
2013-03-13 17:58:26 +00:00
|
|
|
*/
|
2013-03-13 17:41:19 +00:00
|
|
|
static int
|
|
|
|
virSecuritySELinuxMCSGetProcessRange(char **sens,
|
|
|
|
int *catMin,
|
|
|
|
int *catMax)
|
|
|
|
{
|
2012-08-10 13:27:51 +00:00
|
|
|
security_context_t ourSecContext = NULL;
|
|
|
|
context_t ourContext = NULL;
|
2013-03-13 17:58:26 +00:00
|
|
|
char *cat = NULL;
|
|
|
|
char *tmp;
|
2013-06-10 12:37:40 +00:00
|
|
|
const char *contextRange;
|
2013-03-13 17:41:19 +00:00
|
|
|
int ret = -1;
|
2012-08-10 13:27:51 +00:00
|
|
|
|
2012-10-05 14:41:22 +00:00
|
|
|
if (getcon_raw(&ourSecContext) < 0) {
|
2012-08-10 13:27:51 +00:00
|
|
|
virReportSystemError(errno, "%s",
|
|
|
|
_("Unable to get current process SELinux context"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
if (!(ourContext = context_new(ourSecContext))) {
|
|
|
|
virReportSystemError(errno,
|
|
|
|
_("Unable to parse current SELinux context '%s'"),
|
|
|
|
ourSecContext);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2013-06-10 12:37:40 +00:00
|
|
|
if (!(contextRange = context_range_get(ourContext)))
|
|
|
|
contextRange = "s0";
|
2012-08-10 13:27:51 +00:00
|
|
|
|
2013-06-10 12:37:40 +00:00
|
|
|
if (VIR_STRDUP(*sens, contextRange) < 0)
|
2012-08-10 13:27:51 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2013-03-13 17:58:26 +00:00
|
|
|
/* Find and blank out the category part (if any) */
|
|
|
|
tmp = strchr(*sens, ':');
|
|
|
|
if (tmp) {
|
|
|
|
*tmp = '\0';
|
|
|
|
cat = tmp + 1;
|
2012-08-10 13:27:51 +00:00
|
|
|
}
|
|
|
|
/* Find and blank out the sensitivity upper bound */
|
2013-03-13 17:41:19 +00:00
|
|
|
if ((tmp = strchr(*sens, '-')))
|
2012-08-10 13:27:51 +00:00
|
|
|
*tmp = '\0';
|
|
|
|
/* sens now just contains the sensitivity lower bound */
|
|
|
|
|
Fix off-by-1 in default SELinux MCS range
For a while we're have random failures of 'securityselinuxtest'
which were not at all reproducible. Fortunately we finally
caught a failure with VIR_TEST_DEBUG=1 enabled. This revealed
TEST: securityselinuxtest
1) GenLabel "dynamic unconfined, s0, c0.c1023" ... OK
2) GenLabel "dynamic unconfined, s0, c0.c1023" ... OK
3) GenLabel "dynamic unconfined, s0, c0.c1023" ... OK
4) GenLabel "dynamic virtd, s0, c0.c1023" ... OK
5) GenLabel "dynamic virtd, s0, c0.c10" ... OK
6) GenLabel "dynamic virtd, s2-s3, c0.c1023" ... OK
7) GenLabel "dynamic virtd, missing range" ... Category two 1024 is out of range 0-1023
FAILED
FAIL: securityselinuxtest
And sure enough we had an off-by-1 in the MCS range code when
the current process has no range set. The test suite randomly
allocates 2 categories from 0->1024 so the chances of hitting
this in the test suite were slim indeed :-)
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-11-19 17:45:59 +00:00
|
|
|
/* If there was no category part, just assume c0.c1023 */
|
2013-03-13 17:58:26 +00:00
|
|
|
if (!cat) {
|
|
|
|
*catMin = 0;
|
Fix off-by-1 in default SELinux MCS range
For a while we're have random failures of 'securityselinuxtest'
which were not at all reproducible. Fortunately we finally
caught a failure with VIR_TEST_DEBUG=1 enabled. This revealed
TEST: securityselinuxtest
1) GenLabel "dynamic unconfined, s0, c0.c1023" ... OK
2) GenLabel "dynamic unconfined, s0, c0.c1023" ... OK
3) GenLabel "dynamic unconfined, s0, c0.c1023" ... OK
4) GenLabel "dynamic virtd, s0, c0.c1023" ... OK
5) GenLabel "dynamic virtd, s0, c0.c10" ... OK
6) GenLabel "dynamic virtd, s2-s3, c0.c1023" ... OK
7) GenLabel "dynamic virtd, missing range" ... Category two 1024 is out of range 0-1023
FAILED
FAIL: securityselinuxtest
And sure enough we had an off-by-1 in the MCS range code when
the current process has no range set. The test suite randomly
allocates 2 categories from 0->1024 so the chances of hitting
this in the test suite were slim indeed :-)
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-11-19 17:45:59 +00:00
|
|
|
*catMax = 1023;
|
2013-03-13 17:58:26 +00:00
|
|
|
ret = 0;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2012-08-10 13:27:51 +00:00
|
|
|
/* Find & extract category min */
|
|
|
|
tmp = cat;
|
|
|
|
if (tmp[0] != 'c') {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Cannot parse category in %s"),
|
|
|
|
cat);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
tmp++;
|
2013-03-13 17:41:19 +00:00
|
|
|
if (virStrToLong_i(tmp, &tmp, 10, catMin) < 0) {
|
2012-08-10 13:27:51 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Cannot parse category in %s"),
|
|
|
|
cat);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* We *must* have a pair of categories otherwise
|
|
|
|
* there's no range to allocate VM categories from */
|
|
|
|
if (!tmp[0]) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("No category range available"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Find & extract category max (if any) */
|
|
|
|
if (tmp[0] != '.') {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Cannot parse category in %s"),
|
|
|
|
cat);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
tmp++;
|
|
|
|
if (tmp[0] != 'c') {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Cannot parse category in %s"),
|
|
|
|
cat);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
tmp++;
|
2013-03-13 17:41:19 +00:00
|
|
|
if (virStrToLong_i(tmp, &tmp, 10, catMax) < 0) {
|
2012-08-10 13:27:51 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Cannot parse category in %s"),
|
|
|
|
cat);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2013-03-13 17:41:19 +00:00
|
|
|
ret = 0;
|
2012-08-09 16:43:12 +00:00
|
|
|
|
2014-03-25 06:57:22 +00:00
|
|
|
cleanup:
|
2013-03-13 17:41:19 +00:00
|
|
|
if (ret < 0)
|
|
|
|
VIR_FREE(*sens);
|
2012-08-10 13:27:51 +00:00
|
|
|
freecon(ourSecContext);
|
|
|
|
context_free(ourContext);
|
2013-03-13 17:41:19 +00:00
|
|
|
return ret;
|
2012-08-09 16:43:12 +00:00
|
|
|
}
|
|
|
|
|
2012-10-15 09:03:49 +00:00
|
|
|
static char *
|
|
|
|
virSecuritySELinuxContextAddRange(security_context_t src,
|
|
|
|
security_context_t dst)
|
|
|
|
{
|
|
|
|
char *str = NULL;
|
|
|
|
char *ret = NULL;
|
|
|
|
context_t srccon = NULL;
|
|
|
|
context_t dstcon = NULL;
|
|
|
|
|
|
|
|
if (!src || !dst)
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
if (!(srccon = context_new(src)) || !(dstcon = context_new(dst))) {
|
|
|
|
virReportSystemError(errno, "%s",
|
|
|
|
_("unable to allocate security context"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (context_range_set(dstcon, context_range_get(srccon)) == -1) {
|
|
|
|
virReportSystemError(errno,
|
|
|
|
_("unable to set security context range '%s'"), dst);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(str = context_str(dstcon))) {
|
|
|
|
virReportSystemError(errno, "%s",
|
|
|
|
_("Unable to format SELinux context"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2013-05-03 12:48:43 +00:00
|
|
|
ignore_value(VIR_STRDUP(ret, str));
|
2012-10-15 09:03:49 +00:00
|
|
|
|
2014-03-25 06:57:22 +00:00
|
|
|
cleanup:
|
2012-10-15 09:03:49 +00:00
|
|
|
if (srccon) context_free(srccon);
|
|
|
|
if (dstcon) context_free(dstcon);
|
|
|
|
return ret;
|
|
|
|
}
|
2012-08-09 16:43:12 +00:00
|
|
|
|
2009-03-03 10:06:49 +00:00
|
|
|
static char *
|
2012-08-20 14:12:14 +00:00
|
|
|
virSecuritySELinuxGenNewContext(const char *basecontext,
|
|
|
|
const char *mcs,
|
|
|
|
bool isObjectContext)
|
2009-03-03 10:06:49 +00:00
|
|
|
{
|
2012-08-09 16:20:25 +00:00
|
|
|
context_t context = NULL;
|
2012-08-09 16:07:51 +00:00
|
|
|
char *ret = NULL;
|
|
|
|
char *str;
|
2012-08-09 16:20:25 +00:00
|
|
|
security_context_t ourSecContext = NULL;
|
|
|
|
context_t ourContext = NULL;
|
|
|
|
|
2012-08-10 13:27:51 +00:00
|
|
|
VIR_DEBUG("basecontext=%s mcs=%s isObjectContext=%d",
|
|
|
|
basecontext, mcs, isObjectContext);
|
|
|
|
|
2012-10-05 14:41:22 +00:00
|
|
|
if (getcon_raw(&ourSecContext) < 0) {
|
2012-08-09 16:20:25 +00:00
|
|
|
virReportSystemError(errno, "%s",
|
|
|
|
_("Unable to get current process SELinux context"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
if (!(ourContext = context_new(ourSecContext))) {
|
|
|
|
virReportSystemError(errno,
|
|
|
|
_("Unable to parse current SELinux context '%s'"),
|
|
|
|
ourSecContext);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2012-08-10 13:27:51 +00:00
|
|
|
VIR_DEBUG("process=%s", ourSecContext);
|
2012-08-09 16:07:51 +00:00
|
|
|
|
|
|
|
if (!(context = context_new(basecontext))) {
|
|
|
|
virReportSystemError(errno,
|
|
|
|
_("Unable to parse base SELinux context '%s'"),
|
|
|
|
basecontext);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2012-08-09 16:20:25 +00:00
|
|
|
if (context_user_set(context,
|
|
|
|
context_user_get(ourContext)) != 0) {
|
|
|
|
virReportSystemError(errno,
|
|
|
|
_("Unable to set SELinux context user '%s'"),
|
|
|
|
context_user_get(ourContext));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2012-08-20 14:12:14 +00:00
|
|
|
if (!isObjectContext &&
|
|
|
|
context_role_set(context,
|
2012-08-09 16:20:25 +00:00
|
|
|
context_role_get(ourContext)) != 0) {
|
|
|
|
virReportSystemError(errno,
|
2012-08-20 14:12:14 +00:00
|
|
|
_("Unable to set SELinux context role '%s'"),
|
2012-08-09 16:20:25 +00:00
|
|
|
context_role_get(ourContext));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2012-08-09 16:07:51 +00:00
|
|
|
if (context_range_set(context, mcs) != 0) {
|
|
|
|
virReportSystemError(errno,
|
|
|
|
_("Unable to set SELinux context MCS '%s'"),
|
|
|
|
mcs);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
if (!(str = context_str(context))) {
|
|
|
|
virReportSystemError(errno, "%s",
|
|
|
|
_("Unable to format SELinux context"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2013-05-03 12:48:43 +00:00
|
|
|
if (VIR_STRDUP(ret, str) < 0)
|
2012-08-09 16:07:51 +00:00
|
|
|
goto cleanup;
|
2012-08-10 13:27:51 +00:00
|
|
|
VIR_DEBUG("Generated context '%s'", ret);
|
2014-03-25 06:57:22 +00:00
|
|
|
cleanup:
|
2012-08-09 16:20:25 +00:00
|
|
|
freecon(ourSecContext);
|
|
|
|
context_free(ourContext);
|
2012-08-09 16:07:51 +00:00
|
|
|
context_free(context);
|
|
|
|
return ret;
|
2009-03-03 10:06:49 +00:00
|
|
|
}
|
|
|
|
|
2012-05-11 09:54:31 +00:00
|
|
|
|
2012-05-16 13:18:25 +00:00
|
|
|
#ifdef HAVE_SELINUX_LXC_CONTEXTS_PATH
|
2009-03-03 10:06:49 +00:00
|
|
|
static int
|
2012-05-24 15:42:51 +00:00
|
|
|
virSecuritySELinuxLXCInitialize(virSecurityManagerPtr mgr)
|
2012-05-11 09:54:31 +00:00
|
|
|
{
|
|
|
|
virConfPtr selinux_conf;
|
|
|
|
virSecuritySELinuxDataPtr data = virSecurityManagerGetPrivateData(mgr);
|
|
|
|
|
2012-11-28 13:54:39 +00:00
|
|
|
data->skipAllLabel = true;
|
|
|
|
|
2013-01-24 13:10:50 +00:00
|
|
|
# if HAVE_SELINUX_LABEL_H
|
2013-01-23 20:09:04 +00:00
|
|
|
data->label_handle = selabel_open(SELABEL_CTX_FILE, NULL, 0);
|
|
|
|
if (!data->label_handle) {
|
|
|
|
virReportSystemError(errno, "%s",
|
|
|
|
_("cannot open SELinux label_handle"));
|
|
|
|
return -1;
|
|
|
|
}
|
2013-01-24 13:10:50 +00:00
|
|
|
# endif
|
2013-01-23 20:09:04 +00:00
|
|
|
|
2013-12-04 15:23:11 +00:00
|
|
|
if (!(selinux_conf = virConfReadFile(selinux_lxc_contexts_path(), 0)))
|
2013-01-23 20:09:04 +00:00
|
|
|
goto error;
|
2012-05-11 09:54:31 +00:00
|
|
|
|
2016-07-08 12:53:00 +00:00
|
|
|
if (virConfGetValueString(selinux_conf, "process", &data->domain_context) < 0)
|
2012-05-11 09:54:31 +00:00
|
|
|
goto error;
|
|
|
|
|
2016-07-08 12:53:00 +00:00
|
|
|
if (!data->domain_context) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("missing 'process' value in selinux lxc contexts file '%s'"),
|
|
|
|
selinux_lxc_contexts_path());
|
2012-05-11 09:54:31 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
2016-07-08 12:53:00 +00:00
|
|
|
if (virConfGetValueString(selinux_conf, "file", &data->file_context) < 0)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
if (!data->file_context) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("missing 'file' value in selinux lxc contexts file '%s'"),
|
|
|
|
selinux_lxc_contexts_path());
|
2012-05-11 09:54:31 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
2016-07-08 12:53:00 +00:00
|
|
|
if (virConfGetValueString(selinux_conf, "content", &data->content_context) < 0)
|
|
|
|
goto error;
|
|
|
|
|
|
|
|
if (!data->content_context) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("missing 'content' value in selinux lxc contexts file '%s'"),
|
|
|
|
selinux_lxc_contexts_path());
|
2012-05-11 09:54:31 +00:00
|
|
|
goto error;
|
2016-07-08 12:53:00 +00:00
|
|
|
}
|
2012-05-24 16:22:29 +00:00
|
|
|
|
|
|
|
if (!(data->mcs = virHashCreate(10, NULL)))
|
|
|
|
goto error;
|
|
|
|
|
2012-05-11 09:54:31 +00:00
|
|
|
virConfFree(selinux_conf);
|
|
|
|
return 0;
|
|
|
|
|
2014-03-25 06:57:22 +00:00
|
|
|
error:
|
2013-01-24 13:10:50 +00:00
|
|
|
# if HAVE_SELINUX_LABEL_H
|
2013-01-23 20:09:04 +00:00
|
|
|
selabel_close(data->label_handle);
|
2013-10-01 11:15:12 +00:00
|
|
|
data->label_handle = NULL;
|
2013-01-24 13:10:50 +00:00
|
|
|
# endif
|
2012-05-11 09:54:31 +00:00
|
|
|
virConfFree(selinux_conf);
|
|
|
|
VIR_FREE(data->domain_context);
|
|
|
|
VIR_FREE(data->file_context);
|
|
|
|
VIR_FREE(data->content_context);
|
2012-05-24 16:22:29 +00:00
|
|
|
virHashFree(data->mcs);
|
2012-05-11 09:54:31 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2012-05-16 13:18:25 +00:00
|
|
|
#else
|
|
|
|
static int
|
2012-05-24 15:42:51 +00:00
|
|
|
virSecuritySELinuxLXCInitialize(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED)
|
2012-05-16 13:18:25 +00:00
|
|
|
{
|
|
|
|
virReportSystemError(ENOSYS, "%s",
|
|
|
|
_("libselinux does not support LXC contexts path"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
#endif
|
2012-05-11 09:54:31 +00:00
|
|
|
|
|
|
|
|
|
|
|
static int
|
2012-05-24 15:42:51 +00:00
|
|
|
virSecuritySELinuxQEMUInitialize(virSecurityManagerPtr mgr)
|
2009-03-03 10:06:49 +00:00
|
|
|
{
|
2012-05-11 09:43:30 +00:00
|
|
|
char *ptr;
|
|
|
|
virSecuritySELinuxDataPtr data = virSecurityManagerGetPrivateData(mgr);
|
2009-03-03 10:06:49 +00:00
|
|
|
|
2012-11-28 13:54:39 +00:00
|
|
|
data->skipAllLabel = false;
|
|
|
|
|
2013-01-23 20:09:04 +00:00
|
|
|
#if HAVE_SELINUX_LABEL_H
|
|
|
|
data->label_handle = selabel_open(SELABEL_CTX_FILE, NULL, 0);
|
|
|
|
if (!data->label_handle) {
|
|
|
|
virReportSystemError(errno, "%s",
|
|
|
|
_("cannot open SELinux label_handle"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2012-05-11 09:43:30 +00:00
|
|
|
if (virFileReadAll(selinux_virtual_domain_context_path(), MAX_CONTEXT, &(data->domain_context)) < 0) {
|
2010-02-04 20:02:58 +00:00
|
|
|
virReportSystemError(errno,
|
2012-05-11 09:43:30 +00:00
|
|
|
_("cannot read SELinux virtual domain context file '%s'"),
|
2009-08-28 17:44:43 +00:00
|
|
|
selinux_virtual_domain_context_path());
|
2012-05-11 09:43:30 +00:00
|
|
|
goto error;
|
2009-03-03 10:06:49 +00:00
|
|
|
}
|
|
|
|
|
2012-05-11 09:43:30 +00:00
|
|
|
ptr = strchrnul(data->domain_context, '\n');
|
2012-12-12 11:47:19 +00:00
|
|
|
if (ptr && *ptr == '\n') {
|
2012-05-11 09:43:30 +00:00
|
|
|
*ptr = '\0';
|
2012-12-12 11:47:19 +00:00
|
|
|
ptr++;
|
|
|
|
if (*ptr != '\0') {
|
2013-05-03 12:48:43 +00:00
|
|
|
if (VIR_STRDUP(data->alt_domain_context, ptr) < 0)
|
2012-12-12 11:47:19 +00:00
|
|
|
goto error;
|
|
|
|
ptr = strchrnul(data->alt_domain_context, '\n');
|
|
|
|
if (ptr && *ptr == '\n')
|
|
|
|
*ptr = '\0';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
VIR_DEBUG("Loaded domain context '%s', alt domain context '%s'",
|
|
|
|
data->domain_context, NULLSTR(data->alt_domain_context));
|
|
|
|
|
2009-03-03 10:06:49 +00:00
|
|
|
|
2012-05-11 09:43:30 +00:00
|
|
|
if (virFileReadAll(selinux_virtual_image_context_path(), 2*MAX_CONTEXT, &(data->file_context)) < 0) {
|
2010-02-04 20:02:58 +00:00
|
|
|
virReportSystemError(errno,
|
2009-08-28 17:44:43 +00:00
|
|
|
_("cannot read SELinux virtual image context file %s"),
|
|
|
|
selinux_virtual_image_context_path());
|
2012-05-11 09:43:30 +00:00
|
|
|
goto error;
|
2009-03-03 10:06:49 +00:00
|
|
|
}
|
|
|
|
|
2012-05-11 09:43:30 +00:00
|
|
|
ptr = strchrnul(data->file_context, '\n');
|
|
|
|
if (ptr && *ptr == '\n') {
|
2009-07-03 10:26:37 +00:00
|
|
|
*ptr = '\0';
|
2013-05-03 12:48:43 +00:00
|
|
|
if (VIR_STRDUP(data->content_context, ptr + 1) < 0)
|
2012-05-11 09:43:30 +00:00
|
|
|
goto error;
|
|
|
|
ptr = strchrnul(data->content_context, '\n');
|
|
|
|
if (ptr && *ptr == '\n')
|
2009-07-03 10:26:37 +00:00
|
|
|
*ptr = '\0';
|
|
|
|
}
|
2012-05-11 09:43:30 +00:00
|
|
|
|
2012-12-12 11:47:19 +00:00
|
|
|
VIR_DEBUG("Loaded file context '%s', content context '%s'",
|
|
|
|
data->file_context, data->content_context);
|
|
|
|
|
2012-05-24 16:22:29 +00:00
|
|
|
if (!(data->mcs = virHashCreate(10, NULL)))
|
|
|
|
goto error;
|
|
|
|
|
2009-03-03 10:06:49 +00:00
|
|
|
return 0;
|
2012-05-11 09:43:30 +00:00
|
|
|
|
2014-03-25 06:57:22 +00:00
|
|
|
error:
|
2013-01-23 20:09:04 +00:00
|
|
|
#if HAVE_SELINUX_LABEL_H
|
|
|
|
selabel_close(data->label_handle);
|
2013-10-01 11:15:12 +00:00
|
|
|
data->label_handle = NULL;
|
2013-01-23 20:09:04 +00:00
|
|
|
#endif
|
2012-05-11 09:43:30 +00:00
|
|
|
VIR_FREE(data->domain_context);
|
2012-12-12 11:47:19 +00:00
|
|
|
VIR_FREE(data->alt_domain_context);
|
2012-05-11 09:43:30 +00:00
|
|
|
VIR_FREE(data->file_context);
|
|
|
|
VIR_FREE(data->content_context);
|
2012-05-24 16:22:29 +00:00
|
|
|
virHashFree(data->mcs);
|
2012-05-11 09:43:30 +00:00
|
|
|
return -1;
|
2009-03-03 10:06:49 +00:00
|
|
|
}
|
|
|
|
|
2012-05-11 09:54:31 +00:00
|
|
|
|
|
|
|
static int
|
2012-05-24 15:42:51 +00:00
|
|
|
virSecuritySELinuxInitialize(virSecurityManagerPtr mgr)
|
2012-05-11 09:54:31 +00:00
|
|
|
{
|
|
|
|
VIR_DEBUG("SELinuxInitialize %s", virSecurityManagerGetDriver(mgr));
|
2016-12-14 16:11:05 +00:00
|
|
|
|
|
|
|
if (virThreadLocalInit(&contextList,
|
|
|
|
virSecuritySELinuxContextListFree) < 0) {
|
|
|
|
virReportSystemError(errno, "%s",
|
|
|
|
_("Unable to initialize thread local variable"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2012-05-11 09:54:31 +00:00
|
|
|
if (STREQ(virSecurityManagerGetDriver(mgr), "LXC")) {
|
2012-05-24 15:42:51 +00:00
|
|
|
return virSecuritySELinuxLXCInitialize(mgr);
|
2012-05-11 09:54:31 +00:00
|
|
|
} else {
|
2012-05-24 15:42:51 +00:00
|
|
|
return virSecuritySELinuxQEMUInitialize(mgr);
|
2012-05-11 09:54:31 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-03-03 10:06:49 +00:00
|
|
|
static int
|
2015-12-09 13:34:34 +00:00
|
|
|
virSecuritySELinuxGenLabel(virSecurityManagerPtr mgr,
|
|
|
|
virDomainDefPtr def)
|
2009-03-03 10:06:49 +00:00
|
|
|
{
|
|
|
|
int rc = -1;
|
2011-06-24 09:21:33 +00:00
|
|
|
char *mcs = NULL;
|
2009-03-03 10:06:49 +00:00
|
|
|
char *scontext = NULL;
|
2011-06-24 09:21:33 +00:00
|
|
|
context_t ctx = NULL;
|
Add two new security label types
Curently security labels can be of type 'dynamic' or 'static'.
If no security label is given, then 'dynamic' is assumed. The
current code takes advantage of this default, and avoids even
saving <seclabel> elements with type='dynamic' to disk. This
means if you temporarily change security driver, the guests
can all still start.
With the introduction of sVirt to LXC though, there needs to be
a new default of 'none' to allow unconfined LXC containers.
This patch introduces two new security label types
- default: the host configuration decides whether to run the
guest with type 'none' or 'dynamic' at guest start
- none: the guest will run unconfined by security policy
The 'none' label type will obviously be undesirable for some
deployments, so a new qemu.conf option allows a host admin to
mandate confined guests. It is also possible to turn off default
confinement
security_default_confined = 1|0 (default == 1)
security_require_confined = 1|0 (default == 0)
* src/conf/domain_conf.c, src/conf/domain_conf.h: Add new
seclabel types
* src/security/security_manager.c, src/security/security_manager.h:
Set default sec label types
* src/security/security_selinux.c: Handle 'none' seclabel type
* src/qemu/qemu.conf, src/qemu/qemu_conf.c, src/qemu/qemu_conf.h,
src/qemu/libvirtd_qemu.aug: New security config options
* src/qemu/qemu_driver.c: Tell security driver about default
config
2012-01-25 14:12:52 +00:00
|
|
|
const char *range;
|
2012-08-15 22:10:37 +00:00
|
|
|
virSecurityLabelDefPtr seclabel;
|
|
|
|
virSecuritySELinuxDataPtr data;
|
2012-12-12 11:47:19 +00:00
|
|
|
const char *baselabel;
|
2013-03-13 17:41:19 +00:00
|
|
|
char *sens = NULL;
|
|
|
|
int catMin, catMax;
|
2010-01-13 14:03:04 +00:00
|
|
|
|
2012-08-15 22:10:37 +00:00
|
|
|
seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
|
2013-07-02 16:27:09 +00:00
|
|
|
if (seclabel == NULL)
|
2014-06-09 14:23:52 +00:00
|
|
|
return 0;
|
2012-08-15 22:10:37 +00:00
|
|
|
|
|
|
|
data = virSecurityManagerGetPrivateData(mgr);
|
|
|
|
|
|
|
|
VIR_DEBUG("label=%s", virSecurityManagerGetDriver(mgr));
|
|
|
|
if (seclabel->type == VIR_DOMAIN_SECLABEL_DYNAMIC &&
|
|
|
|
seclabel->label) {
|
2013-07-02 16:27:09 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("security label already defined for VM"));
|
2010-10-27 10:01:27 +00:00
|
|
|
return rc;
|
2009-03-03 15:18:24 +00:00
|
|
|
}
|
2009-03-03 10:06:49 +00:00
|
|
|
|
2012-08-15 22:10:37 +00:00
|
|
|
if (seclabel->imagelabel) {
|
2013-07-02 16:27:09 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("security image label already defined for VM"));
|
2011-06-24 09:21:33 +00:00
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2012-08-15 22:10:37 +00:00
|
|
|
if (seclabel->model &&
|
|
|
|
STRNEQ(seclabel->model, SECURITY_SELINUX_NAME)) {
|
2012-07-18 14:39:18 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("security label model %s is not supported with selinux"),
|
2012-08-15 22:10:37 +00:00
|
|
|
seclabel->model);
|
2011-06-23 14:48:48 +00:00
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2012-08-15 22:10:37 +00:00
|
|
|
VIR_DEBUG("type=%d", seclabel->type);
|
2012-05-11 09:43:30 +00:00
|
|
|
|
2012-08-15 22:10:37 +00:00
|
|
|
switch (seclabel->type) {
|
Add two new security label types
Curently security labels can be of type 'dynamic' or 'static'.
If no security label is given, then 'dynamic' is assumed. The
current code takes advantage of this default, and avoids even
saving <seclabel> elements with type='dynamic' to disk. This
means if you temporarily change security driver, the guests
can all still start.
With the introduction of sVirt to LXC though, there needs to be
a new default of 'none' to allow unconfined LXC containers.
This patch introduces two new security label types
- default: the host configuration decides whether to run the
guest with type 'none' or 'dynamic' at guest start
- none: the guest will run unconfined by security policy
The 'none' label type will obviously be undesirable for some
deployments, so a new qemu.conf option allows a host admin to
mandate confined guests. It is also possible to turn off default
confinement
security_default_confined = 1|0 (default == 1)
security_require_confined = 1|0 (default == 0)
* src/conf/domain_conf.c, src/conf/domain_conf.h: Add new
seclabel types
* src/security/security_manager.c, src/security/security_manager.h:
Set default sec label types
* src/security/security_selinux.c: Handle 'none' seclabel type
* src/qemu/qemu.conf, src/qemu/qemu_conf.c, src/qemu/qemu_conf.h,
src/qemu/libvirtd_qemu.aug: New security config options
* src/qemu/qemu_driver.c: Tell security driver about default
config
2012-01-25 14:12:52 +00:00
|
|
|
case VIR_DOMAIN_SECLABEL_STATIC:
|
2012-10-17 09:23:12 +00:00
|
|
|
if (!(ctx = context_new(seclabel->label))) {
|
2011-06-24 09:21:33 +00:00
|
|
|
virReportSystemError(errno,
|
|
|
|
_("unable to allocate socket security context '%s'"),
|
2012-08-15 22:10:37 +00:00
|
|
|
seclabel->label);
|
2011-06-24 09:21:33 +00:00
|
|
|
return rc;
|
2009-03-03 10:06:49 +00:00
|
|
|
}
|
|
|
|
|
2013-07-02 16:27:09 +00:00
|
|
|
if (!(range = context_range_get(ctx))) {
|
2013-07-04 10:15:50 +00:00
|
|
|
virReportSystemError(errno, "%s", _("unable to get selinux context range"));
|
2011-06-24 09:21:33 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
2013-05-03 12:48:43 +00:00
|
|
|
if (VIR_STRDUP(mcs, range) < 0)
|
|
|
|
goto cleanup;
|
Add two new security label types
Curently security labels can be of type 'dynamic' or 'static'.
If no security label is given, then 'dynamic' is assumed. The
current code takes advantage of this default, and avoids even
saving <seclabel> elements with type='dynamic' to disk. This
means if you temporarily change security driver, the guests
can all still start.
With the introduction of sVirt to LXC though, there needs to be
a new default of 'none' to allow unconfined LXC containers.
This patch introduces two new security label types
- default: the host configuration decides whether to run the
guest with type 'none' or 'dynamic' at guest start
- none: the guest will run unconfined by security policy
The 'none' label type will obviously be undesirable for some
deployments, so a new qemu.conf option allows a host admin to
mandate confined guests. It is also possible to turn off default
confinement
security_default_confined = 1|0 (default == 1)
security_require_confined = 1|0 (default == 0)
* src/conf/domain_conf.c, src/conf/domain_conf.h: Add new
seclabel types
* src/security/security_manager.c, src/security/security_manager.h:
Set default sec label types
* src/security/security_selinux.c: Handle 'none' seclabel type
* src/qemu/qemu.conf, src/qemu/qemu_conf.c, src/qemu/qemu_conf.h,
src/qemu/libvirtd_qemu.aug: New security config options
* src/qemu/qemu_driver.c: Tell security driver about default
config
2012-01-25 14:12:52 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_SECLABEL_DYNAMIC:
|
2013-03-13 17:41:19 +00:00
|
|
|
if (virSecuritySELinuxMCSGetProcessRange(&sens,
|
|
|
|
&catMin,
|
|
|
|
&catMax) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (!(mcs = virSecuritySELinuxMCSFind(mgr,
|
|
|
|
sens,
|
|
|
|
catMin,
|
|
|
|
catMax)))
|
2012-08-09 16:43:12 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (virSecuritySELinuxMCSAdd(mgr, mcs) < 0)
|
|
|
|
goto cleanup;
|
2011-06-24 09:21:33 +00:00
|
|
|
|
2012-12-12 11:47:19 +00:00
|
|
|
baselabel = seclabel->baselabel;
|
|
|
|
if (!baselabel) {
|
|
|
|
if (def->virtType == VIR_DOMAIN_VIRT_QEMU) {
|
|
|
|
if (data->alt_domain_context == NULL) {
|
2014-10-28 20:17:04 +00:00
|
|
|
static bool warned;
|
2012-12-12 11:47:19 +00:00
|
|
|
if (!warned) {
|
|
|
|
VIR_WARN("SELinux policy does not define a domain type for QEMU TCG. "
|
|
|
|
"Guest startup may be denied due to missing 'execmem' privilege "
|
|
|
|
"unless the 'virt_use_execmem' policy boolean is enabled");
|
|
|
|
warned = true;
|
|
|
|
}
|
|
|
|
baselabel = data->domain_context;
|
|
|
|
} else {
|
|
|
|
baselabel = data->alt_domain_context;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
baselabel = data->domain_context;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-04-24 12:38:54 +00:00
|
|
|
seclabel->label = virSecuritySELinuxGenNewContext(baselabel, mcs, false);
|
|
|
|
if (!seclabel->label)
|
2011-06-24 09:21:33 +00:00
|
|
|
goto cleanup;
|
2013-04-24 12:38:54 +00:00
|
|
|
|
Add two new security label types
Curently security labels can be of type 'dynamic' or 'static'.
If no security label is given, then 'dynamic' is assumed. The
current code takes advantage of this default, and avoids even
saving <seclabel> elements with type='dynamic' to disk. This
means if you temporarily change security driver, the guests
can all still start.
With the introduction of sVirt to LXC though, there needs to be
a new default of 'none' to allow unconfined LXC containers.
This patch introduces two new security label types
- default: the host configuration decides whether to run the
guest with type 'none' or 'dynamic' at guest start
- none: the guest will run unconfined by security policy
The 'none' label type will obviously be undesirable for some
deployments, so a new qemu.conf option allows a host admin to
mandate confined guests. It is also possible to turn off default
confinement
security_default_confined = 1|0 (default == 1)
security_require_confined = 1|0 (default == 0)
* src/conf/domain_conf.c, src/conf/domain_conf.h: Add new
seclabel types
* src/security/security_manager.c, src/security/security_manager.h:
Set default sec label types
* src/security/security_selinux.c: Handle 'none' seclabel type
* src/qemu/qemu.conf, src/qemu/qemu_conf.c, src/qemu/qemu_conf.h,
src/qemu/libvirtd_qemu.aug: New security config options
* src/qemu/qemu_driver.c: Tell security driver about default
config
2012-01-25 14:12:52 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_SECLABEL_NONE:
|
2014-02-05 17:34:51 +00:00
|
|
|
if (virSecuritySELinuxMCSGetProcessRange(&sens,
|
|
|
|
&catMin,
|
|
|
|
&catMax) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (VIR_STRDUP(mcs, sens) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
Add two new security label types
Curently security labels can be of type 'dynamic' or 'static'.
If no security label is given, then 'dynamic' is assumed. The
current code takes advantage of this default, and avoids even
saving <seclabel> elements with type='dynamic' to disk. This
means if you temporarily change security driver, the guests
can all still start.
With the introduction of sVirt to LXC though, there needs to be
a new default of 'none' to allow unconfined LXC containers.
This patch introduces two new security label types
- default: the host configuration decides whether to run the
guest with type 'none' or 'dynamic' at guest start
- none: the guest will run unconfined by security policy
The 'none' label type will obviously be undesirable for some
deployments, so a new qemu.conf option allows a host admin to
mandate confined guests. It is also possible to turn off default
confinement
security_default_confined = 1|0 (default == 1)
security_require_confined = 1|0 (default == 0)
* src/conf/domain_conf.c, src/conf/domain_conf.h: Add new
seclabel types
* src/security/security_manager.c, src/security/security_manager.h:
Set default sec label types
* src/security/security_selinux.c: Handle 'none' seclabel type
* src/qemu/qemu.conf, src/qemu/qemu_conf.c, src/qemu/qemu_conf.h,
src/qemu/libvirtd_qemu.aug: New security config options
* src/qemu/qemu_driver.c: Tell security driver about default
config
2012-01-25 14:12:52 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
2012-07-18 14:39:18 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("unexpected security label type '%s'"),
|
2012-08-15 22:10:37 +00:00
|
|
|
virDomainSeclabelTypeToString(seclabel->type));
|
2011-06-24 09:21:33 +00:00
|
|
|
goto cleanup;
|
2009-03-03 15:18:24 +00:00
|
|
|
}
|
2011-06-24 09:21:33 +00:00
|
|
|
|
2013-07-02 16:34:58 +00:00
|
|
|
/* always generate a image label, needed to label new objects */
|
|
|
|
seclabel->imagelabel = virSecuritySELinuxGenNewContext(data->file_context,
|
|
|
|
mcs,
|
|
|
|
true);
|
|
|
|
if (!seclabel->imagelabel)
|
|
|
|
goto cleanup;
|
Add two new security label types
Curently security labels can be of type 'dynamic' or 'static'.
If no security label is given, then 'dynamic' is assumed. The
current code takes advantage of this default, and avoids even
saving <seclabel> elements with type='dynamic' to disk. This
means if you temporarily change security driver, the guests
can all still start.
With the introduction of sVirt to LXC though, there needs to be
a new default of 'none' to allow unconfined LXC containers.
This patch introduces two new security label types
- default: the host configuration decides whether to run the
guest with type 'none' or 'dynamic' at guest start
- none: the guest will run unconfined by security policy
The 'none' label type will obviously be undesirable for some
deployments, so a new qemu.conf option allows a host admin to
mandate confined guests. It is also possible to turn off default
confinement
security_default_confined = 1|0 (default == 1)
security_require_confined = 1|0 (default == 0)
* src/conf/domain_conf.c, src/conf/domain_conf.h: Add new
seclabel types
* src/security/security_manager.c, src/security/security_manager.h:
Set default sec label types
* src/security/security_selinux.c: Handle 'none' seclabel type
* src/qemu/qemu.conf, src/qemu/qemu_conf.c, src/qemu/qemu_conf.h,
src/qemu/libvirtd_qemu.aug: New security config options
* src/qemu/qemu_driver.c: Tell security driver about default
config
2012-01-25 14:12:52 +00:00
|
|
|
|
2012-08-15 22:10:37 +00:00
|
|
|
if (!seclabel->model &&
|
2013-05-03 12:48:43 +00:00
|
|
|
VIR_STRDUP(seclabel->model, SECURITY_SELINUX_NAME) < 0)
|
2011-06-24 09:21:33 +00:00
|
|
|
goto cleanup;
|
2009-03-03 15:18:24 +00:00
|
|
|
|
2009-03-03 10:06:49 +00:00
|
|
|
rc = 0;
|
2011-06-24 09:21:33 +00:00
|
|
|
|
2014-03-25 06:57:22 +00:00
|
|
|
cleanup:
|
2011-06-24 09:21:33 +00:00
|
|
|
if (rc != 0) {
|
2012-08-15 22:10:37 +00:00
|
|
|
if (seclabel->type == VIR_DOMAIN_SECLABEL_DYNAMIC)
|
|
|
|
VIR_FREE(seclabel->label);
|
|
|
|
VIR_FREE(seclabel->imagelabel);
|
|
|
|
if (seclabel->type == VIR_DOMAIN_SECLABEL_DYNAMIC &&
|
|
|
|
!seclabel->baselabel)
|
|
|
|
VIR_FREE(seclabel->model);
|
2011-06-24 09:21:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (ctx)
|
|
|
|
context_free(ctx);
|
2009-03-03 15:18:24 +00:00
|
|
|
VIR_FREE(scontext);
|
2011-06-24 09:21:33 +00:00
|
|
|
VIR_FREE(mcs);
|
2013-03-13 17:41:19 +00:00
|
|
|
VIR_FREE(sens);
|
2011-06-24 09:21:33 +00:00
|
|
|
|
|
|
|
VIR_DEBUG("model=%s label=%s imagelabel=%s baselabel=%s",
|
2012-08-15 22:10:37 +00:00
|
|
|
NULLSTR(seclabel->model),
|
|
|
|
NULLSTR(seclabel->label),
|
|
|
|
NULLSTR(seclabel->imagelabel),
|
|
|
|
NULLSTR(seclabel->baselabel));
|
2011-06-24 09:21:33 +00:00
|
|
|
|
2009-03-03 10:06:49 +00:00
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2009-06-12 11:38:50 +00:00
|
|
|
static int
|
2015-12-09 13:34:34 +00:00
|
|
|
virSecuritySELinuxReserveLabel(virSecurityManagerPtr mgr,
|
|
|
|
virDomainDefPtr def,
|
|
|
|
pid_t pid)
|
2009-06-12 11:38:50 +00:00
|
|
|
{
|
|
|
|
security_context_t pctx;
|
|
|
|
context_t ctx = NULL;
|
|
|
|
const char *mcs;
|
2012-05-24 15:52:18 +00:00
|
|
|
int rv;
|
2012-08-15 22:10:37 +00:00
|
|
|
virSecurityLabelDefPtr seclabel;
|
2009-06-12 11:38:50 +00:00
|
|
|
|
2012-08-15 22:10:37 +00:00
|
|
|
seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
|
2014-09-04 09:12:32 +00:00
|
|
|
if (!seclabel ||
|
|
|
|
seclabel->type == VIR_DOMAIN_SECLABEL_NONE ||
|
|
|
|
seclabel->type == VIR_DOMAIN_SECLABEL_STATIC)
|
2010-01-13 14:03:04 +00:00
|
|
|
return 0;
|
|
|
|
|
2012-10-05 14:41:22 +00:00
|
|
|
if (getpidcon_raw(pid, &pctx) == -1) {
|
2010-02-04 20:02:58 +00:00
|
|
|
virReportSystemError(errno,
|
Change security driver APIs to use virDomainDefPtr instead of virDomainObjPtr
When sVirt is integrated with the LXC driver, it will be neccessary
to invoke the security driver APIs using only a virDomainDefPtr
since the lxc_container.c code has no virDomainObjPtr available.
Aside from two functions which want obj->pid, every bit of the
security driver code only touches obj->def. So we don't need to
pass a virDomainObjPtr into the security drivers, a virDomainDefPtr
is sufficient. Two functions also gain a 'pid_t pid' argument.
* src/qemu/qemu_driver.c, src/qemu/qemu_hotplug.c,
src/qemu/qemu_migration.c, src/qemu/qemu_process.c,
src/security/security_apparmor.c,
src/security/security_dac.c,
src/security/security_driver.h,
src/security/security_manager.c,
src/security/security_manager.h,
src/security/security_nop.c,
src/security/security_selinux.c,
src/security/security_stack.c: Change all security APIs to use a
virDomainDefPtr instead of virDomainObjPtr
2011-07-14 13:32:06 +00:00
|
|
|
_("unable to get PID %d security context"), pid);
|
2009-06-12 11:38:50 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
ctx = context_new(pctx);
|
2010-11-24 21:09:58 +00:00
|
|
|
freecon(pctx);
|
2009-06-12 11:38:50 +00:00
|
|
|
if (!ctx)
|
2012-05-24 15:52:18 +00:00
|
|
|
goto error;
|
2009-06-12 11:38:50 +00:00
|
|
|
|
|
|
|
mcs = context_range_get(ctx);
|
|
|
|
if (!mcs)
|
2012-05-24 15:52:18 +00:00
|
|
|
goto error;
|
|
|
|
|
2012-05-24 16:22:29 +00:00
|
|
|
if ((rv = virSecuritySELinuxMCSAdd(mgr, mcs)) < 0)
|
2012-05-24 15:52:18 +00:00
|
|
|
goto error;
|
2009-06-12 11:38:50 +00:00
|
|
|
|
2012-05-24 15:52:18 +00:00
|
|
|
if (rv == 1) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("MCS level for existing domain label %s already reserved"),
|
|
|
|
(char*)pctx);
|
|
|
|
goto error;
|
|
|
|
}
|
2009-06-12 11:38:50 +00:00
|
|
|
|
|
|
|
context_free(ctx);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
2014-03-25 06:57:22 +00:00
|
|
|
error:
|
2009-06-12 11:38:50 +00:00
|
|
|
context_free(ctx);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-03-03 10:06:49 +00:00
|
|
|
static int
|
2016-12-14 15:34:49 +00:00
|
|
|
virSecuritySELinuxDriverProbe(const char *virtDriver)
|
2009-03-03 10:06:49 +00:00
|
|
|
{
|
2014-03-20 15:05:14 +00:00
|
|
|
if (is_selinux_enabled() <= 0)
|
2012-05-11 09:43:30 +00:00
|
|
|
return SECURITY_DRIVER_DISABLE;
|
|
|
|
|
2012-05-16 13:18:25 +00:00
|
|
|
if (virtDriver && STREQ(virtDriver, "LXC")) {
|
|
|
|
#if HAVE_SELINUX_LXC_CONTEXTS_PATH
|
|
|
|
if (!virFileExists(selinux_lxc_contexts_path()))
|
|
|
|
#endif
|
|
|
|
return SECURITY_DRIVER_DISABLE;
|
|
|
|
}
|
2012-05-11 09:43:30 +00:00
|
|
|
|
|
|
|
return SECURITY_DRIVER_ENABLE;
|
2009-03-03 10:06:49 +00:00
|
|
|
}
|
|
|
|
|
2012-05-11 09:43:30 +00:00
|
|
|
|
2009-03-03 10:06:49 +00:00
|
|
|
static int
|
2016-12-14 15:34:49 +00:00
|
|
|
virSecuritySELinuxDriverOpen(virSecurityManagerPtr mgr)
|
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
|
|
|
{
|
2012-05-24 15:42:51 +00:00
|
|
|
return virSecuritySELinuxInitialize(mgr);
|
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
|
|
|
}
|
|
|
|
|
2012-05-11 09:43:30 +00:00
|
|
|
|
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
|
2016-12-14 15:34:49 +00:00
|
|
|
virSecuritySELinuxDriverClose(virSecurityManagerPtr mgr)
|
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
|
|
|
{
|
2012-05-11 09:43:30 +00:00
|
|
|
virSecuritySELinuxDataPtr data = virSecurityManagerGetPrivateData(mgr);
|
|
|
|
|
|
|
|
if (!data)
|
|
|
|
return 0;
|
|
|
|
|
2013-01-23 20:09:04 +00:00
|
|
|
#if HAVE_SELINUX_LABEL_H
|
2013-10-01 11:15:12 +00:00
|
|
|
if (data->label_handle)
|
|
|
|
selabel_close(data->label_handle);
|
2013-01-23 20:09:04 +00:00
|
|
|
#endif
|
|
|
|
|
2012-05-24 16:22:29 +00:00
|
|
|
virHashFree(data->mcs);
|
|
|
|
|
2012-05-11 09:43:30 +00:00
|
|
|
VIR_FREE(data->domain_context);
|
2012-12-12 11:47:19 +00:00
|
|
|
VIR_FREE(data->alt_domain_context);
|
2012-05-11 09:43:30 +00:00
|
|
|
VIR_FREE(data->file_context);
|
|
|
|
VIR_FREE(data->content_context);
|
|
|
|
|
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
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-05-24 15:42:51 +00:00
|
|
|
static const char *
|
2016-12-14 15:34:49 +00:00
|
|
|
virSecuritySELinuxGetModel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED)
|
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
|
|
|
{
|
|
|
|
return SECURITY_SELINUX_NAME;
|
|
|
|
}
|
|
|
|
|
2012-05-24 15:42:51 +00:00
|
|
|
static const char *
|
2016-12-14 15:34:49 +00:00
|
|
|
virSecuritySELinuxGetDOI(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED)
|
2009-03-03 10:06:49 +00:00
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Where will the DOI come from? SELinux configuration, or qemu
|
|
|
|
* configuration? For the moment, we'll just set it to "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
|
|
|
return SECURITY_SELINUX_VOID_DOI;
|
2009-03-03 10:06:49 +00:00
|
|
|
}
|
|
|
|
|
2016-12-14 16:11:05 +00:00
|
|
|
/**
|
|
|
|
* virSecuritySELinuxTransactionStart:
|
|
|
|
* @mgr: security manager
|
|
|
|
*
|
|
|
|
* Starts a new transaction. In transaction nothing is changed context
|
|
|
|
* until TransactionCommit() is called. This is implemented as a list
|
|
|
|
* that is appended to whenever setfilecon() would be called. Since
|
|
|
|
* secdriver APIs can be called from multiple threads (to work over
|
|
|
|
* different domains) the pointer to the list is stored in thread local
|
|
|
|
* variable.
|
|
|
|
*
|
|
|
|
* Returns 0 on success,
|
|
|
|
* -1 otherwise.
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
virSecuritySELinuxTransactionStart(virSecurityManagerPtr mgr)
|
|
|
|
{
|
|
|
|
bool privileged = virSecurityManagerGetPrivileged(mgr);
|
|
|
|
virSecuritySELinuxContextListPtr list;
|
|
|
|
|
|
|
|
list = virThreadLocalGet(&contextList);
|
|
|
|
if (list) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("Another relabel transaction is already started"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (VIR_ALLOC(list) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
list->privileged = privileged;
|
|
|
|
|
|
|
|
if (virThreadLocalSet(&contextList, list) < 0) {
|
|
|
|
virReportSystemError(errno, "%s",
|
|
|
|
_("Unable to set thread local variable"));
|
|
|
|
VIR_FREE(list);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virSecuritySELinuxTransactionCommit:
|
|
|
|
* @mgr: security manager
|
|
|
|
* @pid: domain's PID
|
|
|
|
*
|
|
|
|
* Enters the @pid namespace (usually @pid refers to a domain) and
|
|
|
|
* performs all the sefilecon()-s on the list. Note that the
|
|
|
|
* transaction is also freed, therefore new one has to be started after
|
|
|
|
* successful return from this function. Also it is considered as error
|
|
|
|
* if there's no transaction set and this function is called.
|
|
|
|
*
|
|
|
|
* Returns: 0 on success,
|
|
|
|
* -1 otherwise.
|
|
|
|
*/
|
|
|
|
static int
|
|
|
|
virSecuritySELinuxTransactionCommit(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
|
|
|
|
pid_t pid)
|
|
|
|
{
|
|
|
|
virSecuritySELinuxContextListPtr list;
|
|
|
|
int ret = 0;
|
|
|
|
|
|
|
|
list = virThreadLocalGet(&contextList);
|
|
|
|
if (!list)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (virThreadLocalSet(&contextList, NULL) < 0) {
|
|
|
|
virReportSystemError(errno, "%s",
|
|
|
|
_("Unable to clear thread local variable"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (virProcessRunInMountNamespace(pid,
|
|
|
|
virSecuritySELinuxTransactionRun,
|
|
|
|
list) < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
cleanup:
|
|
|
|
virSecuritySELinuxContextListFree(list);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virSecuritySELinuxTransactionAbort:
|
|
|
|
* @mgr: security manager
|
|
|
|
*
|
|
|
|
* Cancels and frees any out standing transaction.
|
|
|
|
*/
|
|
|
|
static void
|
|
|
|
virSecuritySELinuxTransactionAbort(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED)
|
|
|
|
{
|
|
|
|
virSecuritySELinuxContextListPtr list;
|
|
|
|
|
|
|
|
list = virThreadLocalGet(&contextList);
|
|
|
|
if (!list)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (virThreadLocalSet(&contextList, NULL) < 0)
|
|
|
|
VIR_DEBUG("Unable to clear thread local variable");
|
|
|
|
virSecuritySELinuxContextListFree(list);
|
|
|
|
}
|
|
|
|
|
2009-03-03 10:06:49 +00:00
|
|
|
static int
|
2015-12-09 13:34:34 +00:00
|
|
|
virSecuritySELinuxGetProcessLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
|
|
|
|
virDomainDefPtr def ATTRIBUTE_UNUSED,
|
|
|
|
pid_t pid,
|
|
|
|
virSecurityLabelPtr sec)
|
2009-03-03 10:06:49 +00:00
|
|
|
{
|
|
|
|
security_context_t ctx;
|
|
|
|
|
2012-10-05 14:41:22 +00:00
|
|
|
if (getpidcon_raw(pid, &ctx) == -1) {
|
2010-02-04 20:02:58 +00:00
|
|
|
virReportSystemError(errno,
|
2009-08-28 17:44:43 +00:00
|
|
|
_("unable to get PID %d security context"),
|
Change security driver APIs to use virDomainDefPtr instead of virDomainObjPtr
When sVirt is integrated with the LXC driver, it will be neccessary
to invoke the security driver APIs using only a virDomainDefPtr
since the lxc_container.c code has no virDomainObjPtr available.
Aside from two functions which want obj->pid, every bit of the
security driver code only touches obj->def. So we don't need to
pass a virDomainObjPtr into the security drivers, a virDomainDefPtr
is sufficient. Two functions also gain a 'pid_t pid' argument.
* src/qemu/qemu_driver.c, src/qemu/qemu_hotplug.c,
src/qemu/qemu_migration.c, src/qemu/qemu_process.c,
src/security/security_apparmor.c,
src/security/security_dac.c,
src/security/security_driver.h,
src/security/security_manager.c,
src/security/security_manager.h,
src/security/security_nop.c,
src/security/security_selinux.c,
src/security/security_stack.c: Change all security APIs to use a
virDomainDefPtr instead of virDomainObjPtr
2011-07-14 13:32:06 +00:00
|
|
|
pid);
|
2009-03-03 10:06:49 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (strlen((char *) ctx) >= VIR_SECURITY_LABEL_BUFLEN) {
|
2012-07-18 14:39:18 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("security label exceeds "
|
|
|
|
"maximum length: %d"),
|
|
|
|
VIR_SECURITY_LABEL_BUFLEN - 1);
|
2010-11-24 21:09:58 +00:00
|
|
|
freecon(ctx);
|
2009-03-03 10:06:49 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
strcpy(sec->label, (char *) ctx);
|
2010-11-24 21:09:58 +00:00
|
|
|
freecon(ctx);
|
2009-03-03 10:06:49 +00:00
|
|
|
|
2012-05-24 15:42:51 +00:00
|
|
|
VIR_DEBUG("label=%s", sec->label);
|
2009-03-03 10:06:49 +00:00
|
|
|
sec->enforcing = security_getenforce();
|
|
|
|
if (sec->enforcing == -1) {
|
2010-02-04 20:02:58 +00:00
|
|
|
virReportSystemError(errno, "%s",
|
2009-08-28 17:44:43 +00:00
|
|
|
_("error calling security_getenforce()"));
|
2009-03-03 10:06:49 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-12-23 15:31:51 +00:00
|
|
|
/* Attempt to change the label of PATH to TCON. If OPTIONAL is true,
|
|
|
|
* return 1 if labelling was not possible. Otherwise, require a label
|
|
|
|
* change, and return 0 for success, -1 for failure. */
|
2009-03-03 10:06:49 +00:00
|
|
|
static int
|
2016-12-14 16:11:05 +00:00
|
|
|
virSecuritySELinuxSetFileconHelper(const char *path, const char *tcon,
|
2015-09-10 11:27:28 +00:00
|
|
|
bool optional, bool privileged)
|
2009-03-03 10:06:49 +00:00
|
|
|
{
|
2009-07-03 10:27:46 +00:00
|
|
|
security_context_t econ;
|
2016-12-14 16:11:05 +00:00
|
|
|
int rc;
|
|
|
|
|
|
|
|
/* Be aware that this function might run in a separate process.
|
|
|
|
* Therefore, any driver state changes would be thrown away. */
|
|
|
|
|
|
|
|
if ((rc = virSecuritySELinuxTransactionAppend(path, tcon, optional)) < 0)
|
|
|
|
return -1;
|
|
|
|
else if (rc > 0)
|
|
|
|
return 0;
|
2009-03-03 10:06:49 +00:00
|
|
|
|
2009-07-03 10:26:37 +00:00
|
|
|
VIR_INFO("Setting SELinux context on '%s' to '%s'", path, tcon);
|
|
|
|
|
2017-01-10 15:33:58 +00:00
|
|
|
if (setfilecon_raw(path, (VIR_SELINUX_CTX_CONST char *) tcon) < 0) {
|
2009-08-21 14:57:29 +00:00
|
|
|
int setfilecon_errno = errno;
|
|
|
|
|
2012-10-05 14:41:22 +00:00
|
|
|
if (getfilecon_raw(path, &econ) >= 0) {
|
2009-07-03 10:27:46 +00:00
|
|
|
if (STREQ(tcon, econ)) {
|
|
|
|
freecon(econ);
|
|
|
|
/* It's alright, there's nothing to change anyway. */
|
2011-12-23 15:31:51 +00:00
|
|
|
return optional ? 1 : 0;
|
2009-07-03 10:27:46 +00:00
|
|
|
}
|
|
|
|
freecon(econ);
|
|
|
|
}
|
2009-08-21 14:57:29 +00:00
|
|
|
|
2014-01-17 11:57:13 +00:00
|
|
|
/* If the error complaint is related to an image hosted on a (possibly
|
|
|
|
* read-only) NFS mount, or a usbfs/sysfs filesystem not supporting
|
|
|
|
* labelling, then just ignore it & hope for the best. The user
|
|
|
|
* hopefully sets one of the necessary SELinux virt_use_{nfs,usb,pci}
|
|
|
|
* boolean tunables to allow it ...
|
2009-08-21 14:57:29 +00:00
|
|
|
*/
|
2016-04-10 16:22:20 +00:00
|
|
|
VIR_WARNINGS_NO_WLOGICALOP_EQUAL_EXPR
|
2014-01-17 11:57:13 +00:00
|
|
|
if (setfilecon_errno != EOPNOTSUPP && setfilecon_errno != ENOTSUP &&
|
|
|
|
setfilecon_errno != EROFS) {
|
2016-04-10 16:22:20 +00:00
|
|
|
VIR_WARNINGS_RESET
|
2010-02-04 20:02:58 +00:00
|
|
|
virReportSystemError(setfilecon_errno,
|
2011-09-22 08:57:24 +00:00
|
|
|
_("unable to set security context '%s' on '%s'"),
|
2009-08-28 17:44:43 +00:00
|
|
|
tcon, path);
|
2015-09-10 11:27:28 +00:00
|
|
|
/* However, don't claim error if SELinux is in Enforcing mode and
|
|
|
|
* we are running as unprivileged user and we really did see EPERM.
|
|
|
|
* Otherwise we want to return error if SELinux is Enforcing. */
|
|
|
|
if (security_getenforce() == 1 && (setfilecon_errno != EPERM || privileged))
|
2009-08-21 14:57:29 +00:00
|
|
|
return -1;
|
2009-08-28 17:44:43 +00:00
|
|
|
} else {
|
2011-09-22 08:57:24 +00:00
|
|
|
const char *msg;
|
2014-03-29 20:15:33 +00:00
|
|
|
if (virFileIsSharedFSType(path, VIR_FILE_SHFS_NFS) == 1 &&
|
2011-09-22 08:57:24 +00:00
|
|
|
security_get_boolean_active("virt_use_nfs") != 1) {
|
|
|
|
msg = _("Setting security context '%s' on '%s' not supported. "
|
|
|
|
"Consider setting virt_use_nfs");
|
selinux: distinguish failure to label from request to avoid label
https://bugzilla.redhat.com/show_bug.cgi?id=924153
Commit 904e05a2 (v0.9.9) added a per-<disk> seclabel element with
an attribute relabel='no' in order to try and minimize the
impact of shutdown delays when an NFS server disappears. The idea
was that if a disk is on NFS and can't be labeled in the first
place, there is no need to attempt the (no-op) relabel on domain
shutdown. Unfortunately, the way this was implemented was by
modifying the domain XML so that the optimization would survive
libvirtd restart, but in a way that is indistinguishable from an
explicit user setting. Furthermore, once the setting is turned
on, libvirt avoids attempts at labeling, even for operations like
snapshot or blockcopy where the chain is being extended or pivoted
onto non-NFS, where SELinux labeling is once again possible. As
a result, it was impossible to do a blockcopy to pivot from an
NFS image file onto a local file.
The solution is to separate the semantics of a chain that must
not be labeled (which the user can set even on persistent domains)
vs. the optimization of not attempting a relabel on cleanup (a
live-only annotation), and using only the user's explicit notation
rather than the optimization as the decision on whether to skip
a label attempt in the first place. When upgrading an older
libvirtd to a newer, an NFS volume will still attempt the relabel;
but as the avoidance of a relabel was only an optimization, this
shouldn't cause any problems.
In the ideal future, libvirt will eventually have XML describing
EVERY file in the backing chain, with each file having a separate
<seclabel> element. At that point, libvirt will be able to track
more closely which files need a relabel attempt at shutdown. But
until we reach that point, the single <seclabel> for the entire
<disk> chain is treated as a hint - when a chain has only one
file, then we know it is accurate; but if the chain has more than
one file, we have to attempt relabel in spite of the attribute,
in case part of the chain is local and SELinux mattered for that
portion of the chain.
* src/conf/domain_conf.h (_virSecurityDeviceLabelDef): Add new
member.
* src/conf/domain_conf.c (virSecurityDeviceLabelDefParseXML):
Parse it, for live images only.
(virSecurityDeviceLabelDefFormat): Output it.
(virDomainDiskDefParseXML, virDomainChrSourceDefParseXML)
(virDomainDiskSourceDefFormat, virDomainChrDefFormat)
(virDomainDiskDefFormat): Pass flags on through.
* src/security/security_selinux.c
(virSecuritySELinuxRestoreSecurityImageLabelInt): Honor labelskip
when possible.
(virSecuritySELinuxSetSecurityFileLabel): Set labelskip, not
norelabel, if labeling fails.
(virSecuritySELinuxSetFileconHelper): Fix indentation.
* docs/formatdomain.html.in (seclabel): Document new xml.
* docs/schemas/domaincommon.rng (devSeclabel): Allow it in RNG.
* tests/qemuxml2argvdata/qemuxml2argv-seclabel-*-labelskip.xml:
* tests/qemuxml2argvdata/qemuxml2argv-seclabel-*-labelskip.args:
* tests/qemuxml2xmloutdata/qemuxml2xmlout-seclabel-*-labelskip.xml:
New test files.
* tests/qemuxml2argvtest.c (mymain): Run the new tests.
* tests/qemuxml2xmltest.c (mymain): Likewise.
Signed-off-by: Eric Blake <eblake@redhat.com>
2013-08-12 15:15:42 +00:00
|
|
|
if (security_getenforce() == 1)
|
|
|
|
VIR_WARN(msg, tcon, path);
|
|
|
|
else
|
|
|
|
VIR_INFO(msg, tcon, path);
|
2011-09-22 08:57:24 +00:00
|
|
|
} else {
|
|
|
|
VIR_INFO("Setting security context '%s' on '%s' not supported",
|
|
|
|
tcon, path);
|
|
|
|
}
|
2011-12-23 15:31:51 +00:00
|
|
|
if (optional)
|
|
|
|
return 1;
|
2009-08-21 14:57:29 +00:00
|
|
|
}
|
2009-03-03 10:06:49 +00:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-12-23 15:31:51 +00:00
|
|
|
static int
|
2015-09-10 11:27:28 +00:00
|
|
|
virSecuritySELinuxSetFileconOptional(virSecurityManagerPtr mgr,
|
2016-12-14 16:11:05 +00:00
|
|
|
const char *path, const char *tcon)
|
2011-12-23 15:31:51 +00:00
|
|
|
{
|
2015-09-10 11:27:28 +00:00
|
|
|
bool privileged = virSecurityManagerGetPrivileged(mgr);
|
|
|
|
return virSecuritySELinuxSetFileconHelper(path, tcon, true, privileged);
|
2011-12-23 15:31:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2015-09-10 11:27:28 +00:00
|
|
|
virSecuritySELinuxSetFilecon(virSecurityManagerPtr mgr,
|
2016-12-14 16:11:05 +00:00
|
|
|
const char *path, const char *tcon)
|
2011-12-23 15:31:51 +00:00
|
|
|
{
|
2015-09-10 11:27:28 +00:00
|
|
|
bool privileged = virSecurityManagerGetPrivileged(mgr);
|
|
|
|
return virSecuritySELinuxSetFileconHelper(path, tcon, false, privileged);
|
2011-12-23 15:31:51 +00:00
|
|
|
}
|
|
|
|
|
2011-01-23 21:02:42 +00:00
|
|
|
static int
|
2012-05-24 15:42:51 +00:00
|
|
|
virSecuritySELinuxFSetFilecon(int fd, char *tcon)
|
2011-01-23 21:02:42 +00:00
|
|
|
{
|
|
|
|
security_context_t econ;
|
|
|
|
|
|
|
|
VIR_INFO("Setting SELinux context on fd %d to '%s'", fd, tcon);
|
|
|
|
|
2012-10-05 14:41:22 +00:00
|
|
|
if (fsetfilecon_raw(fd, tcon) < 0) {
|
2011-01-23 21:02:42 +00:00
|
|
|
int fsetfilecon_errno = errno;
|
|
|
|
|
2012-10-05 14:41:22 +00:00
|
|
|
if (fgetfilecon_raw(fd, &econ) >= 0) {
|
2011-01-23 21:02:42 +00:00
|
|
|
if (STREQ(tcon, econ)) {
|
|
|
|
freecon(econ);
|
|
|
|
/* It's alright, there's nothing to change anyway. */
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
freecon(econ);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* if the error complaint is related to an image hosted on
|
|
|
|
* an nfs mount, or a usbfs/sysfs filesystem not supporting
|
|
|
|
* labelling, then just ignore it & hope for the best.
|
|
|
|
* The user hopefully set one of the necessary SELinux
|
|
|
|
* virt_use_{nfs,usb,pci} boolean tunables to allow it...
|
|
|
|
*/
|
|
|
|
if (fsetfilecon_errno != EOPNOTSUPP) {
|
|
|
|
virReportSystemError(fsetfilecon_errno,
|
|
|
|
_("unable to set security context '%s' on fd %d"),
|
|
|
|
tcon, fd);
|
|
|
|
if (security_getenforce() == 1)
|
|
|
|
return -1;
|
|
|
|
} else {
|
|
|
|
VIR_INFO("Setting security context '%s' on fd %d not supported",
|
|
|
|
tcon, fd);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2010-12-15 00:07:52 +00:00
|
|
|
/* Set fcon to the appropriate label for path and mode, or return -1. */
|
|
|
|
static int
|
2013-02-12 00:12:25 +00:00
|
|
|
getContext(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
|
2013-01-23 20:09:04 +00:00
|
|
|
const char *newpath, mode_t mode, security_context_t *fcon)
|
2010-12-15 00:07:52 +00:00
|
|
|
{
|
|
|
|
#if HAVE_SELINUX_LABEL_H
|
2013-01-23 20:09:04 +00:00
|
|
|
virSecuritySELinuxDataPtr data = virSecurityManagerGetPrivateData(mgr);
|
2010-12-15 00:07:52 +00:00
|
|
|
|
2013-01-23 20:09:04 +00:00
|
|
|
return selabel_lookup_raw(data->label_handle, fcon, newpath, mode);
|
2010-12-15 00:07:52 +00:00
|
|
|
#else
|
|
|
|
return matchpathcon(newpath, mode, fcon);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2010-05-28 11:19:13 +00:00
|
|
|
|
|
|
|
/* This method shouldn't raise errors, since they'll overwrite
|
|
|
|
* errors that the caller(s) are already dealing with */
|
2009-03-03 10:06:49 +00:00
|
|
|
static int
|
2015-12-09 13:34:34 +00:00
|
|
|
virSecuritySELinuxRestoreFileLabel(virSecurityManagerPtr mgr,
|
|
|
|
const char *path)
|
2009-03-03 10:06:49 +00:00
|
|
|
{
|
2009-03-17 11:35:40 +00:00
|
|
|
struct stat buf;
|
|
|
|
security_context_t fcon = NULL;
|
|
|
|
int rc = -1;
|
|
|
|
char *newpath = NULL;
|
2010-05-28 11:19:13 +00:00
|
|
|
char ebuf[1024];
|
2009-07-15 11:45:13 +00:00
|
|
|
|
2016-02-02 21:08:59 +00:00
|
|
|
/* Some paths are auto-generated, so let's be safe here and do
|
|
|
|
* nothing if nothing is needed.
|
|
|
|
*/
|
|
|
|
if (!path)
|
|
|
|
return 0;
|
|
|
|
|
2009-08-28 17:44:43 +00:00
|
|
|
VIR_INFO("Restoring SELinux context on '%s'", path);
|
|
|
|
|
2010-05-14 20:50:27 +00:00
|
|
|
if (virFileResolveLink(path, &newpath) < 0) {
|
2010-05-28 11:19:13 +00:00
|
|
|
VIR_WARN("cannot resolve symlink %s: %s", path,
|
|
|
|
virStrerror(errno, ebuf, sizeof(ebuf)));
|
2009-04-01 10:26:22 +00:00
|
|
|
goto err;
|
2009-03-03 10:06:49 +00:00
|
|
|
}
|
2009-03-17 11:35:40 +00:00
|
|
|
|
2010-04-30 11:35:15 +00:00
|
|
|
if (stat(newpath, &buf) != 0) {
|
2010-05-28 11:19:13 +00:00
|
|
|
VIR_WARN("cannot stat %s: %s", newpath,
|
|
|
|
virStrerror(errno, ebuf, sizeof(ebuf)));
|
2009-04-01 10:26:22 +00:00
|
|
|
goto err;
|
2010-04-30 11:35:15 +00:00
|
|
|
}
|
2009-04-01 10:26:22 +00:00
|
|
|
|
2013-01-23 20:09:04 +00:00
|
|
|
if (getContext(mgr, newpath, buf.st_mode, &fcon) < 0) {
|
2012-10-20 19:57:28 +00:00
|
|
|
/* Any user created path likely does not have a default label,
|
|
|
|
* which makes this an expected non error
|
|
|
|
*/
|
2010-12-01 01:22:54 +00:00
|
|
|
VIR_WARN("cannot lookup default selinux label for %s", newpath);
|
2012-10-20 19:57:28 +00:00
|
|
|
rc = 0;
|
2010-04-30 11:35:15 +00:00
|
|
|
} else {
|
2015-09-10 11:27:28 +00:00
|
|
|
rc = virSecuritySELinuxSetFilecon(mgr, newpath, fcon);
|
2009-03-17 11:35:40 +00:00
|
|
|
}
|
2010-04-30 11:35:15 +00:00
|
|
|
|
2014-03-25 06:57:22 +00:00
|
|
|
err:
|
2010-11-24 21:09:58 +00:00
|
|
|
freecon(fcon);
|
2009-03-17 11:35:40 +00:00
|
|
|
VIR_FREE(newpath);
|
|
|
|
return rc;
|
2009-03-03 10:06:49 +00:00
|
|
|
}
|
|
|
|
|
2013-04-12 20:55:46 +00:00
|
|
|
|
2015-11-20 07:25:41 +00:00
|
|
|
static int
|
|
|
|
virSecuritySELinuxSetInputLabel(virSecurityManagerPtr mgr,
|
|
|
|
virDomainDefPtr def,
|
|
|
|
virDomainInputDefPtr input)
|
|
|
|
{
|
|
|
|
virSecurityLabelDefPtr seclabel;
|
|
|
|
|
|
|
|
seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
|
|
|
|
if (seclabel == NULL)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
switch ((virDomainInputType) input->type) {
|
|
|
|
case VIR_DOMAIN_INPUT_TYPE_PASSTHROUGH:
|
|
|
|
if (virSecuritySELinuxSetFilecon(mgr, input->source.evdev,
|
|
|
|
seclabel->imagelabel) < 0)
|
|
|
|
return -1;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_INPUT_TYPE_MOUSE:
|
|
|
|
case VIR_DOMAIN_INPUT_TYPE_TABLET:
|
|
|
|
case VIR_DOMAIN_INPUT_TYPE_KBD:
|
|
|
|
case VIR_DOMAIN_INPUT_TYPE_LAST:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
virSecuritySELinuxRestoreInputLabel(virSecurityManagerPtr mgr,
|
|
|
|
virDomainDefPtr def,
|
|
|
|
virDomainInputDefPtr input)
|
|
|
|
{
|
|
|
|
int rc = 0;
|
|
|
|
virSecurityLabelDefPtr seclabel;
|
|
|
|
|
|
|
|
seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
|
|
|
|
if (seclabel == NULL)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
switch ((virDomainInputType) input->type) {
|
|
|
|
case VIR_DOMAIN_INPUT_TYPE_PASSTHROUGH:
|
2015-12-09 13:34:34 +00:00
|
|
|
rc = virSecuritySELinuxRestoreFileLabel(mgr, input->source.evdev);
|
2015-11-20 07:25:41 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_INPUT_TYPE_MOUSE:
|
|
|
|
case VIR_DOMAIN_INPUT_TYPE_TABLET:
|
|
|
|
case VIR_DOMAIN_INPUT_TYPE_KBD:
|
|
|
|
case VIR_DOMAIN_INPUT_TYPE_LAST:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-08-04 12:04:38 +00:00
|
|
|
static int
|
|
|
|
virSecuritySELinuxSetMemoryLabel(virSecurityManagerPtr mgr,
|
|
|
|
virDomainDefPtr def,
|
|
|
|
virDomainMemoryDefPtr mem)
|
|
|
|
{
|
|
|
|
virSecurityLabelDefPtr seclabel;
|
|
|
|
|
|
|
|
switch ((virDomainMemoryModel) mem->model) {
|
|
|
|
case VIR_DOMAIN_MEMORY_MODEL_NVDIMM:
|
|
|
|
seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
|
|
|
|
if (!seclabel || !seclabel->relabel)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (virSecuritySELinuxSetFilecon(mgr, mem->nvdimmPath,
|
|
|
|
seclabel->imagelabel) < 0)
|
|
|
|
return -1;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_MEMORY_MODEL_NONE:
|
|
|
|
case VIR_DOMAIN_MEMORY_MODEL_DIMM:
|
|
|
|
case VIR_DOMAIN_MEMORY_MODEL_LAST:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
virSecuritySELinuxRestoreMemoryLabel(virSecurityManagerPtr mgr,
|
|
|
|
virDomainDefPtr def,
|
|
|
|
virDomainMemoryDefPtr mem)
|
|
|
|
{
|
|
|
|
int ret = -1;
|
|
|
|
virSecurityLabelDefPtr seclabel;
|
|
|
|
|
|
|
|
switch ((virDomainMemoryModel) mem->model) {
|
|
|
|
case VIR_DOMAIN_MEMORY_MODEL_NVDIMM:
|
|
|
|
seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
|
|
|
|
if (!seclabel || !seclabel->relabel)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
ret = virSecuritySELinuxRestoreFileLabel(mgr, mem->nvdimmPath);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_MEMORY_MODEL_DIMM:
|
|
|
|
case VIR_DOMAIN_MEMORY_MODEL_NONE:
|
|
|
|
case VIR_DOMAIN_MEMORY_MODEL_LAST:
|
|
|
|
ret = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-04-12 20:55:46 +00:00
|
|
|
static int
|
2015-12-09 13:34:34 +00:00
|
|
|
virSecuritySELinuxSetTPMFileLabel(virSecurityManagerPtr mgr,
|
|
|
|
virDomainDefPtr def,
|
|
|
|
virDomainTPMDefPtr tpm)
|
2013-04-12 20:55:46 +00:00
|
|
|
{
|
|
|
|
int rc;
|
|
|
|
virSecurityLabelDefPtr seclabel;
|
|
|
|
char *cancel_path;
|
|
|
|
const char *tpmdev;
|
|
|
|
|
|
|
|
seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
|
|
|
|
if (seclabel == NULL)
|
2014-06-09 14:23:52 +00:00
|
|
|
return 0;
|
2013-04-12 20:55:46 +00:00
|
|
|
|
|
|
|
switch (tpm->type) {
|
|
|
|
case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH:
|
|
|
|
tpmdev = tpm->data.passthrough.source.data.file.path;
|
2015-09-10 11:27:28 +00:00
|
|
|
rc = virSecuritySELinuxSetFilecon(mgr, tpmdev, seclabel->imagelabel);
|
2013-04-12 20:55:46 +00:00
|
|
|
if (rc < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
if ((cancel_path = virTPMCreateCancelPath(tpmdev)) != NULL) {
|
2015-09-10 11:27:28 +00:00
|
|
|
rc = virSecuritySELinuxSetFilecon(mgr,
|
|
|
|
cancel_path,
|
2013-04-12 20:55:46 +00:00
|
|
|
seclabel->imagelabel);
|
|
|
|
VIR_FREE(cancel_path);
|
|
|
|
if (rc < 0) {
|
2015-12-09 13:34:34 +00:00
|
|
|
virSecuritySELinuxRestoreTPMFileLabelInt(mgr, def, tpm);
|
2013-04-12 20:55:46 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case VIR_DOMAIN_TPM_TYPE_LAST:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
2015-12-09 13:34:34 +00:00
|
|
|
virSecuritySELinuxRestoreTPMFileLabelInt(virSecurityManagerPtr mgr,
|
|
|
|
virDomainDefPtr def,
|
|
|
|
virDomainTPMDefPtr tpm)
|
2013-04-12 20:55:46 +00:00
|
|
|
{
|
|
|
|
int rc = 0;
|
|
|
|
virSecurityLabelDefPtr seclabel;
|
|
|
|
char *cancel_path;
|
|
|
|
const char *tpmdev;
|
|
|
|
|
|
|
|
seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
|
|
|
|
if (seclabel == NULL)
|
2014-06-09 14:23:52 +00:00
|
|
|
return 0;
|
2013-04-12 20:55:46 +00:00
|
|
|
|
|
|
|
switch (tpm->type) {
|
|
|
|
case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH:
|
|
|
|
tpmdev = tpm->data.passthrough.source.data.file.path;
|
2015-12-09 13:34:34 +00:00
|
|
|
rc = virSecuritySELinuxRestoreFileLabel(mgr, tpmdev);
|
2013-04-12 20:55:46 +00:00
|
|
|
|
|
|
|
if ((cancel_path = virTPMCreateCancelPath(tpmdev)) != NULL) {
|
2015-12-09 13:34:34 +00:00
|
|
|
if (virSecuritySELinuxRestoreFileLabel(mgr, cancel_path) < 0)
|
2013-04-12 20:55:46 +00:00
|
|
|
rc = -1;
|
|
|
|
VIR_FREE(cancel_path);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case VIR_DOMAIN_TPM_TYPE_LAST:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-08-14 13:23:11 +00:00
|
|
|
static int
|
2015-12-09 13:34:34 +00:00
|
|
|
virSecuritySELinuxRestoreImageLabelInt(virSecurityManagerPtr mgr,
|
|
|
|
virDomainDefPtr def,
|
|
|
|
virStorageSourcePtr src,
|
|
|
|
bool migrated)
|
2009-08-14 13:23:11 +00:00
|
|
|
{
|
2012-08-15 22:10:37 +00:00
|
|
|
virSecurityLabelDefPtr seclabel;
|
|
|
|
virSecurityDeviceLabelDefPtr disk_seclabel;
|
2014-06-23 15:19:25 +00:00
|
|
|
|
|
|
|
if (!src->path || !virStorageSourceIsLocalStorage(src))
|
|
|
|
return 0;
|
2012-08-15 22:10:37 +00:00
|
|
|
|
|
|
|
seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
|
|
|
|
if (seclabel == NULL)
|
2014-06-09 14:23:52 +00:00
|
|
|
return 0;
|
2010-01-13 14:03:04 +00:00
|
|
|
|
2014-06-23 15:19:25 +00:00
|
|
|
disk_seclabel = virStorageSourceGetSecurityLabelDef(src,
|
2012-08-15 22:10:37 +00:00
|
|
|
SECURITY_SELINUX_NAME);
|
2014-07-09 12:11:49 +00:00
|
|
|
if (!seclabel->relabel || (disk_seclabel && !disk_seclabel->relabel))
|
2010-01-13 14:03:04 +00:00
|
|
|
return 0;
|
|
|
|
|
selinux: distinguish failure to label from request to avoid label
https://bugzilla.redhat.com/show_bug.cgi?id=924153
Commit 904e05a2 (v0.9.9) added a per-<disk> seclabel element with
an attribute relabel='no' in order to try and minimize the
impact of shutdown delays when an NFS server disappears. The idea
was that if a disk is on NFS and can't be labeled in the first
place, there is no need to attempt the (no-op) relabel on domain
shutdown. Unfortunately, the way this was implemented was by
modifying the domain XML so that the optimization would survive
libvirtd restart, but in a way that is indistinguishable from an
explicit user setting. Furthermore, once the setting is turned
on, libvirt avoids attempts at labeling, even for operations like
snapshot or blockcopy where the chain is being extended or pivoted
onto non-NFS, where SELinux labeling is once again possible. As
a result, it was impossible to do a blockcopy to pivot from an
NFS image file onto a local file.
The solution is to separate the semantics of a chain that must
not be labeled (which the user can set even on persistent domains)
vs. the optimization of not attempting a relabel on cleanup (a
live-only annotation), and using only the user's explicit notation
rather than the optimization as the decision on whether to skip
a label attempt in the first place. When upgrading an older
libvirtd to a newer, an NFS volume will still attempt the relabel;
but as the avoidance of a relabel was only an optimization, this
shouldn't cause any problems.
In the ideal future, libvirt will eventually have XML describing
EVERY file in the backing chain, with each file having a separate
<seclabel> element. At that point, libvirt will be able to track
more closely which files need a relabel attempt at shutdown. But
until we reach that point, the single <seclabel> for the entire
<disk> chain is treated as a hint - when a chain has only one
file, then we know it is accurate; but if the chain has more than
one file, we have to attempt relabel in spite of the attribute,
in case part of the chain is local and SELinux mattered for that
portion of the chain.
* src/conf/domain_conf.h (_virSecurityDeviceLabelDef): Add new
member.
* src/conf/domain_conf.c (virSecurityDeviceLabelDefParseXML):
Parse it, for live images only.
(virSecurityDeviceLabelDefFormat): Output it.
(virDomainDiskDefParseXML, virDomainChrSourceDefParseXML)
(virDomainDiskSourceDefFormat, virDomainChrDefFormat)
(virDomainDiskDefFormat): Pass flags on through.
* src/security/security_selinux.c
(virSecuritySELinuxRestoreSecurityImageLabelInt): Honor labelskip
when possible.
(virSecuritySELinuxSetSecurityFileLabel): Set labelskip, not
norelabel, if labeling fails.
(virSecuritySELinuxSetFileconHelper): Fix indentation.
* docs/formatdomain.html.in (seclabel): Document new xml.
* docs/schemas/domaincommon.rng (devSeclabel): Allow it in RNG.
* tests/qemuxml2argvdata/qemuxml2argv-seclabel-*-labelskip.xml:
* tests/qemuxml2argvdata/qemuxml2argv-seclabel-*-labelskip.args:
* tests/qemuxml2xmloutdata/qemuxml2xmlout-seclabel-*-labelskip.xml:
New test files.
* tests/qemuxml2argvtest.c (mymain): Run the new tests.
* tests/qemuxml2xmltest.c (mymain): Likewise.
Signed-off-by: Eric Blake <eblake@redhat.com>
2013-08-12 15:15:42 +00:00
|
|
|
/* If labelskip is true and there are no backing files, then we
|
|
|
|
* know it is safe to skip the restore. FIXME - backing files should
|
|
|
|
* be tracked in domain XML, at which point labelskip should be a
|
2014-06-23 15:19:25 +00:00
|
|
|
* per-file attribute instead of a disk attribute. */
|
selinux: distinguish failure to label from request to avoid label
https://bugzilla.redhat.com/show_bug.cgi?id=924153
Commit 904e05a2 (v0.9.9) added a per-<disk> seclabel element with
an attribute relabel='no' in order to try and minimize the
impact of shutdown delays when an NFS server disappears. The idea
was that if a disk is on NFS and can't be labeled in the first
place, there is no need to attempt the (no-op) relabel on domain
shutdown. Unfortunately, the way this was implemented was by
modifying the domain XML so that the optimization would survive
libvirtd restart, but in a way that is indistinguishable from an
explicit user setting. Furthermore, once the setting is turned
on, libvirt avoids attempts at labeling, even for operations like
snapshot or blockcopy where the chain is being extended or pivoted
onto non-NFS, where SELinux labeling is once again possible. As
a result, it was impossible to do a blockcopy to pivot from an
NFS image file onto a local file.
The solution is to separate the semantics of a chain that must
not be labeled (which the user can set even on persistent domains)
vs. the optimization of not attempting a relabel on cleanup (a
live-only annotation), and using only the user's explicit notation
rather than the optimization as the decision on whether to skip
a label attempt in the first place. When upgrading an older
libvirtd to a newer, an NFS volume will still attempt the relabel;
but as the avoidance of a relabel was only an optimization, this
shouldn't cause any problems.
In the ideal future, libvirt will eventually have XML describing
EVERY file in the backing chain, with each file having a separate
<seclabel> element. At that point, libvirt will be able to track
more closely which files need a relabel attempt at shutdown. But
until we reach that point, the single <seclabel> for the entire
<disk> chain is treated as a hint - when a chain has only one
file, then we know it is accurate; but if the chain has more than
one file, we have to attempt relabel in spite of the attribute,
in case part of the chain is local and SELinux mattered for that
portion of the chain.
* src/conf/domain_conf.h (_virSecurityDeviceLabelDef): Add new
member.
* src/conf/domain_conf.c (virSecurityDeviceLabelDefParseXML):
Parse it, for live images only.
(virSecurityDeviceLabelDefFormat): Output it.
(virDomainDiskDefParseXML, virDomainChrSourceDefParseXML)
(virDomainDiskSourceDefFormat, virDomainChrDefFormat)
(virDomainDiskDefFormat): Pass flags on through.
* src/security/security_selinux.c
(virSecuritySELinuxRestoreSecurityImageLabelInt): Honor labelskip
when possible.
(virSecuritySELinuxSetSecurityFileLabel): Set labelskip, not
norelabel, if labeling fails.
(virSecuritySELinuxSetFileconHelper): Fix indentation.
* docs/formatdomain.html.in (seclabel): Document new xml.
* docs/schemas/domaincommon.rng (devSeclabel): Allow it in RNG.
* tests/qemuxml2argvdata/qemuxml2argv-seclabel-*-labelskip.xml:
* tests/qemuxml2argvdata/qemuxml2argv-seclabel-*-labelskip.args:
* tests/qemuxml2xmloutdata/qemuxml2xmlout-seclabel-*-labelskip.xml:
New test files.
* tests/qemuxml2argvtest.c (mymain): Run the new tests.
* tests/qemuxml2xmltest.c (mymain): Likewise.
Signed-off-by: Eric Blake <eblake@redhat.com>
2013-08-12 15:15:42 +00:00
|
|
|
if (disk_seclabel && disk_seclabel->labelskip &&
|
2014-06-23 15:19:25 +00:00
|
|
|
!src->backingStore)
|
selinux: distinguish failure to label from request to avoid label
https://bugzilla.redhat.com/show_bug.cgi?id=924153
Commit 904e05a2 (v0.9.9) added a per-<disk> seclabel element with
an attribute relabel='no' in order to try and minimize the
impact of shutdown delays when an NFS server disappears. The idea
was that if a disk is on NFS and can't be labeled in the first
place, there is no need to attempt the (no-op) relabel on domain
shutdown. Unfortunately, the way this was implemented was by
modifying the domain XML so that the optimization would survive
libvirtd restart, but in a way that is indistinguishable from an
explicit user setting. Furthermore, once the setting is turned
on, libvirt avoids attempts at labeling, even for operations like
snapshot or blockcopy where the chain is being extended or pivoted
onto non-NFS, where SELinux labeling is once again possible. As
a result, it was impossible to do a blockcopy to pivot from an
NFS image file onto a local file.
The solution is to separate the semantics of a chain that must
not be labeled (which the user can set even on persistent domains)
vs. the optimization of not attempting a relabel on cleanup (a
live-only annotation), and using only the user's explicit notation
rather than the optimization as the decision on whether to skip
a label attempt in the first place. When upgrading an older
libvirtd to a newer, an NFS volume will still attempt the relabel;
but as the avoidance of a relabel was only an optimization, this
shouldn't cause any problems.
In the ideal future, libvirt will eventually have XML describing
EVERY file in the backing chain, with each file having a separate
<seclabel> element. At that point, libvirt will be able to track
more closely which files need a relabel attempt at shutdown. But
until we reach that point, the single <seclabel> for the entire
<disk> chain is treated as a hint - when a chain has only one
file, then we know it is accurate; but if the chain has more than
one file, we have to attempt relabel in spite of the attribute,
in case part of the chain is local and SELinux mattered for that
portion of the chain.
* src/conf/domain_conf.h (_virSecurityDeviceLabelDef): Add new
member.
* src/conf/domain_conf.c (virSecurityDeviceLabelDefParseXML):
Parse it, for live images only.
(virSecurityDeviceLabelDefFormat): Output it.
(virDomainDiskDefParseXML, virDomainChrSourceDefParseXML)
(virDomainDiskSourceDefFormat, virDomainChrDefFormat)
(virDomainDiskDefFormat): Pass flags on through.
* src/security/security_selinux.c
(virSecuritySELinuxRestoreSecurityImageLabelInt): Honor labelskip
when possible.
(virSecuritySELinuxSetSecurityFileLabel): Set labelskip, not
norelabel, if labeling fails.
(virSecuritySELinuxSetFileconHelper): Fix indentation.
* docs/formatdomain.html.in (seclabel): Document new xml.
* docs/schemas/domaincommon.rng (devSeclabel): Allow it in RNG.
* tests/qemuxml2argvdata/qemuxml2argv-seclabel-*-labelskip.xml:
* tests/qemuxml2argvdata/qemuxml2argv-seclabel-*-labelskip.args:
* tests/qemuxml2xmloutdata/qemuxml2xmlout-seclabel-*-labelskip.xml:
New test files.
* tests/qemuxml2argvtest.c (mymain): Run the new tests.
* tests/qemuxml2xmltest.c (mymain): Likewise.
Signed-off-by: Eric Blake <eblake@redhat.com>
2013-08-12 15:15:42 +00:00
|
|
|
return 0;
|
|
|
|
|
2014-11-26 17:35:46 +00:00
|
|
|
/* Don't restore labels on readonly/shared disks, because other VMs may
|
2014-06-23 15:19:25 +00:00
|
|
|
* 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 (src->readonly || src->shared)
|
2009-08-14 13:23:11 +00:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
2014-06-23 15:19:25 +00:00
|
|
|
/* If we have a shared FS and are doing migration, 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 :-) */
|
Don't reset user/group/security label on shared filesystems during migrate
When QEMU runs with its disk on NFS, and as a non-root user, the
disk is chownd to that non-root user. When migration completes
the last step is shutting down the QEMU on the source host. THis
normally resets user/group/security label. This is bad when the
VM was just migrated because the file is still in use on the dest
host. It is thus neccessary to skip the reset step for any files
found to be on a shared filesystem
* src/libvirt_private.syms: Export virStorageFileIsSharedFS
* src/util/storage_file.c, src/util/storage_file.h: Add a new
method virStorageFileIsSharedFS() to determine if a file is
on a shared filesystem (NFS, GFS, OCFS2, etc)
* src/qemu/qemu_driver.c: Tell security driver not to reset
disk labels on migration completion
* src/qemu/qemu_security_dac.c, src/qemu/qemu_security_stacked.c,
src/security/security_selinux.c, src/security/security_driver.h,
src/security/security_apparmor.c: Add ability to skip disk
restore step for files on shared filesystems.
2010-05-13 15:49:22 +00:00
|
|
|
if (migrated) {
|
2014-06-23 15:19:25 +00:00
|
|
|
int rc = virFileIsSharedFS(src->path);
|
Don't reset user/group/security label on shared filesystems during migrate
When QEMU runs with its disk on NFS, and as a non-root user, the
disk is chownd to that non-root user. When migration completes
the last step is shutting down the QEMU on the source host. THis
normally resets user/group/security label. This is bad when the
VM was just migrated because the file is still in use on the dest
host. It is thus neccessary to skip the reset step for any files
found to be on a shared filesystem
* src/libvirt_private.syms: Export virStorageFileIsSharedFS
* src/util/storage_file.c, src/util/storage_file.h: Add a new
method virStorageFileIsSharedFS() to determine if a file is
on a shared filesystem (NFS, GFS, OCFS2, etc)
* src/qemu/qemu_driver.c: Tell security driver not to reset
disk labels on migration completion
* src/qemu/qemu_security_dac.c, src/qemu/qemu_security_stacked.c,
src/security/security_selinux.c, src/security/security_driver.h,
src/security/security_apparmor.c: Add ability to skip disk
restore step for files on shared filesystems.
2010-05-13 15:49:22 +00:00
|
|
|
if (rc < 0)
|
|
|
|
return -1;
|
|
|
|
if (rc == 1) {
|
|
|
|
VIR_DEBUG("Skipping image label restore on %s because FS is shared",
|
2014-06-23 15:19:25 +00:00
|
|
|
src->path);
|
Don't reset user/group/security label on shared filesystems during migrate
When QEMU runs with its disk on NFS, and as a non-root user, the
disk is chownd to that non-root user. When migration completes
the last step is shutting down the QEMU on the source host. THis
normally resets user/group/security label. This is bad when the
VM was just migrated because the file is still in use on the dest
host. It is thus neccessary to skip the reset step for any files
found to be on a shared filesystem
* src/libvirt_private.syms: Export virStorageFileIsSharedFS
* src/util/storage_file.c, src/util/storage_file.h: Add a new
method virStorageFileIsSharedFS() to determine if a file is
on a shared filesystem (NFS, GFS, OCFS2, etc)
* src/qemu/qemu_driver.c: Tell security driver not to reset
disk labels on migration completion
* src/qemu/qemu_security_dac.c, src/qemu/qemu_security_stacked.c,
src/security/security_selinux.c, src/security/security_driver.h,
src/security/security_apparmor.c: Add ability to skip disk
restore step for files on shared filesystems.
2010-05-13 15:49:22 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-12-09 13:34:34 +00:00
|
|
|
return virSecuritySELinuxRestoreFileLabel(mgr, src->path);
|
2009-08-14 13:23:11 +00:00
|
|
|
}
|
|
|
|
|
Don't reset user/group/security label on shared filesystems during migrate
When QEMU runs with its disk on NFS, and as a non-root user, the
disk is chownd to that non-root user. When migration completes
the last step is shutting down the QEMU on the source host. THis
normally resets user/group/security label. This is bad when the
VM was just migrated because the file is still in use on the dest
host. It is thus neccessary to skip the reset step for any files
found to be on a shared filesystem
* src/libvirt_private.syms: Export virStorageFileIsSharedFS
* src/util/storage_file.c, src/util/storage_file.h: Add a new
method virStorageFileIsSharedFS() to determine if a file is
on a shared filesystem (NFS, GFS, OCFS2, etc)
* src/qemu/qemu_driver.c: Tell security driver not to reset
disk labels on migration completion
* src/qemu/qemu_security_dac.c, src/qemu/qemu_security_stacked.c,
src/security/security_selinux.c, src/security/security_driver.h,
src/security/security_apparmor.c: Add ability to skip disk
restore step for files on shared filesystems.
2010-05-13 15:49:22 +00:00
|
|
|
|
|
|
|
static int
|
2015-12-09 13:34:34 +00:00
|
|
|
virSecuritySELinuxRestoreDiskLabel(virSecurityManagerPtr mgr,
|
|
|
|
virDomainDefPtr def,
|
|
|
|
virDomainDiskDefPtr disk)
|
Don't reset user/group/security label on shared filesystems during migrate
When QEMU runs with its disk on NFS, and as a non-root user, the
disk is chownd to that non-root user. When migration completes
the last step is shutting down the QEMU on the source host. THis
normally resets user/group/security label. This is bad when the
VM was just migrated because the file is still in use on the dest
host. It is thus neccessary to skip the reset step for any files
found to be on a shared filesystem
* src/libvirt_private.syms: Export virStorageFileIsSharedFS
* src/util/storage_file.c, src/util/storage_file.h: Add a new
method virStorageFileIsSharedFS() to determine if a file is
on a shared filesystem (NFS, GFS, OCFS2, etc)
* src/qemu/qemu_driver.c: Tell security driver not to reset
disk labels on migration completion
* src/qemu/qemu_security_dac.c, src/qemu/qemu_security_stacked.c,
src/security/security_selinux.c, src/security/security_driver.h,
src/security/security_apparmor.c: Add ability to skip disk
restore step for files on shared filesystems.
2010-05-13 15:49:22 +00:00
|
|
|
{
|
2015-12-09 13:34:34 +00:00
|
|
|
return virSecuritySELinuxRestoreImageLabelInt(mgr, def, disk->src,
|
|
|
|
false);
|
2014-06-23 15:19:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
2015-12-09 13:34:34 +00:00
|
|
|
virSecuritySELinuxRestoreImageLabel(virSecurityManagerPtr mgr,
|
|
|
|
virDomainDefPtr def,
|
|
|
|
virStorageSourcePtr src)
|
2014-06-23 15:19:25 +00:00
|
|
|
{
|
2015-12-09 13:34:34 +00:00
|
|
|
return virSecuritySELinuxRestoreImageLabelInt(mgr, def, src, false);
|
Don't reset user/group/security label on shared filesystems during migrate
When QEMU runs with its disk on NFS, and as a non-root user, the
disk is chownd to that non-root user. When migration completes
the last step is shutting down the QEMU on the source host. THis
normally resets user/group/security label. This is bad when the
VM was just migrated because the file is still in use on the dest
host. It is thus neccessary to skip the reset step for any files
found to be on a shared filesystem
* src/libvirt_private.syms: Export virStorageFileIsSharedFS
* src/util/storage_file.c, src/util/storage_file.h: Add a new
method virStorageFileIsSharedFS() to determine if a file is
on a shared filesystem (NFS, GFS, OCFS2, etc)
* src/qemu/qemu_driver.c: Tell security driver not to reset
disk labels on migration completion
* src/qemu/qemu_security_dac.c, src/qemu/qemu_security_stacked.c,
src/security/security_selinux.c, src/security/security_driver.h,
src/security/security_apparmor.c: Add ability to skip disk
restore step for files on shared filesystems.
2010-05-13 15:49:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-06-15 15:40:47 +00:00
|
|
|
static int
|
2015-12-09 13:34:34 +00:00
|
|
|
virSecuritySELinuxSetImageLabelInternal(virSecurityManagerPtr mgr,
|
|
|
|
virDomainDefPtr def,
|
|
|
|
virStorageSourcePtr src,
|
|
|
|
bool first)
|
2010-06-15 15:40:47 +00:00
|
|
|
{
|
2014-06-24 15:04:21 +00:00
|
|
|
virSecuritySELinuxDataPtr data = virSecurityManagerGetPrivateData(mgr);
|
|
|
|
virSecurityLabelDefPtr secdef;
|
2012-08-15 22:10:37 +00:00
|
|
|
virSecurityDeviceLabelDefPtr disk_seclabel;
|
2014-06-24 15:04:21 +00:00
|
|
|
int ret;
|
2010-06-15 15:40:47 +00:00
|
|
|
|
2014-06-24 15:04:21 +00:00
|
|
|
if (!src->path || !virStorageSourceIsLocalStorage(src))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
|
2014-07-09 11:23:58 +00:00
|
|
|
if (!secdef || !secdef->relabel)
|
2014-06-24 15:04:21 +00:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
disk_seclabel = virStorageSourceGetSecurityLabelDef(src,
|
2012-08-15 22:10:37 +00:00
|
|
|
SECURITY_SELINUX_NAME);
|
|
|
|
|
2014-07-09 12:11:49 +00:00
|
|
|
if (disk_seclabel && !disk_seclabel->relabel)
|
2011-12-23 15:31:51 +00:00
|
|
|
return 0;
|
|
|
|
|
2014-07-09 12:11:49 +00:00
|
|
|
if (disk_seclabel && disk_seclabel->relabel && disk_seclabel->label) {
|
2015-09-10 11:27:28 +00:00
|
|
|
ret = virSecuritySELinuxSetFilecon(mgr, src->path, disk_seclabel->label);
|
2014-06-24 15:04:21 +00:00
|
|
|
} else if (first) {
|
|
|
|
if (src->shared) {
|
2015-09-10 11:27:28 +00:00
|
|
|
ret = virSecuritySELinuxSetFileconOptional(mgr,
|
|
|
|
src->path,
|
2014-06-24 15:04:21 +00:00
|
|
|
data->file_context);
|
|
|
|
} else if (src->readonly) {
|
2015-09-10 11:27:28 +00:00
|
|
|
ret = virSecuritySELinuxSetFileconOptional(mgr,
|
|
|
|
src->path,
|
2014-06-24 15:04:21 +00:00
|
|
|
data->content_context);
|
2010-06-15 15:40:47 +00:00
|
|
|
} else if (secdef->imagelabel) {
|
2015-09-10 11:27:28 +00:00
|
|
|
ret = virSecuritySELinuxSetFileconOptional(mgr,
|
|
|
|
src->path,
|
2014-06-24 15:04:21 +00:00
|
|
|
secdef->imagelabel);
|
2010-06-15 15:40:47 +00:00
|
|
|
} else {
|
2010-11-10 19:39:43 +00:00
|
|
|
ret = 0;
|
2010-06-15 15:40:47 +00:00
|
|
|
}
|
|
|
|
} else {
|
2015-09-10 11:27:28 +00:00
|
|
|
ret = virSecuritySELinuxSetFileconOptional(mgr,
|
|
|
|
src->path,
|
2014-06-24 15:04:21 +00:00
|
|
|
data->content_context);
|
2011-12-23 15:31:51 +00:00
|
|
|
}
|
2014-06-24 15:04:21 +00:00
|
|
|
|
2012-08-15 22:10:37 +00:00
|
|
|
if (ret == 1 && !disk_seclabel) {
|
2011-12-23 15:31:51 +00:00
|
|
|
/* If we failed to set a label, but virt_use_nfs let us
|
|
|
|
* proceed anyway, then we don't need to relabel later. */
|
2014-03-26 20:09:46 +00:00
|
|
|
disk_seclabel = virSecurityDeviceLabelDefNew(SECURITY_SELINUX_NAME);
|
2013-01-18 14:34:13 +00:00
|
|
|
if (!disk_seclabel)
|
2011-12-23 15:31:51 +00:00
|
|
|
return -1;
|
selinux: distinguish failure to label from request to avoid label
https://bugzilla.redhat.com/show_bug.cgi?id=924153
Commit 904e05a2 (v0.9.9) added a per-<disk> seclabel element with
an attribute relabel='no' in order to try and minimize the
impact of shutdown delays when an NFS server disappears. The idea
was that if a disk is on NFS and can't be labeled in the first
place, there is no need to attempt the (no-op) relabel on domain
shutdown. Unfortunately, the way this was implemented was by
modifying the domain XML so that the optimization would survive
libvirtd restart, but in a way that is indistinguishable from an
explicit user setting. Furthermore, once the setting is turned
on, libvirt avoids attempts at labeling, even for operations like
snapshot or blockcopy where the chain is being extended or pivoted
onto non-NFS, where SELinux labeling is once again possible. As
a result, it was impossible to do a blockcopy to pivot from an
NFS image file onto a local file.
The solution is to separate the semantics of a chain that must
not be labeled (which the user can set even on persistent domains)
vs. the optimization of not attempting a relabel on cleanup (a
live-only annotation), and using only the user's explicit notation
rather than the optimization as the decision on whether to skip
a label attempt in the first place. When upgrading an older
libvirtd to a newer, an NFS volume will still attempt the relabel;
but as the avoidance of a relabel was only an optimization, this
shouldn't cause any problems.
In the ideal future, libvirt will eventually have XML describing
EVERY file in the backing chain, with each file having a separate
<seclabel> element. At that point, libvirt will be able to track
more closely which files need a relabel attempt at shutdown. But
until we reach that point, the single <seclabel> for the entire
<disk> chain is treated as a hint - when a chain has only one
file, then we know it is accurate; but if the chain has more than
one file, we have to attempt relabel in spite of the attribute,
in case part of the chain is local and SELinux mattered for that
portion of the chain.
* src/conf/domain_conf.h (_virSecurityDeviceLabelDef): Add new
member.
* src/conf/domain_conf.c (virSecurityDeviceLabelDefParseXML):
Parse it, for live images only.
(virSecurityDeviceLabelDefFormat): Output it.
(virDomainDiskDefParseXML, virDomainChrSourceDefParseXML)
(virDomainDiskSourceDefFormat, virDomainChrDefFormat)
(virDomainDiskDefFormat): Pass flags on through.
* src/security/security_selinux.c
(virSecuritySELinuxRestoreSecurityImageLabelInt): Honor labelskip
when possible.
(virSecuritySELinuxSetSecurityFileLabel): Set labelskip, not
norelabel, if labeling fails.
(virSecuritySELinuxSetFileconHelper): Fix indentation.
* docs/formatdomain.html.in (seclabel): Document new xml.
* docs/schemas/domaincommon.rng (devSeclabel): Allow it in RNG.
* tests/qemuxml2argvdata/qemuxml2argv-seclabel-*-labelskip.xml:
* tests/qemuxml2argvdata/qemuxml2argv-seclabel-*-labelskip.args:
* tests/qemuxml2xmloutdata/qemuxml2xmlout-seclabel-*-labelskip.xml:
New test files.
* tests/qemuxml2argvtest.c (mymain): Run the new tests.
* tests/qemuxml2xmltest.c (mymain): Likewise.
Signed-off-by: Eric Blake <eblake@redhat.com>
2013-08-12 15:15:42 +00:00
|
|
|
disk_seclabel->labelskip = true;
|
2014-06-24 15:04:21 +00:00
|
|
|
if (VIR_APPEND_ELEMENT(src->seclabels, src->nseclabels,
|
2013-07-04 10:15:50 +00:00
|
|
|
disk_seclabel) < 0) {
|
2013-03-21 15:12:55 +00:00
|
|
|
virSecurityDeviceLabelDefFree(disk_seclabel);
|
|
|
|
return -1;
|
|
|
|
}
|
2011-12-23 15:31:51 +00:00
|
|
|
ret = 0;
|
2010-06-15 15:40:47 +00:00
|
|
|
}
|
2014-06-24 15:04:21 +00:00
|
|
|
|
2010-11-10 19:39:43 +00:00
|
|
|
return ret;
|
2010-06-15 15:40:47 +00:00
|
|
|
}
|
|
|
|
|
2014-06-24 15:04:21 +00:00
|
|
|
|
|
|
|
static int
|
2015-12-09 13:34:34 +00:00
|
|
|
virSecuritySELinuxSetImageLabel(virSecurityManagerPtr mgr,
|
|
|
|
virDomainDefPtr def,
|
|
|
|
virStorageSourcePtr src)
|
2014-06-24 15:04:21 +00:00
|
|
|
{
|
2015-12-09 13:34:34 +00:00
|
|
|
return virSecuritySELinuxSetImageLabelInternal(mgr, def, src, true);
|
2014-06-24 15:04:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-03-03 10:06:49 +00:00
|
|
|
static int
|
2015-12-09 13:34:34 +00:00
|
|
|
virSecuritySELinuxSetDiskLabel(virSecurityManagerPtr mgr,
|
|
|
|
virDomainDefPtr def,
|
|
|
|
virDomainDiskDefPtr disk)
|
2009-03-03 10:06:49 +00:00
|
|
|
|
|
|
|
{
|
2014-06-24 15:04:21 +00:00
|
|
|
bool first = true;
|
|
|
|
virStorageSourcePtr next;
|
2012-05-11 09:43:30 +00:00
|
|
|
|
2014-06-24 15:04:21 +00:00
|
|
|
for (next = disk->src; next; next = next->backingStore) {
|
2015-12-09 13:34:34 +00:00
|
|
|
if (virSecuritySELinuxSetImageLabelInternal(mgr, def, next, first) < 0)
|
2014-06-24 15:04:21 +00:00
|
|
|
return -1;
|
2010-01-13 14:03:04 +00:00
|
|
|
|
2014-06-24 15:04:21 +00:00
|
|
|
first = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
2009-03-03 10:06:49 +00:00
|
|
|
}
|
|
|
|
|
2009-08-14 13:23:11 +00:00
|
|
|
static int
|
2015-12-09 13:34:34 +00:00
|
|
|
virSecuritySELinuxSetHostdevLabelHelper(const char *file, void *opaque)
|
2009-08-14 13:23:11 +00:00
|
|
|
{
|
2012-08-15 22:10:37 +00:00
|
|
|
virSecurityLabelDefPtr secdef;
|
2015-09-10 11:27:28 +00:00
|
|
|
virSecuritySELinuxCallbackDataPtr data = opaque;
|
|
|
|
virSecurityManagerPtr mgr = data->mgr;
|
|
|
|
virDomainDefPtr def = data->def;
|
2009-08-14 13:23:11 +00:00
|
|
|
|
2012-08-15 22:10:37 +00:00
|
|
|
secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
|
|
|
|
if (secdef == NULL)
|
2014-06-09 14:23:52 +00:00
|
|
|
return 0;
|
2015-09-10 11:27:28 +00:00
|
|
|
return virSecuritySELinuxSetFilecon(mgr, file, secdef->imagelabel);
|
2009-08-14 13:23:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2015-12-09 13:34:34 +00:00
|
|
|
virSecuritySELinuxSetPCILabel(virPCIDevicePtr dev ATTRIBUTE_UNUSED,
|
|
|
|
const char *file, void *opaque)
|
2009-08-14 13:23:11 +00:00
|
|
|
{
|
2015-12-09 13:34:34 +00:00
|
|
|
return virSecuritySELinuxSetHostdevLabelHelper(file, opaque);
|
2013-05-03 18:07:28 +00:00
|
|
|
}
|
2009-08-14 13:23:11 +00:00
|
|
|
|
2013-05-03 18:07:28 +00:00
|
|
|
static int
|
2015-12-09 13:34:34 +00:00
|
|
|
virSecuritySELinuxSetUSBLabel(virUSBDevicePtr dev ATTRIBUTE_UNUSED,
|
|
|
|
const char *file, void *opaque)
|
2013-05-03 18:07:28 +00:00
|
|
|
{
|
2015-12-09 13:34:34 +00:00
|
|
|
return virSecuritySELinuxSetHostdevLabelHelper(file, opaque);
|
2009-08-14 13:23:11 +00:00
|
|
|
}
|
|
|
|
|
2013-05-03 18:07:28 +00:00
|
|
|
static int
|
2015-12-09 13:34:34 +00:00
|
|
|
virSecuritySELinuxSetSCSILabel(virSCSIDevicePtr dev,
|
|
|
|
const char *file, void *opaque)
|
2013-05-03 18:07:28 +00:00
|
|
|
{
|
2014-11-26 17:35:46 +00:00
|
|
|
virSecurityLabelDefPtr secdef;
|
2015-09-10 11:49:18 +00:00
|
|
|
virSecuritySELinuxCallbackDataPtr ptr = opaque;
|
2014-11-26 17:35:46 +00:00
|
|
|
virSecurityManagerPtr mgr = ptr->mgr;
|
|
|
|
virSecuritySELinuxDataPtr data = virSecurityManagerGetPrivateData(mgr);
|
|
|
|
|
|
|
|
secdef = virDomainDefGetSecurityLabelDef(ptr->def, SECURITY_SELINUX_NAME);
|
|
|
|
if (secdef == NULL)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (virSCSIDeviceGetShareable(dev))
|
2015-09-10 11:27:28 +00:00
|
|
|
return virSecuritySELinuxSetFileconOptional(mgr, file,
|
2014-11-26 17:35:46 +00:00
|
|
|
data->file_context);
|
|
|
|
else if (virSCSIDeviceGetReadonly(dev))
|
2015-09-10 11:27:28 +00:00
|
|
|
return virSecuritySELinuxSetFileconOptional(mgr, file,
|
2014-11-26 17:35:46 +00:00
|
|
|
data->content_context);
|
|
|
|
else
|
2015-09-10 11:27:28 +00:00
|
|
|
return virSecuritySELinuxSetFileconOptional(mgr, file,
|
|
|
|
secdef->imagelabel);
|
2013-05-03 18:07:28 +00:00
|
|
|
}
|
2012-11-28 15:54:56 +00:00
|
|
|
|
2016-11-22 03:58:21 +00:00
|
|
|
static int
|
|
|
|
virSecuritySELinuxSetHostLabel(virSCSIVHostDevicePtr dev ATTRIBUTE_UNUSED,
|
|
|
|
const char *file, void *opaque)
|
|
|
|
{
|
|
|
|
return virSecuritySELinuxSetHostdevLabelHelper(file, opaque);
|
|
|
|
}
|
|
|
|
|
2017-02-03 12:25:57 +00:00
|
|
|
|
2009-08-14 13:23:11 +00:00
|
|
|
static int
|
2015-12-09 13:34:34 +00:00
|
|
|
virSecuritySELinuxSetHostdevSubsysLabel(virSecurityManagerPtr mgr,
|
|
|
|
virDomainDefPtr def,
|
|
|
|
virDomainHostdevDefPtr dev,
|
|
|
|
const char *vroot)
|
2009-08-14 13:23:11 +00:00
|
|
|
|
|
|
|
{
|
2014-07-03 19:43:05 +00:00
|
|
|
virDomainHostdevSubsysUSBPtr usbsrc = &dev->source.subsys.u.usb;
|
2014-07-03 20:31:39 +00:00
|
|
|
virDomainHostdevSubsysPCIPtr pcisrc = &dev->source.subsys.u.pci;
|
2014-07-03 21:01:10 +00:00
|
|
|
virDomainHostdevSubsysSCSIPtr scsisrc = &dev->source.subsys.u.scsi;
|
2016-11-22 03:58:21 +00:00
|
|
|
virDomainHostdevSubsysSCSIVHostPtr hostsrc = &dev->source.subsys.u.scsi_host;
|
2017-02-03 12:25:57 +00:00
|
|
|
virDomainHostdevSubsysMediatedDevPtr mdevsrc = &dev->source.subsys.u.mdev;
|
2015-09-10 11:27:28 +00:00
|
|
|
virSecuritySELinuxCallbackData data = {.mgr = mgr, .def = def};
|
|
|
|
|
2009-08-14 13:23:11 +00:00
|
|
|
int ret = -1;
|
|
|
|
|
2015-12-09 13:34:34 +00:00
|
|
|
/* Like virSecuritySELinuxSetImageLabelInternal() for a networked
|
2014-07-09 13:31:38 +00:00
|
|
|
* disk, do nothing for an iSCSI hostdev
|
|
|
|
*/
|
2014-09-24 15:47:46 +00:00
|
|
|
if (dev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI &&
|
|
|
|
scsisrc->protocol == VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_ISCSI)
|
2014-07-09 13:31:38 +00:00
|
|
|
return 0;
|
|
|
|
|
2016-11-08 18:26:23 +00:00
|
|
|
switch ((virDomainHostdevSubsysType) dev->source.subsys.type) {
|
2009-08-14 13:23:11 +00:00
|
|
|
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB: {
|
2013-01-14 22:11:44 +00:00
|
|
|
virUSBDevicePtr usb;
|
2009-08-14 13:23:11 +00:00
|
|
|
|
2012-10-03 14:57:28 +00:00
|
|
|
if (dev->missing)
|
|
|
|
return 0;
|
|
|
|
|
2014-07-03 19:43:05 +00:00
|
|
|
usb = virUSBDeviceNew(usbsrc->bus,
|
|
|
|
usbsrc->device,
|
2013-01-14 22:11:44 +00:00
|
|
|
vroot);
|
2010-01-11 16:40:46 +00:00
|
|
|
if (!usb)
|
|
|
|
goto done;
|
2009-08-14 13:23:11 +00:00
|
|
|
|
2015-12-09 13:34:34 +00:00
|
|
|
ret = virUSBDeviceFileIterate(usb, virSecuritySELinuxSetUSBLabel, &data);
|
2013-01-14 22:11:44 +00:00
|
|
|
virUSBDeviceFree(usb);
|
2009-09-30 17:37:03 +00:00
|
|
|
break;
|
2009-08-14 13:23:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI: {
|
2013-01-14 22:11:44 +00:00
|
|
|
virPCIDevicePtr pci =
|
2014-07-03 20:31:39 +00:00
|
|
|
virPCIDeviceNew(pcisrc->addr.domain, pcisrc->addr.bus,
|
|
|
|
pcisrc->addr.slot, pcisrc->addr.function);
|
2009-08-14 13:23:11 +00:00
|
|
|
|
|
|
|
if (!pci)
|
|
|
|
goto done;
|
|
|
|
|
2014-07-03 20:31:39 +00:00
|
|
|
if (pcisrc->backend == VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO) {
|
2013-06-14 20:18:44 +00:00
|
|
|
char *vfioGroupDev = virPCIDeviceGetIOMMUGroupDev(pci);
|
2013-04-25 10:37:21 +00:00
|
|
|
|
2013-04-30 14:59:29 +00:00
|
|
|
if (!vfioGroupDev) {
|
|
|
|
virPCIDeviceFree(pci);
|
2013-04-25 10:37:21 +00:00
|
|
|
goto done;
|
2013-04-30 14:59:29 +00:00
|
|
|
}
|
2015-12-09 13:34:34 +00:00
|
|
|
ret = virSecuritySELinuxSetPCILabel(pci, vfioGroupDev, &data);
|
2013-04-25 10:37:21 +00:00
|
|
|
VIR_FREE(vfioGroupDev);
|
|
|
|
} else {
|
2015-12-09 13:34:34 +00:00
|
|
|
ret = virPCIDeviceFileIterate(pci, virSecuritySELinuxSetPCILabel, &data);
|
2013-04-25 10:37:21 +00:00
|
|
|
}
|
2013-01-14 22:11:44 +00:00
|
|
|
virPCIDeviceFree(pci);
|
2009-08-14 13:23:11 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2013-05-03 18:07:28 +00:00
|
|
|
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI: {
|
2014-06-20 15:35:46 +00:00
|
|
|
virDomainHostdevSubsysSCSIHostPtr scsihostsrc = &scsisrc->u.host;
|
2014-11-26 17:35:46 +00:00
|
|
|
|
2013-05-03 18:07:28 +00:00
|
|
|
virSCSIDevicePtr scsi =
|
2014-01-30 07:05:59 +00:00
|
|
|
virSCSIDeviceNew(NULL,
|
2014-06-20 15:35:46 +00:00
|
|
|
scsihostsrc->adapter, scsihostsrc->bus,
|
|
|
|
scsihostsrc->target, scsihostsrc->unit,
|
2014-07-03 21:01:10 +00:00
|
|
|
dev->readonly, dev->shareable);
|
2013-05-03 18:07:28 +00:00
|
|
|
|
|
|
|
if (!scsi)
|
|
|
|
goto done;
|
|
|
|
|
2014-11-26 17:35:46 +00:00
|
|
|
ret = virSCSIDeviceFileIterate(scsi,
|
2015-12-09 13:34:34 +00:00
|
|
|
virSecuritySELinuxSetSCSILabel,
|
2014-11-26 17:35:46 +00:00
|
|
|
&data);
|
2013-05-03 18:07:28 +00:00
|
|
|
virSCSIDeviceFree(scsi);
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2016-11-22 03:58:16 +00:00
|
|
|
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST: {
|
2016-11-22 03:58:21 +00:00
|
|
|
virSCSIVHostDevicePtr host = virSCSIVHostDeviceNew(hostsrc->wwpn);
|
|
|
|
|
|
|
|
if (!host)
|
|
|
|
goto done;
|
|
|
|
|
|
|
|
ret = virSCSIVHostDeviceFileIterate(host,
|
|
|
|
virSecuritySELinuxSetHostLabel,
|
|
|
|
&data);
|
|
|
|
virSCSIVHostDeviceFree(host);
|
|
|
|
break;
|
2016-11-22 03:58:16 +00:00
|
|
|
}
|
|
|
|
|
2017-02-03 12:25:57 +00:00
|
|
|
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_MDEV: {
|
|
|
|
char *vfiodev = NULL;
|
|
|
|
|
2017-04-26 12:47:15 +00:00
|
|
|
if (!(vfiodev = virMediatedDeviceGetIOMMUGroupDev(mdevsrc->uuidstr)))
|
2017-02-03 12:25:57 +00:00
|
|
|
goto done;
|
|
|
|
|
|
|
|
ret = virSecuritySELinuxSetHostdevLabelHelper(vfiodev, &data);
|
|
|
|
|
|
|
|
VIR_FREE(vfiodev);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2016-11-08 18:26:23 +00:00
|
|
|
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST:
|
2009-08-14 13:23:11 +00:00
|
|
|
ret = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2014-03-25 06:57:22 +00:00
|
|
|
done:
|
2009-08-14 13:23:11 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2009-11-11 12:07:00 +00:00
|
|
|
|
2012-11-28 16:07:27 +00:00
|
|
|
static int
|
2015-12-09 13:34:34 +00:00
|
|
|
virSecuritySELinuxSetHostdevCapsLabel(virSecurityManagerPtr mgr,
|
|
|
|
virDomainDefPtr def,
|
|
|
|
virDomainHostdevDefPtr dev,
|
|
|
|
const char *vroot)
|
2012-11-28 16:07:27 +00:00
|
|
|
{
|
|
|
|
int ret = -1;
|
|
|
|
virSecurityLabelDefPtr secdef;
|
|
|
|
char *path;
|
|
|
|
|
|
|
|
secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
|
|
|
|
if (secdef == NULL)
|
2014-06-09 14:23:52 +00:00
|
|
|
return 0;
|
2012-11-28 16:07:27 +00:00
|
|
|
|
|
|
|
switch (dev->source.caps.type) {
|
|
|
|
case VIR_DOMAIN_HOSTDEV_CAPS_TYPE_STORAGE: {
|
|
|
|
if (vroot) {
|
|
|
|
if (virAsprintf(&path, "%s/%s", vroot,
|
2013-07-04 10:15:50 +00:00
|
|
|
dev->source.caps.u.storage.block) < 0)
|
2012-11-28 16:07:27 +00:00
|
|
|
return -1;
|
|
|
|
} else {
|
2013-05-03 12:48:43 +00:00
|
|
|
if (VIR_STRDUP(path, dev->source.caps.u.storage.block) < 0)
|
2012-11-28 16:07:27 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2015-09-10 11:27:28 +00:00
|
|
|
ret = virSecuritySELinuxSetFilecon(mgr, path, secdef->imagelabel);
|
2012-11-28 16:07:27 +00:00
|
|
|
VIR_FREE(path);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case VIR_DOMAIN_HOSTDEV_CAPS_TYPE_MISC: {
|
|
|
|
if (vroot) {
|
|
|
|
if (virAsprintf(&path, "%s/%s", vroot,
|
2013-07-04 10:15:50 +00:00
|
|
|
dev->source.caps.u.misc.chardev) < 0)
|
2012-11-28 16:07:27 +00:00
|
|
|
return -1;
|
|
|
|
} else {
|
2013-05-03 12:48:43 +00:00
|
|
|
if (VIR_STRDUP(path, dev->source.caps.u.misc.chardev) < 0)
|
2012-11-28 16:07:27 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2015-09-10 11:27:28 +00:00
|
|
|
ret = virSecuritySELinuxSetFilecon(mgr, path, secdef->imagelabel);
|
2012-11-28 16:07:27 +00:00
|
|
|
VIR_FREE(path);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
ret = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-11-28 15:54:56 +00:00
|
|
|
static int
|
2015-12-09 13:34:34 +00:00
|
|
|
virSecuritySELinuxSetHostdevLabel(virSecurityManagerPtr mgr,
|
|
|
|
virDomainDefPtr def,
|
|
|
|
virDomainHostdevDefPtr dev,
|
|
|
|
const char *vroot)
|
2012-11-28 15:54:56 +00:00
|
|
|
|
|
|
|
{
|
|
|
|
virSecurityLabelDefPtr secdef;
|
|
|
|
|
|
|
|
secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
|
2014-07-09 11:23:58 +00:00
|
|
|
if (!secdef || !secdef->relabel)
|
2012-11-28 15:54:56 +00:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
switch (dev->mode) {
|
|
|
|
case VIR_DOMAIN_HOSTDEV_MODE_SUBSYS:
|
2015-12-09 13:34:34 +00:00
|
|
|
return virSecuritySELinuxSetHostdevSubsysLabel(mgr, def, dev, vroot);
|
2012-11-28 15:54:56 +00:00
|
|
|
|
2012-11-28 16:07:27 +00:00
|
|
|
case VIR_DOMAIN_HOSTDEV_MODE_CAPABILITIES:
|
2015-12-09 13:34:34 +00:00
|
|
|
return virSecuritySELinuxSetHostdevCapsLabel(mgr, def, dev, vroot);
|
2012-11-28 16:07:27 +00:00
|
|
|
|
2012-11-28 15:54:56 +00:00
|
|
|
default:
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-08-14 13:23:11 +00:00
|
|
|
static int
|
2015-12-09 13:34:34 +00:00
|
|
|
virSecuritySELinuxRestorePCILabel(virPCIDevicePtr dev ATTRIBUTE_UNUSED,
|
|
|
|
const char *file,
|
|
|
|
void *opaque)
|
2009-08-14 13:23:11 +00:00
|
|
|
{
|
2013-01-23 20:09:04 +00:00
|
|
|
virSecurityManagerPtr mgr = opaque;
|
|
|
|
|
2015-12-09 13:34:34 +00:00
|
|
|
return virSecuritySELinuxRestoreFileLabel(mgr, file);
|
2009-08-14 13:23:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2015-12-09 13:34:34 +00:00
|
|
|
virSecuritySELinuxRestoreUSBLabel(virUSBDevicePtr dev ATTRIBUTE_UNUSED,
|
|
|
|
const char *file,
|
|
|
|
void *opaque)
|
2009-08-14 13:23:11 +00:00
|
|
|
{
|
2013-01-23 20:09:04 +00:00
|
|
|
virSecurityManagerPtr mgr = opaque;
|
|
|
|
|
2015-12-09 13:34:34 +00:00
|
|
|
return virSecuritySELinuxRestoreFileLabel(mgr, file);
|
2009-08-14 13:23:11 +00:00
|
|
|
}
|
|
|
|
|
2012-11-28 15:54:56 +00:00
|
|
|
|
2013-05-03 18:07:28 +00:00
|
|
|
static int
|
2015-12-09 13:34:34 +00:00
|
|
|
virSecuritySELinuxRestoreSCSILabel(virSCSIDevicePtr dev,
|
|
|
|
const char *file,
|
|
|
|
void *opaque)
|
2013-05-03 18:07:28 +00:00
|
|
|
{
|
|
|
|
virSecurityManagerPtr mgr = opaque;
|
|
|
|
|
2014-11-26 17:35:46 +00:00
|
|
|
/* Don't restore labels on a shareable or readonly hostdev, because
|
|
|
|
* other VMs may still be accessing.
|
|
|
|
*/
|
|
|
|
if (virSCSIDeviceGetShareable(dev) || virSCSIDeviceGetReadonly(dev))
|
|
|
|
return 0;
|
|
|
|
|
2015-12-09 13:34:34 +00:00
|
|
|
return virSecuritySELinuxRestoreFileLabel(mgr, file);
|
2013-05-03 18:07:28 +00:00
|
|
|
}
|
|
|
|
|
2016-11-22 03:58:21 +00:00
|
|
|
static int
|
|
|
|
virSecuritySELinuxRestoreHostLabel(virSCSIVHostDevicePtr dev ATTRIBUTE_UNUSED,
|
|
|
|
const char *file,
|
|
|
|
void *opaque)
|
|
|
|
{
|
|
|
|
virSecurityManagerPtr mgr = opaque;
|
|
|
|
|
|
|
|
return virSecuritySELinuxRestoreFileLabel(mgr, file);
|
|
|
|
}
|
|
|
|
|
2017-02-03 12:25:57 +00:00
|
|
|
|
2009-08-14 13:23:11 +00:00
|
|
|
static int
|
2015-12-09 13:34:34 +00:00
|
|
|
virSecuritySELinuxRestoreHostdevSubsysLabel(virSecurityManagerPtr mgr,
|
|
|
|
virDomainHostdevDefPtr dev,
|
|
|
|
const char *vroot)
|
2009-08-14 13:23:11 +00:00
|
|
|
|
|
|
|
{
|
2014-07-03 19:43:05 +00:00
|
|
|
virDomainHostdevSubsysUSBPtr usbsrc = &dev->source.subsys.u.usb;
|
2014-07-03 20:31:39 +00:00
|
|
|
virDomainHostdevSubsysPCIPtr pcisrc = &dev->source.subsys.u.pci;
|
2014-07-03 21:01:10 +00:00
|
|
|
virDomainHostdevSubsysSCSIPtr scsisrc = &dev->source.subsys.u.scsi;
|
2016-11-22 03:58:21 +00:00
|
|
|
virDomainHostdevSubsysSCSIVHostPtr hostsrc = &dev->source.subsys.u.scsi_host;
|
2017-02-03 12:25:57 +00:00
|
|
|
virDomainHostdevSubsysMediatedDevPtr mdevsrc = &dev->source.subsys.u.mdev;
|
2009-08-14 13:23:11 +00:00
|
|
|
int ret = -1;
|
|
|
|
|
2015-12-09 13:34:34 +00:00
|
|
|
/* Like virSecuritySELinuxRestoreImageLabelInt() for a networked
|
2014-07-09 13:31:38 +00:00
|
|
|
* disk, do nothing for an iSCSI hostdev
|
|
|
|
*/
|
2014-09-24 15:47:46 +00:00
|
|
|
if (dev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI &&
|
|
|
|
scsisrc->protocol == VIR_DOMAIN_HOSTDEV_SCSI_PROTOCOL_TYPE_ISCSI)
|
2014-07-09 13:31:38 +00:00
|
|
|
return 0;
|
|
|
|
|
2016-11-08 18:26:23 +00:00
|
|
|
switch ((virDomainHostdevSubsysType) dev->source.subsys.type) {
|
2009-08-14 13:23:11 +00:00
|
|
|
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB: {
|
2013-01-14 22:11:44 +00:00
|
|
|
virUSBDevicePtr usb;
|
2012-10-03 14:57:28 +00:00
|
|
|
|
|
|
|
if (dev->missing)
|
|
|
|
return 0;
|
2009-08-14 13:23:11 +00:00
|
|
|
|
2014-07-03 19:43:05 +00:00
|
|
|
usb = virUSBDeviceNew(usbsrc->bus,
|
|
|
|
usbsrc->device,
|
2013-01-14 22:11:44 +00:00
|
|
|
vroot);
|
2009-08-14 13:23:11 +00:00
|
|
|
if (!usb)
|
|
|
|
goto done;
|
|
|
|
|
2015-12-09 13:34:34 +00:00
|
|
|
ret = virUSBDeviceFileIterate(usb, virSecuritySELinuxRestoreUSBLabel, mgr);
|
2013-01-14 22:11:44 +00:00
|
|
|
virUSBDeviceFree(usb);
|
2009-08-14 13:23:11 +00:00
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI: {
|
2013-01-14 22:11:44 +00:00
|
|
|
virPCIDevicePtr pci =
|
2014-07-03 20:31:39 +00:00
|
|
|
virPCIDeviceNew(pcisrc->addr.domain, pcisrc->addr.bus,
|
|
|
|
pcisrc->addr.slot, pcisrc->addr.function);
|
2009-08-14 13:23:11 +00:00
|
|
|
|
|
|
|
if (!pci)
|
|
|
|
goto done;
|
|
|
|
|
2014-07-03 20:31:39 +00:00
|
|
|
if (pcisrc->backend == VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO) {
|
2013-06-14 20:18:44 +00:00
|
|
|
char *vfioGroupDev = virPCIDeviceGetIOMMUGroupDev(pci);
|
2013-04-25 10:37:21 +00:00
|
|
|
|
2013-04-30 14:59:29 +00:00
|
|
|
if (!vfioGroupDev) {
|
|
|
|
virPCIDeviceFree(pci);
|
2013-04-25 10:37:21 +00:00
|
|
|
goto done;
|
2013-04-30 14:59:29 +00:00
|
|
|
}
|
2015-12-09 13:34:34 +00:00
|
|
|
ret = virSecuritySELinuxRestorePCILabel(pci, vfioGroupDev, mgr);
|
2013-04-25 10:37:21 +00:00
|
|
|
VIR_FREE(vfioGroupDev);
|
|
|
|
} else {
|
2015-12-09 13:34:34 +00:00
|
|
|
ret = virPCIDeviceFileIterate(pci, virSecuritySELinuxRestorePCILabel, mgr);
|
2013-04-25 10:37:21 +00:00
|
|
|
}
|
2013-01-14 22:11:44 +00:00
|
|
|
virPCIDeviceFree(pci);
|
2009-08-14 13:23:11 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2013-05-03 18:07:28 +00:00
|
|
|
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI: {
|
2014-06-20 15:35:46 +00:00
|
|
|
virDomainHostdevSubsysSCSIHostPtr scsihostsrc = &scsisrc->u.host;
|
2013-05-03 18:07:28 +00:00
|
|
|
virSCSIDevicePtr scsi =
|
2014-01-30 07:05:59 +00:00
|
|
|
virSCSIDeviceNew(NULL,
|
2014-06-20 15:35:46 +00:00
|
|
|
scsihostsrc->adapter, scsihostsrc->bus,
|
|
|
|
scsihostsrc->target, scsihostsrc->unit,
|
2014-07-03 21:01:10 +00:00
|
|
|
dev->readonly, dev->shareable);
|
2013-05-03 18:07:28 +00:00
|
|
|
|
2015-11-20 09:29:21 +00:00
|
|
|
if (!scsi)
|
|
|
|
goto done;
|
2013-05-03 18:07:28 +00:00
|
|
|
|
2015-12-09 13:34:34 +00:00
|
|
|
ret = virSCSIDeviceFileIterate(scsi, virSecuritySELinuxRestoreSCSILabel, mgr);
|
2015-11-20 09:29:21 +00:00
|
|
|
virSCSIDeviceFree(scsi);
|
2013-05-03 18:07:28 +00:00
|
|
|
|
2015-11-20 09:29:21 +00:00
|
|
|
break;
|
|
|
|
}
|
2013-05-03 18:07:28 +00:00
|
|
|
|
2016-11-22 03:58:16 +00:00
|
|
|
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST: {
|
2016-11-22 03:58:21 +00:00
|
|
|
virSCSIVHostDevicePtr host = virSCSIVHostDeviceNew(hostsrc->wwpn);
|
|
|
|
|
|
|
|
if (!host)
|
|
|
|
goto done;
|
|
|
|
|
|
|
|
ret = virSCSIVHostDeviceFileIterate(host,
|
|
|
|
virSecuritySELinuxRestoreHostLabel,
|
|
|
|
mgr);
|
|
|
|
virSCSIVHostDeviceFree(host);
|
|
|
|
|
|
|
|
break;
|
2016-11-22 03:58:16 +00:00
|
|
|
}
|
|
|
|
|
2017-02-03 12:25:57 +00:00
|
|
|
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_MDEV: {
|
|
|
|
char *vfiodev = NULL;
|
|
|
|
|
2017-04-26 12:47:15 +00:00
|
|
|
if (!(vfiodev = virMediatedDeviceGetIOMMUGroupDev(mdevsrc->uuidstr)))
|
2017-02-03 12:25:57 +00:00
|
|
|
goto done;
|
|
|
|
|
|
|
|
ret = virSecuritySELinuxRestoreFileLabel(mgr, vfiodev);
|
|
|
|
|
|
|
|
VIR_FREE(vfiodev);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2016-11-08 18:26:23 +00:00
|
|
|
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST:
|
2009-08-14 13:23:11 +00:00
|
|
|
ret = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2014-03-25 06:57:22 +00:00
|
|
|
done:
|
2009-08-14 13:23:11 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2010-06-23 15:17:15 +00:00
|
|
|
|
2012-11-28 16:07:27 +00:00
|
|
|
static int
|
2015-12-09 13:34:34 +00:00
|
|
|
virSecuritySELinuxRestoreHostdevCapsLabel(virSecurityManagerPtr mgr,
|
|
|
|
virDomainHostdevDefPtr dev,
|
|
|
|
const char *vroot)
|
2012-11-28 16:07:27 +00:00
|
|
|
{
|
|
|
|
int ret = -1;
|
|
|
|
char *path;
|
|
|
|
|
|
|
|
switch (dev->source.caps.type) {
|
|
|
|
case VIR_DOMAIN_HOSTDEV_CAPS_TYPE_STORAGE: {
|
|
|
|
if (vroot) {
|
|
|
|
if (virAsprintf(&path, "%s/%s", vroot,
|
2013-07-04 10:15:50 +00:00
|
|
|
dev->source.caps.u.storage.block) < 0)
|
2012-11-28 16:07:27 +00:00
|
|
|
return -1;
|
|
|
|
} else {
|
2013-05-03 12:48:43 +00:00
|
|
|
if (VIR_STRDUP(path, dev->source.caps.u.storage.block) < 0)
|
2012-11-28 16:07:27 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2015-12-09 13:34:34 +00:00
|
|
|
ret = virSecuritySELinuxRestoreFileLabel(mgr, path);
|
2012-11-28 16:07:27 +00:00
|
|
|
VIR_FREE(path);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case VIR_DOMAIN_HOSTDEV_CAPS_TYPE_MISC: {
|
|
|
|
if (vroot) {
|
|
|
|
if (virAsprintf(&path, "%s/%s", vroot,
|
2013-07-04 10:15:50 +00:00
|
|
|
dev->source.caps.u.misc.chardev) < 0)
|
2012-11-28 16:07:27 +00:00
|
|
|
return -1;
|
|
|
|
} else {
|
2013-05-03 12:48:43 +00:00
|
|
|
if (VIR_STRDUP(path, dev->source.caps.u.misc.chardev) < 0)
|
2012-11-28 16:07:27 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2015-12-09 13:34:34 +00:00
|
|
|
ret = virSecuritySELinuxRestoreFileLabel(mgr, path);
|
2012-11-28 16:07:27 +00:00
|
|
|
VIR_FREE(path);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
ret = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-11-28 15:54:56 +00:00
|
|
|
static int
|
2015-12-09 13:34:34 +00:00
|
|
|
virSecuritySELinuxRestoreHostdevLabel(virSecurityManagerPtr mgr,
|
|
|
|
virDomainDefPtr def,
|
|
|
|
virDomainHostdevDefPtr dev,
|
|
|
|
const char *vroot)
|
2012-11-28 15:54:56 +00:00
|
|
|
|
|
|
|
{
|
|
|
|
virSecurityLabelDefPtr secdef;
|
|
|
|
|
|
|
|
secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
|
2014-07-09 11:23:58 +00:00
|
|
|
if (!secdef || !secdef->relabel)
|
2012-11-28 15:54:56 +00:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
switch (dev->mode) {
|
|
|
|
case VIR_DOMAIN_HOSTDEV_MODE_SUBSYS:
|
2015-12-09 13:34:34 +00:00
|
|
|
return virSecuritySELinuxRestoreHostdevSubsysLabel(mgr, dev, vroot);
|
2012-11-28 15:54:56 +00:00
|
|
|
|
2012-11-28 16:07:27 +00:00
|
|
|
case VIR_DOMAIN_HOSTDEV_MODE_CAPABILITIES:
|
2015-12-09 13:34:34 +00:00
|
|
|
return virSecuritySELinuxRestoreHostdevCapsLabel(mgr, dev, vroot);
|
2012-11-28 16:07:27 +00:00
|
|
|
|
2012-11-28 15:54:56 +00:00
|
|
|
default:
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-06-23 15:17:15 +00:00
|
|
|
static int
|
2015-12-09 13:34:34 +00:00
|
|
|
virSecuritySELinuxSetChardevLabel(virSecurityManagerPtr mgr,
|
|
|
|
virDomainDefPtr def,
|
2017-05-29 12:27:51 +00:00
|
|
|
virDomainChrSourceDefPtr dev_source,
|
|
|
|
bool chardevStdioLogd)
|
2010-06-23 15:17:15 +00:00
|
|
|
|
|
|
|
{
|
2012-09-20 13:16:17 +00:00
|
|
|
virSecurityLabelDefPtr seclabel;
|
|
|
|
virSecurityDeviceLabelDefPtr chr_seclabel = NULL;
|
|
|
|
char *imagelabel = NULL;
|
2010-06-23 15:17:15 +00:00
|
|
|
char *in = NULL, *out = NULL;
|
|
|
|
int ret = -1;
|
|
|
|
|
2012-09-20 13:16:17 +00:00
|
|
|
seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
|
2014-07-09 11:23:58 +00:00
|
|
|
if (!seclabel || !seclabel->relabel)
|
2014-06-09 14:23:52 +00:00
|
|
|
return 0;
|
2012-08-15 22:10:37 +00:00
|
|
|
|
2017-05-26 15:53:09 +00:00
|
|
|
chr_seclabel = virDomainChrSourceDefGetSecurityLabelDef(dev_source,
|
|
|
|
SECURITY_SELINUX_NAME);
|
2012-09-20 13:16:17 +00:00
|
|
|
|
2014-07-09 12:11:49 +00:00
|
|
|
if (chr_seclabel && !chr_seclabel->relabel)
|
2010-06-23 15:17:15 +00:00
|
|
|
return 0;
|
|
|
|
|
2017-06-22 11:51:58 +00:00
|
|
|
if (!chr_seclabel &&
|
|
|
|
dev_source->type == VIR_DOMAIN_CHR_TYPE_FILE &&
|
|
|
|
chardevStdioLogd)
|
2017-05-29 12:27:51 +00:00
|
|
|
return 0;
|
|
|
|
|
2012-09-20 13:16:17 +00:00
|
|
|
if (chr_seclabel)
|
|
|
|
imagelabel = chr_seclabel->label;
|
|
|
|
if (!imagelabel)
|
|
|
|
imagelabel = seclabel->imagelabel;
|
|
|
|
|
|
|
|
switch (dev_source->type) {
|
2010-06-23 15:17:15 +00:00
|
|
|
case VIR_DOMAIN_CHR_TYPE_DEV:
|
|
|
|
case VIR_DOMAIN_CHR_TYPE_FILE:
|
2015-09-10 11:27:28 +00:00
|
|
|
ret = virSecuritySELinuxSetFilecon(mgr,
|
|
|
|
dev_source->data.file.path,
|
2012-09-20 13:16:17 +00:00
|
|
|
imagelabel);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_CHR_TYPE_UNIX:
|
|
|
|
if (!dev_source->data.nix.listen) {
|
2015-09-10 11:27:28 +00:00
|
|
|
if (virSecuritySELinuxSetFilecon(mgr,
|
|
|
|
dev_source->data.nix.path,
|
2012-09-20 13:16:17 +00:00
|
|
|
imagelabel) < 0)
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
ret = 0;
|
2010-06-23 15:17:15 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_CHR_TYPE_PIPE:
|
2012-09-20 13:16:17 +00:00
|
|
|
if ((virAsprintf(&in, "%s.in", dev_source->data.file.path) < 0) ||
|
2013-07-04 10:15:50 +00:00
|
|
|
(virAsprintf(&out, "%s.out", dev_source->data.file.path) < 0))
|
2011-09-27 18:04:53 +00:00
|
|
|
goto done;
|
|
|
|
if (virFileExists(in) && virFileExists(out)) {
|
2015-09-10 11:27:28 +00:00
|
|
|
if ((virSecuritySELinuxSetFilecon(mgr, in, imagelabel) < 0) ||
|
|
|
|
(virSecuritySELinuxSetFilecon(mgr, out, imagelabel) < 0)) {
|
2011-03-29 14:46:48 +00:00
|
|
|
goto done;
|
2011-09-27 18:04:53 +00:00
|
|
|
}
|
2015-09-10 11:27:28 +00:00
|
|
|
} else if (virSecuritySELinuxSetFilecon(mgr,
|
|
|
|
dev_source->data.file.path,
|
2012-09-20 13:16:17 +00:00
|
|
|
imagelabel) < 0) {
|
2011-09-27 18:04:53 +00:00
|
|
|
goto done;
|
2010-06-23 15:17:15 +00:00
|
|
|
}
|
|
|
|
ret = 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
ret = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2014-03-25 06:57:22 +00:00
|
|
|
done:
|
2010-06-23 15:17:15 +00:00
|
|
|
VIR_FREE(in);
|
|
|
|
VIR_FREE(out);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2015-12-09 13:34:34 +00:00
|
|
|
virSecuritySELinuxRestoreChardevLabel(virSecurityManagerPtr mgr,
|
|
|
|
virDomainDefPtr def,
|
2017-05-29 12:27:51 +00:00
|
|
|
virDomainChrSourceDefPtr dev_source,
|
|
|
|
bool chardevStdioLogd)
|
2010-06-23 15:17:15 +00:00
|
|
|
|
|
|
|
{
|
2012-09-20 13:16:17 +00:00
|
|
|
virSecurityLabelDefPtr seclabel;
|
|
|
|
virSecurityDeviceLabelDefPtr chr_seclabel = NULL;
|
2010-06-23 15:17:15 +00:00
|
|
|
char *in = NULL, *out = NULL;
|
|
|
|
int ret = -1;
|
|
|
|
|
2012-09-20 13:16:17 +00:00
|
|
|
seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
|
2014-07-09 11:23:58 +00:00
|
|
|
if (!seclabel || !seclabel->relabel)
|
2014-06-09 14:23:52 +00:00
|
|
|
return 0;
|
2012-08-15 22:10:37 +00:00
|
|
|
|
2017-05-26 15:53:09 +00:00
|
|
|
chr_seclabel = virDomainChrSourceDefGetSecurityLabelDef(dev_source,
|
|
|
|
SECURITY_SELINUX_NAME);
|
2014-07-09 12:11:49 +00:00
|
|
|
if (chr_seclabel && !chr_seclabel->relabel)
|
2010-06-23 15:17:15 +00:00
|
|
|
return 0;
|
|
|
|
|
2017-06-22 11:51:58 +00:00
|
|
|
if (!chr_seclabel &&
|
|
|
|
dev_source->type == VIR_DOMAIN_CHR_TYPE_FILE &&
|
|
|
|
chardevStdioLogd)
|
2017-05-29 12:27:51 +00:00
|
|
|
return 0;
|
|
|
|
|
2012-09-20 13:16:17 +00:00
|
|
|
switch (dev_source->type) {
|
2010-06-23 15:17:15 +00:00
|
|
|
case VIR_DOMAIN_CHR_TYPE_DEV:
|
|
|
|
case VIR_DOMAIN_CHR_TYPE_FILE:
|
2015-12-09 13:34:34 +00:00
|
|
|
if (virSecuritySELinuxRestoreFileLabel(mgr, dev_source->data.file.path) < 0)
|
2010-11-18 16:55:14 +00:00
|
|
|
goto done;
|
|
|
|
ret = 0;
|
2010-06-23 15:17:15 +00:00
|
|
|
break;
|
2012-09-20 13:16:17 +00:00
|
|
|
|
|
|
|
case VIR_DOMAIN_CHR_TYPE_UNIX:
|
|
|
|
if (!dev_source->data.nix.listen) {
|
2015-12-09 13:34:34 +00:00
|
|
|
if (virSecuritySELinuxRestoreFileLabel(mgr, dev_source->data.file.path) < 0)
|
2012-09-20 13:16:17 +00:00
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
ret = 0;
|
|
|
|
break;
|
|
|
|
|
2010-06-23 15:17:15 +00:00
|
|
|
case VIR_DOMAIN_CHR_TYPE_PIPE:
|
2012-09-20 13:16:17 +00:00
|
|
|
if ((virAsprintf(&out, "%s.out", dev_source->data.file.path) < 0) ||
|
2013-07-04 10:15:50 +00:00
|
|
|
(virAsprintf(&in, "%s.in", dev_source->data.file.path) < 0))
|
2010-06-23 15:17:15 +00:00
|
|
|
goto done;
|
2011-09-27 18:04:53 +00:00
|
|
|
if (virFileExists(in) && virFileExists(out)) {
|
2015-12-09 13:34:34 +00:00
|
|
|
if ((virSecuritySELinuxRestoreFileLabel(mgr, out) < 0) ||
|
|
|
|
(virSecuritySELinuxRestoreFileLabel(mgr, in) < 0)) {
|
2011-09-27 18:04:53 +00:00
|
|
|
goto done;
|
|
|
|
}
|
2015-12-09 13:34:34 +00:00
|
|
|
} else if (virSecuritySELinuxRestoreFileLabel(mgr, dev_source->data.file.path) < 0) {
|
2010-06-23 15:17:15 +00:00
|
|
|
goto done;
|
2011-09-27 18:04:53 +00:00
|
|
|
}
|
2010-06-23 15:17:15 +00:00
|
|
|
ret = 0;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
ret = 0;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2014-03-25 06:57:22 +00:00
|
|
|
done:
|
2010-06-23 15:17:15 +00:00
|
|
|
VIR_FREE(in);
|
|
|
|
VIR_FREE(out);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2017-05-29 12:27:51 +00:00
|
|
|
struct _virSecuritySELinuxChardevCallbackData {
|
|
|
|
virSecurityManagerPtr mgr;
|
|
|
|
bool chardevStdioLogd;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2010-06-23 15:17:15 +00:00
|
|
|
static int
|
2012-05-24 15:42:51 +00:00
|
|
|
virSecuritySELinuxRestoreSecurityChardevCallback(virDomainDefPtr def,
|
2017-05-26 15:53:09 +00:00
|
|
|
virDomainChrDefPtr dev ATTRIBUTE_UNUSED,
|
2013-01-23 20:09:04 +00:00
|
|
|
void *opaque)
|
2010-06-23 15:17:15 +00:00
|
|
|
{
|
2017-05-29 12:27:51 +00:00
|
|
|
struct _virSecuritySELinuxChardevCallbackData *data = opaque;
|
2013-01-23 20:09:04 +00:00
|
|
|
|
2017-05-29 12:27:51 +00:00
|
|
|
return virSecuritySELinuxRestoreChardevLabel(data->mgr, def, dev->source,
|
|
|
|
data->chardevStdioLogd);
|
2010-06-23 15:17:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-01-14 19:17:17 +00:00
|
|
|
static int
|
2012-05-24 15:42:51 +00:00
|
|
|
virSecuritySELinuxRestoreSecuritySmartcardCallback(virDomainDefPtr def,
|
|
|
|
virDomainSmartcardDefPtr dev,
|
2013-01-23 20:09:04 +00:00
|
|
|
void *opaque)
|
2011-01-14 19:17:17 +00:00
|
|
|
{
|
2013-01-23 20:09:04 +00:00
|
|
|
virSecurityManagerPtr mgr = opaque;
|
2011-01-14 19:17:17 +00:00
|
|
|
const char *database;
|
|
|
|
|
|
|
|
switch (dev->type) {
|
|
|
|
case VIR_DOMAIN_SMARTCARD_TYPE_HOST:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_SMARTCARD_TYPE_HOST_CERTIFICATES:
|
|
|
|
database = dev->data.cert.database;
|
|
|
|
if (!database)
|
|
|
|
database = VIR_DOMAIN_SMARTCARD_DEFAULT_DATABASE;
|
2015-12-09 13:34:34 +00:00
|
|
|
return virSecuritySELinuxRestoreFileLabel(mgr, database);
|
2011-01-14 19:17:17 +00:00
|
|
|
|
|
|
|
case VIR_DOMAIN_SMARTCARD_TYPE_PASSTHROUGH:
|
2017-05-29 12:27:51 +00:00
|
|
|
return virSecuritySELinuxRestoreChardevLabel(mgr, def,
|
|
|
|
dev->data.passthru, false);
|
2011-01-14 19:17:17 +00:00
|
|
|
|
|
|
|
default:
|
2012-07-18 14:39:18 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("unknown smartcard type %d"),
|
|
|
|
dev->type);
|
2011-01-14 19:17:17 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-10-18 12:13:20 +00:00
|
|
|
static const char *
|
|
|
|
virSecuritySELinuxGetBaseLabel(virSecurityManagerPtr mgr, int virtType)
|
|
|
|
{
|
|
|
|
virSecuritySELinuxDataPtr priv = virSecurityManagerGetPrivateData(mgr);
|
|
|
|
if (virtType == VIR_DOMAIN_VIRT_QEMU && priv->alt_domain_context)
|
|
|
|
return priv->alt_domain_context;
|
|
|
|
else
|
|
|
|
return priv->domain_context;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-03-03 10:06:49 +00:00
|
|
|
static int
|
2015-12-09 13:34:34 +00:00
|
|
|
virSecuritySELinuxRestoreAllLabel(virSecurityManagerPtr mgr,
|
|
|
|
virDomainDefPtr def,
|
2017-05-29 12:27:51 +00:00
|
|
|
bool migrated,
|
|
|
|
bool chardevStdioLogd)
|
2009-03-03 10:06:49 +00:00
|
|
|
{
|
2012-08-15 22:10:37 +00:00
|
|
|
virSecurityLabelDefPtr secdef;
|
2012-11-28 13:54:39 +00:00
|
|
|
virSecuritySELinuxDataPtr data = virSecurityManagerGetPrivateData(mgr);
|
Convert 'int i' to 'size_t i' in src/security files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 14:09:33 +00:00
|
|
|
size_t i;
|
2009-03-03 10:06:49 +00:00
|
|
|
int rc = 0;
|
2009-08-28 17:44:43 +00:00
|
|
|
|
Change security driver APIs to use virDomainDefPtr instead of virDomainObjPtr
When sVirt is integrated with the LXC driver, it will be neccessary
to invoke the security driver APIs using only a virDomainDefPtr
since the lxc_container.c code has no virDomainObjPtr available.
Aside from two functions which want obj->pid, every bit of the
security driver code only touches obj->def. So we don't need to
pass a virDomainObjPtr into the security drivers, a virDomainDefPtr
is sufficient. Two functions also gain a 'pid_t pid' argument.
* src/qemu/qemu_driver.c, src/qemu/qemu_hotplug.c,
src/qemu/qemu_migration.c, src/qemu/qemu_process.c,
src/security/security_apparmor.c,
src/security/security_dac.c,
src/security/security_driver.h,
src/security/security_manager.c,
src/security/security_manager.h,
src/security/security_nop.c,
src/security/security_selinux.c,
src/security/security_stack.c: Change all security APIs to use a
virDomainDefPtr instead of virDomainObjPtr
2011-07-14 13:32:06 +00:00
|
|
|
VIR_DEBUG("Restoring security label on %s", def->name);
|
2009-08-28 17:44:43 +00:00
|
|
|
|
2012-08-15 22:10:37 +00:00
|
|
|
secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
|
|
|
|
|
2014-07-09 11:23:58 +00:00
|
|
|
if (!secdef || !secdef->relabel || data->skipAllLabel)
|
2010-01-13 14:03:04 +00:00
|
|
|
return 0;
|
|
|
|
|
2013-04-12 20:55:46 +00:00
|
|
|
if (def->tpm) {
|
2015-12-09 13:34:34 +00:00
|
|
|
if (virSecuritySELinuxRestoreTPMFileLabelInt(mgr, def, def->tpm) < 0)
|
2013-04-12 20:55:46 +00:00
|
|
|
rc = -1;
|
|
|
|
}
|
|
|
|
|
2013-05-21 07:21:21 +00:00
|
|
|
for (i = 0; i < def->nhostdevs; i++) {
|
2015-12-09 13:34:34 +00:00
|
|
|
if (virSecuritySELinuxRestoreHostdevLabel(mgr,
|
|
|
|
def,
|
|
|
|
def->hostdevs[i],
|
|
|
|
NULL) < 0)
|
2010-01-13 14:03:04 +00:00
|
|
|
rc = -1;
|
2009-03-03 10:06:49 +00:00
|
|
|
}
|
2015-11-20 07:25:41 +00:00
|
|
|
|
|
|
|
for (i = 0; i < def->ninputs; i++) {
|
|
|
|
if (virSecuritySELinuxRestoreInputLabel(mgr, def, def->inputs[i]) < 0)
|
|
|
|
rc = -1;
|
|
|
|
}
|
|
|
|
|
2016-08-04 12:04:38 +00:00
|
|
|
for (i = 0; i < def->nmems; i++) {
|
|
|
|
if (virSecuritySELinuxRestoreMemoryLabel(mgr, def, def->mems[i]) < 0)
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2013-05-21 07:21:21 +00:00
|
|
|
for (i = 0; i < def->ndisks; i++) {
|
2014-06-23 15:19:25 +00:00
|
|
|
virDomainDiskDefPtr disk = def->disks[i];
|
|
|
|
|
2015-12-09 13:34:34 +00:00
|
|
|
if (virSecuritySELinuxRestoreImageLabelInt(mgr, def, disk->src,
|
|
|
|
migrated) < 0)
|
2010-01-13 14:03:04 +00:00
|
|
|
rc = -1;
|
|
|
|
}
|
2010-01-11 11:04:40 +00:00
|
|
|
|
2017-05-29 12:27:51 +00:00
|
|
|
struct _virSecuritySELinuxChardevCallbackData chardevData = {
|
|
|
|
.mgr = mgr,
|
|
|
|
.chardevStdioLogd = chardevStdioLogd
|
|
|
|
};
|
|
|
|
|
Change security driver APIs to use virDomainDefPtr instead of virDomainObjPtr
When sVirt is integrated with the LXC driver, it will be neccessary
to invoke the security driver APIs using only a virDomainDefPtr
since the lxc_container.c code has no virDomainObjPtr available.
Aside from two functions which want obj->pid, every bit of the
security driver code only touches obj->def. So we don't need to
pass a virDomainObjPtr into the security drivers, a virDomainDefPtr
is sufficient. Two functions also gain a 'pid_t pid' argument.
* src/qemu/qemu_driver.c, src/qemu/qemu_hotplug.c,
src/qemu/qemu_migration.c, src/qemu/qemu_process.c,
src/security/security_apparmor.c,
src/security/security_dac.c,
src/security/security_driver.h,
src/security/security_manager.c,
src/security/security_manager.h,
src/security/security_nop.c,
src/security/security_selinux.c,
src/security/security_stack.c: Change all security APIs to use a
virDomainDefPtr instead of virDomainObjPtr
2011-07-14 13:32:06 +00:00
|
|
|
if (virDomainChrDefForeach(def,
|
2010-06-23 15:17:15 +00:00
|
|
|
false,
|
2012-05-24 15:42:51 +00:00
|
|
|
virSecuritySELinuxRestoreSecurityChardevCallback,
|
2017-05-29 12:27:51 +00:00
|
|
|
&chardevData) < 0)
|
2010-06-23 15:17:15 +00:00
|
|
|
rc = -1;
|
|
|
|
|
Change security driver APIs to use virDomainDefPtr instead of virDomainObjPtr
When sVirt is integrated with the LXC driver, it will be neccessary
to invoke the security driver APIs using only a virDomainDefPtr
since the lxc_container.c code has no virDomainObjPtr available.
Aside from two functions which want obj->pid, every bit of the
security driver code only touches obj->def. So we don't need to
pass a virDomainObjPtr into the security drivers, a virDomainDefPtr
is sufficient. Two functions also gain a 'pid_t pid' argument.
* src/qemu/qemu_driver.c, src/qemu/qemu_hotplug.c,
src/qemu/qemu_migration.c, src/qemu/qemu_process.c,
src/security/security_apparmor.c,
src/security/security_dac.c,
src/security/security_driver.h,
src/security/security_manager.c,
src/security/security_manager.h,
src/security/security_nop.c,
src/security/security_selinux.c,
src/security/security_stack.c: Change all security APIs to use a
virDomainDefPtr instead of virDomainObjPtr
2011-07-14 13:32:06 +00:00
|
|
|
if (virDomainSmartcardDefForeach(def,
|
2011-01-14 19:17:17 +00:00
|
|
|
false,
|
2012-05-24 15:42:51 +00:00
|
|
|
virSecuritySELinuxRestoreSecuritySmartcardCallback,
|
2013-01-23 20:09:04 +00:00
|
|
|
mgr) < 0)
|
2011-01-14 19:17:17 +00:00
|
|
|
rc = -1;
|
|
|
|
|
2014-08-07 11:50:00 +00:00
|
|
|
if (def->os.loader && def->os.loader->nvram &&
|
2015-12-09 13:34:34 +00:00
|
|
|
virSecuritySELinuxRestoreFileLabel(mgr, def->os.loader->nvram) < 0)
|
2014-08-07 11:50:00 +00:00
|
|
|
rc = -1;
|
|
|
|
|
2010-01-11 11:04:40 +00:00
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2015-12-09 13:34:34 +00:00
|
|
|
virSecuritySELinuxReleaseLabel(virSecurityManagerPtr mgr,
|
|
|
|
virDomainDefPtr def)
|
2010-01-11 11:04:40 +00:00
|
|
|
{
|
2012-08-15 22:10:37 +00:00
|
|
|
virSecurityLabelDefPtr secdef;
|
|
|
|
|
|
|
|
secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
|
|
|
|
if (secdef == NULL)
|
2014-06-09 14:23:52 +00:00
|
|
|
return 0;
|
2010-01-11 11:04:40 +00:00
|
|
|
|
2011-06-24 09:21:33 +00:00
|
|
|
if (secdef->type == VIR_DOMAIN_SECLABEL_DYNAMIC) {
|
|
|
|
if (secdef->label != NULL) {
|
|
|
|
context_t con = context_new(secdef->label);
|
|
|
|
if (con) {
|
2012-05-24 16:22:29 +00:00
|
|
|
virSecuritySELinuxMCSRemove(mgr, context_range_get(con));
|
2011-06-24 09:21:33 +00:00
|
|
|
context_free(con);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
VIR_FREE(secdef->label);
|
|
|
|
if (!secdef->baselabel)
|
|
|
|
VIR_FREE(secdef->model);
|
2010-01-13 14:03:04 +00:00
|
|
|
}
|
|
|
|
VIR_FREE(secdef->imagelabel);
|
|
|
|
|
2010-01-11 11:04:40 +00:00
|
|
|
return 0;
|
2009-03-03 10:06:49 +00:00
|
|
|
}
|
|
|
|
|
2009-11-11 12:07:00 +00:00
|
|
|
|
|
|
|
static int
|
2015-09-10 11:27:28 +00:00
|
|
|
virSecuritySELinuxSetSavedStateLabel(virSecurityManagerPtr mgr,
|
2012-05-24 15:42:51 +00:00
|
|
|
virDomainDefPtr def,
|
|
|
|
const char *savefile)
|
2009-11-11 12:07:00 +00:00
|
|
|
{
|
2012-08-15 22:10:37 +00:00
|
|
|
virSecurityLabelDefPtr secdef;
|
|
|
|
|
|
|
|
secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
|
2014-07-09 11:23:58 +00:00
|
|
|
if (!secdef || !secdef->relabel)
|
2010-01-13 14:03:04 +00:00
|
|
|
return 0;
|
|
|
|
|
2015-09-10 11:27:28 +00:00
|
|
|
return virSecuritySELinuxSetFilecon(mgr, savefile, secdef->imagelabel);
|
2009-11-11 12:07:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
2013-01-23 20:09:04 +00:00
|
|
|
virSecuritySELinuxRestoreSavedStateLabel(virSecurityManagerPtr mgr,
|
2012-05-24 15:42:51 +00:00
|
|
|
virDomainDefPtr def,
|
|
|
|
const char *savefile)
|
2009-11-11 12:07:00 +00:00
|
|
|
{
|
2012-08-15 22:10:37 +00:00
|
|
|
virSecurityLabelDefPtr secdef;
|
|
|
|
|
|
|
|
secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
|
2014-07-09 11:23:58 +00:00
|
|
|
if (!secdef || !secdef->relabel)
|
2010-01-13 14:03:04 +00:00
|
|
|
return 0;
|
|
|
|
|
2015-12-09 13:34:34 +00:00
|
|
|
return virSecuritySELinuxRestoreFileLabel(mgr, savefile);
|
2009-11-11 12:07:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-04-03 10:55:51 +00:00
|
|
|
static int
|
2016-12-14 15:34:49 +00:00
|
|
|
virSecuritySELinuxVerify(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
|
|
|
|
virDomainDefPtr def)
|
2009-04-03 10:55:51 +00:00
|
|
|
{
|
2012-08-15 22:10:37 +00:00
|
|
|
virSecurityLabelDefPtr secdef;
|
|
|
|
|
|
|
|
secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
|
|
|
|
if (secdef == NULL)
|
2014-06-09 14:23:52 +00:00
|
|
|
return 0;
|
2012-08-15 22:10:37 +00:00
|
|
|
|
2015-10-20 16:15:12 +00:00
|
|
|
if (STRNEQ(SECURITY_SELINUX_NAME, secdef->model)) {
|
2012-07-18 14:39:18 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("security label driver mismatch: "
|
|
|
|
"'%s' model configured for domain, but "
|
|
|
|
"hypervisor driver is '%s'."),
|
2013-02-11 14:22:56 +00:00
|
|
|
secdef->model, SECURITY_SELINUX_NAME);
|
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
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2009-04-03 10:55:51 +00:00
|
|
|
if (secdef->type == VIR_DOMAIN_SECLABEL_STATIC) {
|
|
|
|
if (security_check_context(secdef->label) != 0) {
|
2012-07-18 14:39:18 +00:00
|
|
|
virReportError(VIR_ERR_XML_ERROR,
|
|
|
|
_("Invalid security label %s"), secdef->label);
|
2009-04-03 10:55:51 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2009-03-03 10:06:49 +00:00
|
|
|
static int
|
2015-12-09 13:34:34 +00:00
|
|
|
virSecuritySELinuxSetProcessLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
|
|
|
|
virDomainDefPtr def)
|
2009-03-03 10:06:49 +00:00
|
|
|
{
|
|
|
|
/* TODO: verify DOI */
|
2012-08-15 22:10:37 +00:00
|
|
|
virSecurityLabelDefPtr secdef;
|
|
|
|
|
|
|
|
secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
|
2014-06-09 14:23:52 +00:00
|
|
|
if (!secdef || !secdef->label)
|
2010-01-13 14:03:04 +00:00
|
|
|
return 0;
|
|
|
|
|
2012-08-15 22:10:37 +00:00
|
|
|
VIR_DEBUG("label=%s", secdef->label);
|
2015-10-20 16:15:12 +00:00
|
|
|
if (STRNEQ(SECURITY_SELINUX_NAME, secdef->model)) {
|
2012-07-18 14:39:18 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("security label driver mismatch: "
|
|
|
|
"'%s' model configured for domain, but "
|
|
|
|
"hypervisor driver is '%s'."),
|
2013-02-11 14:22:56 +00:00
|
|
|
secdef->model, SECURITY_SELINUX_NAME);
|
2009-03-03 10:06:49 +00:00
|
|
|
if (security_getenforce() == 1)
|
2009-08-28 17:44:43 +00:00
|
|
|
return -1;
|
2009-03-03 10:06:49 +00:00
|
|
|
}
|
|
|
|
|
2012-10-05 14:41:22 +00:00
|
|
|
if (setexeccon_raw(secdef->label) == -1) {
|
2010-02-04 20:02:58 +00:00
|
|
|
virReportSystemError(errno,
|
2009-08-28 17:44:43 +00:00
|
|
|
_("unable to set security context '%s'"),
|
|
|
|
secdef->label);
|
2009-03-03 10:06:49 +00:00
|
|
|
if (security_getenforce() == 1)
|
2009-08-28 17:44:43 +00:00
|
|
|
return -1;
|
2009-03-03 10:06:49 +00:00
|
|
|
}
|
|
|
|
|
2010-01-11 11:04:40 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
security: add new virSecurityManagerSetChildProcessLabel API
The existing virSecurityManagerSetProcessLabel() API is designed so
that it must be called after forking the child process, but before
exec'ing the child. Due to the way the virCommand API works, that
means it needs to be put in a "hook" function that virCommand is told
to call out to at that time.
Setting the child process label is a basic enough need when executing
any process that virCommand should have a method of doing that. But
virCommand must be told what label to set, and only the security
driver knows the answer to that question.
The new virSecurityManagerSet*Child*ProcessLabel() API is the way to
transfer the knowledge about what label to set from the security
driver to the virCommand object. It is given a virCommandPtr, and each
security driver calls the appropriate virCommand* API to tell
virCommand what to do between fork and exec.
1) in the case of the DAC security driver, it calls
virCommandSetUID/GID() to set a uid and gid that must be set for the
child process.
2) for the SELinux security driver, it calls
virCommandSetSELinuxLabel() to save a copy of the char* that will be
sent to setexeccon_raw() *after forking the child process*.
3) for the AppArmor security drivers, it calls
virCommandSetAppArmorProfile() to save a copy of the char* that will
be sent to aa_change_profile() *after forking the child process*.
With this new API in place, we will be able to remove
virSecurityManagerSetProcessLabel() from any virCommand pre-exec
hooks.
(Unfortunately, the LXC driver uses clone() rather than virCommand, so
it can't take advantage of this new security driver API, meaning that
we need to keep around the older virSecurityManagerSetProcessLabel(),
at least for now.)
2013-02-01 20:02:03 +00:00
|
|
|
static int
|
2015-12-09 13:34:34 +00:00
|
|
|
virSecuritySELinuxSetChildProcessLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
|
|
|
|
virDomainDefPtr def,
|
|
|
|
virCommandPtr cmd)
|
security: add new virSecurityManagerSetChildProcessLabel API
The existing virSecurityManagerSetProcessLabel() API is designed so
that it must be called after forking the child process, but before
exec'ing the child. Due to the way the virCommand API works, that
means it needs to be put in a "hook" function that virCommand is told
to call out to at that time.
Setting the child process label is a basic enough need when executing
any process that virCommand should have a method of doing that. But
virCommand must be told what label to set, and only the security
driver knows the answer to that question.
The new virSecurityManagerSet*Child*ProcessLabel() API is the way to
transfer the knowledge about what label to set from the security
driver to the virCommand object. It is given a virCommandPtr, and each
security driver calls the appropriate virCommand* API to tell
virCommand what to do between fork and exec.
1) in the case of the DAC security driver, it calls
virCommandSetUID/GID() to set a uid and gid that must be set for the
child process.
2) for the SELinux security driver, it calls
virCommandSetSELinuxLabel() to save a copy of the char* that will be
sent to setexeccon_raw() *after forking the child process*.
3) for the AppArmor security drivers, it calls
virCommandSetAppArmorProfile() to save a copy of the char* that will
be sent to aa_change_profile() *after forking the child process*.
With this new API in place, we will be able to remove
virSecurityManagerSetProcessLabel() from any virCommand pre-exec
hooks.
(Unfortunately, the LXC driver uses clone() rather than virCommand, so
it can't take advantage of this new security driver API, meaning that
we need to keep around the older virSecurityManagerSetProcessLabel(),
at least for now.)
2013-02-01 20:02:03 +00:00
|
|
|
{
|
|
|
|
/* TODO: verify DOI */
|
|
|
|
virSecurityLabelDefPtr secdef;
|
|
|
|
|
|
|
|
secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
|
2014-06-09 14:23:52 +00:00
|
|
|
if (!secdef || !secdef->label)
|
security: add new virSecurityManagerSetChildProcessLabel API
The existing virSecurityManagerSetProcessLabel() API is designed so
that it must be called after forking the child process, but before
exec'ing the child. Due to the way the virCommand API works, that
means it needs to be put in a "hook" function that virCommand is told
to call out to at that time.
Setting the child process label is a basic enough need when executing
any process that virCommand should have a method of doing that. But
virCommand must be told what label to set, and only the security
driver knows the answer to that question.
The new virSecurityManagerSet*Child*ProcessLabel() API is the way to
transfer the knowledge about what label to set from the security
driver to the virCommand object. It is given a virCommandPtr, and each
security driver calls the appropriate virCommand* API to tell
virCommand what to do between fork and exec.
1) in the case of the DAC security driver, it calls
virCommandSetUID/GID() to set a uid and gid that must be set for the
child process.
2) for the SELinux security driver, it calls
virCommandSetSELinuxLabel() to save a copy of the char* that will be
sent to setexeccon_raw() *after forking the child process*.
3) for the AppArmor security drivers, it calls
virCommandSetAppArmorProfile() to save a copy of the char* that will
be sent to aa_change_profile() *after forking the child process*.
With this new API in place, we will be able to remove
virSecurityManagerSetProcessLabel() from any virCommand pre-exec
hooks.
(Unfortunately, the LXC driver uses clone() rather than virCommand, so
it can't take advantage of this new security driver API, meaning that
we need to keep around the older virSecurityManagerSetProcessLabel(),
at least for now.)
2013-02-01 20:02:03 +00:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
VIR_DEBUG("label=%s", secdef->label);
|
2015-10-20 16:15:12 +00:00
|
|
|
if (STRNEQ(SECURITY_SELINUX_NAME, secdef->model)) {
|
security: add new virSecurityManagerSetChildProcessLabel API
The existing virSecurityManagerSetProcessLabel() API is designed so
that it must be called after forking the child process, but before
exec'ing the child. Due to the way the virCommand API works, that
means it needs to be put in a "hook" function that virCommand is told
to call out to at that time.
Setting the child process label is a basic enough need when executing
any process that virCommand should have a method of doing that. But
virCommand must be told what label to set, and only the security
driver knows the answer to that question.
The new virSecurityManagerSet*Child*ProcessLabel() API is the way to
transfer the knowledge about what label to set from the security
driver to the virCommand object. It is given a virCommandPtr, and each
security driver calls the appropriate virCommand* API to tell
virCommand what to do between fork and exec.
1) in the case of the DAC security driver, it calls
virCommandSetUID/GID() to set a uid and gid that must be set for the
child process.
2) for the SELinux security driver, it calls
virCommandSetSELinuxLabel() to save a copy of the char* that will be
sent to setexeccon_raw() *after forking the child process*.
3) for the AppArmor security drivers, it calls
virCommandSetAppArmorProfile() to save a copy of the char* that will
be sent to aa_change_profile() *after forking the child process*.
With this new API in place, we will be able to remove
virSecurityManagerSetProcessLabel() from any virCommand pre-exec
hooks.
(Unfortunately, the LXC driver uses clone() rather than virCommand, so
it can't take advantage of this new security driver API, meaning that
we need to keep around the older virSecurityManagerSetProcessLabel(),
at least for now.)
2013-02-01 20:02:03 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("security label driver mismatch: "
|
|
|
|
"'%s' model configured for domain, but "
|
|
|
|
"hypervisor driver is '%s'."),
|
|
|
|
secdef->model, SECURITY_SELINUX_NAME);
|
|
|
|
if (security_getenforce() == 1)
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* save in cmd to be set after fork/before child process is exec'ed */
|
|
|
|
virCommandSetSELinuxLabel(cmd, secdef->label);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2010-05-27 15:44:47 +00:00
|
|
|
static int
|
2015-12-09 13:34:34 +00:00
|
|
|
virSecuritySELinuxSetDaemonSocketLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
|
|
|
|
virDomainDefPtr def)
|
2010-05-27 15:44:47 +00:00
|
|
|
{
|
|
|
|
/* TODO: verify DOI */
|
2012-08-15 22:10:37 +00:00
|
|
|
virSecurityLabelDefPtr secdef;
|
2010-05-27 15:44:47 +00:00
|
|
|
security_context_t scon = NULL;
|
2012-10-15 09:03:49 +00:00
|
|
|
char *str = NULL;
|
2010-05-27 15:44:47 +00:00
|
|
|
int rc = -1;
|
|
|
|
|
2012-08-15 22:10:37 +00:00
|
|
|
secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
|
2014-06-09 14:23:52 +00:00
|
|
|
if (!secdef || !secdef->label)
|
2010-05-27 15:44:47 +00:00
|
|
|
return 0;
|
|
|
|
|
2015-10-20 16:15:12 +00:00
|
|
|
if (STRNEQ(SECURITY_SELINUX_NAME, secdef->model)) {
|
2012-07-18 14:39:18 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("security label driver mismatch: "
|
|
|
|
"'%s' model configured for domain, but "
|
|
|
|
"hypervisor driver is '%s'."),
|
2013-02-11 14:22:56 +00:00
|
|
|
secdef->model, SECURITY_SELINUX_NAME);
|
2010-05-27 15:44:47 +00:00
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
2012-10-05 14:41:22 +00:00
|
|
|
if (getcon_raw(&scon) == -1) {
|
2010-05-27 15:44:47 +00:00
|
|
|
virReportSystemError(errno,
|
|
|
|
_("unable to get current process context '%s'"),
|
|
|
|
secdef->label);
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
2012-10-15 09:03:49 +00:00
|
|
|
if (!(str = virSecuritySELinuxContextAddRange(secdef->label, scon)))
|
2010-05-27 15:44:47 +00:00
|
|
|
goto done;
|
|
|
|
|
2012-10-15 09:03:49 +00:00
|
|
|
VIR_DEBUG("Setting VM %s socket context %s", def->name, str);
|
|
|
|
if (setsockcreatecon_raw(str) == -1) {
|
2010-05-27 15:44:47 +00:00
|
|
|
virReportSystemError(errno,
|
2012-10-15 09:03:49 +00:00
|
|
|
_("unable to set socket security context '%s'"), str);
|
2010-05-27 15:44:47 +00:00
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
rc = 0;
|
2014-03-25 06:57:22 +00:00
|
|
|
done:
|
2010-05-27 15:44:47 +00:00
|
|
|
|
|
|
|
if (security_getenforce() != 1)
|
|
|
|
rc = 0;
|
|
|
|
freecon(scon);
|
2012-10-15 09:03:49 +00:00
|
|
|
VIR_FREE(str);
|
2010-05-27 15:44:47 +00:00
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2011-08-26 07:39:32 +00:00
|
|
|
static int
|
2015-12-09 13:34:34 +00:00
|
|
|
virSecuritySELinuxSetSocketLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
|
|
|
|
virDomainDefPtr vm)
|
2011-08-26 07:39:32 +00:00
|
|
|
{
|
2012-08-15 22:10:37 +00:00
|
|
|
virSecurityLabelDefPtr secdef;
|
2011-08-26 07:39:32 +00:00
|
|
|
int rc = -1;
|
|
|
|
|
2012-08-15 22:10:37 +00:00
|
|
|
secdef = virDomainDefGetSecurityLabelDef(vm, SECURITY_SELINUX_NAME);
|
2014-06-09 14:23:52 +00:00
|
|
|
if (!secdef || !secdef->label)
|
2011-08-26 07:39:32 +00:00
|
|
|
return 0;
|
|
|
|
|
2015-10-20 16:15:12 +00:00
|
|
|
if (STRNEQ(SECURITY_SELINUX_NAME, secdef->model)) {
|
2012-07-18 14:39:18 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("security label driver mismatch: "
|
|
|
|
"'%s' model configured for domain, but "
|
|
|
|
"hypervisor driver is '%s'."),
|
2013-02-11 14:22:56 +00:00
|
|
|
secdef->model, SECURITY_SELINUX_NAME);
|
2011-08-26 07:39:32 +00:00
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
VIR_DEBUG("Setting VM %s socket context %s",
|
Change security driver APIs to use virDomainDefPtr instead of virDomainObjPtr
When sVirt is integrated with the LXC driver, it will be neccessary
to invoke the security driver APIs using only a virDomainDefPtr
since the lxc_container.c code has no virDomainObjPtr available.
Aside from two functions which want obj->pid, every bit of the
security driver code only touches obj->def. So we don't need to
pass a virDomainObjPtr into the security drivers, a virDomainDefPtr
is sufficient. Two functions also gain a 'pid_t pid' argument.
* src/qemu/qemu_driver.c, src/qemu/qemu_hotplug.c,
src/qemu/qemu_migration.c, src/qemu/qemu_process.c,
src/security/security_apparmor.c,
src/security/security_dac.c,
src/security/security_driver.h,
src/security/security_manager.c,
src/security/security_manager.h,
src/security/security_nop.c,
src/security/security_selinux.c,
src/security/security_stack.c: Change all security APIs to use a
virDomainDefPtr instead of virDomainObjPtr
2011-07-14 13:32:06 +00:00
|
|
|
vm->name, secdef->label);
|
2012-10-05 14:41:22 +00:00
|
|
|
if (setsockcreatecon_raw(secdef->label) == -1) {
|
2011-08-26 07:39:32 +00:00
|
|
|
virReportSystemError(errno,
|
|
|
|
_("unable to set socket security context '%s'"),
|
|
|
|
secdef->label);
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
|
|
|
|
rc = 0;
|
|
|
|
|
2014-03-25 06:57:22 +00:00
|
|
|
done:
|
2011-08-26 07:39:32 +00:00
|
|
|
if (security_getenforce() != 1)
|
|
|
|
rc = 0;
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
2010-05-27 15:44:47 +00:00
|
|
|
static int
|
2015-12-09 13:34:34 +00:00
|
|
|
virSecuritySELinuxClearSocketLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
|
|
|
|
virDomainDefPtr def)
|
2010-05-27 15:44:47 +00:00
|
|
|
{
|
|
|
|
/* TODO: verify DOI */
|
2012-08-15 22:10:37 +00:00
|
|
|
virSecurityLabelDefPtr secdef;
|
|
|
|
|
|
|
|
secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
|
2014-06-09 14:23:52 +00:00
|
|
|
if (!secdef || !secdef->label)
|
2010-05-27 15:44:47 +00:00
|
|
|
return 0;
|
|
|
|
|
2015-10-20 16:15:12 +00:00
|
|
|
if (STRNEQ(SECURITY_SELINUX_NAME, secdef->model)) {
|
2012-07-18 14:39:18 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("security label driver mismatch: "
|
|
|
|
"'%s' model configured for domain, but "
|
|
|
|
"hypervisor driver is '%s'."),
|
2013-02-11 14:22:56 +00:00
|
|
|
secdef->model, SECURITY_SELINUX_NAME);
|
2010-05-27 15:44:47 +00:00
|
|
|
if (security_getenforce() == 1)
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2012-10-05 14:41:22 +00:00
|
|
|
if (setsockcreatecon_raw(NULL) == -1) {
|
2010-05-27 15:44:47 +00:00
|
|
|
virReportSystemError(errno,
|
|
|
|
_("unable to clear socket security context '%s'"),
|
|
|
|
secdef->label);
|
|
|
|
if (security_getenforce() == 1)
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2010-06-23 15:17:15 +00:00
|
|
|
|
|
|
|
static int
|
2012-05-24 15:42:51 +00:00
|
|
|
virSecuritySELinuxSetSecurityChardevCallback(virDomainDefPtr def,
|
2017-05-26 15:53:09 +00:00
|
|
|
virDomainChrDefPtr dev ATTRIBUTE_UNUSED,
|
2015-09-10 11:27:28 +00:00
|
|
|
void *opaque)
|
2010-06-23 15:17:15 +00:00
|
|
|
{
|
2017-05-29 12:27:51 +00:00
|
|
|
struct _virSecuritySELinuxChardevCallbackData *data = opaque;
|
2015-09-10 11:27:28 +00:00
|
|
|
|
2017-05-29 12:27:51 +00:00
|
|
|
return virSecuritySELinuxSetChardevLabel(data->mgr, def, dev->source,
|
|
|
|
data->chardevStdioLogd);
|
2010-06-23 15:17:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-01-14 19:17:17 +00:00
|
|
|
static int
|
2012-05-24 15:42:51 +00:00
|
|
|
virSecuritySELinuxSetSecuritySmartcardCallback(virDomainDefPtr def,
|
|
|
|
virDomainSmartcardDefPtr dev,
|
|
|
|
void *opaque)
|
2011-01-14 19:17:17 +00:00
|
|
|
{
|
|
|
|
const char *database;
|
2012-05-11 09:43:30 +00:00
|
|
|
virSecurityManagerPtr mgr = opaque;
|
|
|
|
virSecuritySELinuxDataPtr data = virSecurityManagerGetPrivateData(mgr);
|
2011-01-14 19:17:17 +00:00
|
|
|
|
|
|
|
switch (dev->type) {
|
|
|
|
case VIR_DOMAIN_SMARTCARD_TYPE_HOST:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_SMARTCARD_TYPE_HOST_CERTIFICATES:
|
|
|
|
database = dev->data.cert.database;
|
|
|
|
if (!database)
|
|
|
|
database = VIR_DOMAIN_SMARTCARD_DEFAULT_DATABASE;
|
2015-09-10 11:27:28 +00:00
|
|
|
return virSecuritySELinuxSetFilecon(mgr, database, data->content_context);
|
2011-01-14 19:17:17 +00:00
|
|
|
|
|
|
|
case VIR_DOMAIN_SMARTCARD_TYPE_PASSTHROUGH:
|
2017-05-26 15:53:09 +00:00
|
|
|
return virSecuritySELinuxSetChardevLabel(mgr, def,
|
2017-05-29 12:27:51 +00:00
|
|
|
dev->data.passthru, false);
|
2011-01-14 19:17:17 +00:00
|
|
|
|
|
|
|
default:
|
2012-07-18 14:39:18 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("unknown smartcard type %d"),
|
|
|
|
dev->type);
|
2011-01-14 19:17:17 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-01-11 11:04:40 +00:00
|
|
|
static int
|
2015-12-09 13:34:34 +00:00
|
|
|
virSecuritySELinuxSetAllLabel(virSecurityManagerPtr mgr,
|
|
|
|
virDomainDefPtr def,
|
2017-05-29 12:27:51 +00:00
|
|
|
const char *stdin_path,
|
|
|
|
bool chardevStdioLogd)
|
2010-01-11 11:04:40 +00:00
|
|
|
{
|
Convert 'int i' to 'size_t i' in src/security files
Convert the type of loop iterators named 'i', 'j', k',
'ii', 'jj', 'kk', to be 'size_t' instead of 'int' or
'unsigned int', also santizing 'ii', 'jj', 'kk' to use
the normal 'i', 'j', 'k' naming
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
2013-07-08 14:09:33 +00:00
|
|
|
size_t i;
|
2012-08-15 22:10:37 +00:00
|
|
|
virSecuritySELinuxDataPtr data = virSecurityManagerGetPrivateData(mgr);
|
|
|
|
virSecurityLabelDefPtr secdef;
|
|
|
|
|
|
|
|
secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
|
2010-01-11 11:04:40 +00:00
|
|
|
|
2014-07-09 11:23:58 +00:00
|
|
|
if (!secdef || !secdef->relabel || data->skipAllLabel)
|
2010-01-11 11:04:40 +00:00
|
|
|
return 0;
|
|
|
|
|
2013-05-21 07:21:21 +00:00
|
|
|
for (i = 0; i < def->ndisks; i++) {
|
2010-01-11 11:04:40 +00:00
|
|
|
/* XXX fixme - we need to recursively label the entire tree :-( */
|
conf: move host disk type to util/
A continuation of the migration of disk details to virstoragefile.
This patch moves a single enum, but converting the name has quite
a bit of fallout.
* src/conf/domain_conf.h (virDomainDiskType): Move...
* src/util/virstoragefile.h (virStorageType): ...and rename.
* src/bhyve/bhyve_command.c (bhyveBuildDiskArgStr)
(virBhyveProcessBuildLoadCmd): Update clients.
* src/conf/domain_conf.c (virDomainDiskSourceDefParse)
(virDomainDiskDefParseXML, virDomainDiskSourceDefFormatInternal)
(virDomainDiskDefFormat, virDomainDiskGetActualType)
(virDomainDiskDefForeachPath, virDomainDiskSourceIsBlockType):
Likewise.
* src/conf/snapshot_conf.h (_virDomainSnapshotDiskDef): Likewise.
* src/conf/snapshot_conf.c (virDomainSnapshotDiskDefParseXML)
(virDomainSnapshotAlignDisks, virDomainSnapshotDiskDefFormat):
Likewise.
* src/esx/esx_driver.c (esxAutodetectSCSIControllerModel)
(esxDomainDefineXML): Likewise.
* src/locking/domain_lock.c (virDomainLockManagerAddDisk):
Likewise.
* src/lxc/lxc_controller.c
(virLXCControllerSetupLoopDeviceDisk)
(virLXCControllerSetupNBDDeviceDisk)
(virLXCControllerSetupLoopDevices, virLXCControllerSetupDisk):
Likewise.
* src/parallels/parallels_driver.c (parallelsGetHddInfo):
Likewise.
* src/phyp/phyp_driver.c (phypDiskType): Likewise.
* src/qemu/qemu_command.c (qemuGetDriveSourceString)
(qemuDomainDiskGetSourceString, qemuBuildDriveStr)
(qemuBuildCommandLine, qemuParseCommandLineDisk)
(qemuParseCommandLine): Likewise.
* src/qemu/qemu_conf.c (qemuCheckSharedDevice)
(qemuTranslateDiskSourcePool)
(qemuTranslateSnapshotDiskSourcePool): Likewise.
* src/qemu/qemu_domain.c (qemuDomainDeviceDefPostParse)
(qemuDomainDetermineDiskChain): Likewise.
* src/qemu/qemu_driver.c (qemuDomainGetBlockInfo)
(qemuDomainSnapshotPrepareDiskExternalBackingInactive)
(qemuDomainSnapshotPrepareDiskExternalBackingActive)
(qemuDomainSnapshotPrepareDiskExternalOverlayActive)
(qemuDomainSnapshotPrepareDiskExternalOverlayInactive)
(qemuDomainSnapshotPrepareDiskInternal)
(qemuDomainSnapshotPrepare)
(qemuDomainSnapshotCreateSingleDiskActive): Likewise.
* src/qemu/qemu_hotplug.c (qemuDomainChangeEjectableMedia):
Likewise.
* src/qemu/qemu_migration.c (qemuMigrationIsSafe): Likewise.
* src/security/security_apparmor.c
(AppArmorRestoreSecurityImageLabel)
(AppArmorSetSecurityImageLabel): Likewise.
* src/security/security_dac.c (virSecurityDACSetSecurityImageLabel)
(virSecurityDACRestoreSecurityImageLabelInt)
(virSecurityDACSetSecurityAllLabel): Likewise.
* src/security/security_selinux.c
(virSecuritySELinuxRestoreSecurityImageLabelInt)
(virSecuritySELinuxSetSecurityImageLabel)
(virSecuritySELinuxSetSecurityAllLabel): Likewise.
* src/storage/storage_backend.c (virStorageFileBackendForType):
Likewise.
* src/storage/storage_backend_fs.c (virStorageFileBackendFile)
(virStorageFileBackendBlock): Likewise.
* src/storage/storage_backend_gluster.c
(virStorageFileBackendGluster): Likewise.
* src/vbox/vbox_tmpl.c (vboxDomainGetXMLDesc, vboxAttachDrives)
(vboxDomainAttachDeviceImpl, vboxDomainDetachDevice): Likewise.
* src/vmware/vmware_conf.c (vmwareVmxPath): Likewise.
* src/vmx/vmx.c (virVMXParseDisk, virVMXFormatDisk)
(virVMXFormatFloppy): Likewise.
* src/xenxs/xen_sxpr.c (xenParseSxprDisks, xenParseSxpr)
(xenFormatSxprDisk): Likewise.
* src/xenxs/xen_xm.c (xenParseXM, xenFormatXMDisk): Likewise.
* tests/securityselinuxlabeltest.c (testSELinuxLoadDef):
Likewise.
* src/libvirt_private.syms (domain_conf.h): Move symbols...
(virstoragefile.h): ...as appropriate.
Signed-off-by: Eric Blake <eblake@redhat.com>
2014-03-27 21:57:49 +00:00
|
|
|
if (virDomainDiskGetType(def->disks[i]) == VIR_STORAGE_TYPE_DIR) {
|
2010-01-11 11:04:40 +00:00
|
|
|
VIR_WARN("Unable to relabel directory tree %s for disk %s",
|
2014-03-18 19:55:04 +00:00
|
|
|
virDomainDiskGetSource(def->disks[i]),
|
|
|
|
def->disks[i]->dst);
|
2010-01-11 11:04:40 +00:00
|
|
|
continue;
|
2009-08-14 13:23:11 +00:00
|
|
|
}
|
2015-12-09 13:34:34 +00:00
|
|
|
if (virSecuritySELinuxSetDiskLabel(mgr,
|
|
|
|
def, def->disks[i]) < 0)
|
2010-01-11 11:04:40 +00:00
|
|
|
return -1;
|
|
|
|
}
|
Change security driver APIs to use virDomainDefPtr instead of virDomainObjPtr
When sVirt is integrated with the LXC driver, it will be neccessary
to invoke the security driver APIs using only a virDomainDefPtr
since the lxc_container.c code has no virDomainObjPtr available.
Aside from two functions which want obj->pid, every bit of the
security driver code only touches obj->def. So we don't need to
pass a virDomainObjPtr into the security drivers, a virDomainDefPtr
is sufficient. Two functions also gain a 'pid_t pid' argument.
* src/qemu/qemu_driver.c, src/qemu/qemu_hotplug.c,
src/qemu/qemu_migration.c, src/qemu/qemu_process.c,
src/security/security_apparmor.c,
src/security/security_dac.c,
src/security/security_driver.h,
src/security/security_manager.c,
src/security/security_manager.h,
src/security/security_nop.c,
src/security/security_selinux.c,
src/security/security_stack.c: Change all security APIs to use a
virDomainDefPtr instead of virDomainObjPtr
2011-07-14 13:32:06 +00:00
|
|
|
/* XXX fixme process def->fss if relabel == true */
|
2011-06-24 09:21:33 +00:00
|
|
|
|
2013-05-21 07:21:21 +00:00
|
|
|
for (i = 0; i < def->nhostdevs; i++) {
|
2015-12-09 13:34:34 +00:00
|
|
|
if (virSecuritySELinuxSetHostdevLabel(mgr,
|
|
|
|
def,
|
|
|
|
def->hostdevs[i],
|
|
|
|
NULL) < 0)
|
2010-01-11 11:04:40 +00:00
|
|
|
return -1;
|
2009-03-03 10:06:49 +00:00
|
|
|
}
|
2015-11-20 07:25:41 +00:00
|
|
|
|
|
|
|
for (i = 0; i < def->ninputs; i++) {
|
|
|
|
if (virSecuritySELinuxSetInputLabel(mgr, def, def->inputs[i]) < 0)
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2016-08-04 12:04:38 +00:00
|
|
|
for (i = 0; i < def->nmems; i++) {
|
|
|
|
if (virSecuritySELinuxSetMemoryLabel(mgr, def, def->mems[i]) < 0)
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2013-04-12 20:55:46 +00:00
|
|
|
if (def->tpm) {
|
2015-12-09 13:34:34 +00:00
|
|
|
if (virSecuritySELinuxSetTPMFileLabel(mgr, def, def->tpm) < 0)
|
2013-04-12 20:55:46 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2009-03-03 10:06:49 +00:00
|
|
|
|
2017-05-29 12:27:51 +00:00
|
|
|
struct _virSecuritySELinuxChardevCallbackData chardevData = {
|
|
|
|
.mgr = mgr,
|
|
|
|
.chardevStdioLogd = chardevStdioLogd
|
|
|
|
};
|
|
|
|
|
Change security driver APIs to use virDomainDefPtr instead of virDomainObjPtr
When sVirt is integrated with the LXC driver, it will be neccessary
to invoke the security driver APIs using only a virDomainDefPtr
since the lxc_container.c code has no virDomainObjPtr available.
Aside from two functions which want obj->pid, every bit of the
security driver code only touches obj->def. So we don't need to
pass a virDomainObjPtr into the security drivers, a virDomainDefPtr
is sufficient. Two functions also gain a 'pid_t pid' argument.
* src/qemu/qemu_driver.c, src/qemu/qemu_hotplug.c,
src/qemu/qemu_migration.c, src/qemu/qemu_process.c,
src/security/security_apparmor.c,
src/security/security_dac.c,
src/security/security_driver.h,
src/security/security_manager.c,
src/security/security_manager.h,
src/security/security_nop.c,
src/security/security_selinux.c,
src/security/security_stack.c: Change all security APIs to use a
virDomainDefPtr instead of virDomainObjPtr
2011-07-14 13:32:06 +00:00
|
|
|
if (virDomainChrDefForeach(def,
|
2010-06-23 15:17:15 +00:00
|
|
|
true,
|
2012-05-24 15:42:51 +00:00
|
|
|
virSecuritySELinuxSetSecurityChardevCallback,
|
2017-05-29 12:27:51 +00:00
|
|
|
&chardevData) < 0)
|
2010-06-23 15:17:15 +00:00
|
|
|
return -1;
|
|
|
|
|
Change security driver APIs to use virDomainDefPtr instead of virDomainObjPtr
When sVirt is integrated with the LXC driver, it will be neccessary
to invoke the security driver APIs using only a virDomainDefPtr
since the lxc_container.c code has no virDomainObjPtr available.
Aside from two functions which want obj->pid, every bit of the
security driver code only touches obj->def. So we don't need to
pass a virDomainObjPtr into the security drivers, a virDomainDefPtr
is sufficient. Two functions also gain a 'pid_t pid' argument.
* src/qemu/qemu_driver.c, src/qemu/qemu_hotplug.c,
src/qemu/qemu_migration.c, src/qemu/qemu_process.c,
src/security/security_apparmor.c,
src/security/security_dac.c,
src/security/security_driver.h,
src/security/security_manager.c,
src/security/security_manager.h,
src/security/security_nop.c,
src/security/security_selinux.c,
src/security/security_stack.c: Change all security APIs to use a
virDomainDefPtr instead of virDomainObjPtr
2011-07-14 13:32:06 +00:00
|
|
|
if (virDomainSmartcardDefForeach(def,
|
2011-01-14 19:17:17 +00:00
|
|
|
true,
|
2012-05-24 15:42:51 +00:00
|
|
|
virSecuritySELinuxSetSecuritySmartcardCallback,
|
2012-05-11 09:43:30 +00:00
|
|
|
mgr) < 0)
|
2011-01-14 19:17:17 +00:00
|
|
|
return -1;
|
|
|
|
|
2014-09-11 10:09:04 +00:00
|
|
|
/* This is different than kernel or initrd. The nvram store
|
|
|
|
* is really a disk, qemu can read and write to it. */
|
2014-08-07 11:50:00 +00:00
|
|
|
if (def->os.loader && def->os.loader->nvram &&
|
2014-09-11 10:09:04 +00:00
|
|
|
secdef && secdef->imagelabel &&
|
2015-09-10 11:27:28 +00:00
|
|
|
virSecuritySELinuxSetFilecon(mgr, def->os.loader->nvram,
|
|
|
|
secdef->imagelabel) < 0)
|
2014-08-07 11:50:00 +00:00
|
|
|
return -1;
|
|
|
|
|
Change security driver APIs to use virDomainDefPtr instead of virDomainObjPtr
When sVirt is integrated with the LXC driver, it will be neccessary
to invoke the security driver APIs using only a virDomainDefPtr
since the lxc_container.c code has no virDomainObjPtr available.
Aside from two functions which want obj->pid, every bit of the
security driver code only touches obj->def. So we don't need to
pass a virDomainObjPtr into the security drivers, a virDomainDefPtr
is sufficient. Two functions also gain a 'pid_t pid' argument.
* src/qemu/qemu_driver.c, src/qemu/qemu_hotplug.c,
src/qemu/qemu_migration.c, src/qemu/qemu_process.c,
src/security/security_apparmor.c,
src/security/security_dac.c,
src/security/security_driver.h,
src/security/security_manager.c,
src/security/security_manager.h,
src/security/security_nop.c,
src/security/security_selinux.c,
src/security/security_stack.c: Change all security APIs to use a
virDomainDefPtr instead of virDomainObjPtr
2011-07-14 13:32:06 +00:00
|
|
|
if (def->os.kernel &&
|
2015-09-10 11:27:28 +00:00
|
|
|
virSecuritySELinuxSetFilecon(mgr, def->os.kernel,
|
|
|
|
data->content_context) < 0)
|
2010-03-12 18:38:39 +00:00
|
|
|
return -1;
|
|
|
|
|
Change security driver APIs to use virDomainDefPtr instead of virDomainObjPtr
When sVirt is integrated with the LXC driver, it will be neccessary
to invoke the security driver APIs using only a virDomainDefPtr
since the lxc_container.c code has no virDomainObjPtr available.
Aside from two functions which want obj->pid, every bit of the
security driver code only touches obj->def. So we don't need to
pass a virDomainObjPtr into the security drivers, a virDomainDefPtr
is sufficient. Two functions also gain a 'pid_t pid' argument.
* src/qemu/qemu_driver.c, src/qemu/qemu_hotplug.c,
src/qemu/qemu_migration.c, src/qemu/qemu_process.c,
src/security/security_apparmor.c,
src/security/security_dac.c,
src/security/security_driver.h,
src/security/security_manager.c,
src/security/security_manager.h,
src/security/security_nop.c,
src/security/security_selinux.c,
src/security/security_stack.c: Change all security APIs to use a
virDomainDefPtr instead of virDomainObjPtr
2011-07-14 13:32:06 +00:00
|
|
|
if (def->os.initrd &&
|
2015-09-10 11:27:28 +00:00
|
|
|
virSecuritySELinuxSetFilecon(mgr, def->os.initrd,
|
|
|
|
data->content_context) < 0)
|
2010-03-12 18:38:39 +00:00
|
|
|
return -1;
|
|
|
|
|
2013-03-14 04:49:44 +00:00
|
|
|
if (def->os.dtb &&
|
2015-09-10 11:27:28 +00:00
|
|
|
virSecuritySELinuxSetFilecon(mgr, def->os.dtb,
|
|
|
|
data->content_context) < 0)
|
2013-03-14 04:49:44 +00:00
|
|
|
return -1;
|
|
|
|
|
2016-05-13 14:16:55 +00:00
|
|
|
if (def->os.slic_table &&
|
|
|
|
virSecuritySELinuxSetFilecon(mgr, def->os.slic_table,
|
|
|
|
data->content_context) < 0)
|
|
|
|
return -1;
|
|
|
|
|
2015-09-10 11:29:36 +00:00
|
|
|
if (stdin_path &&
|
2015-09-10 11:27:28 +00:00
|
|
|
virSecuritySELinuxSetFilecon(mgr, stdin_path,
|
|
|
|
data->content_context) < 0)
|
2015-09-10 11:29:36 +00:00
|
|
|
return -1;
|
2010-06-24 21:58:59 +00:00
|
|
|
|
2009-03-03 10:06:49 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-01-23 21:02:42 +00:00
|
|
|
static int
|
2012-05-24 15:42:51 +00:00
|
|
|
virSecuritySELinuxSetImageFDLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
|
|
|
|
virDomainDefPtr def,
|
|
|
|
int fd)
|
2011-01-23 21:02:42 +00:00
|
|
|
{
|
2012-08-15 22:10:37 +00:00
|
|
|
virSecurityLabelDefPtr secdef;
|
|
|
|
|
|
|
|
secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
|
2014-06-09 14:23:52 +00:00
|
|
|
if (!secdef || !secdef->imagelabel)
|
2011-01-23 21:02:42 +00:00
|
|
|
return 0;
|
|
|
|
|
2012-05-24 15:42:51 +00:00
|
|
|
return virSecuritySELinuxFSetFilecon(fd, secdef->imagelabel);
|
2011-01-23 21:02:42 +00:00
|
|
|
}
|
|
|
|
|
2012-10-15 09:03:49 +00:00
|
|
|
static int
|
2014-09-18 13:17:29 +00:00
|
|
|
virSecuritySELinuxSetTapFDLabel(virSecurityManagerPtr mgr,
|
2012-10-15 09:03:49 +00:00
|
|
|
virDomainDefPtr def,
|
|
|
|
int fd)
|
|
|
|
{
|
2014-09-18 13:17:29 +00:00
|
|
|
struct stat buf;
|
|
|
|
security_context_t fcon = NULL;
|
2012-10-15 09:03:49 +00:00
|
|
|
virSecurityLabelDefPtr secdef;
|
2014-10-07 14:22:17 +00:00
|
|
|
char *str = NULL, *proc = NULL, *fd_path = NULL;
|
2014-09-18 13:17:29 +00:00
|
|
|
int rc = -1;
|
2012-10-15 09:03:49 +00:00
|
|
|
|
|
|
|
secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
|
2014-09-18 13:17:29 +00:00
|
|
|
if (!secdef || !secdef->label)
|
2012-10-15 09:03:49 +00:00
|
|
|
return 0;
|
|
|
|
|
2014-09-18 13:17:29 +00:00
|
|
|
if (fstat(fd, &buf) < 0) {
|
|
|
|
virReportSystemError(errno, _("cannot stat tap fd %d"), fd);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((buf.st_mode & S_IFMT) != S_IFCHR) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("tap fd %d is not character device"), fd);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2014-10-07 14:22:17 +00:00
|
|
|
/* Label /dev/tap.* devices only. Leave /dev/net/tun alone! */
|
|
|
|
if (virAsprintf(&proc, "/proc/self/fd/%d", fd) == -1)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
if (virFileResolveLink(proc, &fd_path) < 0) {
|
|
|
|
virReportSystemError(errno,
|
|
|
|
_("Unable to resolve link: %s"), proc);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!STRPREFIX(fd_path, "/dev/tap")) {
|
|
|
|
VIR_DEBUG("fd=%d points to %s not setting SELinux label",
|
|
|
|
fd, fd_path);
|
|
|
|
rc = 0;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (getContext(mgr, "/dev/tap*", buf.st_mode, &fcon) < 0) {
|
2014-09-18 13:17:29 +00:00
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("cannot lookup default selinux label for tap fd %d"), fd);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(str = virSecuritySELinuxContextAddRange(secdef->label, fcon))) {
|
|
|
|
goto cleanup;
|
|
|
|
} else {
|
|
|
|
rc = virSecuritySELinuxFSetFilecon(fd, str);
|
|
|
|
}
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
freecon(fcon);
|
2014-10-07 14:22:17 +00:00
|
|
|
VIR_FREE(fd_path);
|
|
|
|
VIR_FREE(proc);
|
2014-09-18 13:17:29 +00:00
|
|
|
VIR_FREE(str);
|
|
|
|
return rc;
|
2012-10-15 09:03:49 +00:00
|
|
|
}
|
|
|
|
|
2012-05-24 15:42:51 +00:00
|
|
|
static char *
|
|
|
|
virSecuritySELinuxGenImageLabel(virSecurityManagerPtr mgr,
|
|
|
|
virDomainDefPtr def)
|
|
|
|
{
|
2012-08-15 22:10:37 +00:00
|
|
|
virSecurityLabelDefPtr secdef;
|
2012-05-01 14:16:04 +00:00
|
|
|
virSecuritySELinuxDataPtr data = virSecurityManagerGetPrivateData(mgr);
|
|
|
|
const char *range;
|
|
|
|
context_t ctx = NULL;
|
|
|
|
char *label = NULL;
|
2013-05-03 12:48:43 +00:00
|
|
|
char *mcs = NULL;
|
2012-05-01 14:16:04 +00:00
|
|
|
|
2012-08-15 22:10:37 +00:00
|
|
|
secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
|
|
|
|
if (secdef == NULL)
|
|
|
|
goto cleanup;
|
|
|
|
|
2012-05-01 14:16:04 +00:00
|
|
|
if (secdef->label) {
|
|
|
|
ctx = context_new(secdef->label);
|
|
|
|
if (!ctx) {
|
2013-07-04 10:15:50 +00:00
|
|
|
virReportSystemError(errno, _("unable to create selinux context for: %s"),
|
|
|
|
secdef->label);
|
2012-05-01 14:16:04 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
range = context_range_get(ctx);
|
|
|
|
if (range) {
|
2013-05-03 12:48:43 +00:00
|
|
|
if (VIR_STRDUP(mcs, range) < 0)
|
2012-05-01 14:16:04 +00:00
|
|
|
goto cleanup;
|
2012-08-20 14:12:14 +00:00
|
|
|
if (!(label = virSecuritySELinuxGenNewContext(data->file_context,
|
|
|
|
mcs, true)))
|
2012-05-01 14:16:04 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-03-25 06:57:22 +00:00
|
|
|
cleanup:
|
2013-05-03 12:48:43 +00:00
|
|
|
context_free(ctx);
|
|
|
|
VIR_FREE(mcs);
|
|
|
|
return label;
|
2012-05-01 14:16:04 +00:00
|
|
|
}
|
|
|
|
|
2012-05-24 15:42:51 +00:00
|
|
|
static char *
|
|
|
|
virSecuritySELinuxGetSecurityMountOptions(virSecurityManagerPtr mgr,
|
|
|
|
virDomainDefPtr def)
|
|
|
|
{
|
2012-05-01 14:16:04 +00:00
|
|
|
char *opts = NULL;
|
2012-08-15 22:10:37 +00:00
|
|
|
virSecurityLabelDefPtr secdef;
|
|
|
|
|
2012-11-22 14:11:35 +00:00
|
|
|
if ((secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME))) {
|
|
|
|
if (!secdef->imagelabel)
|
|
|
|
secdef->imagelabel = virSecuritySELinuxGenImageLabel(mgr, def);
|
|
|
|
|
|
|
|
if (secdef->imagelabel &&
|
|
|
|
virAsprintf(&opts,
|
|
|
|
",context=\"%s\"",
|
2013-07-04 10:15:50 +00:00
|
|
|
(const char*) secdef->imagelabel) < 0)
|
2012-11-22 14:11:35 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
2012-05-01 14:16:04 +00:00
|
|
|
|
2013-05-03 12:48:43 +00:00
|
|
|
if (!opts && VIR_STRDUP(opts, "") < 0)
|
2012-11-22 14:11:35 +00:00
|
|
|
return NULL;
|
2012-05-01 14:16:04 +00:00
|
|
|
|
2012-12-13 10:44:37 +00:00
|
|
|
VIR_DEBUG("imageLabel=%s opts=%s",
|
|
|
|
secdef ? secdef->imagelabel : "(null)", opts);
|
2012-05-01 14:16:04 +00:00
|
|
|
return opts;
|
|
|
|
}
|
|
|
|
|
2015-08-24 12:04:37 +00:00
|
|
|
static int
|
2016-04-14 07:20:55 +00:00
|
|
|
virSecuritySELinuxDomainSetPathLabel(virSecurityManagerPtr mgr,
|
|
|
|
virDomainDefPtr def,
|
|
|
|
const char *path)
|
2015-08-17 18:07:07 +00:00
|
|
|
{
|
|
|
|
virSecurityLabelDefPtr seclabel;
|
|
|
|
|
|
|
|
seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
|
|
|
|
if (!seclabel || !seclabel->relabel)
|
|
|
|
return 0;
|
|
|
|
|
2015-09-10 11:27:28 +00:00
|
|
|
return virSecuritySELinuxSetFilecon(mgr, path, seclabel->imagelabel);
|
2015-08-17 18:07:07 +00:00
|
|
|
}
|
|
|
|
|
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 virSecurityDriverSELinux = {
|
2012-05-24 13:11:26 +00:00
|
|
|
.privateDataLen = sizeof(virSecuritySELinuxData),
|
|
|
|
.name = SECURITY_SELINUX_NAME,
|
2016-12-14 15:34:49 +00:00
|
|
|
.probe = virSecuritySELinuxDriverProbe,
|
|
|
|
.open = virSecuritySELinuxDriverOpen,
|
|
|
|
.close = virSecuritySELinuxDriverClose,
|
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
|
|
|
|
2016-12-14 15:34:49 +00:00
|
|
|
.getModel = virSecuritySELinuxGetModel,
|
|
|
|
.getDOI = virSecuritySELinuxGetDOI,
|
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
|
|
|
|
2016-12-14 16:11:05 +00:00
|
|
|
.transactionStart = virSecuritySELinuxTransactionStart,
|
|
|
|
.transactionCommit = virSecuritySELinuxTransactionCommit,
|
|
|
|
.transactionAbort = virSecuritySELinuxTransactionAbort,
|
|
|
|
|
2016-12-14 15:34:49 +00:00
|
|
|
.domainSecurityVerify = virSecuritySELinuxVerify,
|
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
|
|
|
|
2015-12-09 13:34:34 +00:00
|
|
|
.domainSetSecurityDiskLabel = virSecuritySELinuxSetDiskLabel,
|
|
|
|
.domainRestoreSecurityDiskLabel = virSecuritySELinuxRestoreDiskLabel,
|
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
|
|
|
|
2015-12-09 13:34:34 +00:00
|
|
|
.domainSetSecurityImageLabel = virSecuritySELinuxSetImageLabel,
|
|
|
|
.domainRestoreSecurityImageLabel = virSecuritySELinuxRestoreImageLabel,
|
2014-06-23 15:19:25 +00:00
|
|
|
|
2016-08-04 12:55:16 +00:00
|
|
|
.domainSetSecurityMemoryLabel = virSecuritySELinuxSetMemoryLabel,
|
|
|
|
.domainRestoreSecurityMemoryLabel = virSecuritySELinuxRestoreMemoryLabel,
|
|
|
|
|
2015-12-09 13:34:34 +00:00
|
|
|
.domainSetSecurityDaemonSocketLabel = virSecuritySELinuxSetDaemonSocketLabel,
|
|
|
|
.domainSetSecuritySocketLabel = virSecuritySELinuxSetSocketLabel,
|
|
|
|
.domainClearSecuritySocketLabel = virSecuritySELinuxClearSocketLabel,
|
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
|
|
|
|
2015-12-09 13:34:34 +00:00
|
|
|
.domainGenSecurityLabel = virSecuritySELinuxGenLabel,
|
|
|
|
.domainReserveSecurityLabel = virSecuritySELinuxReserveLabel,
|
|
|
|
.domainReleaseSecurityLabel = virSecuritySELinuxReleaseLabel,
|
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
|
|
|
|
2015-12-09 13:34:34 +00:00
|
|
|
.domainGetSecurityProcessLabel = virSecuritySELinuxGetProcessLabel,
|
|
|
|
.domainSetSecurityProcessLabel = virSecuritySELinuxSetProcessLabel,
|
|
|
|
.domainSetSecurityChildProcessLabel = virSecuritySELinuxSetChildProcessLabel,
|
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
|
|
|
|
2015-12-09 13:34:34 +00:00
|
|
|
.domainSetSecurityAllLabel = virSecuritySELinuxSetAllLabel,
|
|
|
|
.domainRestoreSecurityAllLabel = virSecuritySELinuxRestoreAllLabel,
|
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
|
|
|
|
2015-12-09 13:34:34 +00:00
|
|
|
.domainSetSecurityHostdevLabel = virSecuritySELinuxSetHostdevLabel,
|
|
|
|
.domainRestoreSecurityHostdevLabel = virSecuritySELinuxRestoreHostdevLabel,
|
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
|
|
|
|
2012-05-24 15:42:51 +00:00
|
|
|
.domainSetSavedStateLabel = virSecuritySELinuxSetSavedStateLabel,
|
|
|
|
.domainRestoreSavedStateLabel = virSecuritySELinuxRestoreSavedStateLabel,
|
2011-01-23 21:02:42 +00:00
|
|
|
|
2012-05-24 15:42:51 +00:00
|
|
|
.domainSetSecurityImageFDLabel = virSecuritySELinuxSetImageFDLabel,
|
2012-10-15 09:03:49 +00:00
|
|
|
.domainSetSecurityTapFDLabel = virSecuritySELinuxSetTapFDLabel,
|
2012-05-01 14:16:04 +00:00
|
|
|
|
2012-05-24 15:42:51 +00:00
|
|
|
.domainGetSecurityMountOptions = virSecuritySELinuxGetSecurityMountOptions,
|
2013-10-18 12:13:20 +00:00
|
|
|
.getBaseLabel = virSecuritySELinuxGetBaseLabel,
|
2015-08-17 18:07:07 +00:00
|
|
|
|
2016-04-14 07:20:55 +00:00
|
|
|
.domainSetPathLabel = virSecuritySELinuxDomainSetPathLabel,
|
2009-03-03 10:06:49 +00:00
|
|
|
};
|