mirror of
https://github.com/libvirt/libvirt.git
synced 2025-02-25 18:55:26 -06:00
The qemusecuritytest checks for random domain XMLs from qemuxml2argvdata/ whether set+restore seclabels leaves something behind. It can be an XATTR that we forgot to remove or a file that the owner was not restored on. But so far only DAC driver is checked. Implement missing pieces and enable SELinux testing too. This is done by mocking some libselinux APIs and following the same logic used for DAC - everything is implemented in memory, there is new hash table introduced that holds SELinux labels for paths that were setfilecon_raw()-ed and in the end the hash table is checked for entries that don't have the default SELinux label (i.e. were not restored). Signed-off-by: Michal Privoznik <mprivozn@redhat.com> Reviewed-by: Andrea Bolognani <abologna@redhat.com>
265 lines
8.0 KiB
C
265 lines
8.0 KiB
C
/*
|
|
* Copyright (C) 2018 Red Hat, Inc.
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library. If not, see
|
|
* <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include <config.h>
|
|
|
|
#include "qemusecuritytest.h"
|
|
#include "testutils.h"
|
|
#include "testutilsqemu.h"
|
|
#include "security/security_manager.h"
|
|
#include "conf/domain_conf.h"
|
|
#include "qemu/qemu_domain.h"
|
|
#include "qemu/qemu_security.h"
|
|
|
|
#define VIR_FROM_THIS VIR_FROM_NONE
|
|
|
|
struct testData {
|
|
virQEMUDriverPtr driver;
|
|
const char *file; /* file name to load VM def XML from; qemuxml2argvdata/ */
|
|
};
|
|
|
|
|
|
static int
|
|
prepareObjects(virQEMUDriverPtr driver,
|
|
const char *xmlname,
|
|
virDomainObjPtr *vm_ret)
|
|
{
|
|
qemuDomainObjPrivatePtr priv;
|
|
g_autoptr(virDomainObj) vm = NULL;
|
|
g_autofree char *filename = NULL;
|
|
g_autofree char *domxml = NULL;
|
|
g_autofree char *latestCapsFile = NULL;
|
|
|
|
filename = g_strdup_printf("%s/qemuxml2argvdata/%s.xml", abs_srcdir, xmlname);
|
|
|
|
if (virTestLoadFile(filename, &domxml) < 0)
|
|
return -1;
|
|
|
|
if (!(vm = virDomainObjNew(driver->xmlopt)))
|
|
return -1;
|
|
|
|
vm->pid = -1;
|
|
priv = vm->privateData;
|
|
priv->chardevStdioLogd = false;
|
|
priv->rememberOwner = true;
|
|
|
|
if (!(latestCapsFile = testQemuGetLatestCapsForArch("x86_64", "xml")))
|
|
return -1;
|
|
|
|
if (!(priv->qemuCaps = qemuTestParseCapabilitiesArch(VIR_ARCH_X86_64, latestCapsFile)))
|
|
return -1;
|
|
|
|
if (qemuTestCapsCacheInsert(driver->qemuCapsCache, priv->qemuCaps) < 0)
|
|
return -1;
|
|
|
|
if (!(vm->def = virDomainDefParseString(domxml,
|
|
driver->xmlopt,
|
|
NULL,
|
|
0)))
|
|
return -1;
|
|
|
|
if (virSecurityManagerGenLabel(driver->securityManager, vm->def) < 0)
|
|
return -1;
|
|
|
|
*vm_ret = g_steal_pointer(&vm);
|
|
return 0;
|
|
}
|
|
|
|
|
|
static int
|
|
testDomain(const void *opaque)
|
|
{
|
|
const struct testData *data = opaque;
|
|
g_autoptr(virDomainObj) vm = NULL;
|
|
VIR_AUTOSTRINGLIST notRestored = NULL;
|
|
size_t i;
|
|
int ret = -1;
|
|
|
|
if (prepareObjects(data->driver, data->file, &vm) < 0)
|
|
return -1;
|
|
|
|
for (i = 0; i < vm->def->ndisks; i++) {
|
|
virStorageSourcePtr src = vm->def->disks[i]->src;
|
|
virStorageSourcePtr n;
|
|
|
|
if (!src)
|
|
continue;
|
|
|
|
if (virStorageSourceIsLocalStorage(src) && src->path &&
|
|
(src->shared || src->readonly) &&
|
|
virStringListAdd(¬Restored, src->path) < 0)
|
|
return -1;
|
|
|
|
for (n = src->backingStore; virStorageSourceIsBacking(n); n = n->backingStore) {
|
|
if (virStorageSourceIsLocalStorage(n) && n->path &&
|
|
virStringListAdd(¬Restored, n->path) < 0)
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
/* Mocking is enabled only when this env variable is set.
|
|
* See mock code for explanation. */
|
|
if (g_setenv(ENVVAR, "1", FALSE) == FALSE)
|
|
return -1;
|
|
|
|
if (qemuSecuritySetAllLabel(data->driver, vm, NULL, false) < 0)
|
|
goto cleanup;
|
|
|
|
qemuSecurityRestoreAllLabel(data->driver, vm, false);
|
|
|
|
if (checkPaths((const char **) notRestored) < 0)
|
|
goto cleanup;
|
|
|
|
ret = 0;
|
|
cleanup:
|
|
g_unsetenv(ENVVAR);
|
|
freePaths();
|
|
return ret;
|
|
}
|
|
|
|
|
|
static int
|
|
mymain(void)
|
|
{
|
|
virQEMUDriver driver;
|
|
virSecurityManagerPtr stack = NULL;
|
|
virSecurityManagerPtr dac = NULL;
|
|
#ifdef WITH_SELINUX
|
|
virSecurityManagerPtr selinux = NULL;
|
|
#endif
|
|
int ret = 0;
|
|
|
|
if (virInitialize() < 0 ||
|
|
qemuTestDriverInit(&driver) < 0)
|
|
return -1;
|
|
|
|
/* Now fix the secdriver */
|
|
virObjectUnref(driver.securityManager);
|
|
|
|
if (!(dac = virSecurityManagerNewDAC("test", 1000, 1000,
|
|
VIR_SECURITY_MANAGER_PRIVILEGED |
|
|
VIR_SECURITY_MANAGER_DYNAMIC_OWNERSHIP,
|
|
NULL))) {
|
|
fprintf(stderr, "Cannot initialize DAC security driver");
|
|
ret = -1;
|
|
goto cleanup;
|
|
}
|
|
|
|
if (!(stack = virSecurityManagerNewStack(dac))) {
|
|
fprintf(stderr, "Cannot initialize stack security driver");
|
|
ret = -1;
|
|
goto cleanup;
|
|
}
|
|
dac = NULL;
|
|
|
|
#if WITH_SELINUX
|
|
selinux = virSecurityManagerNew("selinux", "test",
|
|
VIR_SECURITY_MANAGER_PRIVILEGED |
|
|
VIR_SECURITY_MANAGER_DEFAULT_CONFINED |
|
|
VIR_SECURITY_MANAGER_REQUIRE_CONFINED);
|
|
if (!selinux) {
|
|
fprintf(stderr, "Cannot initialize selinux security driver");
|
|
ret = -1;
|
|
goto cleanup;
|
|
}
|
|
|
|
if (virSecurityManagerStackAddNested(stack, selinux) < 0) {
|
|
fprintf(stderr, "Cannot add selinux security driver onto stack");
|
|
ret = -1;
|
|
goto cleanup;
|
|
}
|
|
selinux = NULL;
|
|
#endif
|
|
|
|
driver.securityManager = g_steal_pointer(&stack);
|
|
|
|
|
|
#define DO_TEST_DOMAIN(f) \
|
|
do { \
|
|
struct testData data = {.driver = &driver, .file = f}; \
|
|
if (virTestRun(f, testDomain, &data) < 0) \
|
|
ret = -1; \
|
|
} while (0)
|
|
|
|
DO_TEST_DOMAIN("acpi-table");
|
|
DO_TEST_DOMAIN("channel-unix-guestfwd");
|
|
DO_TEST_DOMAIN("console-virtio-unix");
|
|
DO_TEST_DOMAIN("controller-virtio-scsi");
|
|
DO_TEST_DOMAIN("disk-aio");
|
|
DO_TEST_DOMAIN("disk-backing-chains-noindex");
|
|
DO_TEST_DOMAIN("disk-cache");
|
|
DO_TEST_DOMAIN("disk-cdrom");
|
|
DO_TEST_DOMAIN("disk-cdrom-bus-other");
|
|
DO_TEST_DOMAIN("disk-cdrom-network");
|
|
DO_TEST_DOMAIN("disk-cdrom-tray");
|
|
DO_TEST_DOMAIN("disk-copy_on_read");
|
|
DO_TEST_DOMAIN("disk-detect-zeroes");
|
|
DO_TEST_DOMAIN("disk-error-policy");
|
|
DO_TEST_DOMAIN("disk-floppy");
|
|
DO_TEST_DOMAIN("disk-floppy-q35-2_11");
|
|
DO_TEST_DOMAIN("disk-floppy-q35-2_9");
|
|
DO_TEST_DOMAIN("disk-network-gluster");
|
|
DO_TEST_DOMAIN("disk-network-iscsi");
|
|
DO_TEST_DOMAIN("disk-network-nbd");
|
|
DO_TEST_DOMAIN("disk-network-rbd");
|
|
DO_TEST_DOMAIN("disk-network-sheepdog");
|
|
DO_TEST_DOMAIN("disk-network-source-auth");
|
|
DO_TEST_DOMAIN("disk-network-tlsx509-nbd");
|
|
DO_TEST_DOMAIN("disk-network-tlsx509-vxhs");
|
|
DO_TEST_DOMAIN("disk-readonly-disk");
|
|
DO_TEST_DOMAIN("disk-scsi");
|
|
DO_TEST_DOMAIN("disk-scsi-device-auto");
|
|
DO_TEST_DOMAIN("disk-shared");
|
|
DO_TEST_DOMAIN("disk-virtio");
|
|
DO_TEST_DOMAIN("disk-virtio-scsi-reservations");
|
|
DO_TEST_DOMAIN("graphics-vnc-tls-secret");
|
|
DO_TEST_DOMAIN("hugepages-nvdimm");
|
|
DO_TEST_DOMAIN("iothreads-virtio-scsi-pci");
|
|
DO_TEST_DOMAIN("memory-hotplug-nvdimm");
|
|
DO_TEST_DOMAIN("memory-hotplug-nvdimm-access");
|
|
DO_TEST_DOMAIN("memory-hotplug-nvdimm-align");
|
|
DO_TEST_DOMAIN("memory-hotplug-nvdimm-label");
|
|
DO_TEST_DOMAIN("memory-hotplug-nvdimm-pmem");
|
|
DO_TEST_DOMAIN("memory-hotplug-nvdimm-readonly");
|
|
DO_TEST_DOMAIN("net-vhostuser");
|
|
DO_TEST_DOMAIN("os-firmware-bios");
|
|
DO_TEST_DOMAIN("os-firmware-efi");
|
|
DO_TEST_DOMAIN("os-firmware-efi-secboot");
|
|
DO_TEST_DOMAIN("pci-bridge-many-disks");
|
|
DO_TEST_DOMAIN("tseg-explicit-size");
|
|
DO_TEST_DOMAIN("usb-redir-unix");
|
|
DO_TEST_DOMAIN("virtio-non-transitional");
|
|
DO_TEST_DOMAIN("virtio-transitional");
|
|
DO_TEST_DOMAIN("x86_64-pc-graphics");
|
|
DO_TEST_DOMAIN("x86_64-pc-headless");
|
|
DO_TEST_DOMAIN("x86_64-q35-graphics");
|
|
DO_TEST_DOMAIN("x86_64-q35-headless");
|
|
|
|
cleanup:
|
|
qemuTestDriverFree(&driver);
|
|
#ifdef WITH_SELINUX
|
|
virObjectUnref(selinux);
|
|
#endif
|
|
virObjectUnref(dac);
|
|
virObjectUnref(stack);
|
|
return ret;
|
|
}
|
|
|
|
VIR_TEST_MAIN_PRELOAD(mymain,
|
|
VIR_TEST_MOCK("domaincaps"))
|