[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, 8 months
[libvirt] [PATCH v2] storage: dir: adapts .wipeVol for ploop volumes
by Olga Krishtal
The modification of .volWipe callback wipes ploop volume using one of
given wiping algorithm: dod, nnsa, etc.
However, in case of ploop volume we need to reinitialize root.hds and DiskDescriptor.xml.
v2:
- added check on ploop tools presens
- virCommandAddArgFormat changed to virCommandAddArg
Signed-off-by: Olga Krishtal <okrishtal(a)virtuozzo.com>
---
src/storage/storage_backend.c | 68 +++++++++++++++++++++++++++++++++++++++----
1 file changed, 62 insertions(+), 6 deletions(-)
diff --git a/src/storage/storage_backend.c b/src/storage/storage_backend.c
index 5adf1fd..14b3a64 100644
--- a/src/storage/storage_backend.c
+++ b/src/storage/storage_backend.c
@@ -2195,6 +2195,55 @@ virStorageBackendWipeLocal(virStorageVolDefPtr vol,
return ret;
}
+static int
+virStorageBackendVolWipePloop(virStorageVolDefPtr vol)
+{
+ virCommandPtr cmd = NULL;
+ char *target_path = NULL;
+ char *disk_desc = NULL;
+ char *create_tool = NULL;
+
+ int ret = -1;
+
+ create_tool = virFindFileInPath("ploop");
+ if (!create_tool) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+ _("unable to find ploop tools, please install them"));
+ return -1;
+ }
+
+ if (virAsprintf(&target_path, "%s/root.hds", vol->target.path) < 0)
+ goto cleanup;
+
+ if (virAsprintf(&disk_desc, "%s/DiskDescriptor.xml", vol->target.path) < 0)
+ goto cleanup;
+
+ if (virFileRemove(disk_desc, 0, 0) < 0) {
+ virReportError(errno, _("Failed to delete DiskDescriptor.xml of volume '%s'"),
+ vol->target.path);
+ goto cleanup;
+ }
+ if (virFileRemove(target_path, 0, 0) < 0) {
+ virReportError(errno, _("failed to delete root.hds of volume '%s'"),
+ vol->target.path);
+ goto cleanup;
+ }
+
+ cmd = virCommandNewArgList(create_tool, "init", "-s", NULL);
+
+ virCommandAddArgFormat(cmd, "%lluM", VIR_DIV_UP(vol->target.capacity,
+ (1024 * 1024)));
+ virCommandAddArgList(cmd, "-t", "ext4", NULL);
+ virCommandAddArg(cmd, target_path);
+ ret = virCommandRun(cmd, NULL);
+
+ cleanup:
+ VIR_FREE(disk_desc);
+ VIR_FREE(target_path);
+ VIR_FREE(create_tool);
+ virCommandFree(cmd);
+ return ret;
+}
int
virStorageBackendVolWipeLocal(virConnectPtr conn ATTRIBUTE_UNUSED,
@@ -2207,6 +2256,8 @@ virStorageBackendVolWipeLocal(virConnectPtr conn ATTRIBUTE_UNUSED,
const char *alg_char = NULL;
struct stat st;
virCommandPtr cmd = NULL;
+ char *path = NULL;
+ char *target_path = vol->target.path;
virCheckFlags(0, -1);
@@ -2214,12 +2265,12 @@ virStorageBackendVolWipeLocal(virConnectPtr conn ATTRIBUTE_UNUSED,
vol->target.path, algorithm);
if (vol->target.format == VIR_STORAGE_FILE_PLOOP) {
- virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
- _("wiping for ploop volumes is not supported"));
- goto cleanup;
+ if (virAsprintf(&path, "%s/root.hds", vol->target.path) < 0)
+ goto cleanup;
+ target_path = path;
}
- fd = open(vol->target.path, O_RDWR);
+ fd = open(target_path, O_RDWR);
if (fd == -1) {
virReportSystemError(errno,
_("Failed to open storage volume with path '%s'"),
@@ -2276,13 +2327,12 @@ virStorageBackendVolWipeLocal(virConnectPtr conn ATTRIBUTE_UNUSED,
if (algorithm != VIR_STORAGE_VOL_WIPE_ALG_ZERO) {
cmd = virCommandNew(SCRUB);
virCommandAddArgList(cmd, "-f", "-p", alg_char,
- vol->target.path, NULL);
+ target_path, NULL);
if (virCommandRun(cmd, NULL) < 0)
goto cleanup;
ret = 0;
- goto cleanup;
} else {
if (S_ISREG(st.st_mode) && st.st_blocks < (st.st_size / DEV_BSIZE)) {
ret = virStorageBackendVolZeroSparseFileLocal(vol, st.st_size, fd);
@@ -2292,10 +2342,16 @@ virStorageBackendVolWipeLocal(virConnectPtr conn ATTRIBUTE_UNUSED,
vol->target.allocation,
st.st_blksize);
}
+ if (ret < 0)
+ goto cleanup;
}
+ if (vol->target.format == VIR_STORAGE_FILE_PLOOP)
+ ret = virStorageBackendVolWipePloop(vol);
+
cleanup:
virCommandFree(cmd);
+ VIR_FREE(path);
VIR_FORCE_CLOSE(fd);
return ret;
}
--
1.8.3.1
8 years, 8 months
[libvirt] question about PCI new_id sysfs interface
by Jim Fehlig
After updating the dom0 kernel on one of my Xen test hosts, I noticed problems
with PCI hostdev management. E.g
# virsh nodedev-detach pci_0000_07_10_1
error: Failed to detach device pci_0000_07_10_1
error: Failed to add PCI device ID '8086 1520' to pciback: File exists
It turns out there was a small interface change to new_id with the following
commit to 3.16 kernel
https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/dr...
which now causes xen_pciback to fail writes of "vendorid productid" to new_id. e.g.
# echo "8086 1520" > /sys/bus/pci/drivers/pciback/new_id
-bash: echo: write error: File exists
Interestingly, vfio doesn't encounter the same error
# echo "8086 1520" > /sys/bus/pci/drivers/vfio-pci/new_id
# echo $?
0
vfio-pci has:
static struct pci_driver vfio_pci_driver = {
.name = "vfio-pci",
.id_table = NULL, /* only dynamic ids */
while xen-pciback has:
static const struct pci_device_id pcistub_ids[] = {
{
.vendor = PCI_ANY_ID,
.device = PCI_ANY_ID,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
},
{0,},
};
static struct pci_driver xen_pcibk_pci_driver = {
.name = "pciback",
.id_table = pcistub_ids,
So any vendor/device pair will match for xen-pciback, while none will match for
vfio-pci.
But after reading that commit and the associated thread, it is not clear to me
how to best fix this. Options are
1. set .id_table to NULL for xen-pciback
2. drop using the new_id interface from libvirt
3. pass more values (subvendor, subdevice, class, etc) to the new_id interface
I'm not sure what problems, if any, options 1 and 2 might cause. Option 2 seems
the best approach since new_id seems to be a rather unsafe interface.
Thanks for your opinions!
Regards,
Jim
8 years, 8 months
Re: [libvirt] [Qemu-devel] [RFC 00/28] s390x CPU models: exposing features
by David Hildenbrand
Are there any further comments, especially on patches 23-25, introducing new
QOM interfaces?
Also, if anybody is planning to look into this, please speak up :)
Otherwise it might make sense to put this onto the next KVM call agenda.
David
> This is our second attempt to implement CPU models for s390x. We realized
> that we also want to have features exposed via the CPU model. While doing
> that we realized that we want to have a better interface for libvirt.
>
> Unfortunately, CPU models on s390x are special and we have to take care of:
> - A CPU like z13 looks differently in various environments (under different
> LPAR versions, under different z/VM versions, under different KVM
> versions, export regulation) - we have _a lot_ of feature variability.
> - We still have certain features that are not published but might be
> implemented/introduced in the future. As they are a theoretical part
> of a CPU already, we have to find a way to model these future changes.
> - We still have certain features that are already published, but not
> implemented. Implementation might be added in the future in KVM.
> - We heavily rely on KVM to tell us which features it can actually
> virtualize - user space queries like "STFL(e)" give no guarantees.
> - Certain "subfeatures" were introduced in one run. In practice, they are
> always around, but in theory, subfeatures could be dropped in the future.
> - Just because two CPU models have the same features doesn't mean they
> are equal - some internal numbers might be different. E.g. we won't allow
> running a z13 under a zBC12 just by turning off features.
> - We cannot blindly enable all possible features for a CPU generation,
> the IBC "Instruction Blocking Control" in KVM will try to block
> instructions introduced with certain features. So a CPU generation always
> has some maximum feature set that is guaranteed to work.
>
> It all boils down to a specific released CPU to have.
> a) A fixed feature set that we expect it to be have on every hypervisor.
> b) A variable part that depends on the hypervisor and that could be
> extended in the future (adding not yet implemented features) that we
> always want to enable later on.
> c) A variable part that we want to enable only if requested - nested
> virtualization ("vsie") and assists are one example.
>
> But, the fixed feature set is not really what we want to use as a default.
> It is just like a really minimum, stable base.
>
> So we have
> a) A "stable" CPU model for each released CPU that will never change and
> maps to the minimum feature set we expect to be around on all
> hypervisors. e.g. "z13-base" or "z10EC.2-base". These are migration
> safe.
> b) A "default" CPU model for each released CPU, that can change between
> QEMU versions and that will always include the features we expect to
> be around in our currently supported environments and will contain only
> features we expect to be stable. E.g. nested virtualization will not be
> contained in these models. These models are not migration safe, e.g
> "z13" or "z10EC.2". The feature set can differ between QEMU versions.
> c) An internal "maximum" CPU model for each generation that tells us which
> features were supported as a maximum back when the hardware was
> released. This will not be exposed
>
> To not have to replicate all CPU model changes ("new default fetaures") in
> libvirt, to not duplicate the logic about compatibility and the like,
> our approach tries to keep all the QEMU logic in libvirt and provide
> standardized interfaces for libvirt to e.g. baseline, compare. This
> allows libvirt to not have to care about any model names or feature names,
> it can just pass the data from interface to interface and report it to
> the user.
>
> Also, libvirt might want to know what the "host" model looks like and
> convert a CPU model to a migration safe variant. For this reason, a QMP
> command is added that can create a migration safe variant of a variable
> CPU model, indicating only the delta changes done to a stable model.
>
> So we have:
> a) "query-cpu-model-expansion" - tell us what the "host" or a migration
> unsafe model looks like. Either falling back to a stable model or
> completely exposing all properties. We are interested in stable models.
> b) "query-cpu-model-comparison" - tell us how two CPU models compare,
> indicating which properties were responsible for the decision.
> c) "query-cpu-model-baseline" - create a new model out of two models,
> taking a requested level of stability into account.
>
> As we are aware that e.g. x86 has their own idea of a CPU model and their
> existing implementation in place, but are also looking into to ways to e.g.
> expand the "host" CPU model to a detailed representation, we designed the
> "expansion" interface to also allow that.
>
> Comments are very welcome, but please always keep the restrictions and
> specialties in mind when suggesting some major design changes.
>
> The header update will be replaced by a kvm-next header update as soon as
> the VSIE patches are upstream. The major KVM interface changes are already
> part of kvm-next.
>
> The current state is available on git://github.com/cohuck/qemu on branch
> "cpumodel-s390x".
>
> David Hildenbrand (26):
> s390x/cpumodel: "host" and "qemu" as CPU subclasses
> s390x/cpumodel: expose CPU class properties
> s390x/cpumodel: generate CPU feature group lists
> s390x/cpumodel: introduce CPU feature group definitions
> s390x/cpumodel: register defined CPU models as subclasses
> s390x/cpumodel: store the CPU model in the CPU instance
> s390x/cpumodel: expose features and feature groups as properties
> s390x/cpumodel: let the CPU model handle feature checks
> s390x/cpumodel: check and apply the CPU model
> s390x/sclp: factor out preparation of cpu entries
> s390x/sclp: introduce sclp feature blocks
> s390x/sclp: indicate sclp features
> s390x/sclp: propagate the ibc val(lowest and unblocked ibc)
> s390x/sclp: propagate the mha via sclp
> s390x/sclp: propagate hmfai
> update linux headers (CPU model)
> s390x/kvm: allow runtime-instrumentation for "none" machine
> s390x/kvm: implement CPU model support
> s390x/kvm: disable host model for existing compat machines
> s390x/kvm: let the CPU model control CMM(A)
> qmp: add QMP interface "query-cpu-model-expansion"
> qmp: add QMP interface "query-cpu-model-comparison"
> qmp: add QMP interface "query-cpu-model-baseline"
> s390x/cpumodel: implement QMP interface "query-cpu-model-expansion"
> s390x/cpumodel: implement QMP interface "query-cpu-model-comparison"
> s390x/cpumodel: implement QMP interface "query-cpu-model-baseline"
>
> Michael Mueller (2):
> s390x/cpumodel: introduce CPU features
> s390x/cpumodel: generate CPU feature lists for CPU models
>
> Makefile.target | 2 +-
> hw/s390x/s390-virtio-ccw.c | 5 +
> hw/s390x/s390-virtio.c | 6 +-
> hw/s390x/sclp.c | 35 +-
> include/hw/s390x/sclp.h | 17 +-
> include/sysemu/arch_init.h | 10 +
> linux-headers/asm-s390/kvm.h | 40 ++
> qapi-schema.json | 184 ++++++
> qmp-commands.hx | 18 +
> qmp.c | 22 +
> rules.mak | 1 +
> stubs/Makefile.objs | 3 +
> stubs/arch-query-cpu-model-baseline.c | 13 +
> stubs/arch-query-cpu-model-comparison.c | 12 +
> stubs/arch-query-cpu-model-expansion.c | 12 +
> target-s390x/Makefile.objs | 22 +-
> target-s390x/cpu-qom.h | 5 +
> target-s390x/cpu.c | 35 +-
> target-s390x/cpu.h | 5 +
> target-s390x/cpu_features.c | 376 +++++++++++
> target-s390x/cpu_features.h | 302 +++++++++
> target-s390x/cpu_models.c | 1055 +++++++++++++++++++++++++++++++
> target-s390x/cpu_models.h | 113 ++++
> target-s390x/gen-features.c | 587 +++++++++++++++++
> target-s390x/helper.c | 29 +-
> target-s390x/kvm.c | 346 +++++++++-
> target-s390x/machine.c | 14 +-
> 27 files changed, 3203 insertions(+), 66 deletions(-)
> create mode 100644 stubs/arch-query-cpu-model-baseline.c
> create mode 100644 stubs/arch-query-cpu-model-comparison.c
> create mode 100644 stubs/arch-query-cpu-model-expansion.c
> create mode 100644 target-s390x/cpu_features.c
> create mode 100644 target-s390x/cpu_features.h
> create mode 100644 target-s390x/cpu_models.c
> create mode 100644 target-s390x/cpu_models.h
> create mode 100644 target-s390x/gen-features.c
>
8 years, 8 months
[libvirt] gconfig: Add hostdev support v4
by Zeeshan Ali (Khattak)
Finally I got the time to clean-up and fix the patches. It's been a while last i looked into them already and I got a bit confused at some point so I appologize if I didn't address some of the review comments.
8 years, 8 months
[libvirt] [PATCH v3 00/10] Add support for LUKS encrypted devices
by John Ferlan
v2: http://www.redhat.com/archives/libvir-list/2016-June/msg01691.html
Changes since v2 (all as a result of code review)
Patch 1: New as a result of review comment regarding virSecretDefFormatUsage
Patch 2: Change "id" to "name", fixed the html.in, remove whitespice,
generated patch 1 due to virSecretDefFormatUsage comment
Patch 3: Altered the html.in, don't believe the review comment for
wrong type in qemuProcessGetVolumeQcowPassphrase is right,
also modified the testdata output file to follow suggestion
for changes made in patch 5 & 6
Patch 4: Was essentially ACK'd, but requires previous patches. Took care
of the testdata output file.
Patch 5: Adjusted html.in, modified virStorageEncryptionInfoDef to have
both cipher_* and ivgen_* params in it - affected other places
(and fixed those),
Patch 6: Essentially ACK'd (the chmod was removed)
Patch 7: NEW - going to need this for hot unplug...
Patch 8: Adjusted per review of this series and the other 3 patch series
for rbd disk hot plug/unplug
Patch 9: NEW - Need to generate a different alias for LUKS
Patch 10: Mostly unchanged except to utilze the luks specific alias
generation... also moved the unplug to right place.
John Ferlan (10):
conf: No need to check for usage fields during Format
conf: Add new secret type "passphrase"
util: Add 'usage' for encryption
encryption: Add luks parsing for storageencryption
encryption: Add <cipher> and <ivgen> to encryption
storage: Add support to create a luks volume
qemu: Introduce helper qemuDomainSecretDiskCapable
qemu: Add secinfo for hotplug virtio disk
qemu: Alter the qemuDomainGetSecretAESAlias to add new arg
qemu: Add luks support for domain disk
docs/aclpolkit.html.in | 4 +
docs/formatsecret.html.in | 62 ++++-
docs/formatstorageencryption.html.in | 115 ++++++++-
docs/schemas/secret.rng | 10 +
docs/schemas/storagecommon.rng | 57 ++++-
include/libvirt/libvirt-secret.h | 3 +-
src/access/viraccessdriverpolkit.c | 13 ++
src/conf/domain_conf.c | 11 +
src/conf/secret_conf.c | 36 ++-
src/conf/secret_conf.h | 1 +
src/conf/virsecretobj.c | 5 +
src/libvirt_private.syms | 1 +
src/qemu/qemu_alias.c | 10 +-
src/qemu/qemu_alias.h | 3 +-
src/qemu/qemu_command.c | 9 +
src/qemu/qemu_domain.c | 58 +++--
src/qemu/qemu_domain.h | 3 +
src/qemu/qemu_hotplug.c | 123 +++++++++-
src/qemu/qemu_process.c | 19 +-
src/storage/storage_backend.c | 260 +++++++++++++++++++--
src/storage/storage_backend.h | 3 +-
src/storage/storage_backend_fs.c | 10 +-
src/storage/storage_backend_gluster.c | 2 +
src/util/virqemu.c | 23 ++
src/util/virqemu.h | 6 +
src/util/virstorageencryption.c | 166 +++++++++++--
src/util/virstorageencryption.h | 18 +-
.../qemuxml2argv-encrypted-disk-usage.args | 24 ++
.../qemuxml2argv-encrypted-disk-usage.xml | 36 +++
.../qemuxml2argv-luks-disk-cipher.args | 36 +++
.../qemuxml2argv-luks-disk-cipher.xml | 45 ++++
.../qemuxml2argvdata/qemuxml2argv-luks-disks.args | 36 +++
tests/qemuxml2argvdata/qemuxml2argv-luks-disks.xml | 45 ++++
tests/qemuxml2argvtest.c | 12 +-
.../qemuxml2xmlout-encrypted-disk-usage.xml | 1 +
.../qemuxml2xmlout-luks-disk-cipher.xml | 1 +
.../qemuxml2xmlout-luks-disks.xml | 1 +
tests/qemuxml2xmltest.c | 3 +
tests/secretxml2xmlin/usage-passphrase.xml | 7 +
tests/secretxml2xmltest.c | 1 +
tests/storagevolxml2argvtest.c | 3 +-
tests/storagevolxml2xmlin/vol-luks-cipher.xml | 23 ++
tests/storagevolxml2xmlin/vol-luks.xml | 21 ++
tests/storagevolxml2xmlout/vol-luks-cipher.xml | 23 ++
tests/storagevolxml2xmlout/vol-luks.xml | 21 ++
tests/storagevolxml2xmltest.c | 2 +
46 files changed, 1267 insertions(+), 105 deletions(-)
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-encrypted-disk-usage.args
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-encrypted-disk-usage.xml
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-luks-disk-cipher.args
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-luks-disk-cipher.xml
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-luks-disks.args
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-luks-disks.xml
create mode 120000 tests/qemuxml2xmloutdata/qemuxml2xmlout-encrypted-disk-usage.xml
create mode 120000 tests/qemuxml2xmloutdata/qemuxml2xmlout-luks-disk-cipher.xml
create mode 120000 tests/qemuxml2xmloutdata/qemuxml2xmlout-luks-disks.xml
create mode 100644 tests/secretxml2xmlin/usage-passphrase.xml
create mode 100644 tests/storagevolxml2xmlin/vol-luks-cipher.xml
create mode 100644 tests/storagevolxml2xmlin/vol-luks.xml
create mode 100644 tests/storagevolxml2xmlout/vol-luks-cipher.xml
create mode 100644 tests/storagevolxml2xmlout/vol-luks.xml
--
2.5.5
8 years, 9 months
[libvirt] [PATCH 0/6] bhyve: virConnectDomainXMLFromNative
by Fabian Freyer
Differences to v3:
functional changes:
- Throw an error when there is no bhyverun command (bhyve_argv == NULL)
- Parse the memory size in the same way bhyve does it, and adapt the
relevant
code (vm_parse_memsize) from the FreeBSD source tree.
Here I'm a bit unsure about attribution; the original function comes
from a
BSD 2-Clause Licenced file, and I'm not sure if I also have to
include the
BSD disclaimer to the header.
- Removed capability check for clock offset
- Fix a mixup of NMDM master and slave
- Fixed numbering of disks. When >25 disks are given, disks after
vdz/sdz no
longer get added.
- Fail completely should parsing fail.
bugfixes:
- Fix a possible Null-Pointer dereference in
bhyveParseCommandLineString when
no loader command is given.
- Fix an off-by-one in the string allocation (bhyve_parse_command.c:60)
style:
- Fix some indentation
- Move else-clauses on the same line as the closing bracket from the if
Link to v3:
https://www.redhat.com/archives/libvir-list/2016-June/msg01741.html
Link to v2:
https://www.redhat.com/archives/libvir-list/2016-June/msg00728.html
Link to v1:
https://www.redhat.com/archives/libvir-list/2016-June/msg00001.html
Fabian Freyer (6):
config-post.h: define __GNUC_PREREQ if not defined
gnulib: add getopt module
bhyve: implement virConnectDomainXMLFromNative
bhyve: implement bhyve argument parser
bhyve: implement argument parser for loader
Add some tests for bhyveParseCommandLineString
bootstrap.conf | 1 +
config-post.h | 18 +
m4/virt-driver-bhyve.m4 | 3 +
po/POTFILES.in | 1 +
src/Makefile.am | 2 +
src/bhyve/bhyve_driver.c | 42 +
src/bhyve/bhyve_parse_command.c | 892
+++++++++++++++++++++
src/bhyve/bhyve_parse_command.h | 30 +
tests/Makefile.am | 23 +-
.../bhyveargv2xmldata/bhyveargv2xml-acpiapic.args | 9 +
tests/bhyveargv2xmldata/bhyveargv2xml-acpiapic.xml | 20 +
tests/bhyveargv2xmldata/bhyveargv2xml-ahci-hd.args | 8 +
tests/bhyveargv2xmldata/bhyveargv2xml-ahci-hd.xml | 21 +
tests/bhyveargv2xmldata/bhyveargv2xml-base.args | 7 +
tests/bhyveargv2xmldata/bhyveargv2xml-base.xml | 16 +
.../bhyveargv2xml-bhyveload-bootorder.args | 13 +
.../bhyveargv2xml-bhyveload-bootorder.xml | 27 +
.../bhyveargv2xml-bhyveload-custom.args | 11 +
.../bhyveargv2xml-bhyveload-custom.xml | 18 +
.../bhyveargv2xml-bhyveload-mem-mismatch.args | 12 +
.../bhyveargv2xml-bhyveload-memsize-fail.args | 12 +
.../bhyveargv2xml-bhyveload-name-mismatch.args | 12 +
.../bhyveargv2xml-bhyveload-vda.args | 12 +
.../bhyveargv2xml-bhyveload-vda.xml | 21 +
.../bhyveargv2xml-bhyverun-mem-mismatch.args | 12 +
.../bhyveargv2xml-bhyverun-name-mismatch.args | 12 +
tests/bhyveargv2xmldata/bhyveargv2xml-cdrom.args | 8 +
tests/bhyveargv2xmldata/bhyveargv2xml-cdrom.xml | 21 +
tests/bhyveargv2xmldata/bhyveargv2xml-console.args | 10 +
tests/bhyveargv2xmldata/bhyveargv2xml-console.xml | 28 +
.../bhyveargv2xmldata/bhyveargv2xml-console2.args | 10 +
tests/bhyveargv2xmldata/bhyveargv2xml-console2.xml | 15 +
.../bhyveargv2xmldata/bhyveargv2xml-console3.args | 11 +
tests/bhyveargv2xmldata/bhyveargv2xml-console3.xml | 27 +
.../bhyveargv2xmldata/bhyveargv2xml-console4.args | 10 +
tests/bhyveargv2xmldata/bhyveargv2xml-console4.xml | 15 +
.../bhyveargv2xml-custom-loader.args | 8 +
.../bhyveargv2xml-custom-loader.xml | 18 +
.../bhyveargv2xml-disk-toomany.args | 34 +
.../bhyveargv2xml-disk-toomany.xml | 146 ++++
.../bhyveargv2xmldata/bhyveargv2xml-extraargs.args | 8 +
.../bhyveargv2xml-memsize-fail.args | 7 +
.../bhyveargv2xml-memsize-human.args | 7 +
.../bhyveargv2xml-memsize-human.xml | 16 +
.../bhyveargv2xml-memsize-large.args | 7 +
.../bhyveargv2xml-memsize-large.xml | 16 +
tests/bhyveargv2xmldata/bhyveargv2xml-name.args | 7 +
tests/bhyveargv2xmldata/bhyveargv2xml-name.xml | 16 +
tests/bhyveargv2xmldata/bhyveargv2xml-oneline.args | 1 +
tests/bhyveargv2xmldata/bhyveargv2xml-oneline.xml | 16 +
tests/bhyveargv2xmldata/bhyveargv2xml-utc.args | 8 +
tests/bhyveargv2xmldata/bhyveargv2xml-utc.xml | 16 +
tests/bhyveargv2xmldata/bhyveargv2xml-uuid.args | 8 +
tests/bhyveargv2xmldata/bhyveargv2xml-uuid.xml | 16 +
tests/bhyveargv2xmldata/bhyveargv2xml-uuid2.args | 8 +
tests/bhyveargv2xmldata/bhyveargv2xml-vcpus.args | 7 +
tests/bhyveargv2xmldata/bhyveargv2xml-vcpus.xml | 16 +
.../bhyveargv2xml-virtio-blk.args | 8 +
.../bhyveargv2xmldata/bhyveargv2xml-virtio-blk.xml | 21 +
.../bhyveargv2xml-virtio-net.args | 9 +
.../bhyveargv2xmldata/bhyveargv2xml-virtio-net.xml | 26 +
.../bhyveargv2xml-virtio-net2.args | 8 +
.../bhyveargv2xml-virtio-net2.xml | 16 +
.../bhyveargv2xml-virtio-net3.args | 8 +
.../bhyveargv2xml-virtio-net3.xml | 16 +
.../bhyveargv2xml-virtio-net4.args | 8 +
.../bhyveargv2xml-virtio-net4.xml | 21 +
tests/bhyveargv2xmlmock.c | 27 +
tests/bhyveargv2xmltest.c | 213 +++++
69 files changed, 2174 insertions(+), 3 deletions(-)
create mode 100644 src/bhyve/bhyve_parse_command.c
create mode 100644 src/bhyve/bhyve_parse_command.h
create mode 100644 tests/bhyveargv2xmldata/bhyveargv2xml-acpiapic.args
create mode 100644 tests/bhyveargv2xmldata/bhyveargv2xml-acpiapic.xml
create mode 100644 tests/bhyveargv2xmldata/bhyveargv2xml-ahci-hd.args
create mode 100644 tests/bhyveargv2xmldata/bhyveargv2xml-ahci-hd.xml
create mode 100644 tests/bhyveargv2xmldata/bhyveargv2xml-base.args
create mode 100644 tests/bhyveargv2xmldata/bhyveargv2xml-base.xml
create mode 100644
tests/bhyveargv2xmldata/bhyveargv2xml-bhyveload-bootorder.args
create mode 100644
tests/bhyveargv2xmldata/bhyveargv2xml-bhyveload-bootorder.xml
create mode 100644
tests/bhyveargv2xmldata/bhyveargv2xml-bhyveload-custom.args
create mode 100644
tests/bhyveargv2xmldata/bhyveargv2xml-bhyveload-custom.xml
create mode 100644
tests/bhyveargv2xmldata/bhyveargv2xml-bhyveload-mem-mismatch.args
create mode 100644
tests/bhyveargv2xmldata/bhyveargv2xml-bhyveload-memsize-fail.args
create mode 100644
tests/bhyveargv2xmldata/bhyveargv2xml-bhyveload-name-mismatch.args
create mode 100644 tests/bhyveargv2xmldata/bhyveargv2xml-bhyveload-vda.args
create mode 100644 tests/bhyveargv2xmldata/bhyveargv2xml-bhyveload-vda.xml
create mode 100644
tests/bhyveargv2xmldata/bhyveargv2xml-bhyverun-mem-mismatch.args
create mode 100644
tests/bhyveargv2xmldata/bhyveargv2xml-bhyverun-name-mismatch.args
create mode 100644 tests/bhyveargv2xmldata/bhyveargv2xml-cdrom.args
create mode 100644 tests/bhyveargv2xmldata/bhyveargv2xml-cdrom.xml
create mode 100644 tests/bhyveargv2xmldata/bhyveargv2xml-console.args
create mode 100644 tests/bhyveargv2xmldata/bhyveargv2xml-console.xml
create mode 100644 tests/bhyveargv2xmldata/bhyveargv2xml-console2.args
create mode 100644 tests/bhyveargv2xmldata/bhyveargv2xml-console2.xml
create mode 100644 tests/bhyveargv2xmldata/bhyveargv2xml-console3.args
create mode 100644 tests/bhyveargv2xmldata/bhyveargv2xml-console3.xml
create mode 100644 tests/bhyveargv2xmldata/bhyveargv2xml-console4.args
create mode 100644 tests/bhyveargv2xmldata/bhyveargv2xml-console4.xml
create mode 100644 tests/bhyveargv2xmldata/bhyveargv2xml-custom-loader.args
create mode 100644 tests/bhyveargv2xmldata/bhyveargv2xml-custom-loader.xml
create mode 100644 tests/bhyveargv2xmldata/bhyveargv2xml-disk-toomany.args
create mode 100644 tests/bhyveargv2xmldata/bhyveargv2xml-disk-toomany.xml
create mode 100644 tests/bhyveargv2xmldata/bhyveargv2xml-extraargs.args
create mode 100644 tests/bhyveargv2xmldata/bhyveargv2xml-memsize-fail.args
create mode 100644 tests/bhyveargv2xmldata/bhyveargv2xml-memsize-human.args
create mode 100644 tests/bhyveargv2xmldata/bhyveargv2xml-memsize-human.xml
create mode 100644 tests/bhyveargv2xmldata/bhyveargv2xml-memsize-large.args
create mode 100644 tests/bhyveargv2xmldata/bhyveargv2xml-memsize-large.xml
create mode 100644 tests/bhyveargv2xmldata/bhyveargv2xml-name.args
create mode 100644 tests/bhyveargv2xmldata/bhyveargv2xml-name.xml
create mode 100644 tests/bhyveargv2xmldata/bhyveargv2xml-oneline.args
create mode 100644 tests/bhyveargv2xmldata/bhyveargv2xml-oneline.xml
create mode 100644 tests/bhyveargv2xmldata/bhyveargv2xml-utc.args
create mode 100644 tests/bhyveargv2xmldata/bhyveargv2xml-utc.xml
create mode 100644 tests/bhyveargv2xmldata/bhyveargv2xml-uuid.args
create mode 100644 tests/bhyveargv2xmldata/bhyveargv2xml-uuid.xml
create mode 100644 tests/bhyveargv2xmldata/bhyveargv2xml-uuid2.args
create mode 100644 tests/bhyveargv2xmldata/bhyveargv2xml-vcpus.args
create mode 100644 tests/bhyveargv2xmldata/bhyveargv2xml-vcpus.xml
create mode 100644 tests/bhyveargv2xmldata/bhyveargv2xml-virtio-blk.args
create mode 100644 tests/bhyveargv2xmldata/bhyveargv2xml-virtio-blk.xml
create mode 100644 tests/bhyveargv2xmldata/bhyveargv2xml-virtio-net.args
create mode 100644 tests/bhyveargv2xmldata/bhyveargv2xml-virtio-net.xml
create mode 100644 tests/bhyveargv2xmldata/bhyveargv2xml-virtio-net2.args
create mode 100644 tests/bhyveargv2xmldata/bhyveargv2xml-virtio-net2.xml
create mode 100644 tests/bhyveargv2xmldata/bhyveargv2xml-virtio-net3.args
create mode 100644 tests/bhyveargv2xmldata/bhyveargv2xml-virtio-net3.xml
create mode 100644 tests/bhyveargv2xmldata/bhyveargv2xml-virtio-net4.args
create mode 100644 tests/bhyveargv2xmldata/bhyveargv2xml-virtio-net4.xml
create mode 100644 tests/bhyveargv2xmlmock.c
create mode 100644 tests/bhyveargv2xmltest.c
--
2.5.5
8 years, 9 months
[libvirt] [PATCH v2 0/2] virsh expand virsh list command options
by Chen Hanxiao
Chen Hanxiao (2):
virsh: allow both --uuid and --name at same cmd
virsh: enable --table with --name or --uuid
tools/virsh-domain-monitor.c | 56 +++++++++++++++++++++++++++++++++++++-------
1 file changed, 47 insertions(+), 9 deletions(-)
--
2.5.0
8 years, 9 months
[libvirt] [PATCH REPOST 00/38] Introduce APIs to change daemon's logging settings
by Erik Skultety
Basically the same series as
https://www.redhat.com/archives/libvir-list/2016-March/msg01534.html, just
rebased onto the current HEAD.
Daniel pointed out in 31/38 maybe we do not want to expose an API to set
logging level. Despite the truth being that the functionality of logging levels
can be replaced by logging filters completely, I think that it still provides
us with more convenience than having to specify a big bunch of filters.
Erik Skultety (38):
virlog: Return void instead of int in virLogReset<Foo> methods
virlog: Convert virLogOutputs to a list of pointers to outputs
virlog: Convert virLogFilters to a list of pointers to filters
virlog: Export virLogOutputPtr through header
virlog: Export virLogFilterPtr through header
virlog: Introduce virLogSetFilters
virlog: Introduce virLogSetOutputs
daemon: Replace virLogParseOutputs with virLogSetOutputs in callers
daemon: Replace virLogParseFilters with virLogSetFilters in callers
virlog: Introduce virLogDefineOutputs
virlog: Introduce virLogDefineFilters
virlog: Rename virLogAddOutputTo to virLogNewOutput
virlog: Rename virLogDefineOutput to virLogOutputNew
virlog: Rename virLogDefineFilter to virLogFilterNew
virlog: Introduce virLogOutputFree
virlog: Introduce virLogOutputListFree
virlog: Introduce virLogFilterFree
virlog: Introduce virLogFilterListFree
virlog: Make virLogReset methods use of virLog(Output|Filter)ListFree
virlog: Split output parsing and output defining to separate
operations
virlog: Split filter parsing and filter defining to separate
operations
virlog: Split parsing and setting priority
virlog: Introduce virLogOutputExists
virlog: Make use of virLogOutputExists
virlog: Take a special care of syslog when setting new set of log
outputs
virlog: Swap the new copy of outputs with the global existing one
virlog: Rename virLogFiltersSerial to virLogSerial
virlog: Make virLogSetDefaultPriority trigger source update as well
virlog: Introduce an API mutex that serializes all setters
virlog: Acquire virLogAPILock in each setter API
admin: Introduce virAdmConnectGetLoggingLevel
admin: Introduce virAdmConnectGetLoggingFilters
admin: Introduce virAdmConnectGetLoggingOutputs
admin: Introduce virAdmConnectSetLoggingLevel
admin: Introduce virAdmConnectSetLoggingFilters
admin: Introduce virAdmConnectSetLoggingOutputs
admin: Export logging level constants via libvirt-admin.h
virt-admin: Wire-up the logging APIs
daemon/admin.c | 126 ++++++++
daemon/libvirtd.c | 8 +-
include/libvirt/libvirt-admin.h | 37 +++
src/admin/admin_protocol.x | 74 ++++-
src/admin/admin_remote.c | 86 +++++
src/admin_protocol-structs | 39 +++
src/libvirt-admin.c | 220 +++++++++++++
src/libvirt_admin_private.syms | 9 +
src/libvirt_admin_public.syms | 6 +
src/libvirt_private.syms | 14 +-
src/locking/lock_daemon.c | 8 +-
src/logging/log_daemon.c | 8 +-
src/util/virlog.c | 698 +++++++++++++++++++++++++++-------------
src/util/virlog.h | 50 +--
tests/eventtest.c | 3 +-
tests/testutils.c | 19 +-
tests/virlogtest.c | 12 +-
tools/virt-admin.c | 204 ++++++++++++
18 files changed, 1361 insertions(+), 260 deletions(-)
--
2.4.11
8 years, 9 months