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
|
|
|
* 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>
|
2019-10-09 14:43:53 +00:00
|
|
|
#include <selinux/label.h>
|
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"
|
2018-09-19 08:06:44 +00:00
|
|
|
#include "security_util.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;
|
|
|
|
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;
|
2020-10-22 17:04:18 +00:00
|
|
|
GHashTable *mcs;
|
2012-11-28 13:54:39 +00:00
|
|
|
bool skipAllLabel;
|
2013-01-23 20:09:04 +00:00
|
|
|
struct selabel_handle *label_handle;
|
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;
|
|
|
|
struct _virSecuritySELinuxCallbackData {
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecurityManager *mgr;
|
|
|
|
virDomainDef *def;
|
2014-11-26 17:35:46 +00:00
|
|
|
};
|
|
|
|
|
2016-12-14 16:11:05 +00:00
|
|
|
typedef struct _virSecuritySELinuxContextItem virSecuritySELinuxContextItem;
|
|
|
|
struct _virSecuritySELinuxContextItem {
|
2017-01-17 11:22:14 +00:00
|
|
|
char *path;
|
|
|
|
char *tcon;
|
2019-02-15 14:36:06 +00:00
|
|
|
bool remember; /* Whether owner remembering should be done for @path/@src */
|
2019-02-15 10:23:29 +00:00
|
|
|
bool restore; /* Whether current operation is 'set' or 'restore' */
|
2016-12-14 16:11:05 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
typedef struct _virSecuritySELinuxContextList virSecuritySELinuxContextList;
|
|
|
|
struct _virSecuritySELinuxContextList {
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecurityManager *manager;
|
|
|
|
virSecuritySELinuxContextItem **items;
|
2016-12-14 16:11:05 +00:00
|
|
|
size_t nItems;
|
2018-11-13 09:57:25 +00:00
|
|
|
bool lock;
|
2016-12-14 16:11:05 +00:00
|
|
|
};
|
|
|
|
|
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
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxRestoreTPMFileLabelInt(virSecurityManager *mgr,
|
|
|
|
virDomainDef *def,
|
|
|
|
virDomainTPMDef *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
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxContextItemFree(virSecuritySELinuxContextItem *item)
|
2017-01-17 11:22:14 +00:00
|
|
|
{
|
|
|
|
if (!item)
|
|
|
|
return;
|
|
|
|
|
2021-02-03 19:40:30 +00:00
|
|
|
g_free(item->path);
|
|
|
|
g_free(item->tcon);
|
|
|
|
g_free(item);
|
2017-01-17 11:22:14 +00:00
|
|
|
}
|
|
|
|
|
2016-12-14 16:11:05 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxContextListAppend(virSecuritySELinuxContextList *list,
|
2016-12-14 16:11:05 +00:00
|
|
|
const char *path,
|
|
|
|
const char *tcon,
|
2019-02-15 14:36:06 +00:00
|
|
|
bool remember,
|
2018-09-25 14:32:47 +00:00
|
|
|
bool restore)
|
2016-12-14 16:11:05 +00:00
|
|
|
{
|
2017-01-17 11:22:14 +00:00
|
|
|
int ret = -1;
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxContextItem *item = NULL;
|
2016-12-14 16:11:05 +00:00
|
|
|
|
2020-09-23 20:05:21 +00:00
|
|
|
item = g_new0(virSecuritySELinuxContextItem, 1);
|
2016-12-14 16:11:05 +00:00
|
|
|
|
2019-10-20 11:49:46 +00:00
|
|
|
item->path = g_strdup(path);
|
|
|
|
item->tcon = g_strdup(tcon);
|
2017-01-17 11:22:14 +00:00
|
|
|
|
2019-02-15 14:36:06 +00:00
|
|
|
item->remember = remember;
|
2018-09-25 14:32:47 +00:00
|
|
|
item->restore = restore;
|
2016-12-14 16:11:05 +00:00
|
|
|
|
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)
|
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxContextList *list = opaque;
|
2016-12-14 16:11:05 +00:00
|
|
|
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]);
|
|
|
|
|
2021-02-03 19:40:30 +00:00
|
|
|
g_free(list->items);
|
2018-09-20 12:22:13 +00:00
|
|
|
virObjectUnref(list->manager);
|
2021-02-03 19:40:30 +00:00
|
|
|
g_free(list);
|
2016-12-14 16:11:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virSecuritySELinuxTransactionAppend:
|
|
|
|
* @path: Path to chown
|
|
|
|
* @tcon: target context
|
2019-02-15 14:36:06 +00:00
|
|
|
* @remember: if the original owner should be recorded/recalled
|
2019-02-15 10:23:29 +00:00
|
|
|
* @restore: if current operation is set or restore
|
2016-12-14 16:11:05 +00:00
|
|
|
*
|
|
|
|
* Appends an entry onto transaction list.
|
2019-02-15 14:36:06 +00:00
|
|
|
* The @remember should be true if caller wishes to record/recall
|
|
|
|
* the original owner of @path/@src.
|
2019-02-15 10:23:29 +00:00
|
|
|
* The @restore should be true if the operation is restoring
|
|
|
|
* seclabel and false otherwise.
|
2016-12-14 16:11:05 +00:00
|
|
|
*
|
|
|
|
* 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,
|
2019-02-15 14:36:06 +00:00
|
|
|
bool remember,
|
2018-09-25 14:32:47 +00:00
|
|
|
bool restore)
|
2016-12-14 16:11:05 +00:00
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxContextList *list;
|
2016-12-14 16:11:05 +00:00
|
|
|
|
|
|
|
list = virThreadLocalGet(&contextList);
|
|
|
|
if (!list)
|
|
|
|
return 0;
|
|
|
|
|
2019-02-15 14:36:06 +00:00
|
|
|
if (virSecuritySELinuxContextListAppend(list, path, tcon,
|
2019-08-22 08:21:11 +00:00
|
|
|
remember, restore) < 0)
|
2016-12-14 16:11:05 +00:00
|
|
|
return -1;
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-09-19 08:06:44 +00:00
|
|
|
static int
|
|
|
|
virSecuritySELinuxRememberLabel(const char *path,
|
2020-07-15 10:32:48 +00:00
|
|
|
const char *con)
|
2018-09-19 08:06:44 +00:00
|
|
|
{
|
|
|
|
return virSecuritySetRememberedLabel(SECURITY_SELINUX_NAME,
|
|
|
|
path, con);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
virSecuritySELinuxRecallLabel(const char *path,
|
2020-07-15 10:32:48 +00:00
|
|
|
char **con)
|
2018-09-19 08:06:44 +00:00
|
|
|
{
|
2019-01-15 10:15:19 +00:00
|
|
|
int rv;
|
|
|
|
|
|
|
|
rv = virSecurityGetRememberedLabel(SECURITY_SELINUX_NAME, path, con);
|
|
|
|
if (rv < 0)
|
|
|
|
return rv;
|
2018-09-19 08:06:44 +00:00
|
|
|
|
2018-12-20 21:30:24 +00:00
|
|
|
if (!*con)
|
2018-09-19 08:06:44 +00:00
|
|
|
return 1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-03-11 07:16:13 +00:00
|
|
|
static int virSecuritySELinuxSetFilecon(virSecurityManager *mgr,
|
2019-08-22 08:25:24 +00:00
|
|
|
const char *path,
|
|
|
|
const char *tcon,
|
|
|
|
bool remember);
|
2016-12-14 16:11:05 +00:00
|
|
|
|
2018-09-25 14:32:47 +00:00
|
|
|
|
2021-03-11 07:16:13 +00:00
|
|
|
static int virSecuritySELinuxRestoreFileLabel(virSecurityManager *mgr,
|
2018-09-19 08:06:44 +00:00
|
|
|
const char *path,
|
|
|
|
bool recall);
|
2018-09-25 14:32:47 +00:00
|
|
|
|
|
|
|
|
2016-12-14 16:11:05 +00:00
|
|
|
/**
|
|
|
|
* 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
|
2019-10-14 12:45:33 +00:00
|
|
|
virSecuritySELinuxTransactionRun(pid_t pid G_GNUC_UNUSED,
|
2016-12-14 16:11:05 +00:00
|
|
|
void *opaque)
|
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxContextList *list = opaque;
|
|
|
|
virSecurityManagerMetadataLockState *state;
|
2018-09-10 09:19:55 +00:00
|
|
|
const char **paths = NULL;
|
|
|
|
size_t npaths = 0;
|
2016-12-14 16:11:05 +00:00
|
|
|
size_t i;
|
2018-09-10 09:19:55 +00:00
|
|
|
int rv;
|
|
|
|
int ret = -1;
|
|
|
|
|
2018-11-13 09:57:25 +00:00
|
|
|
if (list->lock) {
|
2020-09-23 20:05:21 +00:00
|
|
|
paths = g_new0(const char *, list->nItems);
|
2018-09-10 09:19:55 +00:00
|
|
|
|
2018-11-13 09:57:25 +00:00
|
|
|
for (i = 0; i < list->nItems; i++) {
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxContextItem *item = list->items[i];
|
2019-10-01 08:30:05 +00:00
|
|
|
const char *p = item->path;
|
2018-09-10 09:19:55 +00:00
|
|
|
|
2019-10-01 08:30:05 +00:00
|
|
|
if (item->remember)
|
|
|
|
VIR_APPEND_ELEMENT_COPY_INPLACE(paths, npaths, p);
|
2018-11-13 09:57:25 +00:00
|
|
|
}
|
2018-09-10 09:19:55 +00:00
|
|
|
|
2018-10-02 12:47:20 +00:00
|
|
|
if (!(state = virSecurityManagerMetadataLock(list->manager, paths, npaths)))
|
2018-11-13 09:57:25 +00:00
|
|
|
goto cleanup;
|
2020-02-20 14:38:10 +00:00
|
|
|
|
|
|
|
for (i = 0; i < list->nItems; i++) {
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxContextItem *item = list->items[i];
|
2020-02-20 14:38:10 +00:00
|
|
|
size_t j;
|
|
|
|
|
|
|
|
for (j = 0; j < state->nfds; j++) {
|
|
|
|
if (STREQ_NULLABLE(item->path, state->paths[j]))
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* If path wasn't locked, don't try to remember its label. */
|
|
|
|
if (j == state->nfds)
|
|
|
|
item->remember = false;
|
|
|
|
}
|
2018-11-13 09:57:25 +00:00
|
|
|
}
|
2016-12-14 16:11:05 +00:00
|
|
|
|
2018-09-10 09:19:55 +00:00
|
|
|
rv = 0;
|
2016-12-14 16:11:05 +00:00
|
|
|
for (i = 0; i < list->nItems; i++) {
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxContextItem *item = list->items[i];
|
2019-02-15 14:36:06 +00:00
|
|
|
const bool remember = item->remember && list->lock;
|
2016-12-14 16:11:05 +00:00
|
|
|
|
2018-09-25 14:32:47 +00:00
|
|
|
if (!item->restore) {
|
2019-08-22 08:25:24 +00:00
|
|
|
rv = virSecuritySELinuxSetFilecon(list->manager,
|
|
|
|
item->path,
|
|
|
|
item->tcon,
|
|
|
|
remember);
|
2018-09-25 14:32:47 +00:00
|
|
|
} else {
|
|
|
|
rv = virSecuritySELinuxRestoreFileLabel(list->manager,
|
2018-09-19 08:06:44 +00:00
|
|
|
item->path,
|
2019-02-15 14:36:06 +00:00
|
|
|
remember);
|
2018-09-10 09:19:55 +00:00
|
|
|
}
|
2018-09-25 14:32:47 +00:00
|
|
|
|
|
|
|
if (rv < 0)
|
|
|
|
break;
|
2016-12-14 16:11:05 +00:00
|
|
|
}
|
|
|
|
|
2018-09-25 13:46:56 +00:00
|
|
|
for (; rv < 0 && i > 0; i--) {
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxContextItem *item = list->items[i - 1];
|
2019-02-15 14:36:06 +00:00
|
|
|
const bool remember = item->remember && list->lock;
|
2018-09-25 13:46:56 +00:00
|
|
|
|
|
|
|
if (!item->restore) {
|
|
|
|
virSecuritySELinuxRestoreFileLabel(list->manager,
|
|
|
|
item->path,
|
2019-02-15 14:36:06 +00:00
|
|
|
remember);
|
2018-09-25 13:46:56 +00:00
|
|
|
} else {
|
|
|
|
VIR_WARN("Ignoring failed restore attempt on %s", item->path);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-10-02 12:47:20 +00:00
|
|
|
if (list->lock)
|
|
|
|
virSecurityManagerMetadataUnlock(list->manager, &state);
|
2018-09-10 09:19:55 +00:00
|
|
|
|
|
|
|
if (rv < 0)
|
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
cleanup:
|
|
|
|
VIR_FREE(paths);
|
|
|
|
return ret;
|
2016-12-14 16:11:05 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
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
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxMCSAdd(virSecurityManager *mgr,
|
2012-05-24 16:22:29 +00:00
|
|
|
const char *mcs)
|
2009-03-03 10:06:49 +00:00
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxData *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
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxMCSRemove(virSecurityManager *mgr,
|
2012-05-24 16:22:29 +00:00
|
|
|
const char *mcs)
|
2009-03-03 10:06:49 +00:00
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxData *data = virSecurityManagerGetPrivateData(mgr);
|
2012-05-24 16:22:29 +00:00
|
|
|
|
|
|
|
virHashRemoveEntry(data->mcs, mcs);
|
2009-03-03 10:06:49 +00:00
|
|
|
}
|
|
|
|
|
2012-08-09 16:43:12 +00:00
|
|
|
|
|
|
|
static char *
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxMCSFind(virSecurityManager *mgr,
|
2013-03-13 17:41:19 +00:00
|
|
|
const char *sens,
|
|
|
|
int catMin,
|
|
|
|
int catMax)
|
2012-08-09 16:43:12 +00:00
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxData *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) {
|
2019-10-22 13:26:14 +00:00
|
|
|
mcs = g_strdup_printf("%s:c%d", sens, catMin + c1);
|
2013-03-13 17:41:19 +00:00
|
|
|
} else {
|
|
|
|
if (c1 > c2) {
|
|
|
|
int t = c1;
|
|
|
|
c1 = c2;
|
|
|
|
c2 = t;
|
|
|
|
}
|
2019-10-22 13:26:14 +00:00
|
|
|
mcs = g_strdup_printf("%s:c%d,c%d", sens, catMin + c1, catMin + c2);
|
2013-03-13 17:41:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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)
|
|
|
|
{
|
2020-07-15 10:32:48 +00:00
|
|
|
char *ourSecContext = NULL;
|
2012-08-10 13:27:51 +00:00
|
|
|
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
|
|
|
|
2019-10-20 11:49:46 +00:00
|
|
|
*sens = g_strdup(contextRange);
|
2012-08-10 13:27:51 +00:00
|
|
|
|
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 *
|
2020-07-15 10:32:48 +00:00
|
|
|
virSecuritySELinuxContextAddRange(char *src,
|
|
|
|
char *dst)
|
2012-10-15 09:03:49 +00:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2019-10-18 11:27:03 +00:00
|
|
|
ret = g_strdup(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;
|
2020-07-15 10:32:48 +00:00
|
|
|
char *ourSecContext = NULL;
|
2012-08-09 16:20:25 +00:00
|
|
|
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;
|
|
|
|
}
|
2019-10-20 11:49:46 +00:00
|
|
|
ret = g_strdup(str);
|
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
|
|
|
|
2009-03-03 10:06:49 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxLXCInitialize(virSecurityManager *mgr)
|
2012-05-11 09:54:31 +00:00
|
|
|
{
|
2019-10-15 12:47:50 +00:00
|
|
|
g_autoptr(virConf) selinux_conf = NULL;
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxData *data = virSecurityManagerGetPrivateData(mgr);
|
2012-05-11 09:54:31 +00:00
|
|
|
|
2012-11-28 13:54:39 +00:00
|
|
|
data->skipAllLabel = true;
|
|
|
|
|
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-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
|
|
|
|
2020-10-20 16:43:20 +00:00
|
|
|
if (!(data->mcs = virHashNew(NULL)))
|
2012-05-24 16:22:29 +00:00
|
|
|
goto error;
|
|
|
|
|
2012-05-11 09:54:31 +00:00
|
|
|
return 0;
|
|
|
|
|
2014-03-25 06:57:22 +00:00
|
|
|
error:
|
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;
|
2012-05-11 09:54:31 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxQEMUInitialize(virSecurityManager *mgr)
|
2009-03-03 10:06:49 +00:00
|
|
|
{
|
2012-05-11 09:43:30 +00:00
|
|
|
char *ptr;
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxData *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
|
|
|
data->label_handle = selabel_open(SELABEL_CTX_FILE, NULL, 0);
|
|
|
|
if (!data->label_handle) {
|
|
|
|
virReportSystemError(errno, "%s",
|
|
|
|
_("cannot open SELinux label_handle"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2020-01-14 10:43:37 +00:00
|
|
|
ptr = strchr(data->domain_context, '\n');
|
|
|
|
if (ptr) {
|
2012-05-11 09:43:30 +00:00
|
|
|
*ptr = '\0';
|
2012-12-12 11:47:19 +00:00
|
|
|
ptr++;
|
|
|
|
if (*ptr != '\0') {
|
2019-10-20 11:49:46 +00:00
|
|
|
data->alt_domain_context = g_strdup(ptr);
|
2020-01-14 10:43:37 +00:00
|
|
|
ptr = strchr(data->alt_domain_context, '\n');
|
|
|
|
if (ptr)
|
2012-12-12 11:47:19 +00:00
|
|
|
*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
|
|
|
}
|
|
|
|
|
2020-01-14 10:43:37 +00:00
|
|
|
ptr = strchr(data->file_context, '\n');
|
|
|
|
if (ptr) {
|
2009-07-03 10:26:37 +00:00
|
|
|
*ptr = '\0';
|
2019-10-20 11:49:46 +00:00
|
|
|
data->content_context = g_strdup(ptr + 1);
|
2020-01-14 10:43:37 +00:00
|
|
|
ptr = strchr(data->content_context, '\n');
|
|
|
|
if (ptr)
|
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);
|
|
|
|
|
2020-10-20 16:43:20 +00:00
|
|
|
if (!(data->mcs = virHashNew(NULL)))
|
2012-05-24 16:22:29 +00:00
|
|
|
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
|
|
|
selabel_close(data->label_handle);
|
2013-10-01 11:15:12 +00:00
|
|
|
data->label_handle = NULL;
|
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
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxInitialize(virSecurityManager *mgr)
|
2012-05-11 09:54:31 +00:00
|
|
|
{
|
2019-09-11 09:20:53 +00:00
|
|
|
VIR_DEBUG("SELinuxInitialize %s", virSecurityManagerGetVirtDriver(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;
|
|
|
|
}
|
|
|
|
|
2019-09-11 09:20:53 +00:00
|
|
|
if (STREQ(virSecurityManagerGetVirtDriver(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
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxGenLabel(virSecurityManager *mgr,
|
|
|
|
virDomainDef *def)
|
2009-03-03 10:06:49 +00:00
|
|
|
{
|
|
|
|
int rc = -1;
|
2011-06-24 09:21:33 +00:00
|
|
|
char *mcs = NULL;
|
|
|
|
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;
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecurityLabelDef *seclabel;
|
|
|
|
virSecuritySELinuxData *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);
|
|
|
|
|
2019-09-11 09:20:53 +00:00
|
|
|
VIR_DEBUG("label=%s", virSecurityManagerGetVirtDriver(mgr));
|
2012-08-15 22:10:37 +00:00
|
|
|
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;
|
|
|
|
}
|
2019-10-20 11:49:46 +00:00
|
|
|
mcs = g_strdup(range);
|
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;
|
|
|
|
|
2019-10-20 11:49:46 +00:00
|
|
|
mcs = g_strdup(sens);
|
2014-02-05 17:34:51 +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;
|
|
|
|
|
|
|
|
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
|
|
|
|
2019-10-18 13:08:21 +00:00
|
|
|
if (!seclabel->model)
|
|
|
|
seclabel->model = g_strdup(SECURITY_SELINUX_NAME);
|
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);
|
|
|
|
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
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxReserveLabel(virSecurityManager *mgr,
|
|
|
|
virDomainDef *def,
|
2015-12-09 13:34:34 +00:00
|
|
|
pid_t pid)
|
2009-06-12 11:38:50 +00:00
|
|
|
{
|
2020-07-15 10:32:48 +00:00
|
|
|
char *pctx;
|
2009-06-12 11:38:50 +00:00
|
|
|
context_t ctx = NULL;
|
|
|
|
const char *mcs;
|
2012-05-24 15:52:18 +00:00
|
|
|
int rv;
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecurityLabelDef *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;
|
|
|
|
|
2020-06-24 08:57:22 +00:00
|
|
|
if (virtDriver && STREQ(virtDriver, "LXC") &&
|
|
|
|
!virFileExists(selinux_lxc_contexts_path())) {
|
|
|
|
return SECURITY_DRIVER_DISABLE;
|
2012-05-16 13:18:25 +00:00
|
|
|
}
|
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
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxDriverOpen(virSecurityManager *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
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxDriverClose(virSecurityManager *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
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxData *data = virSecurityManagerGetPrivateData(mgr);
|
2012-05-11 09:43:30 +00:00
|
|
|
|
|
|
|
if (!data)
|
|
|
|
return 0;
|
|
|
|
|
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
|
|
|
|
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 *
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxGetModel(virSecurityManager *mgr G_GNUC_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 *
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxGetDOI(virSecurityManager *mgr G_GNUC_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
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxTransactionStart(virSecurityManager *mgr)
|
2016-12-14 16:11:05 +00:00
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxContextList *list;
|
2016-12-14 16:11:05 +00:00
|
|
|
|
|
|
|
list = virThreadLocalGet(&contextList);
|
|
|
|
if (list) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("Another relabel transaction is already started"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2020-09-23 20:05:21 +00:00
|
|
|
list = g_new0(virSecuritySELinuxContextList, 1);
|
2016-12-14 16:11:05 +00:00
|
|
|
|
2018-09-20 12:22:13 +00:00
|
|
|
list->manager = virObjectRef(mgr);
|
2016-12-14 16:11:05 +00:00
|
|
|
|
|
|
|
if (virThreadLocalSet(&contextList, list) < 0) {
|
|
|
|
virReportSystemError(errno, "%s",
|
|
|
|
_("Unable to set thread local variable"));
|
2018-09-20 12:22:13 +00:00
|
|
|
virSecuritySELinuxContextListFree(list);
|
2016-12-14 16:11:05 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virSecuritySELinuxTransactionCommit:
|
|
|
|
* @mgr: security manager
|
|
|
|
* @pid: domain's PID
|
2018-11-13 09:57:25 +00:00
|
|
|
* @lock: lock and unlock paths that are relabeled
|
2016-12-14 16:11:05 +00:00
|
|
|
*
|
2018-09-05 11:27:50 +00:00
|
|
|
* If @pis is not -1 then enter the @pid namespace (usually @pid refers
|
|
|
|
* to a domain) and perform all the sefilecon()-s on the list. If @pid
|
|
|
|
* is -1 then the transaction is performed in the namespace of the
|
|
|
|
* caller.
|
|
|
|
*
|
2018-11-13 09:57:25 +00:00
|
|
|
* If @lock is true then all the paths that transaction would
|
|
|
|
* touch are locked before and unlocked after it is done so.
|
|
|
|
*
|
2018-09-05 11:27:50 +00:00
|
|
|
* 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.
|
2016-12-14 16:11:05 +00:00
|
|
|
*
|
|
|
|
* Returns: 0 on success,
|
|
|
|
* -1 otherwise.
|
|
|
|
*/
|
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxTransactionCommit(virSecurityManager *mgr G_GNUC_UNUSED,
|
2018-11-13 09:57:25 +00:00
|
|
|
pid_t pid,
|
|
|
|
bool lock)
|
2016-12-14 16:11:05 +00:00
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxContextList *list;
|
2018-11-13 09:57:25 +00:00
|
|
|
int rc;
|
2018-11-13 15:45:52 +00:00
|
|
|
int ret = -1;
|
2016-12-14 16:11:05 +00:00
|
|
|
|
|
|
|
list = virThreadLocalGet(&contextList);
|
2018-11-13 16:32:29 +00:00
|
|
|
if (!list) {
|
|
|
|
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
|
|
|
|
_("No transaction is set"));
|
|
|
|
return -1;
|
|
|
|
}
|
2016-12-14 16:11:05 +00:00
|
|
|
|
|
|
|
if (virThreadLocalSet(&contextList, NULL) < 0) {
|
|
|
|
virReportSystemError(errno, "%s",
|
|
|
|
_("Unable to clear thread local variable"));
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
2018-11-13 09:57:25 +00:00
|
|
|
list->lock = lock;
|
|
|
|
|
2020-03-18 09:18:46 +00:00
|
|
|
if (pid != -1) {
|
|
|
|
rc = virProcessRunInMountNamespace(pid,
|
|
|
|
virSecuritySELinuxTransactionRun,
|
|
|
|
list);
|
|
|
|
if (rc < 0) {
|
|
|
|
if (virGetLastErrorCode() == VIR_ERR_SYSTEM_ERROR)
|
|
|
|
pid = -1;
|
|
|
|
else
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-11-13 09:57:25 +00:00
|
|
|
if (pid == -1) {
|
|
|
|
if (lock)
|
|
|
|
rc = virProcessRunInFork(virSecuritySELinuxTransactionRun, list);
|
|
|
|
else
|
|
|
|
rc = virSecuritySELinuxTransactionRun(pid, list);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (rc < 0)
|
2016-12-14 16:11:05 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
ret = 0;
|
|
|
|
cleanup:
|
|
|
|
virSecuritySELinuxContextListFree(list);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* virSecuritySELinuxTransactionAbort:
|
|
|
|
* @mgr: security manager
|
|
|
|
*
|
|
|
|
* Cancels and frees any out standing transaction.
|
|
|
|
*/
|
|
|
|
static void
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxTransactionAbort(virSecurityManager *mgr G_GNUC_UNUSED)
|
2016-12-14 16:11:05 +00:00
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxContextList *list;
|
2016-12-14 16:11:05 +00:00
|
|
|
|
|
|
|
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
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxGetProcessLabel(virSecurityManager *mgr G_GNUC_UNUSED,
|
|
|
|
virDomainDef *def G_GNUC_UNUSED,
|
2015-12-09 13:34:34 +00:00
|
|
|
pid_t pid,
|
|
|
|
virSecurityLabelPtr sec)
|
2009-03-03 10:06:49 +00:00
|
|
|
{
|
2020-07-15 10:32:48 +00:00
|
|
|
char *ctx;
|
2009-03-03 10:06:49 +00:00
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2020-12-26 19:04:49 +00:00
|
|
|
if (virStrcpy(sec->label, ctx, VIR_SECURITY_LABEL_BUFLEN) < 0) {
|
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;
|
|
|
|
}
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2019-08-21 15:50:55 +00:00
|
|
|
/**
|
|
|
|
* virSecuritySELinuxSetFileconImpl:
|
|
|
|
* @path: path to the file to set context on
|
|
|
|
* @tcon: target context to set
|
|
|
|
* @privileged: whether running as privileged user
|
|
|
|
*
|
|
|
|
* Set @tcon SELinux context on @path. If unable to do so, check SELinux
|
|
|
|
* configuration and produce sensible error message suggesting solution.
|
|
|
|
* It may happen that setting context fails but hypervisor will be able to
|
|
|
|
* open the @path successfully. This is because some file systems don't
|
|
|
|
* support SELinux, are RO, or the @path had the correct context from the
|
|
|
|
* start. If that is the case, a positive one is returned.
|
|
|
|
*
|
|
|
|
* Returns: 0 if context was set successfully
|
|
|
|
* 1 if setting the context failed in a non-critical fashion
|
|
|
|
* -1 in case of error
|
|
|
|
*/
|
2009-03-03 10:06:49 +00:00
|
|
|
static int
|
2019-08-21 15:50:55 +00:00
|
|
|
virSecuritySELinuxSetFileconImpl(const char *path,
|
|
|
|
const char *tcon,
|
|
|
|
bool privileged)
|
2009-03-03 10:06:49 +00:00
|
|
|
{
|
2016-12-14 16:11:05 +00:00
|
|
|
/* Be aware that this function might run in a separate process.
|
|
|
|
* Therefore, any driver state changes would be thrown away. */
|
|
|
|
|
2009-07-03 10:26:37 +00:00
|
|
|
VIR_INFO("Setting SELinux context on '%s' to '%s'", path, tcon);
|
|
|
|
|
2019-10-09 14:43:53 +00:00
|
|
|
if (setfilecon_raw(path, (const char *)tcon) < 0) {
|
2009-08-21 14:57:29 +00:00
|
|
|
int setfilecon_errno = errno;
|
|
|
|
|
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
|
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. */
|
2019-08-29 15:32:03 +00:00
|
|
|
if (security_getenforce() == 1 &&
|
|
|
|
(setfilecon_errno != EPERM || privileged)) {
|
|
|
|
virReportSystemError(setfilecon_errno,
|
|
|
|
_("unable to set security context '%s' on '%s'"),
|
|
|
|
tcon, path);
|
2009-08-21 14:57:29 +00:00
|
|
|
return -1;
|
2019-08-29 15:32:03 +00:00
|
|
|
}
|
|
|
|
VIR_WARN("unable to set security context '%s' on '%s' (errno %d)",
|
|
|
|
tcon, path, setfilecon_errno);
|
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);
|
|
|
|
}
|
2009-08-21 14:57:29 +00:00
|
|
|
}
|
2019-08-21 15:50:55 +00:00
|
|
|
|
|
|
|
return 1;
|
2009-03-03 10:06:49 +00:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2018-09-10 08:10:25 +00:00
|
|
|
|
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxSetFilecon(virSecurityManager *mgr,
|
2019-08-22 08:25:24 +00:00
|
|
|
const char *path,
|
|
|
|
const char *tcon,
|
|
|
|
bool remember)
|
2018-09-10 08:10:25 +00:00
|
|
|
{
|
2018-09-25 15:07:23 +00:00
|
|
|
bool privileged = virSecurityManagerGetPrivileged(mgr);
|
2020-07-15 10:32:48 +00:00
|
|
|
char *econ = NULL;
|
2018-09-19 08:06:44 +00:00
|
|
|
int refcount;
|
2018-09-10 08:10:25 +00:00
|
|
|
int rc;
|
2019-08-21 08:46:27 +00:00
|
|
|
bool rollback = false;
|
2018-09-19 08:06:44 +00:00
|
|
|
int ret = -1;
|
2018-09-10 08:10:25 +00:00
|
|
|
|
2019-02-15 14:36:06 +00:00
|
|
|
if ((rc = virSecuritySELinuxTransactionAppend(path, tcon,
|
2019-08-22 08:21:11 +00:00
|
|
|
remember, false)) < 0)
|
2018-09-10 08:10:25 +00:00
|
|
|
return -1;
|
|
|
|
else if (rc > 0)
|
|
|
|
return 0;
|
|
|
|
|
2018-09-19 08:06:44 +00:00
|
|
|
if (remember) {
|
|
|
|
if (getfilecon_raw(path, &econ) < 0 &&
|
|
|
|
errno != ENOTSUP && errno != ENODATA) {
|
|
|
|
virReportSystemError(errno,
|
|
|
|
_("unable to get SELinux context of %s"),
|
|
|
|
path);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (econ) {
|
|
|
|
refcount = virSecuritySELinuxRememberLabel(path, econ);
|
2019-08-21 08:46:27 +00:00
|
|
|
if (refcount > 0)
|
|
|
|
rollback = true;
|
2019-01-15 10:15:19 +00:00
|
|
|
if (refcount == -2) {
|
|
|
|
/* Not supported. Don't error though. */
|
|
|
|
} else if (refcount < 0) {
|
2018-09-19 08:06:44 +00:00
|
|
|
goto cleanup;
|
|
|
|
} else if (refcount > 1) {
|
|
|
|
/* Refcount is greater than 1 which means that there
|
|
|
|
* is @refcount domains using the @path. Do not
|
|
|
|
* change the label (as it would almost certainly
|
|
|
|
* cause the other domains to lose access to the
|
2019-08-21 08:46:27 +00:00
|
|
|
* @path). However, the refcounter was
|
|
|
|
* incremented in XATTRs so decrease it. */
|
2018-09-19 08:06:44 +00:00
|
|
|
if (STRNEQ(econ, tcon)) {
|
|
|
|
virReportError(VIR_ERR_OPERATION_INVALID,
|
|
|
|
_("Setting different SELinux label on %s "
|
|
|
|
"which is already in use"), path);
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-22 14:34:02 +00:00
|
|
|
rc = virSecuritySELinuxSetFileconImpl(path, tcon, privileged);
|
|
|
|
if (rc < 0)
|
2019-08-21 08:46:27 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
2019-08-22 14:34:02 +00:00
|
|
|
/* Do not try restoring the label if it was not changed
|
|
|
|
* (setting it failed in a non-critical fashion) */
|
|
|
|
if (rc == 0)
|
|
|
|
rollback = false;
|
|
|
|
|
2019-08-21 08:46:27 +00:00
|
|
|
ret = 0;
|
|
|
|
cleanup:
|
2019-08-22 14:34:02 +00:00
|
|
|
if (rollback) {
|
2018-09-25 15:07:23 +00:00
|
|
|
virErrorPtr origerr;
|
|
|
|
|
|
|
|
virErrorPreserveLast(&origerr);
|
|
|
|
/* Try to restore the label. This is done so that XATTRs
|
|
|
|
* are left in the same state as when the control entered
|
|
|
|
* this function. However, if our attempt fails, there's
|
|
|
|
* not much we can do. XATTRs refcounting is fubar'ed and
|
|
|
|
* the only option we have is warn users. */
|
|
|
|
if (virSecuritySELinuxRestoreFileLabel(mgr, path, remember) < 0)
|
|
|
|
VIR_WARN("Unable to restore label on '%s'. "
|
|
|
|
"XATTRs might have been left in inconsistent state.",
|
|
|
|
path);
|
|
|
|
|
|
|
|
virErrorRestore(&origerr);
|
2018-09-19 08:06:44 +00:00
|
|
|
|
2019-08-21 08:46:27 +00:00
|
|
|
}
|
2018-09-19 08:06:44 +00:00
|
|
|
freecon(econ);
|
|
|
|
return ret;
|
2018-09-10 08:10:25 +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
|
|
|
{
|
|
|
|
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;
|
|
|
|
|
|
|
|
/* 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
|
2021-03-11 07:16:13 +00:00
|
|
|
getContext(virSecurityManager *mgr G_GNUC_UNUSED,
|
2020-07-15 10:32:48 +00:00
|
|
|
const char *newpath, mode_t mode, char **fcon)
|
2010-12-15 00:07:52 +00:00
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxData *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
|
|
|
}
|
|
|
|
|
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
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxRestoreFileLabel(virSecurityManager *mgr,
|
2018-09-19 08:06:44 +00:00
|
|
|
const char *path,
|
|
|
|
bool recall)
|
2009-03-03 10:06:49 +00:00
|
|
|
{
|
2018-09-10 08:10:25 +00:00
|
|
|
bool privileged = virSecurityManagerGetPrivileged(mgr);
|
2009-03-17 11:35:40 +00:00
|
|
|
struct stat buf;
|
2020-07-15 10:32:48 +00:00
|
|
|
char *fcon = NULL;
|
2009-03-17 11:35:40 +00:00
|
|
|
char *newpath = NULL;
|
2018-09-10 08:10:25 +00:00
|
|
|
int rc;
|
2018-09-10 07:55:51 +00:00
|
|
|
int ret = -1;
|
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,
|
2020-02-26 17:57:34 +00:00
|
|
|
g_strerror(errno));
|
2018-09-10 07:45:56 +00:00
|
|
|
goto cleanup;
|
2009-03-03 10:06:49 +00:00
|
|
|
}
|
2009-03-17 11:35:40 +00:00
|
|
|
|
2019-02-15 14:36:06 +00:00
|
|
|
if ((rc = virSecuritySELinuxTransactionAppend(path, NULL,
|
2019-08-22 08:21:11 +00:00
|
|
|
recall, true)) < 0) {
|
2018-12-20 21:27:40 +00:00
|
|
|
goto cleanup;
|
|
|
|
} else if (rc > 0) {
|
|
|
|
ret = 0;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2018-09-10 08:10:25 +00:00
|
|
|
|
2018-09-19 08:06:44 +00:00
|
|
|
if (recall) {
|
2019-01-15 10:15:19 +00:00
|
|
|
rc = virSecuritySELinuxRecallLabel(newpath, &fcon);
|
|
|
|
if (rc == -2) {
|
|
|
|
/* Not supported. Lookup the default label below. */
|
|
|
|
} else if (rc < 0) {
|
2018-09-19 08:06:44 +00:00
|
|
|
goto cleanup;
|
|
|
|
} else if (rc > 0) {
|
|
|
|
ret = 0;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
2019-01-15 10:15:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!recall || rc == -2) {
|
2018-09-19 08:06:44 +00:00
|
|
|
if (stat(newpath, &buf) != 0) {
|
|
|
|
VIR_WARN("cannot stat %s: %s", newpath,
|
2020-02-26 17:57:34 +00:00
|
|
|
g_strerror(errno));
|
2018-09-19 08:06:44 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (getContext(mgr, newpath, buf.st_mode, &fcon) < 0) {
|
|
|
|
/* Any user created path likely does not have a default label,
|
|
|
|
* which makes this an expected non error
|
|
|
|
*/
|
|
|
|
VIR_WARN("cannot lookup default selinux label for %s", newpath);
|
|
|
|
ret = 0;
|
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-21 15:50:55 +00:00
|
|
|
if (virSecuritySELinuxSetFileconImpl(newpath, fcon, privileged) < 0)
|
2018-09-10 07:55:51 +00:00
|
|
|
goto cleanup;
|
|
|
|
|
|
|
|
ret = 0;
|
2018-09-10 07:45:56 +00:00
|
|
|
cleanup:
|
2010-11-24 21:09:58 +00:00
|
|
|
freecon(fcon);
|
2009-03-17 11:35:40 +00:00
|
|
|
VIR_FREE(newpath);
|
2018-09-10 07:55:51 +00:00
|
|
|
return ret;
|
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
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxSetInputLabel(virSecurityManager *mgr,
|
|
|
|
virDomainDef *def,
|
|
|
|
virDomainInputDef *input)
|
2015-11-20 07:25:41 +00:00
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecurityLabelDef *seclabel;
|
2015-11-20 07:25:41 +00:00
|
|
|
|
|
|
|
seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
|
|
|
|
if (seclabel == NULL)
|
|
|
|
return 0;
|
|
|
|
|
2018-04-25 12:42:34 +00:00
|
|
|
switch ((virDomainInputType)input->type) {
|
2015-11-20 07:25:41 +00:00
|
|
|
case VIR_DOMAIN_INPUT_TYPE_PASSTHROUGH:
|
2021-05-21 11:01:07 +00:00
|
|
|
case VIR_DOMAIN_INPUT_TYPE_EVDEV:
|
2015-11-20 07:25:41 +00:00
|
|
|
if (virSecuritySELinuxSetFilecon(mgr, input->source.evdev,
|
2019-02-15 14:36:06 +00:00
|
|
|
seclabel->imagelabel, true) < 0)
|
2015-11-20 07:25:41 +00:00
|
|
|
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
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxRestoreInputLabel(virSecurityManager *mgr,
|
|
|
|
virDomainDef *def,
|
|
|
|
virDomainInputDef *input)
|
2015-11-20 07:25:41 +00:00
|
|
|
{
|
|
|
|
int rc = 0;
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecurityLabelDef *seclabel;
|
2015-11-20 07:25:41 +00:00
|
|
|
|
|
|
|
seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
|
|
|
|
if (seclabel == NULL)
|
|
|
|
return 0;
|
|
|
|
|
2018-04-25 12:42:34 +00:00
|
|
|
switch ((virDomainInputType)input->type) {
|
2015-11-20 07:25:41 +00:00
|
|
|
case VIR_DOMAIN_INPUT_TYPE_PASSTHROUGH:
|
2021-05-21 11:01:07 +00:00
|
|
|
case VIR_DOMAIN_INPUT_TYPE_EVDEV:
|
2019-02-15 14:36:06 +00:00
|
|
|
rc = virSecuritySELinuxRestoreFileLabel(mgr, input->source.evdev, true);
|
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
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxSetMemoryLabel(virSecurityManager *mgr,
|
|
|
|
virDomainDef *def,
|
|
|
|
virDomainMemoryDef *mem)
|
2016-08-04 12:04:38 +00:00
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecurityLabelDef *seclabel;
|
2016-08-04 12:04:38 +00:00
|
|
|
|
2020-10-31 20:24:08 +00:00
|
|
|
switch (mem->model) {
|
2016-08-04 12:04:38 +00:00
|
|
|
case VIR_DOMAIN_MEMORY_MODEL_NVDIMM:
|
2020-12-09 15:33:20 +00:00
|
|
|
case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_PMEM:
|
2016-08-04 12:04:38 +00:00
|
|
|
seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
|
|
|
|
if (!seclabel || !seclabel->relabel)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (virSecuritySELinuxSetFilecon(mgr, mem->nvdimmPath,
|
2019-02-15 14:36:06 +00:00
|
|
|
seclabel->imagelabel, true) < 0)
|
2016-08-04 12:04:38 +00:00
|
|
|
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
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxRestoreMemoryLabel(virSecurityManager *mgr,
|
|
|
|
virDomainDef *def,
|
|
|
|
virDomainMemoryDef *mem)
|
2016-08-04 12:04:38 +00:00
|
|
|
{
|
|
|
|
int ret = -1;
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecurityLabelDef *seclabel;
|
2016-08-04 12:04:38 +00:00
|
|
|
|
2020-10-31 20:24:08 +00:00
|
|
|
switch (mem->model) {
|
2016-08-04 12:04:38 +00:00
|
|
|
case VIR_DOMAIN_MEMORY_MODEL_NVDIMM:
|
2020-12-09 15:33:20 +00:00
|
|
|
case VIR_DOMAIN_MEMORY_MODEL_VIRTIO_PMEM:
|
2016-08-04 12:04:38 +00:00
|
|
|
seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
|
|
|
|
if (!seclabel || !seclabel->relabel)
|
|
|
|
return 0;
|
|
|
|
|
2019-02-15 14:36:06 +00:00
|
|
|
ret = virSecuritySELinuxRestoreFileLabel(mgr, mem->nvdimmPath, true);
|
2016-08-04 12:04:38 +00:00
|
|
|
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
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxSetTPMFileLabel(virSecurityManager *mgr,
|
|
|
|
virDomainDef *def,
|
|
|
|
virDomainTPMDef *tpm)
|
2013-04-12 20:55:46 +00:00
|
|
|
{
|
|
|
|
int rc;
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecurityLabelDef *seclabel;
|
2013-04-12 20:55:46 +00:00
|
|
|
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;
|
2019-10-01 08:32:26 +00:00
|
|
|
rc = virSecuritySELinuxSetFilecon(mgr, tpmdev, seclabel->imagelabel, false);
|
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,
|
2019-10-01 08:32:26 +00:00
|
|
|
seclabel->imagelabel, false);
|
2013-04-12 20:55:46 +00:00
|
|
|
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;
|
2017-04-04 16:22:31 +00:00
|
|
|
case VIR_DOMAIN_TPM_TYPE_EMULATOR:
|
2017-04-04 16:22:31 +00:00
|
|
|
tpmdev = tpm->data.emulator.source.data.nix.path;
|
2019-10-01 08:32:26 +00:00
|
|
|
rc = virSecuritySELinuxSetFilecon(mgr, tpmdev, seclabel->imagelabel, false);
|
2017-04-04 16:22:31 +00:00
|
|
|
if (rc < 0)
|
|
|
|
return -1;
|
|
|
|
break;
|
2013-04-12 20:55:46 +00:00
|
|
|
case VIR_DOMAIN_TPM_TYPE_LAST:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxRestoreTPMFileLabelInt(virSecurityManager *mgr,
|
|
|
|
virDomainDef *def,
|
|
|
|
virDomainTPMDef *tpm)
|
2013-04-12 20:55:46 +00:00
|
|
|
{
|
|
|
|
int rc = 0;
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecurityLabelDef *seclabel;
|
2013-04-12 20:55:46 +00:00
|
|
|
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;
|
2019-10-01 08:32:26 +00:00
|
|
|
rc = virSecuritySELinuxRestoreFileLabel(mgr, tpmdev, false);
|
2013-04-12 20:55:46 +00:00
|
|
|
|
|
|
|
if ((cancel_path = virTPMCreateCancelPath(tpmdev)) != NULL) {
|
2019-10-01 08:32:26 +00:00
|
|
|
if (virSecuritySELinuxRestoreFileLabel(mgr, cancel_path, false) < 0)
|
2013-04-12 20:55:46 +00:00
|
|
|
rc = -1;
|
|
|
|
VIR_FREE(cancel_path);
|
|
|
|
}
|
|
|
|
break;
|
2017-04-04 16:22:31 +00:00
|
|
|
case VIR_DOMAIN_TPM_TYPE_EMULATOR:
|
2017-04-04 16:22:31 +00:00
|
|
|
/* swtpm will have removed the Unix socket upon termination */
|
2013-04-12 20:55:46 +00:00
|
|
|
case VIR_DOMAIN_TPM_TYPE_LAST:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-08-14 13:23:11 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxRestoreImageLabelSingle(virSecurityManager *mgr,
|
|
|
|
virDomainDef *def,
|
|
|
|
virStorageSource *src,
|
2019-10-05 23:45:21 +00:00
|
|
|
bool migrated)
|
2009-08-14 13:23:11 +00:00
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecurityLabelDef *seclabel;
|
|
|
|
virSecurityDeviceLabelDef *disk_seclabel;
|
2019-06-27 09:17:52 +00:00
|
|
|
g_autofree char *vfioGroupDev = NULL;
|
|
|
|
const char *path = src->path;
|
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 &&
|
2017-10-12 17:27:40 +00:00
|
|
|
!virStorageSourceHasBacking(src))
|
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) {
|
2019-06-27 09:17:52 +00:00
|
|
|
int rc = 1;
|
|
|
|
|
|
|
|
if (virStorageSourceIsLocalStorage(src)) {
|
|
|
|
if (!src->path)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if ((rc = virFileIsSharedFS(src->path)) < 0)
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
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 == 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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-27 09:17:52 +00:00
|
|
|
/* This is not very clean. But so far we don't have NVMe
|
|
|
|
* storage pool backend so that its chownCallback would be
|
|
|
|
* called. And this place looks least offensive. */
|
|
|
|
if (src->type == VIR_STORAGE_TYPE_NVME) {
|
|
|
|
const virStorageSourceNVMeDef *nvme = src->nvme;
|
|
|
|
|
|
|
|
if (!(vfioGroupDev = virPCIDeviceAddressGetIOMMUGroupDev(&nvme->pciAddr)))
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
/* Ideally, we would check if there is not another PCI
|
|
|
|
* device within domain def that is in the same IOMMU
|
|
|
|
* group. But we're not doing that for hostdevs yet. */
|
|
|
|
path = vfioGroupDev;
|
|
|
|
}
|
|
|
|
|
|
|
|
return virSecuritySELinuxRestoreFileLabel(mgr, path, true);
|
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
|
|
|
|
2019-10-05 23:45:21 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxRestoreImageLabelInt(virSecurityManager *mgr,
|
|
|
|
virDomainDef *def,
|
|
|
|
virStorageSource *src,
|
2019-10-05 23:45:21 +00:00
|
|
|
bool migrated)
|
|
|
|
{
|
|
|
|
if (virSecuritySELinuxRestoreImageLabelSingle(mgr, def, src, migrated) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-06-23 15:19:25 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxRestoreImageLabel(virSecurityManager *mgr,
|
|
|
|
virDomainDef *def,
|
|
|
|
virStorageSource *src,
|
2019-10-14 12:45:33 +00:00
|
|
|
virSecurityDomainImageLabelFlags flags G_GNUC_UNUSED)
|
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
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxSetImageLabelInternal(virSecurityManager *mgr,
|
|
|
|
virDomainDef *def,
|
|
|
|
virStorageSource *src,
|
|
|
|
virStorageSource *parent,
|
2020-02-27 10:06:22 +00:00
|
|
|
bool isChainTop)
|
2010-06-15 15:40:47 +00:00
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxData *data = virSecurityManagerGetPrivateData(mgr);
|
|
|
|
virSecurityLabelDef *secdef;
|
|
|
|
virSecurityDeviceLabelDef *disk_seclabel;
|
|
|
|
virSecurityDeviceLabelDef *parent_seclabel = NULL;
|
2019-10-05 14:24:44 +00:00
|
|
|
char *use_label = NULL;
|
2019-02-15 10:37:03 +00:00
|
|
|
bool remember;
|
2019-06-27 09:17:52 +00:00
|
|
|
g_autofree char *vfioGroupDev = NULL;
|
|
|
|
const char *path = src->path;
|
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;
|
|
|
|
|
2019-02-15 10:37:03 +00:00
|
|
|
/* We can't do restore on shared resources safely. Not even
|
|
|
|
* with refcounting implemented in XATTRs because if there
|
|
|
|
* was a domain running with the feature turned off the
|
|
|
|
* refcounter in XATTRs would not reflect the actual number
|
|
|
|
* of times the resource is in use and thus the last restore
|
|
|
|
* on the resource (which actually restores the original
|
|
|
|
* owner) might cut off access to the domain with the feature
|
|
|
|
* disabled.
|
|
|
|
* For disks, a shared resource is the whole backing chain
|
|
|
|
* but the top layer, or read only image, or disk explicitly
|
|
|
|
* marked as shared.
|
|
|
|
*/
|
2020-02-27 10:06:22 +00:00
|
|
|
remember = isChainTop && !src->readonly && !src->shared;
|
2019-02-15 10:37:03 +00:00
|
|
|
|
2014-06-24 15:04:21 +00:00
|
|
|
disk_seclabel = virStorageSourceGetSecurityLabelDef(src,
|
2012-08-15 22:10:37 +00:00
|
|
|
SECURITY_SELINUX_NAME);
|
2019-10-07 19:53:27 +00:00
|
|
|
parent_seclabel = virStorageSourceGetSecurityLabelDef(parent,
|
|
|
|
SECURITY_SELINUX_NAME);
|
2012-08-15 22:10:37 +00:00
|
|
|
|
2017-10-17 06:03:42 +00:00
|
|
|
if (disk_seclabel && (!disk_seclabel->relabel || disk_seclabel->label)) {
|
|
|
|
if (!disk_seclabel->relabel)
|
|
|
|
return 0;
|
2011-12-23 15:31:51 +00:00
|
|
|
|
2019-10-05 14:24:44 +00:00
|
|
|
use_label = disk_seclabel->label;
|
2017-10-17 06:03:42 +00:00
|
|
|
} else if (parent_seclabel && (!parent_seclabel->relabel || parent_seclabel->label)) {
|
|
|
|
if (!parent_seclabel->relabel)
|
|
|
|
return 0;
|
|
|
|
|
2019-10-05 14:24:44 +00:00
|
|
|
use_label = parent_seclabel->label;
|
2020-04-24 09:08:04 +00:00
|
|
|
} else if (parent == src) {
|
2014-06-24 15:04:21 +00:00
|
|
|
if (src->shared) {
|
2019-10-05 14:24:44 +00:00
|
|
|
use_label = data->file_context;
|
2014-06-24 15:04:21 +00:00
|
|
|
} else if (src->readonly) {
|
2019-10-05 14:24:44 +00:00
|
|
|
use_label = data->content_context;
|
2010-06-15 15:40:47 +00:00
|
|
|
} else if (secdef->imagelabel) {
|
2019-10-05 14:24:44 +00:00
|
|
|
use_label = secdef->imagelabel;
|
2010-06-15 15:40:47 +00:00
|
|
|
} else {
|
2019-10-05 14:24:44 +00:00
|
|
|
return 0;
|
2010-06-15 15:40:47 +00:00
|
|
|
}
|
|
|
|
} else {
|
2019-10-05 14:24:44 +00:00
|
|
|
use_label = data->content_context;
|
2011-12-23 15:31:51 +00:00
|
|
|
}
|
2014-06-24 15:04:21 +00:00
|
|
|
|
2019-06-27 09:17:52 +00:00
|
|
|
/* This is not very clean. But so far we don't have NVMe
|
|
|
|
* storage pool backend so that its chownCallback would be
|
|
|
|
* called. And this place looks least offensive. */
|
|
|
|
if (src->type == VIR_STORAGE_TYPE_NVME) {
|
|
|
|
const virStorageSourceNVMeDef *nvme = src->nvme;
|
|
|
|
|
|
|
|
if (!(vfioGroupDev = virPCIDeviceAddressGetIOMMUGroupDev(&nvme->pciAddr)))
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
path = vfioGroupDev;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = virSecuritySELinuxSetFilecon(mgr, path, use_label, remember);
|
2019-10-05 14:24:44 +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
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxSetImageLabelRelative(virSecurityManager *mgr,
|
|
|
|
virDomainDef *def,
|
|
|
|
virStorageSource *src,
|
|
|
|
virStorageSource *parent,
|
2019-10-07 19:40:49 +00:00
|
|
|
virSecurityDomainImageLabelFlags flags)
|
2009-03-03 10:06:49 +00:00
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
virStorageSource *n;
|
2012-05-11 09:43:30 +00:00
|
|
|
|
2019-01-23 10:50:33 +00:00
|
|
|
for (n = src; virStorageSourceIsBacking(n); n = n->backingStore) {
|
2020-02-27 10:06:22 +00:00
|
|
|
const bool isChainTop = flags & VIR_SECURITY_DOMAIN_IMAGE_PARENT_CHAIN_TOP;
|
|
|
|
|
|
|
|
if (virSecuritySELinuxSetImageLabelInternal(mgr, def, n, parent, isChainTop) < 0)
|
2014-06-24 15:04:21 +00:00
|
|
|
return -1;
|
2019-01-23 10:50:33 +00:00
|
|
|
|
|
|
|
if (!(flags & VIR_SECURITY_DOMAIN_IMAGE_LABEL_BACKING_CHAIN))
|
|
|
|
break;
|
2020-02-27 10:06:22 +00:00
|
|
|
|
|
|
|
flags &= ~VIR_SECURITY_DOMAIN_IMAGE_PARENT_CHAIN_TOP;
|
2014-06-24 15:04:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
2009-03-03 10:06:49 +00:00
|
|
|
}
|
|
|
|
|
2019-01-23 10:50:33 +00:00
|
|
|
|
2019-10-07 19:40:49 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxSetImageLabel(virSecurityManager *mgr,
|
|
|
|
virDomainDef *def,
|
|
|
|
virStorageSource *src,
|
2019-10-07 19:40:49 +00:00
|
|
|
virSecurityDomainImageLabelFlags flags)
|
|
|
|
{
|
|
|
|
return virSecuritySELinuxSetImageLabelRelative(mgr, def, src, src, flags);
|
|
|
|
}
|
|
|
|
|
2019-03-21 15:21:27 +00:00
|
|
|
struct virSecuritySELinuxMoveImageMetadataData {
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecurityManager *mgr;
|
2019-03-21 15:21:27 +00:00
|
|
|
const char *src;
|
|
|
|
const char *dst;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
2019-10-14 12:45:33 +00:00
|
|
|
virSecuritySELinuxMoveImageMetadataHelper(pid_t pid G_GNUC_UNUSED,
|
2019-03-21 15:21:27 +00:00
|
|
|
void *opaque)
|
|
|
|
{
|
|
|
|
struct virSecuritySELinuxMoveImageMetadataData *data = opaque;
|
|
|
|
const char *paths[2] = { data->src, data->dst };
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecurityManagerMetadataLockState *state;
|
2019-03-21 15:21:27 +00:00
|
|
|
int ret;
|
|
|
|
|
2019-10-15 11:55:26 +00:00
|
|
|
if (!(state = virSecurityManagerMetadataLock(data->mgr, paths, G_N_ELEMENTS(paths))))
|
2019-03-21 15:21:27 +00:00
|
|
|
return -1;
|
|
|
|
|
|
|
|
ret = virSecurityMoveRememberedLabel(SECURITY_SELINUX_NAME, data->src, data->dst);
|
|
|
|
virSecurityManagerMetadataUnlock(data->mgr, &state);
|
2020-05-26 07:33:38 +00:00
|
|
|
|
|
|
|
if (ret == -2) {
|
|
|
|
/* Libvirt built without XATTRS */
|
|
|
|
ret = 0;
|
|
|
|
}
|
|
|
|
|
2019-03-21 15:21:27 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxMoveImageMetadata(virSecurityManager *mgr,
|
2019-03-21 15:21:27 +00:00
|
|
|
pid_t pid,
|
2021-03-11 07:16:13 +00:00
|
|
|
virStorageSource *src,
|
|
|
|
virStorageSource *dst)
|
2019-03-21 15:21:27 +00:00
|
|
|
{
|
|
|
|
struct virSecuritySELinuxMoveImageMetadataData data = { .mgr = mgr, 0 };
|
|
|
|
int rc;
|
|
|
|
|
|
|
|
if (src && virStorageSourceIsLocalStorage(src))
|
|
|
|
data.src = src->path;
|
|
|
|
|
|
|
|
if (dst && virStorageSourceIsLocalStorage(dst))
|
|
|
|
data.dst = dst->path;
|
|
|
|
|
|
|
|
if (!data.src)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (pid == -1) {
|
|
|
|
rc = virProcessRunInFork(virSecuritySELinuxMoveImageMetadataHelper,
|
|
|
|
&data);
|
|
|
|
} else {
|
|
|
|
rc = virProcessRunInMountNamespace(pid,
|
|
|
|
virSecuritySELinuxMoveImageMetadataHelper,
|
|
|
|
&data);
|
|
|
|
}
|
|
|
|
|
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-08-14 13:23:11 +00:00
|
|
|
static int
|
2020-01-27 18:23:20 +00:00
|
|
|
virSecuritySELinuxSetHostdevLabelHelper(const char *file,
|
|
|
|
bool remember,
|
|
|
|
void *opaque)
|
2009-08-14 13:23:11 +00:00
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecurityLabelDef *secdef;
|
|
|
|
virSecuritySELinuxCallbackData *data = opaque;
|
|
|
|
virSecurityManager *mgr = data->mgr;
|
|
|
|
virDomainDef *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;
|
2020-01-27 18:23:20 +00:00
|
|
|
return virSecuritySELinuxSetFilecon(mgr, file, secdef->imagelabel, remember);
|
2009-08-14 13:23:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxSetPCILabel(virPCIDevice *dev G_GNUC_UNUSED,
|
2015-12-09 13:34:34 +00:00
|
|
|
const char *file, void *opaque)
|
2009-08-14 13:23:11 +00:00
|
|
|
{
|
2020-01-27 18:23:20 +00:00
|
|
|
return virSecuritySELinuxSetHostdevLabelHelper(file, true, 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
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxSetUSBLabel(virUSBDevice *dev G_GNUC_UNUSED,
|
2015-12-09 13:34:34 +00:00
|
|
|
const char *file, void *opaque)
|
2013-05-03 18:07:28 +00:00
|
|
|
{
|
2020-01-27 18:23:20 +00:00
|
|
|
return virSecuritySELinuxSetHostdevLabelHelper(file, true, opaque);
|
2009-08-14 13:23:11 +00:00
|
|
|
}
|
|
|
|
|
2013-05-03 18:07:28 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxSetSCSILabel(virSCSIDevice *dev,
|
2015-12-09 13:34:34 +00:00
|
|
|
const char *file, void *opaque)
|
2013-05-03 18:07:28 +00:00
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecurityLabelDef *secdef;
|
|
|
|
virSecuritySELinuxCallbackData *ptr = opaque;
|
|
|
|
virSecurityManager *mgr = ptr->mgr;
|
|
|
|
virSecuritySELinuxData *data = virSecurityManagerGetPrivateData(mgr);
|
2014-11-26 17:35:46 +00:00
|
|
|
|
|
|
|
secdef = virDomainDefGetSecurityLabelDef(ptr->def, SECURITY_SELINUX_NAME);
|
|
|
|
if (secdef == NULL)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (virSCSIDeviceGetShareable(dev))
|
2019-08-22 08:14:05 +00:00
|
|
|
return virSecuritySELinuxSetFilecon(mgr, file,
|
|
|
|
data->file_context, true);
|
2014-11-26 17:35:46 +00:00
|
|
|
else if (virSCSIDeviceGetReadonly(dev))
|
2019-08-22 08:14:05 +00:00
|
|
|
return virSecuritySELinuxSetFilecon(mgr, file,
|
|
|
|
data->content_context, true);
|
2014-11-26 17:35:46 +00:00
|
|
|
else
|
2019-08-22 08:14:05 +00:00
|
|
|
return virSecuritySELinuxSetFilecon(mgr, file,
|
|
|
|
secdef->imagelabel, true);
|
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
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxSetHostLabel(virSCSIVHostDevice *dev G_GNUC_UNUSED,
|
2016-11-22 03:58:21 +00:00
|
|
|
const char *file, void *opaque)
|
|
|
|
{
|
2020-01-27 18:23:20 +00:00
|
|
|
return virSecuritySELinuxSetHostdevLabelHelper(file, true, opaque);
|
2016-11-22 03:58:21 +00:00
|
|
|
}
|
|
|
|
|
2017-02-03 12:25:57 +00:00
|
|
|
|
2009-08-14 13:23:11 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxSetHostdevSubsysLabel(virSecurityManager *mgr,
|
|
|
|
virDomainDef *def,
|
|
|
|
virDomainHostdevDef *dev,
|
2015-12-09 13:34:34 +00:00
|
|
|
const char *vroot)
|
2009-08-14 13:23:11 +00:00
|
|
|
|
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
virDomainHostdevSubsysUSB *usbsrc = &dev->source.subsys.u.usb;
|
|
|
|
virDomainHostdevSubsysPCI *pcisrc = &dev->source.subsys.u.pci;
|
|
|
|
virDomainHostdevSubsysSCSI *scsisrc = &dev->source.subsys.u.scsi;
|
|
|
|
virDomainHostdevSubsysSCSIVHost *hostsrc = &dev->source.subsys.u.scsi_host;
|
|
|
|
virDomainHostdevSubsysMediatedDev *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;
|
|
|
|
|
2018-04-25 12:42:34 +00:00
|
|
|
switch ((virDomainHostdevSubsysType)dev->source.subsys.type) {
|
2009-08-14 13:23:11 +00:00
|
|
|
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB: {
|
2021-01-04 12:54:31 +00:00
|
|
|
g_autoptr(virUSBDevice) usb = NULL;
|
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)
|
2020-01-06 21:57:44 +00:00
|
|
|
return -1;
|
2009-08-14 13:23:11 +00:00
|
|
|
|
2015-12-09 13:34:34 +00:00
|
|
|
ret = virUSBDeviceFileIterate(usb, virSecuritySELinuxSetUSBLabel, &data);
|
2009-09-30 17:37:03 +00:00
|
|
|
break;
|
2009-08-14 13:23:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI: {
|
2021-01-04 12:54:33 +00:00
|
|
|
g_autoptr(virPCIDevice) pci = NULL;
|
|
|
|
|
|
|
|
if (!virPCIDeviceExists(&pcisrc->addr))
|
|
|
|
break;
|
|
|
|
|
|
|
|
pci = virPCIDeviceNew(&pcisrc->addr);
|
2009-08-14 13:23:11 +00:00
|
|
|
|
|
|
|
if (!pci)
|
2020-01-06 21:57:44 +00:00
|
|
|
return -1;
|
2009-08-14 13:23:11 +00:00
|
|
|
|
2014-07-03 20:31:39 +00:00
|
|
|
if (pcisrc->backend == VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO) {
|
2021-01-04 12:54:31 +00:00
|
|
|
g_autofree char *vfioGroupDev = virPCIDeviceGetIOMMUGroupDev(pci);
|
2013-04-25 10:37:21 +00:00
|
|
|
|
2021-01-04 12:54:31 +00:00
|
|
|
if (!vfioGroupDev)
|
2020-01-06 21:57:44 +00:00
|
|
|
return -1;
|
2021-01-04 12:54:31 +00:00
|
|
|
|
2020-01-27 18:23:21 +00:00
|
|
|
ret = virSecuritySELinuxSetHostdevLabelHelper(vfioGroupDev,
|
|
|
|
false,
|
|
|
|
&data);
|
2013-04-25 10:37:21 +00:00
|
|
|
} else {
|
2015-12-09 13:34:34 +00:00
|
|
|
ret = virPCIDeviceFileIterate(pci, virSecuritySELinuxSetPCILabel, &data);
|
2013-04-25 10:37:21 +00:00
|
|
|
}
|
2009-08-14 13:23:11 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2013-05-03 18:07:28 +00:00
|
|
|
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI: {
|
2021-03-11 07:16:13 +00:00
|
|
|
virDomainHostdevSubsysSCSIHost *scsihostsrc = &scsisrc->u.host;
|
2014-11-26 17:35:46 +00:00
|
|
|
|
2021-01-04 12:54:31 +00:00
|
|
|
g_autoptr(virSCSIDevice) 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)
|
2020-01-06 21:57:44 +00:00
|
|
|
return -1;
|
2013-05-03 18:07:28 +00:00
|
|
|
|
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
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2016-11-22 03:58:16 +00:00
|
|
|
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST: {
|
2021-01-04 12:54:31 +00:00
|
|
|
g_autoptr(virSCSIVHostDevice) host = virSCSIVHostDeviceNew(hostsrc->wwpn);
|
2016-11-22 03:58:21 +00:00
|
|
|
|
|
|
|
if (!host)
|
2020-01-06 21:57:44 +00:00
|
|
|
return -1;
|
2016-11-22 03:58:21 +00:00
|
|
|
|
|
|
|
ret = virSCSIVHostDeviceFileIterate(host,
|
|
|
|
virSecuritySELinuxSetHostLabel,
|
|
|
|
&data);
|
|
|
|
break;
|
2016-11-22 03:58:16 +00:00
|
|
|
}
|
|
|
|
|
2017-02-03 12:25:57 +00:00
|
|
|
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_MDEV: {
|
2021-01-04 12:54:31 +00:00
|
|
|
g_autofree char *vfiodev = NULL;
|
2017-02-03 12:25:57 +00:00
|
|
|
|
2017-04-26 12:47:15 +00:00
|
|
|
if (!(vfiodev = virMediatedDeviceGetIOMMUGroupDev(mdevsrc->uuidstr)))
|
2020-01-06 21:57:44 +00:00
|
|
|
return ret;
|
2017-02-03 12:25:57 +00:00
|
|
|
|
2020-01-27 18:23:20 +00:00
|
|
|
ret = virSecuritySELinuxSetHostdevLabelHelper(vfiodev, true, &data);
|
2017-02-03 12:25:57 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2009-11-11 12:07:00 +00:00
|
|
|
|
2012-11-28 16:07:27 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxSetHostdevCapsLabel(virSecurityManager *mgr,
|
|
|
|
virDomainDef *def,
|
|
|
|
virDomainHostdevDef *dev,
|
2015-12-09 13:34:34 +00:00
|
|
|
const char *vroot)
|
2012-11-28 16:07:27 +00:00
|
|
|
{
|
|
|
|
int ret = -1;
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecurityLabelDef *secdef;
|
2012-11-28 16:07:27 +00:00
|
|
|
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) {
|
2019-10-22 13:26:14 +00:00
|
|
|
path = g_strdup_printf("%s/%s", vroot,
|
|
|
|
dev->source.caps.u.storage.block);
|
2012-11-28 16:07:27 +00:00
|
|
|
} else {
|
2019-10-20 11:49:46 +00:00
|
|
|
path = g_strdup(dev->source.caps.u.storage.block);
|
2012-11-28 16:07:27 +00:00
|
|
|
}
|
2019-02-15 14:36:06 +00:00
|
|
|
ret = virSecuritySELinuxSetFilecon(mgr, path, secdef->imagelabel, true);
|
2012-11-28 16:07:27 +00:00
|
|
|
VIR_FREE(path);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case VIR_DOMAIN_HOSTDEV_CAPS_TYPE_MISC: {
|
|
|
|
if (vroot) {
|
2019-10-22 13:26:14 +00:00
|
|
|
path = g_strdup_printf("%s/%s", vroot,
|
|
|
|
dev->source.caps.u.misc.chardev);
|
2012-11-28 16:07:27 +00:00
|
|
|
} else {
|
2019-10-20 11:49:46 +00:00
|
|
|
path = g_strdup(dev->source.caps.u.misc.chardev);
|
2012-11-28 16:07:27 +00:00
|
|
|
}
|
2019-02-15 14:36:06 +00:00
|
|
|
ret = virSecuritySELinuxSetFilecon(mgr, path, secdef->imagelabel, true);
|
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
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxSetHostdevLabel(virSecurityManager *mgr,
|
|
|
|
virDomainDef *def,
|
|
|
|
virDomainHostdevDef *dev,
|
2015-12-09 13:34:34 +00:00
|
|
|
const char *vroot)
|
2012-11-28 15:54:56 +00:00
|
|
|
|
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecurityLabelDef *secdef;
|
2012-11-28 15:54:56 +00:00
|
|
|
|
|
|
|
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
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxRestorePCILabel(virPCIDevice *dev G_GNUC_UNUSED,
|
2015-12-09 13:34:34 +00:00
|
|
|
const char *file,
|
|
|
|
void *opaque)
|
2009-08-14 13:23:11 +00:00
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecurityManager *mgr = opaque;
|
2013-01-23 20:09:04 +00:00
|
|
|
|
2019-02-15 14:36:06 +00:00
|
|
|
return virSecuritySELinuxRestoreFileLabel(mgr, file, true);
|
2009-08-14 13:23:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxRestoreUSBLabel(virUSBDevice *dev G_GNUC_UNUSED,
|
2015-12-09 13:34:34 +00:00
|
|
|
const char *file,
|
|
|
|
void *opaque)
|
2009-08-14 13:23:11 +00:00
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecurityManager *mgr = opaque;
|
2013-01-23 20:09:04 +00:00
|
|
|
|
2019-02-15 14:36:06 +00:00
|
|
|
return virSecuritySELinuxRestoreFileLabel(mgr, file, true);
|
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
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxRestoreSCSILabel(virSCSIDevice *dev,
|
2015-12-09 13:34:34 +00:00
|
|
|
const char *file,
|
|
|
|
void *opaque)
|
2013-05-03 18:07:28 +00:00
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecurityManager *mgr = opaque;
|
2013-05-03 18:07:28 +00:00
|
|
|
|
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;
|
|
|
|
|
2019-02-15 14:36:06 +00:00
|
|
|
return virSecuritySELinuxRestoreFileLabel(mgr, file, true);
|
2013-05-03 18:07:28 +00:00
|
|
|
}
|
|
|
|
|
2016-11-22 03:58:21 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxRestoreHostLabel(virSCSIVHostDevice *dev G_GNUC_UNUSED,
|
2016-11-22 03:58:21 +00:00
|
|
|
const char *file,
|
|
|
|
void *opaque)
|
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecurityManager *mgr = opaque;
|
2016-11-22 03:58:21 +00:00
|
|
|
|
2019-02-15 14:36:06 +00:00
|
|
|
return virSecuritySELinuxRestoreFileLabel(mgr, file, true);
|
2016-11-22 03:58:21 +00:00
|
|
|
}
|
|
|
|
|
2017-02-03 12:25:57 +00:00
|
|
|
|
2009-08-14 13:23:11 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxRestoreHostdevSubsysLabel(virSecurityManager *mgr,
|
|
|
|
virDomainHostdevDef *dev,
|
2015-12-09 13:34:34 +00:00
|
|
|
const char *vroot)
|
2009-08-14 13:23:11 +00:00
|
|
|
|
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
virDomainHostdevSubsysUSB *usbsrc = &dev->source.subsys.u.usb;
|
|
|
|
virDomainHostdevSubsysPCI *pcisrc = &dev->source.subsys.u.pci;
|
|
|
|
virDomainHostdevSubsysSCSI *scsisrc = &dev->source.subsys.u.scsi;
|
|
|
|
virDomainHostdevSubsysSCSIVHost *hostsrc = &dev->source.subsys.u.scsi_host;
|
|
|
|
virDomainHostdevSubsysMediatedDev *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;
|
|
|
|
|
2018-04-25 12:42:34 +00:00
|
|
|
switch ((virDomainHostdevSubsysType)dev->source.subsys.type) {
|
2009-08-14 13:23:11 +00:00
|
|
|
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB: {
|
2021-01-04 12:54:31 +00:00
|
|
|
g_autoptr(virUSBDevice) usb = NULL;
|
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)
|
2020-01-06 21:57:44 +00:00
|
|
|
return -1;
|
2009-08-14 13:23:11 +00:00
|
|
|
|
2015-12-09 13:34:34 +00:00
|
|
|
ret = virUSBDeviceFileIterate(usb, virSecuritySELinuxRestoreUSBLabel, mgr);
|
2009-08-14 13:23:11 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI: {
|
2021-01-04 12:54:33 +00:00
|
|
|
g_autoptr(virPCIDevice) pci = NULL;
|
|
|
|
|
|
|
|
if (!virPCIDeviceExists(&pcisrc->addr))
|
|
|
|
break;
|
|
|
|
|
|
|
|
pci = virPCIDeviceNew(&pcisrc->addr);
|
2009-08-14 13:23:11 +00:00
|
|
|
|
|
|
|
if (!pci)
|
2020-01-06 21:57:44 +00:00
|
|
|
return -1;
|
2009-08-14 13:23:11 +00:00
|
|
|
|
2014-07-03 20:31:39 +00:00
|
|
|
if (pcisrc->backend == VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO) {
|
2021-01-04 12:54:31 +00:00
|
|
|
g_autofree char *vfioGroupDev = virPCIDeviceGetIOMMUGroupDev(pci);
|
2013-04-25 10:37:21 +00:00
|
|
|
|
2021-01-04 12:54:31 +00:00
|
|
|
if (!vfioGroupDev)
|
2020-01-06 21:57:44 +00:00
|
|
|
return -1;
|
2021-01-04 12:54:31 +00:00
|
|
|
|
2020-01-27 18:23:21 +00:00
|
|
|
ret = virSecuritySELinuxRestoreFileLabel(mgr, vfioGroupDev, false);
|
2013-04-25 10:37:21 +00:00
|
|
|
} else {
|
2015-12-09 13:34:34 +00:00
|
|
|
ret = virPCIDeviceFileIterate(pci, virSecuritySELinuxRestorePCILabel, mgr);
|
2013-04-25 10:37:21 +00:00
|
|
|
}
|
2009-08-14 13:23:11 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2013-05-03 18:07:28 +00:00
|
|
|
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI: {
|
2021-03-11 07:16:13 +00:00
|
|
|
virDomainHostdevSubsysSCSIHost *scsihostsrc = &scsisrc->u.host;
|
2021-01-04 12:54:31 +00:00
|
|
|
g_autoptr(virSCSIDevice) 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)
|
2020-01-06 21:57:44 +00:00
|
|
|
return -1;
|
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
|
|
|
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: {
|
2021-01-04 12:54:31 +00:00
|
|
|
g_autoptr(virSCSIVHostDevice) host = virSCSIVHostDeviceNew(hostsrc->wwpn);
|
2016-11-22 03:58:21 +00:00
|
|
|
|
|
|
|
if (!host)
|
2020-01-06 21:57:44 +00:00
|
|
|
return -1;
|
2016-11-22 03:58:21 +00:00
|
|
|
|
|
|
|
ret = virSCSIVHostDeviceFileIterate(host,
|
|
|
|
virSecuritySELinuxRestoreHostLabel,
|
|
|
|
mgr);
|
|
|
|
break;
|
2016-11-22 03:58:16 +00:00
|
|
|
}
|
|
|
|
|
2017-02-03 12:25:57 +00:00
|
|
|
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_MDEV: {
|
2021-01-04 12:54:31 +00:00
|
|
|
g_autofree char *vfiodev = NULL;
|
2017-02-03 12:25:57 +00:00
|
|
|
|
2017-04-26 12:47:15 +00:00
|
|
|
if (!(vfiodev = virMediatedDeviceGetIOMMUGroupDev(mdevsrc->uuidstr)))
|
2020-01-06 21:57:44 +00:00
|
|
|
return -1;
|
2017-02-03 12:25:57 +00:00
|
|
|
|
2019-02-15 14:36:06 +00:00
|
|
|
ret = virSecuritySELinuxRestoreFileLabel(mgr, vfiodev, true);
|
2017-02-03 12:25:57 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
2010-06-23 15:17:15 +00:00
|
|
|
|
2012-11-28 16:07:27 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxRestoreHostdevCapsLabel(virSecurityManager *mgr,
|
|
|
|
virDomainHostdevDef *dev,
|
2015-12-09 13:34:34 +00:00
|
|
|
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) {
|
2019-10-22 13:26:14 +00:00
|
|
|
path = g_strdup_printf("%s/%s", vroot,
|
|
|
|
dev->source.caps.u.storage.block);
|
2012-11-28 16:07:27 +00:00
|
|
|
} else {
|
2019-10-20 11:49:46 +00:00
|
|
|
path = g_strdup(dev->source.caps.u.storage.block);
|
2012-11-28 16:07:27 +00:00
|
|
|
}
|
2019-02-15 14:36:06 +00:00
|
|
|
ret = virSecuritySELinuxRestoreFileLabel(mgr, path, true);
|
2012-11-28 16:07:27 +00:00
|
|
|
VIR_FREE(path);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case VIR_DOMAIN_HOSTDEV_CAPS_TYPE_MISC: {
|
|
|
|
if (vroot) {
|
2019-10-22 13:26:14 +00:00
|
|
|
path = g_strdup_printf("%s/%s", vroot,
|
|
|
|
dev->source.caps.u.misc.chardev);
|
2012-11-28 16:07:27 +00:00
|
|
|
} else {
|
2019-10-20 11:49:46 +00:00
|
|
|
path = g_strdup(dev->source.caps.u.misc.chardev);
|
2012-11-28 16:07:27 +00:00
|
|
|
}
|
2019-02-15 14:36:06 +00:00
|
|
|
ret = virSecuritySELinuxRestoreFileLabel(mgr, path, true);
|
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
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxRestoreHostdevLabel(virSecurityManager *mgr,
|
|
|
|
virDomainDef *def,
|
|
|
|
virDomainHostdevDef *dev,
|
2015-12-09 13:34:34 +00:00
|
|
|
const char *vroot)
|
2012-11-28 15:54:56 +00:00
|
|
|
|
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecurityLabelDef *secdef;
|
2012-11-28 15:54:56 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-06-30 06:26:04 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxSetSavedStateLabel(virSecurityManager *mgr,
|
|
|
|
virDomainDef *def,
|
2020-06-30 06:26:04 +00:00
|
|
|
const char *savefile)
|
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxData *data = virSecurityManagerGetPrivateData(mgr);
|
|
|
|
virSecurityLabelDef *secdef;
|
2020-06-30 06:26:04 +00:00
|
|
|
|
|
|
|
secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
|
|
|
|
|
|
|
|
if (!savefile || !secdef || !secdef->relabel || data->skipAllLabel)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return virSecuritySELinuxSetFilecon(mgr, savefile, data->content_context, false);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxRestoreSavedStateLabel(virSecurityManager *mgr,
|
|
|
|
virDomainDef *def,
|
2020-06-30 06:26:04 +00:00
|
|
|
const char *savefile)
|
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecurityLabelDef *secdef;
|
2020-06-30 06:26:04 +00:00
|
|
|
|
|
|
|
secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
|
|
|
|
if (!secdef || !secdef->relabel)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return virSecuritySELinuxRestoreFileLabel(mgr, savefile, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-06-23 15:17:15 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxSetChardevLabel(virSecurityManager *mgr,
|
|
|
|
virDomainDef *def,
|
|
|
|
virDomainChrSourceDef *dev_source,
|
2017-05-29 12:27:51 +00:00
|
|
|
bool chardevStdioLogd)
|
2010-06-23 15:17:15 +00:00
|
|
|
|
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecurityLabelDef *seclabel;
|
|
|
|
virSecurityDeviceLabelDef *chr_seclabel = NULL;
|
2012-09-20 13:16:17 +00:00
|
|
|
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,
|
2019-02-15 14:36:06 +00:00
|
|
|
imagelabel,
|
|
|
|
true);
|
2012-09-20 13:16:17 +00:00
|
|
|
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,
|
2019-02-15 14:36:06 +00:00
|
|
|
imagelabel,
|
|
|
|
true) < 0)
|
2012-09-20 13:16:17 +00:00
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
ret = 0;
|
2010-06-23 15:17:15 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case VIR_DOMAIN_CHR_TYPE_PIPE:
|
2019-10-22 13:26:14 +00:00
|
|
|
in = g_strdup_printf("%s.in", dev_source->data.file.path);
|
|
|
|
out = g_strdup_printf("%s.out", dev_source->data.file.path);
|
2011-09-27 18:04:53 +00:00
|
|
|
if (virFileExists(in) && virFileExists(out)) {
|
2019-02-15 14:36:06 +00:00
|
|
|
if ((virSecuritySELinuxSetFilecon(mgr, in, imagelabel, true) < 0) ||
|
|
|
|
(virSecuritySELinuxSetFilecon(mgr, out, imagelabel, true) < 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,
|
2019-02-15 14:36:06 +00:00
|
|
|
imagelabel,
|
|
|
|
true) < 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
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxRestoreChardevLabel(virSecurityManager *mgr,
|
|
|
|
virDomainDef *def,
|
|
|
|
virDomainChrSourceDef *dev_source,
|
2017-05-29 12:27:51 +00:00
|
|
|
bool chardevStdioLogd)
|
2010-06-23 15:17:15 +00:00
|
|
|
|
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecurityLabelDef *seclabel;
|
|
|
|
virSecurityDeviceLabelDef *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:
|
2018-09-19 08:06:44 +00:00
|
|
|
if (virSecuritySELinuxRestoreFileLabel(mgr,
|
|
|
|
dev_source->data.file.path,
|
2019-02-15 14:36:06 +00:00
|
|
|
true) < 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) {
|
2018-09-19 08:06:44 +00:00
|
|
|
if (virSecuritySELinuxRestoreFileLabel(mgr,
|
|
|
|
dev_source->data.file.path,
|
2019-02-15 14:36:06 +00:00
|
|
|
true) < 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:
|
2019-10-22 13:26:14 +00:00
|
|
|
out = g_strdup_printf("%s.out", dev_source->data.file.path);
|
|
|
|
in = g_strdup_printf("%s.in", dev_source->data.file.path);
|
2011-09-27 18:04:53 +00:00
|
|
|
if (virFileExists(in) && virFileExists(out)) {
|
2019-02-15 14:36:06 +00:00
|
|
|
if ((virSecuritySELinuxRestoreFileLabel(mgr, out, true) < 0) ||
|
|
|
|
(virSecuritySELinuxRestoreFileLabel(mgr, in, true) < 0)) {
|
2011-09-27 18:04:53 +00:00
|
|
|
goto done;
|
|
|
|
}
|
2018-09-19 08:06:44 +00:00
|
|
|
} else if (virSecuritySELinuxRestoreFileLabel(mgr,
|
|
|
|
dev_source->data.file.path,
|
2019-02-15 14:36:06 +00:00
|
|
|
true) < 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 {
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecurityManager *mgr;
|
2017-05-29 12:27:51 +00:00
|
|
|
bool chardevStdioLogd;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2010-06-23 15:17:15 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxRestoreSecurityChardevCallback(virDomainDef *def,
|
|
|
|
virDomainChrDef *dev G_GNUC_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
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxRestoreSecuritySmartcardCallback(virDomainDef *def,
|
|
|
|
virDomainSmartcardDef *dev,
|
2013-01-23 20:09:04 +00:00
|
|
|
void *opaque)
|
2011-01-14 19:17:17 +00:00
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecurityManager *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;
|
2019-02-15 14:36:06 +00:00
|
|
|
return virSecuritySELinuxRestoreFileLabel(mgr, database, true);
|
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 *
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxGetBaseLabel(virSecurityManager *mgr, int virtType)
|
2013-10-18 12:13:20 +00:00
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxData *priv = virSecurityManagerGetPrivateData(mgr);
|
2013-10-18 12:13:20 +00:00
|
|
|
if (virtType == VIR_DOMAIN_VIRT_QEMU && priv->alt_domain_context)
|
|
|
|
return priv->alt_domain_context;
|
|
|
|
else
|
|
|
|
return priv->domain_context;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-06-02 18:56:09 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxRestoreSysinfoLabel(virSecurityManager *mgr,
|
|
|
|
virSysinfoDef *def)
|
2020-06-02 18:56:09 +00:00
|
|
|
{
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
for (i = 0; i < def->nfw_cfgs; i++) {
|
2021-03-11 07:16:13 +00:00
|
|
|
virSysinfoFWCfgDef *f = &def->fw_cfgs[i];
|
2020-06-02 18:56:09 +00:00
|
|
|
|
|
|
|
if (f->file &&
|
|
|
|
virSecuritySELinuxRestoreFileLabel(mgr, f->file, true) < 0)
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-03-03 10:06:49 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxRestoreAllLabel(virSecurityManager *mgr,
|
|
|
|
virDomainDef *def,
|
2017-05-29 12:27:51 +00:00
|
|
|
bool migrated,
|
|
|
|
bool chardevStdioLogd)
|
2009-03-03 10:06:49 +00:00
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecurityLabelDef *secdef;
|
|
|
|
virSecuritySELinuxData *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
|
|
|
|
2020-07-28 17:59:54 +00:00
|
|
|
struct _virSecuritySELinuxChardevCallbackData chardevData = {
|
|
|
|
.mgr = mgr,
|
|
|
|
.chardevStdioLogd = chardevStdioLogd
|
|
|
|
};
|
|
|
|
|
2019-02-04 15:39:52 +00:00
|
|
|
VIR_DEBUG("Restoring security label on %s migrated=%d", def->name, migrated);
|
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;
|
|
|
|
|
2018-10-03 09:03:04 +00:00
|
|
|
for (i = 0; i < def->ndisks; i++) {
|
2021-03-11 07:16:13 +00:00
|
|
|
virDomainDiskDef *disk = def->disks[i];
|
2018-10-03 09:03:04 +00:00
|
|
|
|
|
|
|
if (virSecuritySELinuxRestoreImageLabelInt(mgr, def, disk->src,
|
|
|
|
migrated) < 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;
|
|
|
|
}
|
|
|
|
|
2020-06-10 18:11:47 +00:00
|
|
|
for (i = 0; i < def->ntpms; i++) {
|
|
|
|
if (virSecuritySELinuxRestoreTPMFileLabelInt(mgr, def, def->tpms[i]) < 0)
|
2010-01-13 14:03:04 +00:00
|
|
|
rc = -1;
|
|
|
|
}
|
2010-01-11 11:04:40 +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
|
|
|
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;
|
|
|
|
|
2020-06-02 18:56:09 +00:00
|
|
|
for (i = 0; i < def->nsysinfo; i++) {
|
|
|
|
if (virSecuritySELinuxRestoreSysinfoLabel(mgr, def->sysinfo[i]) < 0)
|
|
|
|
rc = -1;
|
|
|
|
}
|
|
|
|
|
2014-08-07 11:50:00 +00:00
|
|
|
if (def->os.loader && def->os.loader->nvram &&
|
2019-02-15 14:36:06 +00:00
|
|
|
virSecuritySELinuxRestoreFileLabel(mgr, def->os.loader->nvram, true) < 0)
|
2014-08-07 11:50:00 +00:00
|
|
|
rc = -1;
|
|
|
|
|
2018-10-03 09:08:21 +00:00
|
|
|
if (def->os.kernel &&
|
2019-02-15 14:36:06 +00:00
|
|
|
virSecuritySELinuxRestoreFileLabel(mgr, def->os.kernel, true) < 0)
|
2018-10-03 09:08:21 +00:00
|
|
|
rc = -1;
|
|
|
|
|
|
|
|
if (def->os.initrd &&
|
2019-02-15 14:36:06 +00:00
|
|
|
virSecuritySELinuxRestoreFileLabel(mgr, def->os.initrd, true) < 0)
|
2018-10-03 09:08:21 +00:00
|
|
|
rc = -1;
|
|
|
|
|
|
|
|
if (def->os.dtb &&
|
2019-02-15 14:36:06 +00:00
|
|
|
virSecuritySELinuxRestoreFileLabel(mgr, def->os.dtb, true) < 0)
|
2018-10-03 09:08:21 +00:00
|
|
|
rc = -1;
|
|
|
|
|
|
|
|
if (def->os.slic_table &&
|
2019-02-15 14:36:06 +00:00
|
|
|
virSecuritySELinuxRestoreFileLabel(mgr, def->os.slic_table, true) < 0)
|
2018-10-03 09:08:21 +00:00
|
|
|
rc = -1;
|
|
|
|
|
2010-01-11 11:04:40 +00:00
|
|
|
return rc;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxReleaseLabel(virSecurityManager *mgr,
|
|
|
|
virDomainDef *def)
|
2010-01-11 11:04:40 +00:00
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecurityLabelDef *secdef;
|
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;
|
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
|
|
|
|
2009-04-03 10:55:51 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxVerify(virSecurityManager *mgr G_GNUC_UNUSED,
|
|
|
|
virDomainDef *def)
|
2009-04-03 10:55:51 +00:00
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecurityLabelDef *secdef;
|
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;
|
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
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxSetProcessLabel(virSecurityManager *mgr G_GNUC_UNUSED,
|
|
|
|
virDomainDef *def)
|
2009-03-03 10:06:49 +00:00
|
|
|
{
|
|
|
|
/* TODO: verify DOI */
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecurityLabelDef *secdef;
|
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-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
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxSetChildProcessLabel(virSecurityManager *mgr G_GNUC_UNUSED,
|
|
|
|
virDomainDef *def,
|
|
|
|
virCommand *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 */
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecurityLabelDef *secdef;
|
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
|
|
|
|
|
|
|
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
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxSetDaemonSocketLabel(virSecurityManager *mgr G_GNUC_UNUSED,
|
|
|
|
virDomainDef *def)
|
2010-05-27 15:44:47 +00:00
|
|
|
{
|
|
|
|
/* TODO: verify DOI */
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecurityLabelDef *secdef;
|
2020-07-15 10:32:48 +00:00
|
|
|
char *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
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxSetSocketLabel(virSecurityManager *mgr G_GNUC_UNUSED,
|
|
|
|
virDomainDef *vm)
|
2011-08-26 07:39:32 +00:00
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecurityLabelDef *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
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxClearSocketLabel(virSecurityManager *mgr G_GNUC_UNUSED,
|
|
|
|
virDomainDef *def)
|
2010-05-27 15:44:47 +00:00
|
|
|
{
|
|
|
|
/* TODO: verify DOI */
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecurityLabelDef *secdef;
|
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
|
|
|
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
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxSetSecurityChardevCallback(virDomainDef *def,
|
|
|
|
virDomainChrDef *dev G_GNUC_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
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxSetSecuritySmartcardCallback(virDomainDef *def,
|
|
|
|
virDomainSmartcardDef *dev,
|
2012-05-24 15:42:51 +00:00
|
|
|
void *opaque)
|
2011-01-14 19:17:17 +00:00
|
|
|
{
|
|
|
|
const char *database;
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecurityManager *mgr = opaque;
|
|
|
|
virSecuritySELinuxData *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;
|
2019-02-15 14:36:06 +00:00
|
|
|
return virSecuritySELinuxSetFilecon(mgr, database, data->content_context, true);
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-06-02 18:56:09 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxSetSysinfoLabel(virSecurityManager *mgr,
|
|
|
|
virSysinfoDef *def,
|
|
|
|
virSecuritySELinuxData *data)
|
2020-06-02 18:56:09 +00:00
|
|
|
{
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
for (i = 0; i < def->nfw_cfgs; i++) {
|
2021-03-11 07:16:13 +00:00
|
|
|
virSysinfoFWCfgDef *f = &def->fw_cfgs[i];
|
2020-06-02 18:56:09 +00:00
|
|
|
|
|
|
|
if (f->file &&
|
|
|
|
virSecuritySELinuxSetFilecon(mgr, f->file,
|
|
|
|
data->content_context, true) < 0)
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-01-11 11:04:40 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxSetAllLabel(virSecurityManager *mgr,
|
|
|
|
virDomainDef *def,
|
2020-07-01 09:50:00 +00:00
|
|
|
const char *incomingPath G_GNUC_UNUSED,
|
2019-09-11 05:53:09 +00:00
|
|
|
bool chardevStdioLogd,
|
2019-10-14 12:45:33 +00:00
|
|
|
bool migrated G_GNUC_UNUSED)
|
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;
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxData *data = virSecurityManagerGetPrivateData(mgr);
|
|
|
|
virSecurityLabelDef *secdef;
|
2012-08-15 22:10:37 +00:00
|
|
|
|
2020-07-28 17:59:54 +00:00
|
|
|
struct _virSecuritySELinuxChardevCallbackData chardevData = {
|
|
|
|
.mgr = mgr,
|
|
|
|
.chardevStdioLogd = chardevStdioLogd
|
|
|
|
};
|
|
|
|
|
2012-08-15 22:10:37 +00:00
|
|
|
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
|
|
|
}
|
2019-01-23 10:50:33 +00:00
|
|
|
if (virSecuritySELinuxSetImageLabel(mgr, def, def->disks[i]->src,
|
2020-02-27 10:06:22 +00:00
|
|
|
VIR_SECURITY_DOMAIN_IMAGE_LABEL_BACKING_CHAIN |
|
|
|
|
VIR_SECURITY_DOMAIN_IMAGE_PARENT_CHAIN_TOP) < 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;
|
|
|
|
}
|
|
|
|
|
2020-06-10 18:11:47 +00:00
|
|
|
for (i = 0; i < def->ntpms; i++) {
|
|
|
|
if (virSecuritySELinuxSetTPMFileLabel(mgr, def, def->tpms[i]) < 0)
|
2013-04-12 20:55:46 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2009-03-03 10:06:49 +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
|
|
|
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;
|
|
|
|
|
2020-06-02 18:56:09 +00:00
|
|
|
for (i = 0; i < def->nsysinfo; i++) {
|
|
|
|
if (virSecuritySELinuxSetSysinfoLabel(mgr,
|
|
|
|
def->sysinfo[i],
|
|
|
|
data) < 0)
|
|
|
|
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,
|
2019-02-15 14:36:06 +00:00
|
|
|
secdef->imagelabel, true) < 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,
|
2019-02-15 14:36:06 +00:00
|
|
|
data->content_context, true) < 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,
|
2019-02-15 14:36:06 +00:00
|
|
|
data->content_context, true) < 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,
|
2019-02-15 14:36:06 +00:00
|
|
|
data->content_context, true) < 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,
|
2019-02-15 14:36:06 +00:00
|
|
|
data->content_context, true) < 0)
|
2016-05-13 14:16:55 +00:00
|
|
|
return -1;
|
|
|
|
|
2009-03-03 10:06:49 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2011-01-23 21:02:42 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxSetImageFDLabel(virSecurityManager *mgr G_GNUC_UNUSED,
|
|
|
|
virDomainDef *def,
|
2012-05-24 15:42:51 +00:00
|
|
|
int fd)
|
2011-01-23 21:02:42 +00:00
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecurityLabelDef *secdef;
|
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->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
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxSetTapFDLabel(virSecurityManager *mgr,
|
|
|
|
virDomainDef *def,
|
2012-10-15 09:03:49 +00:00
|
|
|
int fd)
|
|
|
|
{
|
2014-09-18 13:17:29 +00:00
|
|
|
struct stat buf;
|
2020-07-15 10:32:48 +00:00
|
|
|
char *fcon = NULL;
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecurityLabelDef *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;
|
|
|
|
}
|
|
|
|
|
2020-01-07 14:22:30 +00:00
|
|
|
/* Label /dev/tap([0-9]+)? devices only. Leave /dev/net/tun alone! */
|
2019-10-22 13:26:14 +00:00
|
|
|
proc = g_strdup_printf("/proc/self/fd/%d", fd);
|
2014-10-07 14:22:17 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2020-01-07 14:22:30 +00:00
|
|
|
if (getContext(mgr, fd_path, 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 *
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxGenImageLabel(virSecurityManager *mgr,
|
|
|
|
virDomainDef *def)
|
2012-05-24 15:42:51 +00:00
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecurityLabelDef *secdef;
|
|
|
|
virSecuritySELinuxData *data = virSecurityManagerGetPrivateData(mgr);
|
2012-05-01 14:16:04 +00:00
|
|
|
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) {
|
2019-10-20 11:49:46 +00:00
|
|
|
mcs = g_strdup(range);
|
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 *
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxGetSecurityMountOptions(virSecurityManager *mgr,
|
|
|
|
virDomainDef *def)
|
2012-05-24 15:42:51 +00:00
|
|
|
{
|
2012-05-01 14:16:04 +00:00
|
|
|
char *opts = NULL;
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecurityLabelDef *secdef;
|
2012-08-15 22:10:37 +00:00
|
|
|
|
2012-11-22 14:11:35 +00:00
|
|
|
if ((secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME))) {
|
|
|
|
if (!secdef->imagelabel)
|
|
|
|
secdef->imagelabel = virSecuritySELinuxGenImageLabel(mgr, def);
|
|
|
|
|
2019-10-22 13:26:14 +00:00
|
|
|
if (secdef->imagelabel) {
|
|
|
|
opts = g_strdup_printf(
|
|
|
|
",context=\"%s\"",
|
|
|
|
(const char*) secdef->imagelabel);
|
|
|
|
}
|
2012-11-22 14:11:35 +00:00
|
|
|
}
|
2012-05-01 14:16:04 +00:00
|
|
|
|
2019-10-18 13:08:21 +00:00
|
|
|
if (!opts)
|
|
|
|
opts = g_strdup("");
|
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
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxDomainSetPathLabel(virSecurityManager *mgr,
|
|
|
|
virDomainDef *def,
|
2018-01-09 15:04:03 +00:00
|
|
|
const char *path,
|
2019-10-14 12:45:33 +00:00
|
|
|
bool allowSubtree G_GNUC_UNUSED)
|
2015-08-17 18:07:07 +00:00
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecurityLabelDef *seclabel;
|
2015-08-17 18:07:07 +00:00
|
|
|
|
|
|
|
seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
|
|
|
|
if (!seclabel || !seclabel->relabel)
|
|
|
|
return 0;
|
|
|
|
|
2019-02-15 14:36:06 +00:00
|
|
|
return virSecuritySELinuxSetFilecon(mgr, path, seclabel->imagelabel, true);
|
2015-08-17 18:07:07 +00:00
|
|
|
}
|
|
|
|
|
2020-04-03 08:28:17 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxDomainSetPathLabelRO(virSecurityManager *mgr,
|
|
|
|
virDomainDef *def,
|
2020-04-03 08:28:17 +00:00
|
|
|
const char *path)
|
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxData *data = virSecurityManagerGetPrivateData(mgr);
|
|
|
|
virSecurityLabelDef *secdef;
|
2020-04-03 08:28:17 +00:00
|
|
|
|
|
|
|
secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
|
|
|
|
|
|
|
|
if (!path || !secdef || !secdef->relabel || data->skipAllLabel)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return virSecuritySELinuxSetFilecon(mgr, path, data->content_context, false);
|
|
|
|
}
|
2018-04-04 16:40:32 +00:00
|
|
|
|
2020-06-17 09:32:53 +00:00
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxDomainRestorePathLabel(virSecurityManager *mgr,
|
|
|
|
virDomainDef *def,
|
2020-06-17 09:32:53 +00:00
|
|
|
const char *path)
|
|
|
|
{
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecurityLabelDef *secdef;
|
2020-06-17 09:32:53 +00:00
|
|
|
|
|
|
|
secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
|
|
|
|
if (!secdef || !secdef->relabel)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return virSecuritySELinuxRestoreFileLabel(mgr, path, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-04-04 16:40:32 +00:00
|
|
|
/*
|
|
|
|
* virSecuritySELinuxSetFileLabels:
|
|
|
|
*
|
|
|
|
* @mgr: the virSecurityManager
|
|
|
|
* @path: path to a directory or a file
|
|
|
|
* @seclabel: the security label
|
|
|
|
*
|
|
|
|
* Set the file labels on the given path; if the path is a directory
|
|
|
|
* we label all files found there, including the directory itself,
|
|
|
|
* otherwise we just label the file.
|
|
|
|
*/
|
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxSetFileLabels(virSecurityManager *mgr,
|
2018-04-04 16:40:32 +00:00
|
|
|
const char *path,
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecurityLabelDef *seclabel)
|
2018-04-04 16:40:32 +00:00
|
|
|
{
|
|
|
|
int ret = 0;
|
|
|
|
struct dirent *ent;
|
|
|
|
char *filename = NULL;
|
2020-10-25 21:50:51 +00:00
|
|
|
g_autoptr(DIR) dir = NULL;
|
2018-04-04 16:40:32 +00:00
|
|
|
|
2019-02-15 14:36:06 +00:00
|
|
|
if ((ret = virSecuritySELinuxSetFilecon(mgr, path, seclabel->imagelabel, true)))
|
2018-04-04 16:40:32 +00:00
|
|
|
return ret;
|
|
|
|
|
|
|
|
if (!virFileIsDir(path))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (virDirOpen(&dir, path) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
while ((ret = virDirRead(dir, &ent, path)) > 0) {
|
2019-10-22 13:26:14 +00:00
|
|
|
filename = g_strdup_printf("%s/%s", path, ent->d_name);
|
2018-04-04 16:40:32 +00:00
|
|
|
ret = virSecuritySELinuxSetFilecon(mgr, filename,
|
2019-02-15 14:36:06 +00:00
|
|
|
seclabel->imagelabel, true);
|
2018-04-04 16:40:32 +00:00
|
|
|
VIR_FREE(filename);
|
|
|
|
if (ret < 0)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (ret < 0)
|
|
|
|
virReportSystemError(errno, _("Unable to label files under %s"),
|
|
|
|
path);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* virSecuritySELinuxRestoreFileLabels:
|
|
|
|
*
|
|
|
|
* @mgr: the virSecurityManager
|
|
|
|
* @path: path to a directory or a file
|
|
|
|
*
|
|
|
|
* Restore the file labels on the given path; if the path is a directory
|
|
|
|
* we restore all file labels found there, including the label of the
|
|
|
|
* directory itself, otherwise we just restore the label on the file.
|
|
|
|
*/
|
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxRestoreFileLabels(virSecurityManager *mgr,
|
2018-04-04 16:40:32 +00:00
|
|
|
const char *path)
|
|
|
|
{
|
|
|
|
int ret = 0;
|
|
|
|
struct dirent *ent;
|
|
|
|
char *filename = NULL;
|
2020-10-25 21:50:51 +00:00
|
|
|
g_autoptr(DIR) dir = NULL;
|
2018-04-04 16:40:32 +00:00
|
|
|
|
2019-02-15 14:36:06 +00:00
|
|
|
if ((ret = virSecuritySELinuxRestoreFileLabel(mgr, path, true)))
|
2018-04-04 16:40:32 +00:00
|
|
|
return ret;
|
|
|
|
|
|
|
|
if (!virFileIsDir(path))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (virDirOpen(&dir, path) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
while ((ret = virDirRead(dir, &ent, path)) > 0) {
|
2019-10-22 13:26:14 +00:00
|
|
|
filename = g_strdup_printf("%s/%s", path, ent->d_name);
|
2019-02-15 14:36:06 +00:00
|
|
|
ret = virSecuritySELinuxRestoreFileLabel(mgr, filename, true);
|
2018-04-04 16:40:32 +00:00
|
|
|
VIR_FREE(filename);
|
|
|
|
if (ret < 0)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (ret < 0)
|
|
|
|
virReportSystemError(errno, _("Unable to restore file labels under %s"),
|
|
|
|
path);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxSetTPMLabels(virSecurityManager *mgr,
|
|
|
|
virDomainDef *def)
|
2018-04-04 16:40:32 +00:00
|
|
|
{
|
|
|
|
int ret = 0;
|
2020-06-10 18:11:47 +00:00
|
|
|
size_t i;
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecurityLabelDef *seclabel;
|
2018-04-04 16:40:32 +00:00
|
|
|
|
|
|
|
seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
|
|
|
|
if (seclabel == NULL)
|
|
|
|
return 0;
|
|
|
|
|
2020-06-10 18:11:47 +00:00
|
|
|
for (i = 0; i < def->ntpms; i++) {
|
|
|
|
if (def->tpms[i]->type != VIR_DOMAIN_TPM_TYPE_EMULATOR)
|
|
|
|
continue;
|
|
|
|
|
2018-04-04 16:40:32 +00:00
|
|
|
ret = virSecuritySELinuxSetFileLabels(
|
2020-06-10 18:11:47 +00:00
|
|
|
mgr, def->tpms[i]->data.emulator.storagepath,
|
2018-04-04 16:40:32 +00:00
|
|
|
seclabel);
|
2020-06-10 18:11:47 +00:00
|
|
|
if (ret == 0 && def->tpms[i]->data.emulator.logfile)
|
2018-04-04 16:40:32 +00:00
|
|
|
ret = virSecuritySELinuxSetFileLabels(
|
2020-06-10 18:11:47 +00:00
|
|
|
mgr, def->tpms[i]->data.emulator.logfile,
|
2018-04-04 16:40:32 +00:00
|
|
|
seclabel);
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
2021-03-11 07:16:13 +00:00
|
|
|
virSecuritySELinuxRestoreTPMLabels(virSecurityManager *mgr,
|
|
|
|
virDomainDef *def)
|
2018-04-04 16:40:32 +00:00
|
|
|
{
|
|
|
|
int ret = 0;
|
2020-06-10 18:11:47 +00:00
|
|
|
size_t i;
|
|
|
|
|
|
|
|
for (i = 0; i < def->ntpms; i++) {
|
|
|
|
if (def->tpms[i]->type != VIR_DOMAIN_TPM_TYPE_EMULATOR)
|
|
|
|
continue;
|
2018-04-04 16:40:32 +00:00
|
|
|
|
|
|
|
ret = virSecuritySELinuxRestoreFileLabels(
|
2020-06-10 18:11:47 +00:00
|
|
|
mgr, def->tpms[i]->data.emulator.storagepath);
|
|
|
|
if (ret == 0 && def->tpms[i]->data.emulator.logfile)
|
2018-04-04 16:40:32 +00:00
|
|
|
ret = virSecuritySELinuxRestoreFileLabels(
|
2020-06-10 18:11:47 +00:00
|
|
|
mgr, def->tpms[i]->data.emulator.logfile);
|
2018-04-04 16:40:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
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
|
|
|
.domainSetSecurityImageLabel = virSecuritySELinuxSetImageLabel,
|
|
|
|
.domainRestoreSecurityImageLabel = virSecuritySELinuxRestoreImageLabel,
|
2019-03-21 15:21:27 +00:00
|
|
|
.domainMoveImageMetadata = virSecuritySELinuxMoveImageMetadata,
|
2014-06-23 15:19:25 +00:00
|
|
|
|
2016-08-04 12:55:16 +00:00
|
|
|
.domainSetSecurityMemoryLabel = virSecuritySELinuxSetMemoryLabel,
|
|
|
|
.domainRestoreSecurityMemoryLabel = virSecuritySELinuxRestoreMemoryLabel,
|
|
|
|
|
2017-11-21 12:31:53 +00:00
|
|
|
.domainSetSecurityInputLabel = virSecuritySELinuxSetInputLabel,
|
|
|
|
.domainRestoreSecurityInputLabel = virSecuritySELinuxRestoreInputLabel,
|
|
|
|
|
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
|
|
|
|
2020-06-30 06:26:04 +00:00
|
|
|
.domainSetSavedStateLabel = virSecuritySELinuxSetSavedStateLabel,
|
|
|
|
.domainRestoreSavedStateLabel = virSecuritySELinuxRestoreSavedStateLabel,
|
|
|
|
|
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,
|
2020-04-03 08:28:17 +00:00
|
|
|
.domainSetPathLabelRO = virSecuritySELinuxDomainSetPathLabelRO,
|
2020-06-17 09:32:53 +00:00
|
|
|
.domainRestorePathLabel = virSecuritySELinuxDomainRestorePathLabel,
|
2017-12-01 09:39:26 +00:00
|
|
|
|
|
|
|
.domainSetSecurityChardevLabel = virSecuritySELinuxSetChardevLabel,
|
|
|
|
.domainRestoreSecurityChardevLabel = virSecuritySELinuxRestoreChardevLabel,
|
2018-04-04 16:40:32 +00:00
|
|
|
|
|
|
|
.domainSetSecurityTPMLabels = virSecuritySELinuxSetTPMLabels,
|
|
|
|
.domainRestoreSecurityTPMLabels = virSecuritySELinuxRestoreTPMLabels,
|
2009-03-03 10:06:49 +00:00
|
|
|
};
|