/tests/secaatest
/tests/seclabeltest
/tests/securityselinuxtest
+/tests/securityselinuxlabeltest
/tests/sexpr2xmltest
/tests/shunloadtest
/tests/sockettest
#include <string.h>
#include <limits.h>
- #if HAVE_NUMACTL Some system includes aren't supported
+ #if WITH_NUMACTL Some system includes aren't supported
# include <numa.h> everywhere so need these #if guards.
#endif
^((po|tests)/|docs/.*py|run.in$$)
exclude_file_name_regexp--sc_prohibit_raw_allocation = \
- ^(src/util/viralloc\.[ch]|examples/.*)$$
+ ^(src/util/viralloc\.[ch]|examples/.*|tests/securityselinuxhelper.c)$$
exclude_file_name_regexp--sc_prohibit_readlink = \
^src/(util/virutil|lxc/lxc_container)\.c$$
LIBVIRT_COMPILE_WARNINGS
LIBVIRT_CHECK_APPARMOR
+LIBVIRT_CHECK_ATTR
LIBVIRT_CHECK_AUDIT
LIBVIRT_CHECK_AVAHI
LIBVIRT_CHECK_BLKID
AC_MSG_NOTICE([Libraries])
AC_MSG_NOTICE([])
LIBVIRT_RESULT_APPARMOR
+LIBVIRT_RESULT_ATTR
LIBVIRT_RESULT_AUDIT
LIBVIRT_RESULT_AVAHI
LIBVIRT_RESULT_BLKID
BuildRequires: gettext
BuildRequires: libtasn1-devel
BuildRequires: gnutls-devel
+BuildRequires: libattr-devel
%if 0%{?fedora} >= 12 || 0%{?rhel} >= 6
# for augparse, optionally used in testing
BuildRequires: augeas
--- /dev/null
+dnl The libattr.so library
+
+AC_DEFUN([LIBVIRT_CHECK_ATTR],[
+ LIBVIRT_CHECK_LIB([ATTR], [attr], [getxattr], [attr/xattr.h])
+])
+
+AC_DEFUN([LIBVIRT_RESULT_ATTR],[
+ LIBVIRT_RESULT_LIB([ATTR])
+])
qemuxml2argvdata \
qemuxml2xmloutdata \
qemuxmlnsdata \
+ securityselinuxlabeldata \
schematestutils.sh \
sexpr2xmldata \
storagepoolschematest \
if WITH_SECDRIVER_SELINUX
test_programs += securityselinuxtest
+if WITH_ATTR
+test_programs += securityselinuxlabeltest
+endif
endif
if WITH_DRIVER_MODULES
securityselinuxtest.c testutils.h testutils.c
securityselinuxtest_CFLAGS = -Dabs_builddir="\"$(abs_builddir)\"" $(AM_CFLAGS)
securityselinuxtest_LDADD = $(LDADDS)
-securityselinuxtest_DEPENDENCIES = libsecurityselinuxhelper.la
-else
-EXTRA_DIST += securityselinuxtest.c securityselinuxhelper.c
+securityselinuxtest_DEPENDENCIES = libsecurityselinuxhelper.la ../src/libvirt.la
+
+if WITH_QEMU
+if WITH_ATTR
+securityselinuxlabeltest_SOURCES = \
+ securityselinuxlabeltest.c testutils.h testutils.c \
+ testutilsqemu.h testutilsqemu.c
+securityselinuxlabeltest_CFLAGS = -Dabs_builddir="\"$(abs_builddir)\"" $(AM_CFLAGS)
+securityselinuxlabeltest_LDADD = $(qemu_LDADDS)
+securityselinuxlabeltest_DEPENDENCIES = libsecurityselinuxhelper.la ../src/libvirt.la
+endif
+endif
endif
+EXTRA_DIST += securityselinuxtest.c securityselinuxlabeltest.c securityselinuxhelper.c
virbuftest_SOURCES = \
virbuftest.c testutils.h testutils.c
#include <string.h>
#include <unistd.h>
#include <errno.h>
+#include <attr/xattr.h>
+
+
/*
* The kernel policy will not allow us to arbitrarily change
* test process context. This helper is used as an LD_PRELOAD
{
return setenv("FAKE_CONTEXT", context, 1);
}
+
+
+#if WITH_ATTR
+int setfilecon(const char *path, security_context_t con)
+{
+ const char *constr = con;
+ return setxattr(path, "user.libvirt.selinux",
+ constr, strlen(constr), 0);
+}
+
+
+int getfilecon(const char *path, security_context_t *con)
+{
+ char *constr = NULL;
+ ssize_t len = getxattr(path, "user.libvirt.selinux",
+ NULL, 0);
+ if (len < 0)
+ return -1;
+ if (!(constr = malloc(len+1)))
+ return -1;
+ memset(constr, 0, len);
+ if (getxattr(path, "user.libvirt.selinux", constr, len) < 0) {
+ free(constr);
+ return -1;
+ }
+ *con = constr;
+ constr[len] = '\0';
+ return 0;
+}
+#endif
--- /dev/null
+/plain.txt;system_u:object_r:svirt_image_t:s0:c41,c264
+/plain.dev;system_u:object_r:svirt_image_t:s0:c41,c264
+/plain.fifo;system_u:object_r:svirt_image_t:s0:c41,c264
+/nolabel.sock;
+/plain.sock;
+/yeslabel.sock;system_u:object_r:svirt_image_t:s0:c41,c264
+/altlabel.sock;system_u:object_r:svirt_image_custom_t:s0:c41,c264
--- /dev/null
+<domain type='kvm'>
+ <name>vm1</name>
+ <uuid>c7b3edbd-edaf-9455-926a-d65c16db1800</uuid>
+ <memory unit='KiB'>219200</memory>
+ <os>
+ <type arch='i686' machine='pc-1.0'>hvm</type>
+ <boot dev='cdrom'/>
+ </os>
+ <devices>
+ <serial type='file'>
+ <source path='/plain.txt'/>
+ </serial>
+ <serial type='pipe'>
+ <source path='/plain.fifo'/>
+ </serial>
+ <serial type='dev'>
+ <source path='/plain.dev'/>
+ </serial>
+ <serial type='unix'>
+ <source mode='bind' path='/plain.sock'/>
+ </serial>
+ <serial type='unix'>
+ <source mode='connect' path='/nolabel.sock'>
+ <seclabel relabel='no' model='selinux'/>
+ </source>
+ </serial>
+ <serial type='unix'>
+ <source mode='connect' path='/yeslabel.sock'>
+ </source>
+ </serial>
+ <serial type='unix'>
+ <source mode='connect' path='/altlabel.sock'>
+ <seclabel relabel='yes' model='selinux'>
+ <label>system_u:object_r:svirt_image_custom_t:s0:c41,c264</label>
+ </seclabel>
+ </source>
+ </serial>
+ <input type='mouse' bus='ps2'/>
+ <graphics type='vnc' port='-1' autoport='yes' listen='0.0.0.0'>
+ <listen type='address' address='0.0.0.0'/>
+ </graphics>
+ </devices>
+ <seclabel model="selinux" type="dynamic" relabel="yes">
+ <label>system_u:system_r:svirt_t:s0:c41,c264</label>
+ <imagelabel>system_u:object_r:svirt_image_t:s0:c41,c264</imagelabel>
+ </seclabel>
+</domain>
--- /dev/null
+/plain.raw;system_u:object_r:svirt_image_t:s0:c41,c264
+/shared.raw;system_u:object_r:svirt_image_t:s0
+/readonly.raw;system_u:object_r:virt_content_t:s0
+/nolabel.raw;
+/altlabel.raw;system_u:object_r:svirt_image_custom_t:s0:c41,c264
--- /dev/null
+<domain type='kvm'>
+ <name>vm1</name>
+ <uuid>c7b3edbd-edaf-9455-926a-d65c16db1800</uuid>
+ <memory unit='KiB'>219200</memory>
+ <os>
+ <type arch='i686' machine='pc-1.0'>hvm</type>
+ <boot dev='cdrom'/>
+ </os>
+ <devices>
+ <disk type='file' device='disk'>
+ <driver name='qemu' type='raw'/>
+ <source file='/plain.raw'/>
+ <target dev='vda' bus='virtio'/>
+ </disk>
+ <disk type='file' device='disk'>
+ <driver name='qemu' type='raw'/>
+ <source file='/shared.raw'/>
+ <shareable/>
+ <target dev='vdb' bus='virtio'/>
+ </disk>
+ <disk type='file' device='disk'>
+ <driver name='qemu' type='raw'/>
+ <source file='/readonly.raw'/>
+ <readonly/>
+ <target dev='vdc' bus='virtio'/>
+ </disk>
+ <disk type='file' device='disk'>
+ <driver name='qemu' type='raw'/>
+ <source file='/nolabel.raw'>
+ <seclabel model='selinux' relabel='no'/>
+ </source>
+ <target dev='vdd' bus='virtio'/>
+ </disk>
+ <disk type='file' device='disk'>
+ <driver name='qemu' type='raw'/>
+ <source file='/altlabel.raw'>
+ <seclabel model='selinux' relabel='yes'>
+ <label>system_u:object_r:svirt_image_custom_t:s0:c41,c264</label>
+ </seclabel>
+ </source>
+ <target dev='vde' bus='virtio'/>
+ </disk>
+ <input type='mouse' bus='ps2'/>
+ <graphics type='vnc' port='-1' autoport='yes' listen='0.0.0.0'>
+ <listen type='address' address='0.0.0.0'/>
+ </graphics>
+ </devices>
+ <seclabel model="selinux" type="dynamic" relabel="yes">
+ <label>system_u:system_r:svirt_t:s0:c41,c264</label>
+ <imagelabel>system_u:object_r:svirt_image_t:s0:c41,c264</imagelabel>
+ </seclabel>
+</domain>
--- /dev/null
+/vmlinuz.raw;system_u:object_r:virt_content_t:s0
+/initrd.raw;system_u:object_r:virt_content_t:s0
--- /dev/null
+<domain type='kvm'>
+ <name>vm1</name>
+ <uuid>c7b3edbd-edaf-9455-926a-d65c16db1800</uuid>
+ <memory unit='KiB'>219200</memory>
+ <os>
+ <type arch='i686' machine='pc-1.0'>hvm</type>
+ <kernel>/vmlinuz.raw</kernel>
+ <initrd>/initrd.raw</initrd>
+ </os>
+ <devices>
+ <input type='mouse' bus='ps2'/>
+ <graphics type='vnc' port='-1' autoport='yes' listen='0.0.0.0'>
+ <listen type='address' address='0.0.0.0'/>
+ </graphics>
+ </devices>
+ <seclabel model="selinux" type="dynamic" relabel="yes">
+ <label>system_u:system_r:svirt_t:s0:c41,c264</label>
+ <imagelabel>system_u:object_r:svirt_image_t:s0:c41,c264</imagelabel>
+ </seclabel>
+</domain>
--- /dev/null
+/*
+ * Copyright (C) 2011-2012 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * License along with this library; If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include <selinux/selinux.h>
+#include <selinux/context.h>
+
+#include "internal.h"
+#include "testutils.h"
+#include "testutilsqemu.h"
+#include "qemu/qemu_domain.h"
+#include "viralloc.h"
+#include "virerror.h"
+#include "virfile.h"
+#include "virlog.h"
+#include "virutil.h"
+#include "security/security_manager.h"
+
+
+#define VIR_FROM_THIS VIR_FROM_NONE
+
+static virCapsPtr caps;
+
+static virSecurityManagerPtr mgr;
+
+typedef struct testSELinuxFile testSELinuxFile;
+
+struct testSELinuxFile {
+ char *file;
+ char *context;
+};
+
+
+static int
+testSELinuxMungePath(char **path)
+{
+ char *tmp;
+
+ if (virAsprintf(&tmp, "%s/securityselinuxlabeldata%s",
+ abs_srcdir, *path) < 0) {
+ virReportOOMError();
+ return -1;
+ }
+
+ VIR_FREE(*path);
+ *path = tmp;
+ return 0;
+}
+
+static int
+testSELinuxLoadFileList(const char *testname,
+ testSELinuxFile **files,
+ size_t *nfiles)
+{
+ int ret = -1;
+ char *path = NULL;
+ FILE *fp = NULL;
+
+ *files = NULL;
+ *nfiles = 0;
+
+ if (virAsprintf(&path, "%s/securityselinuxlabeldata/%s.txt",
+ abs_srcdir, testname) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ if (!(fp = fopen(path, "r"))) {
+ goto cleanup;
+ }
+
+ while (!feof(fp)) {
+ char *line;
+ char *file, *context;
+ if (VIR_ALLOC_N(line, 1024) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+ if (!fgets(line, 1024, fp)) {
+ if (!feof(fp))
+ goto cleanup;
+ break;
+ }
+
+ char *tmp = strchr(line, ';');
+ *tmp = '\0';
+ tmp++;
+
+ if (virAsprintf(&file, "%s/securityselinuxlabeldata%s", abs_builddir, line) < 0) {
+ VIR_FREE(line);
+ virReportOOMError();
+ goto cleanup;
+ }
+ if (*tmp != '\0' && *tmp != '\n') {
+ if (!(context = strdup(tmp))) {
+ VIR_FREE(line);
+ VIR_FREE(file);
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ tmp = strchr(context, '\n');
+ *tmp = '\0';
+ } else {
+ context = NULL;
+ }
+
+ if (VIR_EXPAND_N(*files, *nfiles, 1) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ (*files)[(*nfiles)-1].file = file;
+ (*files)[(*nfiles)-1].context = context;
+ }
+
+ ret = 0;
+
+cleanup:
+ VIR_FORCE_FCLOSE(fp);
+ VIR_FREE(path);
+ return ret;
+}
+
+
+static virDomainDefPtr
+testSELinuxLoadDef(const char *testname)
+{
+ char *xmlfile = NULL;
+ char *xmlstr = NULL;
+ virDomainDefPtr def = NULL;
+ size_t i;
+
+ if (virAsprintf(&xmlfile, "%s/securityselinuxlabeldata/%s.xml",
+ abs_srcdir, testname) < 0) {
+ virReportOOMError();
+ goto cleanup;
+ }
+
+ if (virFileReadAll(xmlfile, 1024*1024, &xmlstr) < 0) {
+ goto cleanup;
+ }
+
+ if (!(def = virDomainDefParseString(caps, xmlstr,
+ QEMU_EXPECTED_VIRT_TYPES,
+ 0)))
+ goto cleanup;
+
+ for (i = 0 ; i < def->ndisks ; i++) {
+ if (def->disks[i]->type != VIR_DOMAIN_DISK_TYPE_FILE &&
+ def->disks[i]->type != VIR_DOMAIN_DISK_TYPE_BLOCK)
+ continue;
+
+ if (testSELinuxMungePath(&def->disks[i]->src) < 0)
+ goto cleanup;
+ }
+
+ for (i = 0 ; i < def->nserials ; i++) {
+ if (def->serials[i]->source.type != VIR_DOMAIN_CHR_TYPE_FILE &&
+ def->serials[i]->source.type != VIR_DOMAIN_CHR_TYPE_PIPE &&
+ def->serials[i]->source.type != VIR_DOMAIN_CHR_TYPE_DEV &&
+ def->serials[i]->source.type != VIR_DOMAIN_CHR_TYPE_UNIX)
+ continue;
+
+ if (def->serials[i]->source.type == VIR_DOMAIN_CHR_TYPE_UNIX) {
+ if (testSELinuxMungePath(&def->serials[i]->source.data.nix.path) < 0)
+ goto cleanup;
+ } else {
+ if (testSELinuxMungePath(&def->serials[i]->source.data.file.path) < 0)
+ goto cleanup;
+ }
+ }
+
+ if (def->os.kernel &&
+ testSELinuxMungePath(&def->os.kernel) < 0)
+ goto cleanup;
+ if (def->os.initrd &&
+ testSELinuxMungePath(&def->os.initrd) < 0)
+ goto cleanup;
+
+cleanup:
+ VIR_FREE(xmlfile);
+ VIR_FREE(xmlstr);
+ return def;
+}
+
+
+static int
+testSELinuxCreateDisks(testSELinuxFile *files, size_t nfiles)
+{
+ size_t i;
+
+ if (virFileMakePath(abs_builddir "/securityselinuxlabeldata") < 0)
+ return -1;
+
+ for (i = 0 ; i < nfiles ; i++) {
+ if (virFileTouch(files[i].file, 0600) < 0)
+ return -1;
+ }
+ return 0;
+}
+
+static int
+testSELinuxDeleteDisks(testSELinuxFile *files, size_t nfiles)
+{
+ size_t i;
+
+ for (i = 0 ; i < nfiles ; i++) {
+ if (unlink(files[i].file) < 0)
+ return -1;
+ }
+ return 0;
+}
+
+static int
+testSELinuxCheckLabels(testSELinuxFile *files, size_t nfiles)
+{
+ size_t i;
+ security_context_t ctx;
+
+ for (i = 0 ; i < nfiles ; i++) {
+ if (getfilecon(files[i].file, &ctx) < 0) {
+ if (errno == ENODATA) {
+ ctx = NULL;
+ } else {
+ virReportSystemError(errno,
+ "Cannot read label on %s",
+ files[i].file);
+ return -1;
+ }
+ }
+ if (!STREQ_NULLABLE(files[i].context, ctx)) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ "File %s context '%s' did not match epected '%s'",
+ files[i].file, ctx, files[i].context);
+ return -1;
+ }
+ }
+ return 0;
+}
+
+static int
+testSELinuxLabeling(const void *opaque)
+{
+ const char *testname = opaque;
+ int ret = -1;
+ testSELinuxFile *files = NULL;
+ size_t nfiles = 0;
+ size_t i;
+ virDomainDefPtr def = NULL;
+
+ if (testSELinuxLoadFileList(testname, &files, &nfiles) < 0)
+ goto cleanup;
+
+ if (testSELinuxCreateDisks(files, nfiles) < 0)
+ goto cleanup;
+
+ if (!(def = testSELinuxLoadDef(testname)))
+ goto cleanup;
+
+ if (virSecurityManagerSetAllLabel(mgr, def, NULL) < 0)
+ goto cleanup;
+
+ if (testSELinuxCheckLabels(files, nfiles) < 0)
+ goto cleanup;
+
+ ret = 0;
+
+cleanup:
+ if (testSELinuxDeleteDisks(files, nfiles) < 0)
+ goto cleanup;
+
+ virDomainDefFree(def);
+ for (i = 0 ; i < nfiles; i++) {
+ VIR_FREE(files[i].file);
+ VIR_FREE(files[i].context);
+ }
+ VIR_FREE(files);
+ return ret;
+}
+
+
+
+static int
+mymain(void)
+{
+ int ret = 0;
+
+ if (!(mgr = virSecurityManagerNew("selinux", "QEMU", false, true, false))) {
+ virErrorPtr err = virGetLastError();
+ if (err->code == VIR_ERR_CONFIG_UNSUPPORTED)
+ exit(EXIT_AM_SKIP);
+
+ fprintf(stderr, "Unable to initialize security driver: %s\n",
+ err->message);
+ exit(EXIT_FAILURE);
+ }
+
+ if ((caps = testQemuCapsInit()) == NULL)
+ exit(EXIT_FAILURE);
+
+#define DO_TEST_LABELING(name) \
+ if (virtTestRun("Labelling " # name, 1, testSELinuxLabeling, name) < 0) \
+ ret = -1; \
+
+ setcon((security_context_t)"system_r:system_u:libvirtd_t:s0:c0.c1023");
+
+ DO_TEST_LABELING("disks");
+ DO_TEST_LABELING("kernel");
+ DO_TEST_LABELING("chardev");
+
+ return (ret == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
+}
+
+VIRT_TEST_MAIN_PRELOAD(mymain, abs_builddir "/.libs/libsecurityselinuxhelper.so")