[libvirt] [PATCH v2] Introduce Smack security driver for Libvirt
by Randy Aybar (raybar)
Thanks Daniel and Laine for the feedback so far. Below is a brief list of changes since v1 as well as the patch which should be complete this time.
For others, introduction and background can be found here along with latest response:
https://www.redhat.com/archives/libvir-list/2016-May/msg00628.html
Changes since v1:
Security requirements involving kernel patching to bring in a new
Smack interface are now documented in "docs/drvlxc.html.in”
Fixed the syntax and spacing as requested and recommended by the
“make check-syntax” script
Moved Smack related block in configure.ac to the dedicated m4 file
(m4/virt-smack.m4)
Removed the check for Smack-specific driver before calling
SetChildProcessLabel in lxc_container.c and moved the function call
outside of the namespaces conditional.
Replaced calloc/malloc and open/read/close calls with Libvirt specific
macros in the Smack driver.
Modified src/Makefile to include security driver libraries when
compiling libvirt_nss and dependencies
configure.ac | 4 +
docs/drvlxc.html.in | 14 +-
m4/virt-smack.m4 | 69 ++
po/POTFILES.in | 1 +
src/Makefile.am | 14 +-
src/lxc/lxc_container.c | 24 +-
src/lxc/lxc_controller.c | 21 +
src/security/security_apparmor.c | 9 +
src/security/security_dac.c | 9 +
src/security/security_driver.c | 7 +
src/security/security_driver.h | 4 +
src/security/security_manager.c | 17 +
src/security/security_manager.h | 3 +
src/security/security_nop.c | 8 +
src/security/security_selinux.c | 9 +
src/security/security_smack.c | 1484 ++++++++++++++++++++++++++++++++++++++
src/security/security_smack.h | 37 +
src/security/security_stack.c | 9 +
src/util/vircommand.c | 63 ++
src/util/vircommand.h | 3 +
20 files changed, 1798 insertions(+), 11 deletions(-)
create mode 100644 m4/virt-smack.m4
create mode 100644 src/security/security_smack.c
create mode 100644 src/security/security_smack.h
Signed-off-by: Randy Aybar <raybar(a)cisco.com>
---
diff --git a/configure.ac b/configure.ac
index 378069d..c785914 100644
--- a/configure.ac
+++ b/configure.ac
@@ -255,6 +255,7 @@ LIBVIRT_CHECK_READLINE
LIBVIRT_CHECK_SANLOCK
LIBVIRT_CHECK_SASL
LIBVIRT_CHECK_SELINUX
+LIBVIRT_CHECK_SMACK
LIBVIRT_CHECK_SSH2
LIBVIRT_CHECK_SYSTEMD_DAEMON
LIBVIRT_CHECK_UDEV
@@ -1459,6 +1460,7 @@ if test "$with_apparmor" = "no"; then
fi
AM_CONDITIONAL([WITH_APPARMOR_PROFILES], [test "$with_apparmor_profiles" != "no"])
+
dnl DTrace static probes
AC_ARG_WITH([dtrace],
[AS_HELP_STRING([--with-dtrace],
@@ -2754,6 +2756,7 @@ AC_MSG_NOTICE([Security Drivers])
AC_MSG_NOTICE([])
AC_MSG_NOTICE([ SELinux: $with_secdriver_selinux ($SELINUX_MOUNT)])
AC_MSG_NOTICE([AppArmor: $with_secdriver_apparmor (install profiles: $with_apparmor_profiles)])
+AC_MSG_NOTICE([Smack: $with_secdriver_smack])
AC_MSG_NOTICE([])
AC_MSG_NOTICE([Driver Loadable Modules])
AC_MSG_NOTICE([])
@@ -2784,6 +2787,7 @@ LIBVIRT_RESULT_READLINE
LIBVIRT_RESULT_SANLOCK
LIBVIRT_RESULT_SASL
LIBVIRT_RESULT_SELINUX
+LIBVIRT_RESULT_SMACK
LIBVIRT_RESULT_SSH2
LIBVIRT_RESULT_SYSTEMD_DAEMON
LIBVIRT_RESULT_UDEV
diff --git a/docs/drvlxc.html.in b/docs/drvlxc.html.in
index 3dc9d59..f96c9ba 100644
--- a/docs/drvlxc.html.in
+++ b/docs/drvlxc.html.in
@@ -157,8 +157,7 @@ to all containers are
<li><code>/dev/console</code> symlinked to <code>/dev/pts/0</code></li>
</ul>
-<p>
-In addition, for every console defined in the guest configuration,
+<p> In addition, for every console defined in the guest configuration,
a symlink will be created from <code>/dev/ttyN</code> symlinked to
the corresponding <code>/dev/pts/M</code> pseudo TTY device. The
first console will be <code>/dev/tty1</code>, with further consoles
@@ -190,6 +189,17 @@ isolation between a container and the host must ensure that they are
writing a suitable configuration.
</p>
+<p>
+NOTE: The SMACK security driver depends on a security interface provided
+by the SMACK LSM to fully enforced with namespaces. This interface is
+brought in by the Linux kernel version 4.3. It is recommended to use the
+appropriate kernel version or backport the below changes to ensure proper
+opertaion of the SMACK driver with namespaces.
+
+Link that references the change in the kernel:
+<a href="https://lwn.net/Articles/660675/">https://lwn.net/Articles/660675/</a>
+</p>
+
<h3><a name="securenetworking">Network isolation</a></h3>
<p>
diff --git a/m4/virt-smack.m4 b/m4/virt-smack.m4
new file mode 100644
index 0000000..b555733
--- /dev/null
+++ b/m4/virt-smack.m4
@@ -0,0 +1,69 @@
+dnl The libsmack.so library
+dnl
+dnl Copyright (C) 2013 changyaoh.
+dnl
+dnl This library is free software; you can redistribute it and/or
+dnl modify it under the terms of the GNU Lesser General Public
+dnl License as published by the Free Software Foundation; either
+dnl version 2.1 of the License, or (at your option) any later version.
+dnl
+dnl This library is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+dnl Lesser General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU Lesser General Public
+dnl License along with this library. If not, see
+dnl <http://www.gnu.org/licenses/>.
+dnl
+
+AC_DEFUN([LIBVIRT_CHECK_SMACK],[
+ LIBVIRT_CHECK_LIB([SMACK], [smack],
+ [smack_set_label_for_self], [sys/smack.h])
+
+ AC_ARG_WITH([secdriver-smack],
+ [AS_HELP_STRING([--with-secdriver-smack],
+ [use Smack security driver @<:@default=check@:>@])],
+ [],
+ [with_secdriver_smack=check])
+
+ if test "$with_smack" != "yes" ; then
+ if test "$with_secdriver_smack" = "check" ; then
+ with_secdriver_smack=no
+ fi
+ if test "$with_secdriver_smack" != "no" ; then
+ AC_MSG_ERROR([You must install the Smack development package in order to compile libvirt])
+ fi
+ elif test "with_secdriver_smack" != "no" ; then
+ with_secdriver_smack=yes
+ AC_DEFINE_UNQUOTED([WITH_SECDRIVER_SMACK], 1, [whether Smack security driver is available])
+ fi
+ AM_CONDITIONAL([WITH_SECDRIVER_SMACK], [test "$with_secdriver_smack" != "no"])
+
+
+
+ AC_ARG_WITH([smack_mount],
+ [AS_HELP_STRING([--with-smack-mount],
+ [set Smack mount point @<:@default=check@:>@])],
+ [],
+ [with_smack_mount=check])
+
+ if test "$with_smack" = "yes"; then
+ AC_MSG_CHECKING([Smack mount point])
+ if test "$with_smack_mount" = "check" || test -z "$with_smack_mount"; then
+ if test -d /sys/fs/smackfs ; then
+ SMACK_MOUNT=/sys/fs/smackfs
+ else
+ SMACK_MOUNT=/smack
+ fi
+ else
+ SMACK_MOUNT=$with_smack_mount
+ fi
+ AC_MSG_RESULT([$SMACK_MOUNT])
+ AC_DEFINE_UNQUOTED([SMACK_MOUNT], ["$SMACK_MOUNT"], [Smack mount point])
+ fi
+])
+
+AC_DEFUN([LIBVIRT_RESULT_SMACK],[
+ LIBVIRT_RESULT_LIB([SMACK])
+])
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 506d535..99e6d6e 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -159,6 +159,7 @@ src/security/security_dac.c
src/security/security_driver.c
src/security/security_manager.c
src/security/security_selinux.c
+src/security/security_smack.c
src/security/virt-aa-helper.c
src/storage/parthelper.c
src/storage/storage_backend.c
diff --git a/src/Makefile.am b/src/Makefile.am
index 314f6df..9e53ed9 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -68,6 +68,10 @@ if WITH_SECDRIVER_APPARMOR
SECDRIVER_CFLAGS += $(APPARMOR_CFLAGS)
SECDRIVER_LIBS += $(APPARMOR_LIBS)
endif WITH_SECDRIVER_APPARMOR
+if WITH_SECDRIVER_SMACK
+SECDRIVER_CFLAGS += $(SMACK_CFLAGS)
+SECDRIVER_LIBS += $(SMACK_LIBS)
+endif WITH_SECDRIVER_SMACK
if WITH_NETWORK
UUID=$(shell uuidgen 2>/dev/null)
@@ -1017,6 +1021,9 @@ SECURITY_DRIVER_SELINUX_SOURCES = \
SECURITY_DRIVER_APPARMOR_SOURCES = \
security/security_apparmor.h security/security_apparmor.c
+SECURITY_DRIVER_SMACK_SOURCES = \
+ security/security_smack.h security/security_smack.c
+
ACCESS_DRIVER_GENERATED = \
access/viraccessapicheck.h \
access/viraccessapicheck.c \
@@ -1765,6 +1772,10 @@ if WITH_SECDRIVER_APPARMOR
libvirt_security_manager_la_SOURCES += $(SECURITY_DRIVER_APPARMOR_SOURCES)
libvirt_security_manager_la_CFLAGS += $(APPARMOR_CFLAGS)
endif WITH_SECDRIVER_APPARMOR
+if WITH_SECDRIVER_SMACK
+libvirt_security_manager_la_SOURCES += $(SECURITY_DRIVER_SMACK_SOURCES)
+libvirt_security_manager_la_CFLAGS += $(SMACK_CFLAGS)
+endif WITH_SECDRIVER_SMACK
libvirt_driver_access_la_SOURCES = \
$(ACCESS_DRIVER_SOURCES) $(ACCESS_DRIVER_GENERATED)
@@ -1896,6 +1907,7 @@ EXTRA_DIST += \
$(NWFILTER_DRIVER_SOURCES) \
$(SECURITY_DRIVER_SELINUX_SOURCES) \
$(SECURITY_DRIVER_APPARMOR_SOURCES) \
+ $(SECURITY_DRIVER_SMACK_SOURCES) \
$(SECRET_DRIVER_SOURCES) \
$(SECRET_UTIL_SOURCES) \
$(VBOX_DRIVER_EXTRA_DIST) \
@@ -3030,12 +3042,12 @@ libvirt_nss_la_SOURCES = \
libvirt_nss_la_CFLAGS = \
-DLIBVIRT_NSS \
$(AM_CFLAGS) \
+ $(SECDRIVER_LIBS) \
$(YAJL_CFLAGS) \
$(NULL)
libvirt_nss_la_LDFLAGS = \
$(AM_LDFLAGS) \
$(NULL)
-
libvirt_nss_la_LIBADD = \
$(YAJL_LIBS) \
$(NULL)
diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c
index a909b66..ff0e461 100644
--- a/src/lxc/lxc_container.c
+++ b/src/lxc/lxc_container.c
@@ -2206,6 +2206,10 @@ static int lxcContainerChild(void *data)
if (lxcContainerSetID(vmDef) < 0)
goto cleanup;
+ VIR_DEBUG("Setting up security labeling");
+ if (virSecurityManagerSetProcessLabel(argv->securityDriver, vmDef) < 0)
+ goto cleanup;
+
root = virDomainGetFilesystemForTarget(vmDef, "/");
if (argv->nttyPaths) {
@@ -2254,20 +2258,12 @@ static int lxcContainerChild(void *data)
goto cleanup;
}
- /* drop a set of root capabilities */
- if (lxcContainerDropCapabilities(vmDef, !!hasReboot) < 0)
- goto cleanup;
-
if (lxcContainerSendContinue(argv->handshakefd) < 0) {
virReportSystemError(errno, "%s",
_("Failed to send continue signal to controller"));
goto cleanup;
}
- VIR_DEBUG("Setting up security labeling");
- if (virSecurityManagerSetProcessLabel(argv->securityDriver, vmDef) < 0)
- goto cleanup;
-
VIR_DEBUG("Setting up inherited FDs");
VIR_FORCE_CLOSE(argv->handshakefd);
VIR_FORCE_CLOSE(argv->monitor);
@@ -2275,6 +2271,10 @@ static int lxcContainerChild(void *data)
argv->npassFDs, argv->passFDs) < 0)
goto cleanup;
+ /* drop a set of root capabilities */
+ if (lxcContainerDropCapabilities(vmDef, !!hasReboot) < 0)
+ goto cleanup;
+
ret = 0;
cleanup:
VIR_FREE(ttyPath);
@@ -2396,6 +2396,14 @@ int lxcContainerStart(virDomainDefPtr def,
return -1;
}
}
+
+ VIR_DEBUG("Setting up security labeling");
+ if (virSecurityManagerSetChildProcessLabel(securityDriver, def, NULL) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Failed to send label to relabel interface."));
+ return -1;
+ }
+
if (!nsInheritFDs || nsInheritFDs[VIR_LXC_DOMAIN_NAMESPACE_SHARENET] == -1) {
if (lxcNeedNetworkNamespace(def)) {
VIR_DEBUG("Enable network namespaces");
diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c
index 0304354..026762e 100644
--- a/src/lxc/lxc_controller.c
+++ b/src/lxc/lxc_controller.c
@@ -1484,6 +1484,9 @@ static int virLXCControllerSetupDev(virLXCControllerPtr ctrl)
if (lxcContainerChown(ctrl->def, dev) < 0)
goto cleanup;
+ if (virSecurityManagerSetImagePathLabel(ctrl->securityManager, ctrl->def, dev) < 0)
+ goto cleanup;
+
ret = 0;
cleanup:
VIR_FREE(opts);
@@ -1532,6 +1535,11 @@ static int virLXCControllerPopulateDevices(virLXCControllerPtr ctrl)
if (lxcContainerChown(ctrl->def, path) < 0)
goto cleanup;
+ if (virSecurityManagerSetImagePathLabel(ctrl->securityManager,
+ ctrl->def,
+ path) < 0)
+ goto cleanup;
+
VIR_FREE(path);
}
@@ -2190,6 +2198,14 @@ virLXCControllerSetupDevPTS(virLXCControllerPtr ctrl)
(lxcContainerChown(ctrl->def, devpts) < 0))
goto cleanup;
+ if ((virSecurityManagerSetImagePathLabel(ctrl->securityManager,
+ ctrl->def,
+ ctrl->devptmx)) < 0 ||
+ (virSecurityManagerSetImagePathLabel(ctrl->securityManager,
+ ctrl->def,
+ devpts) < 0))
+ goto cleanup;
+
ret = 0;
cleanup:
@@ -2234,6 +2250,11 @@ virLXCControllerSetupConsoles(virLXCControllerPtr ctrl,
if (lxcContainerChown(ctrl->def, ttyHostPath) < 0)
goto cleanup;
+ if (virSecurityManagerSetImagePathLabel(ctrl->securityManager,
+ ctrl->def,
+ ttyHostPath) < 0)
+ goto cleanup;
+
VIR_FREE(ttyHostPath);
}
diff --git a/src/security/security_apparmor.c b/src/security/security_apparmor.c
index af2b639..bffcf83 100644
--- a/src/security/security_apparmor.c
+++ b/src/security/security_apparmor.c
@@ -986,6 +986,14 @@ AppArmorSetFDLabel(virSecurityManagerPtr mgr,
return reload_profile(mgr, def, fd_path, true);
}
+static int
+AppArmorSetPathLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
+ virDomainDefPtr def ATTRIBUTE_UNUSED,
+ const char *path ATTRIBUTE_UNUSED)
+{
+ return 0;
+}
+
static char *
AppArmorGetMountOptions(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
virDomainDefPtr vm ATTRIBUTE_UNUSED)
@@ -1043,6 +1051,7 @@ virSecurityDriver virAppArmorSecurityDriver = {
.domainRestoreSavedStateLabel = AppArmorRestoreSavedStateLabel,
.domainSetSecurityImageFDLabel = AppArmorSetFDLabel,
+ .domainSetSecurityImagePathLabel = AppArmorSetPathLabel,
.domainSetSecurityTapFDLabel = AppArmorSetFDLabel,
.domainGetSecurityMountOptions = AppArmorGetMountOptions,
diff --git a/src/security/security_dac.c b/src/security/security_dac.c
index df3ed47..0ada728 100644
--- a/src/security/security_dac.c
+++ b/src/security/security_dac.c
@@ -1519,6 +1519,14 @@ virSecurityDACSetImageFDLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
}
static int
+virSecurityDACSetImagePathLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
+ virDomainDefPtr def ATTRIBUTE_UNUSED,
+ const char *path ATTRIBUTE_UNUSED)
+{
+ return 0;
+}
+
+static int
virSecurityDACSetTapFDLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
virDomainDefPtr def ATTRIBUTE_UNUSED,
int fd ATTRIBUTE_UNUSED)
@@ -1601,6 +1609,7 @@ virSecurityDriver virSecurityDriverDAC = {
.domainRestoreSavedStateLabel = virSecurityDACRestoreSavedStateLabel,
.domainSetSecurityImageFDLabel = virSecurityDACSetImageFDLabel,
+ .domainSetSecurityImagePathLabel = virSecurityDACSetImagePathLabel,
.domainSetSecurityTapFDLabel = virSecurityDACSetTapFDLabel,
.domainGetSecurityMountOptions = virSecurityDACGetMountOptions,
diff --git a/src/security/security_driver.c b/src/security/security_driver.c
index 4800d52..3ca3766 100644
--- a/src/security/security_driver.c
+++ b/src/security/security_driver.c
@@ -35,6 +35,10 @@
# include "security_apparmor.h"
#endif
+#ifdef WITH_SECDRIVER_SMACK
+# include "security_smack.h"
+#endif
+
#include "security_nop.h"
#define VIR_FROM_THIS VIR_FROM_SECURITY
@@ -48,6 +52,9 @@ static virSecurityDriverPtr security_drivers[] = {
#ifdef WITH_SECDRIVER_APPARMOR
&virAppArmorSecurityDriver,
#endif
+#ifdef WITH_SECDRIVER_SMACK
+ &virSecurityDriverSmack,
+#endif
&virSecurityDriverNop, /* Must always be last, since it will always probe */
};
diff --git a/src/security/security_driver.h b/src/security/security_driver.h
index 7cb62f0..97c0c30 100644
--- a/src/security/security_driver.h
+++ b/src/security/security_driver.h
@@ -104,6 +104,9 @@ typedef int (*virSecurityDomainSecurityVerify) (virSecurityManagerPtr mgr,
typedef int (*virSecurityDomainSetImageFDLabel) (virSecurityManagerPtr mgr,
virDomainDefPtr def,
int fd);
+typedef int (*virSecurityDomainSetImagePathLabel) (virSecurityManagerPtr mgr,
+ virDomainDefPtr def,
+ const char *path);
typedef int (*virSecurityDomainSetTapFDLabel) (virSecurityManagerPtr mgr,
virDomainDefPtr def,
int fd);
@@ -165,6 +168,7 @@ struct _virSecurityDriver {
virSecurityDomainRestoreSavedStateLabel domainRestoreSavedStateLabel;
virSecurityDomainSetImageFDLabel domainSetSecurityImageFDLabel;
+ virSecurityDomainSetImagePathLabel domainSetSecurityImagePathLabel;
virSecurityDomainSetTapFDLabel domainSetSecurityTapFDLabel;
virSecurityDomainGetMountOptions domainGetSecurityMountOptions;
diff --git a/src/security/security_manager.c b/src/security/security_manager.c
index ecb4a40..507c41e 100644
--- a/src/security/security_manager.c
+++ b/src/security/security_manager.c
@@ -916,6 +916,23 @@ virSecurityManagerSetImageFDLabel(virSecurityManagerPtr mgr,
return -1;
}
+int
+virSecurityManagerSetImagePathLabel(virSecurityManagerPtr mgr,
+ virDomainDefPtr vm,
+ const char* path)
+{
+ if (mgr->drv->domainSetSecurityImagePathLabel) {
+ int ret;
+ virObjectLock(mgr);
+ ret = mgr->drv->domainSetSecurityImagePathLabel(mgr, vm, path);
+ virObjectUnlock(mgr);
+ return ret;
+ }
+
+ virReportUnsupportedError();
+ return -1;
+}
+
int
virSecurityManagerSetTapFDLabel(virSecurityManagerPtr mgr,
diff --git a/src/security/security_manager.h b/src/security/security_manager.h
index 4cbc2d8..886d00a 100644
--- a/src/security/security_manager.h
+++ b/src/security/security_manager.h
@@ -143,6 +143,9 @@ int virSecurityManagerVerify(virSecurityManagerPtr mgr,
int virSecurityManagerSetImageFDLabel(virSecurityManagerPtr mgr,
virDomainDefPtr def,
int fd);
+int virSecurityManagerSetImagePathLabel(virSecurityManagerPtr mgr,
+ virDomainDefPtr def,
+ const char *path);
int virSecurityManagerSetTapFDLabel(virSecurityManagerPtr mgr,
virDomainDefPtr vm,
int fd);
diff --git a/src/security/security_nop.c b/src/security/security_nop.c
index 951125d..3d4d47a 100644
--- a/src/security/security_nop.c
+++ b/src/security/security_nop.c
@@ -236,6 +236,13 @@ virSecurityDomainSetImageLabelNop(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
return 0;
}
+static int
+virSecurityDomainSetPathLabelNop(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
+ virDomainDefPtr def ATTRIBUTE_UNUSED,
+ const char* path ATTRIBUTE_UNUSED)
+{
+ return 0;
+}
virSecurityDriver virSecurityDriverNop = {
.privateDataLen = 0,
@@ -277,6 +284,7 @@ virSecurityDriver virSecurityDriverNop = {
.domainRestoreSavedStateLabel = virSecurityDomainRestoreSavedStateLabelNop,
.domainSetSecurityImageFDLabel = virSecurityDomainSetFDLabelNop,
+ .domainSetSecurityImagePathLabel = virSecurityDomainSetPathLabelNop,
.domainSetSecurityTapFDLabel = virSecurityDomainSetFDLabelNop,
.domainGetSecurityMountOptions = virSecurityDomainGetMountOptionsNop,
diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c
index b33d54a..56e07ca 100644
--- a/src/security/security_selinux.c
+++ b/src/security/security_selinux.c
@@ -2467,6 +2467,14 @@ virSecuritySELinuxSetImageFDLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
}
static int
+virSecuritySELinuxSetImagePathLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
+ virDomainDefPtr def ATTRIBUTE_UNUSED,
+ const char *path ATTRIBUTE_UNUSED)
+{
+ return 0;
+}
+
+static int
virSecuritySELinuxSetTapFDLabel(virSecurityManagerPtr mgr,
virDomainDefPtr def,
int fd)
@@ -2647,6 +2655,7 @@ virSecurityDriver virSecurityDriverSELinux = {
.domainRestoreSavedStateLabel = virSecuritySELinuxRestoreSavedStateLabel,
.domainSetSecurityImageFDLabel = virSecuritySELinuxSetImageFDLabel,
+ .domainSetSecurityImagePathLabel = virSecuritySELinuxSetImagePathLabel,
.domainSetSecurityTapFDLabel = virSecuritySELinuxSetTapFDLabel,
.domainGetSecurityMountOptions = virSecuritySELinuxGetSecurityMountOptions,
diff --git a/src/security/security_smack.c b/src/security/security_smack.c
new file mode 100644
index 0000000..6f43db4
--- /dev/null
+++ b/src/security/security_smack.c
@@ -0,0 +1,1484 @@
+/*
+ * Copyright (C) 2015 Cisco Systems, 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/>.
+ *
+ * Author:
+ * Hongliang Liang <hliang(a)bupt.edu.cn>
+ * Changyao Han <changyao(a)bupt.edu.cn>
+ *
+ * Updated to libvirt v1.2.15: (Original was written for libvirt v1.1.4)
+ * Raghuram S. Sudhaakar <rsudhaak(a)cisco.com>
+ * Randy Aybar <raybar(a)cisco.com>
+ *
+ * Based on security_selinux.c by James Morris <jmorris(a)namei.org>
+ * and security_apparmor.c by Jamie Strandboge <jamie(a)canonical.com>
+ *
+ * Smack scurity driver.
+ *
+ */
+
+#include <config.h>
+
+#include <sys/types.h>
+#include <sys/xattr.h>
+#include <sys/stat.h>
+#include <sys/syscall.h>
+#include <fcntl.h>
+#include <sys/smack.h>
+#include <errno.h>
+#include <unistd.h>
+#include <wait.h>
+#include <stdlib.h>
+
+#include "security_smack.h"
+#include "virerror.h"
+#include "viralloc.h"
+#include "datatypes.h"
+#include "viruuid.h"
+#include "virlog.h"
+#include "virpci.h"
+#include "virusb.h"
+#include "virscsi.h"
+#include "virstoragefile.h"
+#include "virfile.h"
+#include "configmake.h"
+#include "vircommand.h"
+#include "virhash.h"
+#include "virstring.h"
+
+#define VIR_FROM_THIS VIR_FROM_SECURITY
+VIR_LOG_INIT("security.security_smack");
+
+#define SECURITY_SMACK_VOID_DOI "0"
+#define SECURITY_SMACK_NAME "smack"
+
+typedef struct _SmackCallbackData SmackCallbackData;
+typedef SmackCallbackData *SmackCallbackDataPtr;
+
+struct _SmackCallbackData {
+ virSecurityManagerPtr manager;
+ virSecurityLabelDefPtr secdef;
+};
+
+static char *
+virSecuritySmackGetLabelName(virDomainDefPtr def)
+{
+ char uuidstr[VIR_UUID_STRING_BUFLEN];
+ char *name = NULL;
+
+ virUUIDFormat(def->uuid, uuidstr);
+ if (virAsprintf(&name, "%s%s", SMACK_PREFIX, uuidstr) < 0)
+ return NULL;
+
+ return name;
+}
+
+static int
+virSecuritySmackGetPIDLabel(pid_t pid, char **label)
+{
+ char *result, *path;
+ int ret;
+
+ ret = VIR_ALLOC_N(result, SMACK_LABEL_LEN + 1);
+ if (ret < 0 || result == NULL)
+ return -1;
+ ret = virAsprintf(&path, "/proc/%d/attr/current", pid);
+ if (ret < 0)
+ return -1;
+
+ ret = virFileReadAll(path, SMACK_LABEL_LEN, label);
+
+ VIR_FREE(path);
+ return ret;
+}
+
+int
+virSecuritySmackSockCreate(const char *label, const char *attr)
+{
+ int ret = -1;
+ long int tid;
+ char *path;
+
+ tid = syscall(SYS_gettid);
+
+ VIR_DEBUG("/proc/self/task/%ld/attr/%s", tid, attr);
+
+ if (virAsprintf(&path, "/proc/self/task/%ld/attr/%s", tid, attr) < 0)
+ return -1;
+
+ VIR_DEBUG("setSockCreate pid is in %d", getpid());
+ VIR_DEBUG("real user ID is in %d", getuid());
+ VIR_DEBUG("effective user ID is in %d", geteuid());
+ VIR_DEBUG("label from self %s", label);
+ VIR_DEBUG("location /proc/self/attr/%s", attr);
+
+ ret = virFileWriteStr(path, label != NULL ? label : "", 0);
+
+ VIR_FREE(path);
+ return ret;
+}
+
+static int
+virSecuritySmackSetPathLabel(const char *path, const char *tlabel)
+{
+ char * elabel = NULL;
+
+ VIR_INFO("Setting Smack label on '%s' to '%s'", path, tlabel);
+
+ if (smack_set_label_for_path(path, "security.SMACK64", 0, tlabel) < 0) {
+ int setfilelabel_errno = errno;
+
+ if (smack_new_label_from_path(path, "security.SMACK64", 0, &elabel) >= 0) {
+ if (STREQ(tlabel, elabel)) {
+ VIR_FREE(elabel);
+ /* It's alright, there's nothing to change anyway. */
+ return 0;
+ }
+ VIR_FREE(elabel);
+ }
+
+ /* 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.
+ */
+
+ if (setfilelabel_errno != EOPNOTSUPP && setfilelabel_errno != ENOTSUP) {
+ virReportSystemError(setfilelabel_errno,
+ _("unable to set security context '%s' on '%s'"),
+ tlabel, path);
+ return -1;
+
+ } else {
+ const char *msg;
+ if ((virFileIsSharedFS(path) == 1)) {
+ msg = _("Setting security context '%s' on '%s' not supported. ");
+ VIR_WARN(msg, tlabel, path);
+ } else {
+ VIR_INFO("Setting security context '%s' on '%s' not supported",
+ tlabel, path);
+
+ }
+
+ }
+
+ }
+ return 0;
+
+}
+
+static int
+virSecuritySmackSetHostdevLabelHelper(const char *file, void *opaque)
+{
+ virSecurityLabelDefPtr seclabel;
+ virDomainDefPtr def = opaque;
+
+ seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_SMACK_NAME);
+ if (seclabel == NULL)
+ return -1;
+ return virSecuritySmackSetPathLabel(file, seclabel->imagelabel);
+}
+
+static int
+virSecuritySmackSetUSBLabel(virUSBDevicePtr dev ATTRIBUTE_UNUSED,
+ const char *file, void *opaque)
+{
+ return virSecuritySmackSetHostdevLabelHelper(file, opaque);
+}
+
+
+static int
+virSecuritySmackSetPCILabel(virPCIDevicePtr dev ATTRIBUTE_UNUSED,
+ const char *file, void *opaque)
+{
+ return virSecuritySmackSetHostdevLabelHelper(file, opaque);
+}
+
+static int
+virSecuritySmackSetSCSILabel(virSCSIDevicePtr dev ATTRIBUTE_UNUSED,
+ const char *file, void *opaque)
+{
+ return virSecuritySmackSetHostdevLabelHelper(file, opaque);
+}
+
+
+static int
+virSecuritySmackRestoreFileLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
+ const char *path)
+{
+ struct stat buf;
+ int ret = -1;
+ char *newpath = NULL;
+ char ebuf[1024];
+
+ VIR_INFO("Restoring Smack label on '%s'", path);
+
+ if (virFileResolveLink(path, &newpath) < 0) {
+ VIR_WARN("cannot resolve symlink %s: %s", path,
+ virStrerror(errno, ebuf, sizeof(ebuf)));
+ goto err;
+ }
+
+ if (stat(newpath, &buf) != 0) {
+ VIR_WARN("cannot stat %s: %s", newpath,
+ virStrerror(errno, ebuf, sizeof(ebuf)));
+ goto err;
+ }
+
+ ret = virSecuritySmackSetPathLabel(newpath, "smack-unused");
+
+ err:
+ VIR_FREE(newpath);
+ return ret;
+}
+
+
+static int
+virSecuritySmackRestoreUSBLabel(virUSBDevicePtr dev ATTRIBUTE_UNUSED,
+ const char *file,
+ void *opaque)
+{
+ virSecurityManagerPtr mgr = opaque;
+
+ return virSecuritySmackRestoreFileLabel(mgr, file);
+}
+
+static int
+virSecuritySmackRestorePCILabel(virPCIDevicePtr dev ATTRIBUTE_UNUSED,
+ const char *file,
+ void *opaque)
+{
+ virSecurityManagerPtr mgr = opaque;
+
+ return virSecuritySmackRestoreFileLabel(mgr, file);
+}
+
+static int
+virSecuritySmackRestoreSCSILabel(virSCSIDevicePtr dev ATTRIBUTE_UNUSED,
+ const char *file,
+ void *opaque)
+{
+ virSecurityManagerPtr mgr = opaque;
+
+ return virSecuritySmackRestoreFileLabel(mgr, file);
+}
+
+static int
+virSecuritySmackRestoreImageLabelInt(virSecurityManagerPtr mgr,
+ virDomainDefPtr def,
+ virStorageSourcePtr src,
+ bool migrated)
+{
+ virSecurityLabelDefPtr seclabel;
+
+ seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_SMACK_NAME);
+
+ if (seclabel == NULL)
+ return -1;
+
+ if (!seclabel->relabel)
+ return 0;
+
+ if (src->readonly || src->shared)
+ return 0;
+
+ if (!src || src->type == VIR_STORAGE_TYPE_NETWORK)
+ return 0;
+
+ if (migrated) {
+ int ret = virFileIsSharedFS(src->path);
+ if (ret < 0)
+ return -1;
+ if (ret == 1) {
+ VIR_DEBUG("Skipping image label restore on %s because FS is shared", src->path);
+ return 0;
+ }
+
+ }
+
+ return virSecuritySmackRestoreFileLabel(mgr, src->path);
+
+}
+
+static int
+virSecuritySmackSetFileLabel(int fd, char *tlabel)
+{
+ char *elabel = NULL;
+
+ VIR_INFO("Setting Smack label on fd %d to '%s'", fd, tlabel);
+
+ if (smack_set_label_for_file(fd, "security.SMACK64", tlabel) < 0) {
+ int fsetfilelabel_errno = errno;
+
+ if (smack_new_label_from_file(fd, "security.SMACK64", &elabel) >= 0) {
+ if (STREQ(tlabel, elabel)) {
+ VIR_FREE(elabel);
+ /* It's alright, there's nothing to change anyway. */
+
+ return 0;
+ }
+
+ VIR_FREE(elabel);
+ }
+ /* 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.
+ */
+ if (fsetfilelabel_errno != EOPNOTSUPP) {
+ virReportSystemError(fsetfilelabel_errno,
+ _("unable to set security context '%s' on fd %d"), tlabel, fd);
+ return -1;
+ } else {
+ VIR_INFO("Setting security label '%s' on fd %d not supported",
+ tlabel, fd);
+ }
+ }
+ return 0;
+}
+
+
+static int
+virSecuritySmackSetHostdevSubsysLabel(virDomainDefPtr def,
+ virDomainHostdevDefPtr dev,
+ const char *vroot)
+{
+ int ret = -1;
+
+ switch (dev->source.subsys.type) {
+ case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB:
+ {
+ virUSBDevicePtr usb;
+
+ if (dev->missing)
+ return 0;
+
+ usb = virUSBDeviceNew(dev->source.subsys.u.usb.bus,
+ dev->source.subsys.u.usb.device,
+ vroot);
+ if (!usb)
+ goto done;
+
+ ret = virUSBDeviceFileIterate(usb, virSecuritySmackSetUSBLabel, def);
+ virUSBDeviceFree(usb);
+
+ break;
+ }
+
+ case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI:
+ {
+ virPCIDevicePtr pci =
+ virPCIDeviceNew(dev->source.subsys.u.pci.addr.domain,
+ dev->source.subsys.u.pci.addr.bus,
+ dev->source.subsys.u.pci.addr.slot,
+ dev->source.subsys.u.pci.addr.function);
+
+ if (!pci)
+ goto done;
+
+ if (dev->source.subsys.u.pci.backend
+ == VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO) {
+ char *vfioGroupDev = virPCIDeviceGetIOMMUGroupDev(pci);
+
+ if (!vfioGroupDev) {
+ virPCIDeviceFree(pci);
+ goto done;
+ }
+ ret = virSecuritySmackRestorePCILabel(pci, vfioGroupDev, def);
+ VIR_FREE(vfioGroupDev);
+ } else {
+ ret = virPCIDeviceFileIterate(pci, virSecuritySmackSetPCILabel, def);
+ }
+ virPCIDeviceFree(pci);
+ break;
+ }
+
+ case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI:
+ {
+ virDomainHostdevSubsysSCSIHostPtr scsihostsrc =
+ &(dev->source.subsys.u.scsi.u.host);
+ virSCSIDevicePtr scsi =
+ virSCSIDeviceNew(NULL,
+ scsihostsrc->adapter, scsihostsrc->bus,
+ scsihostsrc->target, scsihostsrc->unit,
+ dev->readonly, dev->shareable);
+
+ if (!scsi)
+ goto done;
+
+ ret = virSCSIDeviceFileIterate(scsi, virSecuritySmackSetSCSILabel, def);
+ virSCSIDeviceFree(scsi);
+
+ break;
+ }
+
+ default:
+ ret = 0;
+ break;
+ }
+
+ done:
+ return ret;
+}
+
+static int
+virSecuritySmackSetHostdevCapsLabel(virDomainDefPtr def,
+ virDomainHostdevDefPtr dev,
+ const char *vroot)
+{
+ int ret = -1;
+ virSecurityLabelDefPtr seclabel;
+ char *path;
+
+ seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_SMACK_NAME);
+ if (seclabel == NULL)
+ return -1;
+
+ switch (dev->source.caps.type) {
+ case VIR_DOMAIN_HOSTDEV_CAPS_TYPE_STORAGE:
+ {
+ if (vroot) {
+ if (virAsprintf(&path, "%s/%s", vroot,
+ dev->source.caps.u.storage.block) < 0)
+ return -1;
+ } else {
+ if (VIR_STRDUP(path, dev->source.caps.u.storage.block) < 0)
+ return -1;
+ }
+ ret = virSecuritySmackSetPathLabel(path, seclabel->imagelabel);
+ VIR_FREE(path);
+ break;
+ }
+
+ case VIR_DOMAIN_HOSTDEV_CAPS_TYPE_MISC:
+ {
+ if (vroot) {
+ if (virAsprintf(&path, "%s/%s", vroot,
+ dev->source.caps.u.misc.chardev) < 0)
+ return -1;
+ } else {
+ if (VIR_STRDUP(path, dev->source.caps.u.misc.chardev) < 0)
+ return -1;
+ }
+ ret = virSecuritySmackSetPathLabel(path, seclabel->imagelabel);
+ VIR_FREE(path);
+ break;
+ }
+
+ default:
+ {
+ ret = 0;
+ break;
+ }
+ }
+
+ return ret;
+
+}
+
+static int
+virSecuritySmackSetHostdevLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
+ virDomainDefPtr def,
+ virDomainHostdevDefPtr dev,
+ const char *vroot)
+{
+ virSecurityLabelDefPtr seclabel;
+ seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_SMACK_NAME);
+ if (seclabel == NULL)
+ return -1;
+
+ if (!seclabel->relabel)
+ return 0;
+
+ switch (dev->mode) {
+ case VIR_DOMAIN_HOSTDEV_MODE_SUBSYS:
+ return virSecuritySmackSetHostdevSubsysLabel(def, dev, vroot);
+
+ case VIR_DOMAIN_HOSTDEV_MODE_CAPABILITIES:
+ return virSecuritySmackSetHostdevCapsLabel(def, dev, vroot);
+
+ default:
+ return 0;
+
+ }
+}
+
+static int
+virSecuritySmackRestoreHostdevSubsysLabel(virSecurityManagerPtr mgr,
+ virDomainHostdevDefPtr dev,
+ const char *vroot)
+{
+ int ret = -1;
+
+ switch (dev->source.subsys.type) {
+ case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB:
+ {
+ virUSBDevicePtr usb;
+
+ if (dev->missing)
+ return 0;
+
+ usb = virUSBDeviceNew(dev->source.subsys.u.usb.bus,
+ dev->source.subsys.u.usb.device,
+ vroot);
+ if (!usb)
+ goto done;
+
+ ret = virUSBDeviceFileIterate(usb, virSecuritySmackRestoreUSBLabel, mgr);
+ virUSBDeviceFree(usb);
+
+ break;
+ }
+
+ case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI:
+ {
+ virPCIDevicePtr pci =
+ virPCIDeviceNew(dev->source.subsys.u.pci.addr.domain,
+ dev->source.subsys.u.pci.addr.bus,
+ dev->source.subsys.u.pci.addr.slot,
+ dev->source.subsys.u.pci.addr.function);
+
+ if (!pci)
+ goto done;
+
+ if (dev->source.subsys.u.pci.backend
+ == VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO) {
+ char *vfioGroupDev = virPCIDeviceGetIOMMUGroupDev(pci);
+
+ if (!vfioGroupDev) {
+ virPCIDeviceFree(pci);
+ goto done;
+ }
+ ret = virSecuritySmackRestorePCILabel(pci, vfioGroupDev, mgr);
+ VIR_FREE(vfioGroupDev);
+ } else {
+ ret = virPCIDeviceFileIterate(pci, virSecuritySmackRestorePCILabel, mgr);
+ }
+ virPCIDeviceFree(pci);
+ break;
+ }
+
+ case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI:
+ {
+ virDomainHostdevSubsysSCSIHostPtr scsihostsrc =
+ &(dev->source.subsys.u.scsi.u.host);
+ virSCSIDevicePtr scsi =
+ virSCSIDeviceNew(NULL,
+ scsihostsrc->adapter, scsihostsrc->bus,
+ scsihostsrc->target, scsihostsrc->unit,
+ dev->readonly, dev->shareable);
+
+ if (!scsi)
+ goto done;
+
+ ret = virSCSIDeviceFileIterate(scsi, virSecuritySmackRestoreSCSILabel, mgr);
+ virSCSIDeviceFree(scsi);
+
+ break;
+ }
+
+ default:
+ {
+ ret = 0;
+ break;
+ }
+ }
+
+ done:
+ return ret;
+
+}
+
+static int
+virSecuritySmackRestoreHostdevCapsLabel(virSecurityManagerPtr mgr,
+ virDomainHostdevDefPtr dev,
+ const char *vroot)
+{
+ int ret = -1;
+ char *path;
+
+ switch (dev->source.caps.type) {
+ case VIR_DOMAIN_HOSTDEV_CAPS_TYPE_STORAGE:
+ {
+ if (vroot) {
+ if (virAsprintf(&path, "%s/%s", vroot,
+ dev->source.caps.u.storage.block) < 0)
+ return -1;
+ } else {
+ if (VIR_STRDUP(path, dev->source.caps.u.storage.block) < 0)
+ return -1;
+ }
+ ret = virSecuritySmackRestoreFileLabel(mgr, path);
+ VIR_FREE(path);
+ break;
+ }
+
+ case VIR_DOMAIN_HOSTDEV_CAPS_TYPE_MISC:
+ {
+ if (vroot) {
+ if (virAsprintf(&path, "%s/%s", vroot,
+ dev->source.caps.u.misc.chardev) < 0)
+ return -1;
+ } else {
+ if (VIR_STRDUP(path, dev->source.caps.u.misc.chardev) < 0)
+ return -1;
+ }
+ ret = virSecuritySmackRestoreFileLabel(mgr, path);
+ VIR_FREE(path);
+ break;
+ }
+
+ default:
+ ret = 0;
+ break;
+ }
+
+ return ret;
+}
+
+static int
+virSecuritySmackRestoreHostdevLabel(virSecurityManagerPtr mgr,
+ virDomainDefPtr def,
+ virDomainHostdevDefPtr dev,
+ const char *vroot)
+{
+ virSecurityLabelDefPtr seclabel;
+
+ seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_SMACK_NAME);
+ if (seclabel == NULL)
+ return -1;
+
+ if (!seclabel->relabel)
+ return 0;
+
+ switch (dev->mode) {
+ case VIR_DOMAIN_HOSTDEV_MODE_SUBSYS:
+ return virSecuritySmackRestoreHostdevSubsysLabel(mgr, dev, vroot);
+
+ case VIR_DOMAIN_HOSTDEV_MODE_CAPABILITIES:
+ return virSecuritySmackRestoreHostdevCapsLabel(mgr, dev, vroot);
+
+ default:
+ return 0;
+ }
+}
+
+/*Called on libvirtd startup to see if Smack is available*/
+static int
+virSecuritySmackSecurityDriverProbe(const char *virtDriver)
+{
+ if (!smack_smackfs_path() || NULL == virtDriver)
+ return SECURITY_DRIVER_DISABLE;
+
+ return SECURITY_DRIVER_ENABLE;
+
+}
+
+/*Security dirver initialization .*/
+static int
+virSecuritySmackSecurityDriverOpen(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED)
+{
+ return 0;
+}
+
+static int
+virSecuritySmackSecurityDriverClose(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED)
+{
+ return 0;
+}
+
+static const char *
+virSecuritySmackSecurityDriverGetModel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED)
+{
+ return SECURITY_SMACK_NAME;
+}
+
+static const char *
+virSecuritySmackSecurityDriverGetDOI(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED)
+{
+ return SECURITY_SMACK_VOID_DOI;
+}
+
+static int
+virSecuritySmackSecurityVerify(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
+ virDomainDefPtr def)
+{
+ virSecurityLabelDefPtr seclabel;
+ seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_SMACK_NAME);
+ if (seclabel == NULL)
+ return -1;
+
+ if (STREQ(SECURITY_SMACK_NAME, seclabel->model) != 1) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("security label driver mismatch: "
+ "'%s' model configured for domain, but "
+ "hypervisor driver is '%s'."),
+ seclabel->model, SECURITY_SMACK_NAME);
+ return -1;
+ }
+
+ if (seclabel->type == VIR_DOMAIN_SECLABEL_STATIC) {
+ if (smack_label_length(seclabel->label) < 0) {
+ virReportError(VIR_ERR_XML_ERROR,
+ _("Invalid security label %s"), seclabel->label);
+ return -1;
+ }
+ }
+
+ return 0;
+
+}
+
+static int
+virSecuritySmackSetDiskLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
+ virDomainDefPtr def,
+ virDomainDiskDefPtr disk)
+{
+ virSecurityLabelDefPtr seclabel;
+ seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_SMACK_NAME);
+
+ if (seclabel == NULL)
+ return -1;
+
+ if (!seclabel->relabel)
+ return 0;
+
+ if (disk->src->type == VIR_STORAGE_TYPE_NETWORK)
+ return 0;
+
+ VIR_DEBUG("set disk image security label before");
+
+ if (setxattr(disk->src->path, "security.SMACK64", seclabel->imagelabel,
+ strlen(seclabel->imagelabel) + 1, 0) < 0)
+ return -1;
+
+ VIR_DEBUG("disk image %s", disk->src->path);
+ VIR_DEBUG("set disk image security label after");
+
+ return 0;
+
+}
+
+static int
+virSecuritySmackRestoreDiskLabel(virSecurityManagerPtr mgr,
+ virDomainDefPtr def,
+ virDomainDiskDefPtr disk)
+{
+ return virSecuritySmackRestoreImageLabelInt(mgr, def, disk->src, false);
+}
+
+static int
+virSecuritySmackSetImageLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
+ virDomainDefPtr def,
+ virStorageSourcePtr src)
+{
+ virSecurityLabelDefPtr seclabel;
+ seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_SMACK_NAME);
+
+ if (seclabel == NULL)
+ return -1;
+
+ if (!seclabel->relabel)
+ return 0;
+
+ if (src->type == VIR_STORAGE_TYPE_NETWORK)
+ return 0;
+
+ VIR_DEBUG("set disk image security label before");
+
+ if (setxattr(src->path, "security.SMACK64", seclabel->imagelabel,
+ strlen(seclabel->imagelabel) + 1, 0) < 0)
+ return -1;
+
+ VIR_DEBUG("disk image %s", src->path);
+ VIR_DEBUG("set disk image security label after");
+
+ return 0;
+
+}
+
+static int
+virSecuritySmackRestoreImageLabel(virSecurityManagerPtr mgr,
+ virDomainDefPtr def,
+ virStorageSourcePtr src)
+{
+ return virSecuritySmackRestoreImageLabelInt(mgr, def, src, false);
+
+}
+
+static int
+virSecuritySmackSetDaemonSocketLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
+ virDomainDefPtr vm)
+{
+
+ return 0;
+ virSecurityLabelDefPtr seclabel;
+ char *label = NULL;
+ int ret = -1;
+
+ seclabel = virDomainDefGetSecurityLabelDef(vm, SECURITY_SMACK_NAME);
+ if (seclabel == NULL)
+ return -1;
+
+ if (seclabel->label == NULL)
+ return 0;
+
+ if (STREQ(SECURITY_SMACK_NAME, seclabel->model) != 1) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("security label driver mismatch: "
+ "'%s' model configured for domain, but "
+ "hypervisor driver is '%s'."),
+ seclabel->model, SECURITY_SMACK_NAME);
+ return -1;
+ }
+
+ if (smack_new_label_from_self(&label) == -1) {
+ virReportSystemError(errno,
+ _("unable to get current process context '%s'"), seclabel->label);
+ goto done;
+ }
+
+ VIR_DEBUG("SmackSetSecurityDaemonSocketLabel is in %d", getpid());
+ VIR_DEBUG("label from self %s", label);
+
+
+ if (virSecuritySmackSockCreate(label, "sockincreate") == -1) {
+ virReportSystemError(errno,
+ _("unable to set socket smack label '%s'"), seclabel->label);
+ goto done;
+ }
+
+ ret = 0;
+ done:
+
+ VIR_FREE(label);
+ return ret;
+
+}
+
+static int
+virSecuritySmackSetSocketLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
+ virDomainDefPtr vm)
+{
+
+ virSecurityLabelDefPtr seclabel;
+
+ return 0;
+ seclabel = virDomainDefGetSecurityLabelDef(vm, SECURITY_SMACK_NAME);
+ if (seclabel == NULL)
+ return -1;
+
+ if (seclabel->label == NULL)
+ return 0;
+
+ if (STREQ(SECURITY_SMACK_NAME, seclabel->model) != 1) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("security label driver mismatch: "
+ "'%s' model configured for domain, but "
+ "hypervisor driver is '%s'."),
+ seclabel->model, SECURITY_SMACK_NAME);
+ return -1;
+ }
+
+ VIR_DEBUG("Setting VM %s socket label %s", vm->name, seclabel->label);
+
+ if (virSecuritySmackSockCreate(seclabel->label, "sockoutcreate") == -1) {
+ virReportSystemError(errno,
+ _("unable to set socket smack label '%s'"),
+ seclabel->label);
+ return -1;
+ }
+
+
+ return 0;
+
+}
+
+static int
+virSecuritySmackClearSocketLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
+ virDomainDefPtr def)
+{
+
+ virSecurityLabelDefPtr seclabel;
+
+ return 0;
+ seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_SMACK_NAME);
+ if (seclabel == NULL)
+ return -1;
+
+ if (seclabel->label == NULL)
+ return 0;
+
+ if (STREQ(SECURITY_SMACK_NAME, seclabel->model) != 1) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("security label driver mismatch: "
+ "'%s' model configured for domain, but "
+ "hypervisor driver is '%s'."),
+ seclabel->model, SECURITY_SMACK_NAME);
+ return -1;
+ }
+
+ VIR_DEBUG("clear sock label");
+
+ if (virSecuritySmackSockCreate(NULL, "sockincreate") == -1 ||
+ virSecuritySmackSockCreate(NULL, "sockoutcreate") == -1) {
+ virReportSystemError(errno,
+ _("unable to clear socket smack label '%s'"),
+ seclabel->label);
+
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+*Current called in qemuStartVMDaemon to setup a 'label'. We make the
+*label based on UUID.
+*this is called on 'start'with RestoreSecurityLabel being called on
+*shutdown
+ */
+static int
+virSecuritySmackGenLabel(virSecurityManagerPtr mgr,
+ virDomainDefPtr def)
+{
+ int ret = -1;
+ char *label_name = NULL;
+ virSecurityLabelDefPtr seclabel;
+
+ seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_SMACK_NAME);
+ if (seclabel == NULL)
+ return ret;
+
+ VIR_DEBUG("label=%s", virSecurityManagerGetDriver(mgr));
+ if (seclabel->type == VIR_DOMAIN_SECLABEL_DYNAMIC &&
+ seclabel->label) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("security label already defined for VM"));
+ return ret;
+ }
+
+ if (seclabel->imagelabel) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("security image label already defined for VM"));
+ return ret;
+ }
+
+ if (seclabel->model &&
+ STRNEQ(seclabel->model, SECURITY_SMACK_NAME)) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("security label model %s is not supported with smack"),
+ seclabel->model);
+ return ret;
+ }
+
+ VIR_DEBUG("type=%d", seclabel->type);
+
+ if ((label_name = virSecuritySmackGetLabelName(def)) == NULL)
+ return ret;
+
+ if (seclabel->type == VIR_DOMAIN_SECLABEL_DYNAMIC) {
+
+ /*set process label*/
+ if (VIR_STRDUP(seclabel->label, label_name) < 0)
+ goto cleanup;
+ }
+
+ /*set imagelabel the same as label*/
+ if (VIR_STRDUP(seclabel->imagelabel, label_name) < 0)
+ goto cleanup;
+
+ if (!seclabel->model &&
+ VIR_STRDUP(seclabel->model, SECURITY_SMACK_NAME) < 0)
+ goto cleanup;
+
+ ret = 0;
+
+ cleanup:
+
+ if (ret != 0) {
+ 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);
+ }
+
+ VIR_FREE(label_name);
+
+ VIR_DEBUG("model=%s label=%s imagelabel=%s",
+ NULLSTR(seclabel->model),
+ NULLSTR(seclabel->label),
+ NULLSTR(seclabel->imagelabel));
+
+ return ret;
+
+}
+
+static int
+virSecuritySmackReserveLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
+ virDomainDefPtr def ATTRIBUTE_UNUSED,
+ pid_t pid ATTRIBUTE_UNUSED)
+{
+ /*Security label is based UUID,*/
+ return 0;
+}
+
+/*
+*Called on VM shutdown and destroy.
+*/
+static int
+virSecuritySmackReleaseLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
+ virDomainDefPtr def)
+{
+ virSecurityLabelDefPtr seclabel;
+
+ seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_SMACK_NAME);
+ if (seclabel == NULL)
+ return -1;
+
+ if (seclabel->type == VIR_DOMAIN_SECLABEL_DYNAMIC) {
+ VIR_FREE(seclabel->label);
+ VIR_FREE(seclabel->model);
+ }
+ VIR_FREE(seclabel->imagelabel);
+
+ return 0;
+
+}
+
+/* Seen with 'virsh dominfo <vm>'. This function only called if the VM is
+* running.
+*/
+static int
+virSecuritySmackGetProcessLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
+ virDomainDefPtr def ATTRIBUTE_UNUSED,
+ pid_t pid,
+ virSecurityLabelPtr sec)
+{
+
+ char *label_name = NULL;
+
+ if (virSecuritySmackGetPIDLabel(pid, &label_name) == -1) {
+ virReportSystemError(errno,
+ _("unable to get PID %d security label"),
+ pid);
+ return -1;
+ }
+
+ if (strlen(label_name) >= VIR_SECURITY_LABEL_BUFLEN) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("security label exceeds "
+ "maximum length: %d"),
+ VIR_SECURITY_LABEL_BUFLEN - 1);
+ VIR_FREE(label_name);
+ return -1;
+ }
+
+ label_name = virStrcpy(sec->label, label_name, VIR_SECURITY_LABEL_BUFLEN);
+ VIR_FREE(label_name);
+ /*Smack default enforced*/
+ sec->enforcing = 1;
+
+ return label_name == NULL ? -1 : 0;
+}
+
+static int
+virSecuritySmackSetProcessLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
+ virDomainDefPtr def)
+{
+ virSecurityLabelDefPtr seclabel;
+
+ seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_SMACK_NAME);
+
+ if (seclabel == NULL)
+ return -1;
+
+ if (seclabel->label == NULL)
+ return 0;
+
+ if (STRNEQ(SECURITY_SMACK_NAME, seclabel->model)) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("security label driver mismatch: "
+ "\'%s\' model configured for domain, but "
+ "hypervisor driver is \'%s\'."),
+ seclabel->model, SECURITY_SMACK_NAME);
+
+ return -1;
+ }
+
+ if (smack_set_label_for_self(seclabel->label) < 0) {
+ virReportError(errno,
+ _("unable to set security label '%s'"),
+ seclabel->label);
+
+ return -1;
+ }
+
+ return 0;
+
+}
+
+static int
+virSecuritySmackSetChildProcessLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
+ virDomainDefPtr def,
+ virCommandPtr cmd)
+{
+ virSecurityLabelDefPtr seclabel;
+ int rlbl;
+ char *smackfs_path = NULL;
+
+ seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_SMACK_NAME);
+
+ if (seclabel == NULL)
+ return -1;
+
+ if (seclabel->label == NULL)
+ return 0;
+
+ if (STRNEQ(SECURITY_SMACK_NAME, seclabel->model)) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("security label driver mismatch: "
+ "\'%s\' model configured for domain, but "
+ "hypervisor driver is \'%s\'."),
+ seclabel->model, SECURITY_SMACK_NAME);
+
+ return -1;
+ }
+
+ /*
+ * Send label to relabel-self interface to allow child to label
+ * its self once it finishes setting up. Apply only if interface is
+ * available and user namespace is enabled.
+ */
+
+ if (STREQ(virSecurityManagerGetDriver(mgr), "LXC")) {
+
+ if (!def->idmap.nuidmap)
+ return 0;
+
+ VIR_DEBUG("Applying label %s to relabel-self interface.", seclabel->label);
+
+ if (virAsprintf(&smackfs_path, "%s/relabel-self", smack_smackfs_path()) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("Unable to obtain path for smackfs. Is smack enabled? "));
+ return -1;
+ }
+
+ rlbl = open(smackfs_path, O_WRONLY);
+
+ if (rlbl < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not open relabel interface \'%s\' for writing. Is it "
+ "enabled in the kernel?"),
+ smackfs_path);
+ return -1;
+ }
+
+ if (safewrite(rlbl, seclabel->label, strlen(seclabel->label)) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Could not write to relabel interface \'%s\'."),
+ smackfs_path);
+ return -1;
+ }
+
+ VIR_FORCE_CLOSE(rlbl);
+ }
+
+ /* save in cmd to be set after fork/before child process is exec'ed */
+ virCommandSetSmackLabel(cmd, seclabel->label);
+ VIR_DEBUG("save smack label in cmd %s", seclabel->label);
+
+ return 0;
+
+}
+
+static int
+virSecuritySmackSetAllLabel(virSecurityManagerPtr mgr,
+ virDomainDefPtr def,
+ const char *stdin_path)
+{
+
+ size_t i;
+ virSecurityLabelDefPtr seclabel;
+
+ seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_SMACK_NAME);
+
+ if (seclabel == NULL)
+ return -1;
+
+ if (!seclabel->relabel)
+ return 0;
+
+ VIR_DEBUG("set image security label before");
+
+ for (i = 0; i < def->ndisks; i++) {
+ if (def->disks[i]->src->type == VIR_STORAGE_TYPE_DIR) {
+ VIR_WARN("Unable to relabel directory tree %s for disk %s",
+ def->disks[i]->src->path, def->disks[i]->dst);
+ continue;
+ }
+
+ VIR_DEBUG("set image security label");
+
+ if (virSecuritySmackSetImageLabel(mgr,
+ def, def->disks[i]->src) < 0)
+ return -1;
+ }
+
+ VIR_DEBUG("set image security label after");
+
+ for (i = 0; i< def->nhostdevs; i++) {
+ if (virSecuritySmackSetHostdevLabel(mgr,
+ def,
+ def->hostdevs[i],
+ NULL) < 0)
+ return -1;
+
+ }
+
+ if (stdin_path) {
+ if (setxattr(stdin_path, "security.SMACK64", seclabel->imagelabel,
+ strlen(seclabel->imagelabel) + 1, 0)< 0 &&
+ virFileIsSharedFS(stdin_path) != 1)
+ return -1;
+ }
+
+ return 0;
+
+}
+
+static int
+virSecuritySmackRestoreAllLabel(virSecurityManagerPtr mgr,
+ virDomainDefPtr def,
+ bool migrated ATTRIBUTE_UNUSED)
+{
+ size_t i;
+ virSecurityLabelDefPtr seclabel;
+
+ VIR_DEBUG("Restoring security label on %s", def->name);
+
+ seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_SMACK_NAME);
+
+ if (seclabel == NULL)
+ return -1;
+
+ if (!seclabel->relabel)
+ return 0;
+
+ for (i = 0; i < def->ndisks; i++) {
+
+ if (virSecuritySmackRestoreImageLabelInt(mgr,
+ def,
+ def->disks[i]->src,
+ migrated) < 0)
+
+ return -1;
+
+ }
+
+ return 0;
+
+}
+
+
+static int
+virSecuritySmackSetSavedStateLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
+ virDomainDefPtr def,
+ const char *savefile)
+{
+ virSecurityLabelDefPtr seclabel;
+
+ seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_SMACK_NAME);
+ if (seclabel == NULL)
+ return -1;
+
+ if (!seclabel->relabel)
+ return 0;
+
+ return virSecuritySmackSetPathLabel(savefile, seclabel->imagelabel);
+}
+
+static int
+virSecuritySmackRestoreSavedStateLabel(virSecurityManagerPtr mgr,
+ virDomainDefPtr def,
+ const char *savefile)
+{
+ virSecurityLabelDefPtr seclabel;
+
+ seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_SMACK_NAME);
+ if (seclabel == NULL)
+ return -1;
+
+ if (!seclabel->relabel)
+ return 0;
+
+ return virSecuritySmackRestoreFileLabel(mgr, savefile);
+}
+
+static int
+virSecuritySmackSetImageFDLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
+ virDomainDefPtr def,
+ int fd)
+{
+ virSecurityLabelDefPtr seclabel;
+
+ seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_SMACK_NAME);
+
+ if (seclabel == NULL)
+ return -1;
+
+ if (seclabel->imagelabel == NULL)
+ return 0;
+
+ return virSecuritySmackSetFileLabel(fd, seclabel->imagelabel);
+
+}
+
+static int
+virSecuritySmackSetImagePathLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
+ virDomainDefPtr def,
+ const char *path)
+{
+ virSecurityLabelDefPtr seclabel;
+
+ seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_SMACK_NAME);
+
+ if (seclabel == NULL)
+ return -1;
+
+ if (seclabel->imagelabel == NULL)
+ return 0;
+
+ if (virSecuritySmackSetPathLabel(path, seclabel->imagelabel) < 0)
+ return -1;
+
+ return 0;
+}
+
+static int
+virSecuritySmackSetTapFDLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
+ virDomainDefPtr def,
+ int fd)
+{
+ struct stat buf;
+ virSecurityLabelDefPtr seclabel;
+
+ seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_SMACK_NAME);
+ if (seclabel == NULL)
+ return -1;
+
+ if (seclabel->label == NULL)
+ return 0;
+
+
+ if (fstat(fd, &buf) < 0) {
+ virReportSystemError(errno, _("cannot stat tap fd %d"), fd);
+ return -1;
+ }
+
+ if ((buf.st_mode & S_IFMT) != S_IFCHR) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("tap fd %d is not character device"), fd);
+ return -1;
+ }
+
+ return virSecuritySmackSetFileLabel(fd, seclabel->label);
+
+}
+
+static char *
+virSecuritySmackGetSecurityMountOptions(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
+ virDomainDefPtr def)
+{
+ char *opts = NULL;
+ virSecurityLabelDefPtr seclabel;
+
+ if ((seclabel = virDomainDefGetSecurityLabelDef(def, SECURITY_SMACK_NAME))) {
+ if (!seclabel->imagelabel) {
+ if (!seclabel->label)
+ seclabel->imagelabel = virSecuritySmackGetLabelName(def);
+ else
+ seclabel->imagelabel = seclabel->label;
+ }
+ if (seclabel->imagelabel &&
+ virAsprintf(&opts,
+ ",smackfsdef=\"%s\"",
+ (const char*) seclabel->imagelabel) < 0)
+ return NULL;
+ }
+
+ if (!opts && VIR_STRDUP(opts, "") < 0)
+ return NULL;
+
+ return opts;
+
+}
+
+static const char *
+virSecuritySmackGetBaseLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
+ int virtType ATTRIBUTE_UNUSED)
+{
+ return NULL;
+}
+
+virSecurityDriver virSecurityDriverSmack = {
+ .privateDataLen = 0,
+ .name = SECURITY_SMACK_NAME,
+ .probe = virSecuritySmackSecurityDriverProbe,
+ .open = virSecuritySmackSecurityDriverOpen,
+ .close = virSecuritySmackSecurityDriverClose,
+
+ .getModel = virSecuritySmackSecurityDriverGetModel,
+ .getDOI = virSecuritySmackSecurityDriverGetDOI,
+
+ .domainSecurityVerify = virSecuritySmackSecurityVerify,
+
+ .domainSetSecurityDiskLabel = virSecuritySmackSetDiskLabel,
+ .domainRestoreSecurityDiskLabel = virSecuritySmackRestoreDiskLabel,
+
+ .domainSetSecurityImageLabel = virSecuritySmackSetImageLabel,
+ .domainRestoreSecurityImageLabel = virSecuritySmackRestoreImageLabel,
+
+ .domainSetSecurityDaemonSocketLabel = virSecuritySmackSetDaemonSocketLabel,
+ .domainSetSecuritySocketLabel = virSecuritySmackSetSocketLabel,
+ .domainClearSecuritySocketLabel = virSecuritySmackClearSocketLabel,
+
+ .domainGenSecurityLabel = virSecuritySmackGenLabel,
+ .domainReserveSecurityLabel = virSecuritySmackReserveLabel,
+ .domainReleaseSecurityLabel = virSecuritySmackReleaseLabel,
+
+ .domainGetSecurityProcessLabel = virSecuritySmackGetProcessLabel,
+ .domainSetSecurityProcessLabel = virSecuritySmackSetProcessLabel,
+ .domainSetSecurityChildProcessLabel = virSecuritySmackSetChildProcessLabel,
+
+ .domainSetSecurityAllLabel = virSecuritySmackSetAllLabel,
+ .domainRestoreSecurityAllLabel = virSecuritySmackRestoreAllLabel,
+
+ .domainSetSecurityHostdevLabel = virSecuritySmackSetHostdevLabel,
+ .domainRestoreSecurityHostdevLabel = virSecuritySmackRestoreHostdevLabel,
+
+ .domainSetSavedStateLabel = virSecuritySmackSetSavedStateLabel,
+ .domainRestoreSavedStateLabel = virSecuritySmackRestoreSavedStateLabel,
+
+ .domainSetSecurityImageFDLabel = virSecuritySmackSetImageFDLabel,
+ .domainSetSecurityImagePathLabel = virSecuritySmackSetImagePathLabel,
+ .domainSetSecurityTapFDLabel = virSecuritySmackSetTapFDLabel,
+
+ .domainGetSecurityMountOptions = virSecuritySmackGetSecurityMountOptions,
+
+ .getBaseLabel = virSecuritySmackGetBaseLabel,
+
+};
diff --git a/src/security/security_smack.h b/src/security/security_smack.h
new file mode 100644
index 0000000..3d9fad9
--- /dev/null
+++ b/src/security/security_smack.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2015 Cisco Systems, 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/>.
+ *
+ * Author:
+ * Hongliang Liang <hliang(a)bupt.edu,cn>
+ * Changyao Han <changyao(a)bupt.edu.cn>
+ * Raghuram S. Sudhaakar <rssudhaakar(a)gmail.com>
+ * Randy Aybar <raybar(a)cisco.com>
+ */
+
+#ifndef __VIR_SECURITY_SMACK_H__
+# define __VIR_SECURITY_SMACK_H__
+
+# include "security_driver.h"
+
+int virSecuritySmackSockCreate(const char *label, const char *attr);
+
+
+extern virSecurityDriver virSecurityDriverSmack;
+
+# define SMACK_PREFIX "smack-"
+
+#endif /* __VIR_SECURITY_SMACK_H__ */
diff --git a/src/security/security_stack.c b/src/security/security_stack.c
index 3ea2751..e30f003 100644
--- a/src/security/security_stack.c
+++ b/src/security/security_stack.c
@@ -495,6 +495,14 @@ virSecurityStackSetImageFDLabel(virSecurityManagerPtr mgr,
}
static int
+virSecurityStackSetImagePathLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
+ virDomainDefPtr vm ATTRIBUTE_UNUSED,
+ const char *path ATTRIBUTE_UNUSED)
+{
+ return 0;
+}
+
+static int
virSecurityStackSetTapFDLabel(virSecurityManagerPtr mgr,
virDomainDefPtr vm,
int fd)
@@ -659,6 +667,7 @@ virSecurityDriver virSecurityDriverStack = {
.domainRestoreSavedStateLabel = virSecurityStackRestoreSavedStateLabel,
.domainSetSecurityImageFDLabel = virSecurityStackSetImageFDLabel,
+ .domainSetSecurityImagePathLabel = virSecurityStackSetImagePathLabel,
.domainSetSecurityTapFDLabel = virSecurityStackSetTapFDLabel,
.domainGetSecurityMountOptions = virSecurityStackGetMountOptions,
diff --git a/src/util/vircommand.c b/src/util/vircommand.c
index 027cb64..cdcb3a2 100644
--- a/src/util/vircommand.c
+++ b/src/util/vircommand.c
@@ -41,6 +41,9 @@
#if defined(WITH_SECDRIVER_APPARMOR)
# include <sys/apparmor.h>
#endif
+#if defined(WITH_SECDRIVER_SMACK)
+# include <sys/smack.h>
+#endif
#define __VIR_COMMAND_PRIV_H_ALLOW__
#include "vircommandpriv.h"
@@ -134,6 +137,10 @@ struct _virCommand {
#if defined(WITH_SECDRIVER_APPARMOR)
char *appArmorProfile;
#endif
+#if defined(WITH_SECDRIVER_SMACK)
+ char *smackLabel;
+#endif
+
int mask;
};
@@ -722,6 +729,30 @@ virExec(virCommandPtr cmd)
}
# endif
+# if defined(WITH_SECDRIVER_SMACK)
+ if (cmd->smackLabel) {
+ VIR_DEBUG("Setting child security label to %s", cmd->smackLabel);
+
+ if (smack_set_label_for_self(cmd->smackLabel) < 0) {
+ virReportSystemError(errno,
+ _("unable to set Smack label '%s' "
+ "for '%s'"),
+ cmd->smackLabel, cmd->args[0]);
+ goto fork_error;
+ }
+ }
+# endif
+
+/*
+ * if (smack_new_label_from_self(&label) == -1)
+ * {
+ * goto fork_error;
+ * }
+ * VIR_DEBUG("smack label is %s",label);
+ * free(label);
+ *
+ *
+ */
/* The steps above may need to do something privileged, so we delay
* setuid and clearing capabilities until the last minute.
*/
@@ -1197,6 +1228,35 @@ virCommandSetAppArmorProfile(virCommandPtr cmd,
}
+
+/**
+ * virCommandSetSmackLabel:
+ * @cmd: the command to modify
+ * @label: the Smack label to use for the child process
+ *
+ * Saves a copy of @label to use when setting the Smack context
+ * label (write to /proc/self/attr/current ) after the child process has
+ * been started. If Smack isn't compiled into libvirt, or if label is
+ * NULL, nothing will be done.
+ */
+void
+virCommandSetSmackLabel(virCommandPtr cmd,
+ const char *label ATTRIBUTE_UNUSED)
+
+{
+ if (!cmd || cmd->has_error)
+ return;
+
+#if defined(WITH_SECDRIVER_SMACK)
+ VIR_FREE(cmd->smackLabel);
+ if (VIR_STRDUP_QUIET(cmd->smackLabel, label) < 0)
+ cmd->has_error = ENOMEM;
+#endif
+ return;
+
+}
+
+
/**
* virCommandDaemonize:
* @cmd: the command to modify
@@ -2796,6 +2856,9 @@ virCommandFree(virCommandPtr cmd)
#if defined(WITH_SECDRIVER_APPARMOR)
VIR_FREE(cmd->appArmorProfile);
#endif
+#if defined(WITH_SECDRIVER_SMACK)
+ VIR_FREE(cmd->smackLabel);
+#endif
VIR_FREE(cmd);
}
diff --git a/src/util/vircommand.h b/src/util/vircommand.h
index 198da2f..dfc8a65 100644
--- a/src/util/vircommand.h
+++ b/src/util/vircommand.h
@@ -88,6 +88,9 @@ void virCommandSetSELinuxLabel(virCommandPtr cmd,
void virCommandSetAppArmorProfile(virCommandPtr cmd,
const char *profile);
+void virCommandSetSmackLabel(virCommandPtr cmd,
+ const char *label);
+
void virCommandDaemonize(virCommandPtr cmd);
void virCommandNonblockingFDs(virCommandPtr cmd);
--
1.9.1
8 years, 10 months
[libvirt] [PATCH RFC] virhook: adding virHookCheck() inside virHookCall().
by Julio Faracco
This commit introduces the virHookCheck() before running the command (hook).
The virHookCheck() before virCommandRun() will avoid errors with changes
(removal and other permissions changes) in the hook file, while the libvirt
daemon is running.
Now, when you remove the hook file while libvirtd is running you get the
following error:
virsh # start WINDOWS_7
error: Failed to start domain WINDOWS_7
error: Hook script execution failed: internal error: Child process (LC_ALL=C
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOME=/home/julio USER=root LOGNAME=root /etc/libvirt/hooks/qemu WINDOWS_7
prepare begin -) unexpected exit status 127: libvirt: error : cannot execute
binary /etc/libvirt/hooks/qemu: No such file or directory
Cc: Carlos Castilho <ccast(a)br.ibm.com>
Signed-off-by: Julio Faracco <jcfaracco(a)gmail.com>
---
src/util/virhook.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/src/util/virhook.c b/src/util/virhook.c
index d37d6da..f741b30 100644
--- a/src/util/virhook.c
+++ b/src/util/virhook.c
@@ -294,7 +294,12 @@ virHookCall(int driver,
if (output)
virCommandSetOutputBuffer(cmd, output);
- ret = virCommandRun(cmd, NULL);
+ ret = virHookCheck(driver, virHookDriverTypeToString(driver));
+
+ if (ret > 0) {
+ ret = virCommandRun(cmd, NULL);
+ }
+
if (ret < 0) {
/* Convert INTERNAL_ERROR into known error. */
virReportError(VIR_ERR_HOOK_SCRIPT_FAILED, "%s",
--
1.9.1
8 years, 10 months
[libvirt] [gconfig] gconfig: VIRTIO -> VIRTIO_GPU
by Zeeshan Ali (Khattak)
Rename GVIR_CONFIG_DOMAIN_VIDEO_MODEL_VIRTIO to
GVIR_CONFIG_DOMAIN_VIDEO_MODEL_VIRTIO_GPU to get the naming the same as
used by libosinfo. Consistency is good anyway in general but this would
also mean that Boxes can start using virgl without any changes.
---
examples/config-demo.py | 2 +-
libvirt-gconfig/libvirt-gconfig-domain-video.h | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/examples/config-demo.py b/examples/config-demo.py
index e92aa43..e52996c 100644
--- a/examples/config-demo.py
+++ b/examples/config-demo.py
@@ -62,7 +62,7 @@ graphics.set_gl(True)
domain.add_device(graphics)
video = LibvirtGConfig.DomainVideo.new()
-video.set_model(LibvirtGConfig.DomainVideoModel.VIRTIO)
+video.set_model(LibvirtGConfig.DomainVideoModel.VIRTIO_GPU)
video.set_accel3d(True)
domain.add_device(video)
diff --git a/libvirt-gconfig/libvirt-gconfig-domain-video.h b/libvirt-gconfig/libvirt-gconfig-domain-video.h
index 9fb8e4d..dda3088 100644
--- a/libvirt-gconfig/libvirt-gconfig-domain-video.h
+++ b/libvirt-gconfig/libvirt-gconfig-domain-video.h
@@ -63,7 +63,7 @@ typedef enum {
GVIR_CONFIG_DOMAIN_VIDEO_MODEL_XEN,
GVIR_CONFIG_DOMAIN_VIDEO_MODEL_VBOX,
GVIR_CONFIG_DOMAIN_VIDEO_MODEL_QXL,
- GVIR_CONFIG_DOMAIN_VIDEO_MODEL_VIRTIO
+ GVIR_CONFIG_DOMAIN_VIDEO_MODEL_VIRTIO_GPU
} GVirConfigDomainVideoModel;
GType gvir_config_domain_video_get_type(void);
--
2.7.4
8 years, 10 months
[libvirt] [PATCH] spec: Fix indentation
by Andrea Bolognani
Commit ffc49e579c14 broke syntax-check:
cppi: libvirt.spec.in: line 622: not properly indented
cppi: libvirt.spec.in: line 624: not properly indented
cppi: libvirt.spec.in: line 640: not properly indented
cppi: libvirt.spec.in: line 642: not properly indented
maint.mk: incorrect preprocessor indentation
cfg.mk:697: recipe for target 'sc_spec_indentation' failed
Indent the new conditionals properly.
---
Pushed as build breaker.
libvirt.spec.in | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/libvirt.spec.in b/libvirt.spec.in
index 3afb155..cc5d722 100644
--- a/libvirt.spec.in
+++ b/libvirt.spec.in
@@ -619,9 +619,9 @@ Requires: gzip
Requires: bzip2
Requires: lzop
Requires: xz
-%if 0%{?fedora} >= 24
+ %if 0%{?fedora} >= 24
Requires: systemd-container
-%endif
+ %endif
%description daemon-driver-qemu
The qemu driver plugin for the libvirtd daemon, providing
@@ -637,9 +637,9 @@ Group: Development/Libraries
Requires: libvirt-daemon = %{version}-%{release}
# There really is a hard cross-driver dependency here
Requires: libvirt-daemon-driver-network = %{version}-%{release}
-%if 0%{?fedora} >= 24
+ %if 0%{?fedora} >= 24
Requires: systemd-container
-%endif
+ %endif
%description daemon-driver-lxc
The LXC driver plugin for the libvirtd daemon, providing
--
2.7.4
8 years, 10 months
[libvirt] [PATCH sandbox] docker: rename destdir to templatedir
by Daniel P. Berrange
Use the more common naming for the variable pointing to
the template directory
Signed-off-by: Daniel P. Berrange <berrange(a)redhat.com>
---
libvirt-sandbox/image/sources/DockerSource.py | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/libvirt-sandbox/image/sources/DockerSource.py b/libvirt-sandbox/image/sources/DockerSource.py
index 8f33cb3..c30fe72 100644
--- a/libvirt-sandbox/image/sources/DockerSource.py
+++ b/libvirt-sandbox/image/sources/DockerSource.py
@@ -298,17 +298,17 @@ class DockerSource(Source):
connect)
parentImage = templateImage
- def _get_image_list(self, template, destdir):
+ def _get_image_list(self, template, templatedir):
imageparent = {}
imagenames = {}
- imagedirs = os.listdir(destdir)
+ imagedirs = os.listdir(templatedir)
for imagetagid in imagedirs:
- indexfile = destdir + "/" + imagetagid + "/index.json"
+ indexfile = templatedir + "/" + imagetagid + "/index.json"
if os.path.exists(indexfile):
with open(indexfile,"r") as f:
index = json.load(f)
imagenames[index["name"]] = imagetagid
- jsonfile = destdir + "/" + imagetagid + "/template.json"
+ jsonfile = templatedir + "/" + imagetagid + "/template.json"
if os.path.exists(jsonfile):
with open(jsonfile,"r") as f:
data = json.load(f)
--
2.7.4
8 years, 10 months
[libvirt] [PATCH sandbox] Improve error message for unsupported URIs
by Daniel P. Berrange
Signed-off-by: Daniel P. Berrange <berrange(a)redhat.com>
---
libvirt-sandbox/libvirt-sandbox-context-interactive.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/libvirt-sandbox/libvirt-sandbox-context-interactive.c b/libvirt-sandbox/libvirt-sandbox-context-interactive.c
index 3ab63ec..5ecaf09 100644
--- a/libvirt-sandbox/libvirt-sandbox-context-interactive.c
+++ b/libvirt-sandbox/libvirt-sandbox-context-interactive.c
@@ -229,13 +229,15 @@ static gboolean gvir_sandbox_context_interactive_start(GVirSandboxContext *ctxt,
if (!g_str_equal(uri, "lxc:///") &&
!g_str_equal(uri, "qemu:///system")) {
g_set_error(error, GVIR_SANDBOX_CONTEXT_INTERACTIVE_ERROR, 0,
- _("Only 'lxc:///' or 'qemu:///system' URIs supported when running as root"));
+ _("URI '%s' unsupported as root, try 'lxc:///' or 'qemu:///system'"),
+ uri);
goto cleanup;
}
} else {
if (!g_str_equal(uri, "qemu:///session")) {
g_set_error(error, GVIR_SANDBOX_CONTEXT_INTERACTIVE_ERROR, 0,
- _("Only 'qemu:///session' URIs supported when running as non-root"));
+ _("URI '%s' unsupported as non-root, try 'qemu:///session'"),
+ uri);
goto cleanup;
}
}
--
2.7.4
8 years, 10 months
[libvirt] [PATCH sandbox] Remove transfer annotations on scalar parameters
by Daniel P. Berrange
The (transfer) annotation is only valid on parameters which
are non-scalar in nature. Latest gobject will warn about
this mistake.
Signed-off-by: Daniel P. Berrange <berrange(a)redhat.com>
---
libvirt-sandbox/libvirt-sandbox-config-interactive.c | 4 ++--
libvirt-sandbox/libvirt-sandbox-config-network-route.c | 2 +-
libvirt-sandbox/libvirt-sandbox-config.c | 16 ++++++++--------
3 files changed, 11 insertions(+), 11 deletions(-)
diff --git a/libvirt-sandbox/libvirt-sandbox-config-interactive.c b/libvirt-sandbox/libvirt-sandbox-config-interactive.c
index 27b4c16..88bc015 100644
--- a/libvirt-sandbox/libvirt-sandbox-config-interactive.c
+++ b/libvirt-sandbox/libvirt-sandbox-config-interactive.c
@@ -246,7 +246,7 @@ GVirSandboxConfigInteractive *gvir_sandbox_config_interactive_new(const gchar *n
/**
* gvir_sandbox_config_interactive_set_tty:
* @config: (transfer none): the sandbox config
- * @tty: (transfer none): true if the container should have a tty
+ * @tty: true if the container should have a tty
*
* Set whether the container console should have a interactive tty.
*/
@@ -263,7 +263,7 @@ void gvir_sandbox_config_interactive_set_tty(GVirSandboxConfigInteractive *confi
*
* Retrieves the sandbox tty flag
*
- * Returns: (transfer none): the tty flag
+ * Returns: the tty flag
*/
gboolean gvir_sandbox_config_interactive_get_tty(GVirSandboxConfigInteractive *config)
{
diff --git a/libvirt-sandbox/libvirt-sandbox-config-network-route.c b/libvirt-sandbox/libvirt-sandbox-config-network-route.c
index 1664d18..c6bf6f3 100644
--- a/libvirt-sandbox/libvirt-sandbox-config-network-route.c
+++ b/libvirt-sandbox/libvirt-sandbox-config-network-route.c
@@ -234,7 +234,7 @@ void gvir_sandbox_config_network_route_set_prefix(GVirSandboxConfigNetworkRoute
*
* Retrieves the prefix length of the route
*
- * Returns: (transfer none): the prefix length
+ * Returns: the prefix length
*/
guint gvir_sandbox_config_network_route_get_prefix(GVirSandboxConfigNetworkRoute *config)
{
diff --git a/libvirt-sandbox/libvirt-sandbox-config.c b/libvirt-sandbox/libvirt-sandbox-config.c
index 0ade178..8709736 100644
--- a/libvirt-sandbox/libvirt-sandbox-config.c
+++ b/libvirt-sandbox/libvirt-sandbox-config.c
@@ -699,7 +699,7 @@ const gchar *gvir_sandbox_config_get_kmodpath(GVirSandboxConfig *config)
/**
* gvir_sandbox_config_set_shell:
* @config: (transfer none): the sandbox config
- * @shell: (transfer none): true if the container should have a shell
+ * @shell: true if the container should have a shell
*
* Set whether the container console should have a interactive shell.
*/
@@ -716,7 +716,7 @@ void gvir_sandbox_config_set_shell(GVirSandboxConfig *config, gboolean shell)
*
* Retrieves the sandbox shell flag
*
- * Returns: (transfer none): the shell flag
+ * Returns: the shell flag
*/
gboolean gvir_sandbox_config_get_shell(GVirSandboxConfig *config)
{
@@ -728,7 +728,7 @@ gboolean gvir_sandbox_config_get_shell(GVirSandboxConfig *config)
/**
* gvir_sandbox_config_set_userid:
* @config: (transfer none): the sandbox config
- * @uid: (transfer none): the sandbox user ID
+ * @uid: the sandbox user ID
*
* Set the user ID to invoke the sandbox application under.
* Defaults to the user ID of the current program.
@@ -746,7 +746,7 @@ void gvir_sandbox_config_set_userid(GVirSandboxConfig *config, guint uid)
*
* Get the user ID to invoke the sandbox application under.
*
- * Returns: (transfer none): the user ID
+ * Returns: the user ID
*/
guint gvir_sandbox_config_get_userid(GVirSandboxConfig *config)
{
@@ -758,7 +758,7 @@ guint gvir_sandbox_config_get_userid(GVirSandboxConfig *config)
/**
* gvir_sandbox_config_set_groupid:
* @config: (transfer none): the sandbox config
- * @gid: (transfer none): the sandbox group ID
+ * @gid: the sandbox group ID
*
* Set the group ID to invoke the sandbox application under.
* Defaults to the group ID of the current program.
@@ -776,7 +776,7 @@ void gvir_sandbox_config_set_groupid(GVirSandboxConfig *config, guint gid)
*
* Get the group ID to invoke the sandbox application under.
*
- * Returns: (transfer none): the group ID
+ * Returns: the group ID
*/
guint gvir_sandbox_config_get_groupid(GVirSandboxConfig *config)
{
@@ -1849,7 +1849,7 @@ const gchar *gvir_sandbox_config_get_security_label(GVirSandboxConfig *config)
/**
* gvir_sandbox_config_set_security_dynamic:
* @config: (transfer none): the sandbox config
- * @dynamic: (transfer none): the security mode
+ * @dynamic: the security mode
*
* Set the SELinux security dynamic for the sandbox. The default
* dynamic is "svirt_sandbox_t"
@@ -1866,7 +1866,7 @@ void gvir_sandbox_config_set_security_dynamic(GVirSandboxConfig *config, gboolea
*
* Retrieve the sandbox security mode
*
- * Returns: (transfer none): the security mode
+ * Returns: the security mode
*/
gboolean gvir_sandbox_config_get_security_dynamic(GVirSandboxConfig *config)
{
--
2.7.4
8 years, 10 months
[libvirt] [PATCH] conf: Make really sure we don't access non-existing vCPUs again
by Daniel P. Berrange
From: Martin Kletzander <mkletzan(a)redhat.com>
MinGW complained that we might be dereferencing a NULL pointer. While
that can't be true, the logic certainly allows for that.
../../src/conf/domain_conf.c: In function 'virDomainDefPostParse':
../../src/conf/domain_conf.c:4224:18: error: potential null pointer dereference [-Werror=null-dereference]
if (!vcpu->online && vcpu->cpumask) {
~~~~^~~~~~~~
Signed-off-by: Daniel P. Berrange <berrange(a)redhat.com>
---
Pushed as build fix
src/conf/domain_conf.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index db1a0ff..1fd826d 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -4221,7 +4221,7 @@ virDomainDefRemoveOfflineVcpuPin(virDomainDefPtr def)
for (i = 0; i < virDomainDefGetVcpusMax(def); i++) {
vcpu = virDomainDefGetVcpu(def, i);
- if (!vcpu->online && vcpu->cpumask) {
+ if (vcpu && !vcpu->online && vcpu->cpumask) {
virBitmapFree(vcpu->cpumask);
vcpu->cpumask = NULL;
--
2.7.4
8 years, 10 months
[libvirt] [PATCH] libvirt.spec.in: require systemd-container on >= f24
by Daniel P. Berrange
The systemd-machined tools libvirt uses were split into a
systemd-container RPM. Without depending on this, libvirt
may silently fallback to the non-systemd cgroup impl which
is not desirable.
Signed-off-by: Daniel P. Berrange <berrange(a)redhat.com>
---
libvirt.spec.in | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/libvirt.spec.in b/libvirt.spec.in
index 2b98836..8ebfea5 100644
--- a/libvirt.spec.in
+++ b/libvirt.spec.in
@@ -619,6 +619,9 @@ Requires: gzip
Requires: bzip2
Requires: lzop
Requires: xz
+%if 0%{?fedora} > 23
+Requires: systemd-container
+%endif
%description daemon-driver-qemu
The qemu driver plugin for the libvirtd daemon, providing
@@ -634,6 +637,9 @@ Group: Development/Libraries
Requires: libvirt-daemon = %{version}-%{release}
# There really is a hard cross-driver dependency here
Requires: libvirt-daemon-driver-network = %{version}-%{release}
+%if 0%{?fedora} > 23
+Requires: systemd-container
+%endif
%description daemon-driver-lxc
The LXC driver plugin for the libvirtd daemon, providing
--
2.7.4
8 years, 10 months
[libvirt] [PATCH] qemu: command: Fix awkward formatting
by Andrea Bolognani
---
Pushed as trivial.
src/qemu/qemu_command.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 2ca6d26..fe4bb88 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -5158,9 +5158,7 @@ qemuBuildVirtioSerialPortDevStr(const virDomainDef *def,
dev->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_CCW &&
dev->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_S390) {
/* Check it's a virtio-serial address */
- if (dev->info.type !=
- VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_SERIAL)
- {
+ if (dev->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_SERIAL) {
virReportError(VIR_ERR_INTERNAL_ERROR,
"%s", _("virtio serial device has invalid address type"));
goto error;
--
2.7.4
8 years, 10 months