[libvirt] [PATCH 0/4] bhyve: UEFI bootrom support
by Fabian Freyer
this series of patches adds support for specifying UEFI boot images for bhyve
virtual machines.
The old behaviour is kept; only when a loader pflash is specified the loader
command is omitted and adds a bootrom parameter to the bhyverun command.
Fabian Freyer (4):
bhyve: Separate out checks from virBhyveProbeCaps
bhyve: virBhyveProbeCaps: BHYVE_CAP_LPC_BOOTROM
bhyve: add support for booting from UEFI
bhyve: Test cases for UEFI bhyvexml2argvtest
src/bhyve/bhyve_capabilities.c | 59 ++++++++++++++++++----
src/bhyve/bhyve_capabilities.h | 1 +
src/bhyve/bhyve_command.c | 6 +++
src/bhyve/bhyve_driver.c | 27 ++++++++--
tests/bhyvexml2argvdata/bhyvexml2argv-nouefi.args | 9 ++++
.../bhyvexml2argvdata/bhyvexml2argv-nouefi.ldargs | 1 +
tests/bhyvexml2argvdata/bhyvexml2argv-nouefi.xml | 23 +++++++++
tests/bhyvexml2argvdata/bhyvexml2argv-uefi.args | 10 ++++
tests/bhyvexml2argvdata/bhyvexml2argv-uefi.ldargs | 1 +
tests/bhyvexml2argvdata/bhyvexml2argv-uefi.xml | 23 +++++++++
tests/bhyvexml2argvtest.c | 13 ++++-
11 files changed, 158 insertions(+), 15 deletions(-)
create mode 100644 tests/bhyvexml2argvdata/bhyvexml2argv-nouefi.args
create mode 100644 tests/bhyvexml2argvdata/bhyvexml2argv-nouefi.ldargs
create mode 100644 tests/bhyvexml2argvdata/bhyvexml2argv-nouefi.xml
create mode 100644 tests/bhyvexml2argvdata/bhyvexml2argv-uefi.args
create mode 100644 tests/bhyvexml2argvdata/bhyvexml2argv-uefi.ldargs
create mode 100644 tests/bhyvexml2argvdata/bhyvexml2argv-uefi.xml
--
2.7.0
8 years, 4 months
[libvirt] [PATCH] Introduce Smack security driver for Libvirt
by Randy Aybar (raybar)
First time RFC/mailing list/community submission/etc. so please forgive if not in the appropriate format.
-Randy
---
Incorporate changes that enable native support for Smack within Libvirt.
--------------------------------------------------------------------------------
Table of Contents
i. Contributions
I. Introduction
II. Implementations & Changes
III. Patch
--------------------------------------------------------------------------------
i. Contributions
Below is a list of contributors of the patch described in this document:
-Raghuram S. Sudhaakar rsudhaak(a)cisco.com, Cisco Systems, Inc.
San Jose, California, USA
-Randy Aybar raybar(a)cisco.com, Cisco Systems, Inc.
San Jose, California, USA
-Hongliang Liang hliang(a)bupt.edu.cn, Beijing University of Posts and
Telecommunications (BUPT), Beijing, China
-Changyao Han changyao(a)bupt.edu.cn, Beijing University of Posts and
Telecommunications (BUPT), Beijing, China
Portion of changes are based on existing security drivers within Libvirt:
-James Morris <jmorris(a)namei.org> (SELinux security driver)
-Jamie Strandboge <jamie(a)canonical.org> (AppArmor security driver)
--------------------------------------------------------------------------------
I. Introduction
Libvirt currently has support for two of the various Linux security modules
(LSM), AppArmor and SELinux. While these work well enough for most cases, there
are others in which a platform may require less complexity and overhead.
Smack LSM (http://schaufler-ca.com/description_from_the_linux_source_tree)
intrinsically provides access control with much more simplicity while
remaining secure. A subject-object model is adapted with an access type
relationship to determine if permissions or granted or denied.
Brief history of code authorship
We [folks at Cisco] started work on implementing a Libvirt security driver that
would allow enable Smack support. The goal was to ensure that Libvirt would be
able to enforce security policies using this lightweight module in order
secure our Linux containers running on platforms.
Initial findings on the topic yielded us to a research paper worked on by
students at Beijing University of Posts and Telecommunications. As part of the
paper's objective to create a lightweight approach to secure deployment of
virtual machines in the cloud, a Smack security driver was implemented for use
with QEMU-based virtual machines spawned by using the Libvirt API. After
contacting the authors of the papers, they were more than willing to share the
source code.
Since the initial driver acquired from the university lacked support for
LXC-style VMs, our role was to implement that portion. This patch includes the
collaborative efforts in order to bring a more complete Smack driver to Libvirt.
--------------------------------------------------------------------------------
II. Implementation & Changes
Detailed changes described in this section will be limited to those made by
Cisco engineers. The implementation made by researchers at BUPT can be
read in their research paper and is based on libvirt v1.1.4. Publication information:
A Lightweight Security Isolation Approach for Virtual Machines Deployment
by Hongliang Liang, Changyao Han, Daijie Zhang, and Dongyang Wu
Information Security and Cryptology
10th International Conference, Inscrypt 2014, Beijing, China, December 13-15,
2014, Revised Selected Papers
Editors: Lin, Dongdai, Young, Moti, Zhou, Jianying (Eds.)
Initial code changes made by BUPT can be located at the following GitHub
repository as patches labeled for Libvirt 1.1.4:
https://github.com/rssudhaakar/libvirt-smack
The Smack driver was initially derived from parts of the SELinux
and AppArmor drivers as noted by the authors and uses the Libsmack library to
assign Smack labels when needed.
Changes made by authors Raghuram S Sudhaakar and Randy Aybar are two major parts -
1) Firstly, the code was updated to accommodate the various interface changes made in libvirt v1.2+.
2) Secondly, make the SMACK security driver work with LXC driver
The following is the details on the changes made for #2 above –
A major changes involves modifying the security driver interface to
include an additional hook/function. This decision was made after encountering
several issues while applying labels to certain components of a container as well
as consideration for minimizing the impact of the other security drivers. Details
can be found under security driver changes.
Another thing to note is that the Smack security driver itself depends on a security
interface when fully enforced with namespaces. This interface is brought in
by the Linux kernel in 4.3 but our team has backported and tested Libvirt with version
3.19 kernel. Details on why this was necessary found below in LXC container
changes. Link that references the change in the kernel:
https://lwn.net/Articles/660675/
i. LXC Container (src/lxc/lxc_container.c)
a. Reordering of dropping capabilities and setting up security labeling
Upon forking into a new user namespace (lxcContainerSetID), the child process no
longer has the ability to override LSM and access folders that have been previously assigned
Smack labels. This is important to note since after entering the namespace, the child
still needs to share mount devpts and pivot root however the process does not
take on the container's label until much after this setup. Thus a suggestion to
move the set process label (virSecurityManagerSetProcessLabel) after setting namespaces is made.
Dropping capabilities was also moved after sending the continue signal to the
parent. We had come across an issue as well with setting up FDs and the
container would fail to start.
b. Adding a call to set the child's process label (virSecurityManagerSetChildProcessLabel)
When the child process is spawned from lxcContainerStart, although it has full
capabilities in its own namespace (after SetUID), it is unable to change its own security
context (label). Currently the only workaround is to incorporate an
upcoming patch to the Smack LSM (kernel base) that allows an unprivileged
process to change its context only if the label its trying to acquire exists in
a predefined list held by the parent.
With the patch in place, the LXC driver needs to ensure that the label makes it
to the list of the parent so that the child can continue to take on the context
which brings a change to lxcContainerStart.
Although the SetChildProcessLabel is a hook that is primarily used by QEMU, we
decided to use it as the name best fit the operation being performed.
A check is implemented to ensure that it only continues if Smack is the driver
being used since this does not need to occur in the other LSMs.
Within the Smack driver itself, the hook also performs a check to see if LXC is
used otherwise skip the block pertaining to LXC. In the LXC code, it checks
to see if the Smack relabel-self interface exists and if namespaces is being
used to continue. The label is written with a simple write call to the file. The
logic is allowed to flow into the QEMU portion since no command is passed in,
the function acts as a noop and safely exits.
Any comments for improvement on the logic handled in this change are highly
appreciated!
ii. LXC Controller (src/lxc/lxc_controller.c)
a. Add logic to label the special devices created under
(/var/run/libvirt/lxc/container.XXX)
The following function calls setup the appropriate special devices such as
ttys, ptmx, null, etc. (/dev)
virLXCControllerSetupDev
virLXCControllerPopulateDevices
virLXCControllerSetupDevPTS
virLXCControllerSetupConsoles
It was decided to add the call to do a label operation in these functions due to
the fact that chown'ing also happened at these locations and wanted to provide
some uniformity in that sense. Since the security hook to label these are no-op
in all but the Smack driver it's just a straightforward call with the usual
check to see if it succeeded.
iii. Security Drivers (src/security)
Changes to security driver model include an additional hook to apply a security
label by passing in a string. Although there exists functions made for applying
security labels, complications arose from using either.
The first of these is SetImageLabel which requires to pass in a virStorageSource
that holds the string. LXC does not make use of this data structure and
initializing one for the sake of a string did not seem feasible due to the
numerous and differing members the struct consisted of.
The second function major function to apply security labels is SetImageFDLabel
which uses a file descriptor rather than a string text. While this approach
seemed more promising there were hurdles that came across while attempting to
label items. A file descriptor would be needed to be opened for each special
device available. However devices like tty could not be opened without being
issued as a controlling tty by the process. Note that a workaround was attempted
to change the open call to include the O_PATH flag and obtain the path by looking up the
location the FD pointed to in the process's list of file descriptors within
/proc. While this change worked for the tty case, it was dismissed due to the
additional changes that may have been needed to the other security drivers as we
were targeting to minimize the changes. This solution may be revisited upon further
testing and review.
a. Update Definitions for DAC, Stack, AppArmor, SELinux, Smack,
driver base (security_driver.h), and driver manager (security_manager.c,h)
Changes here involve updated the driver's definitions to include the new hook,
virSecurityDomainSetImagePathLabel. All drivers except Smack implement this by
just returning 0 to not disrupt the flow in a non-Smack setup.
b. Updates to Smack driver to support namespaces with LXC
Already described include changes to implement the extra hook to label a file
using a path as well as SetChildProcessLabel wihthin the driver to
include the process of adding a label to the approved list via relabel-self.
The driver itself was cleaned up a bit and refactored to eliminate the use of
excessive amount of helper functions and rely on the API provided by the
libsmack library. Function names were refactored to match the style of the
SELinux driver (after the dropping of an extra "Security" in the function's
name).
iv. Support for entering namespaces in Smack (src/libvirt-lxc.c)
A small addition was made to enable support for Smack using the
lxc-enter-namespace and was merely a mirror of the other security drivers
included in this file. Smack in this case uses libsmack API call to label the
process entering the namespace.
--------------------------------------------------------------------------------
III. Patch
This patch has been created for patching Libvirt 1.3.1 base source code.
diff --git a/configure.ac b/configure.ac
index 047ad3b..12d0bb8 100644
--- a/configure.ac
+++ b/configure.ac
@@ -253,6 +253,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
@@ -1535,6 +1536,27 @@ if test "$with_apparmor" = "no"; then
fi
AM_CONDITIONAL([WITH_APPARMOR_PROFILES], [test "$with_apparmor_profiles" != "no"])
+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"])
+
+
+
dnl DTrace static probes
AC_ARG_WITH([dtrace],
[AS_HELP_STRING([--with-dtrace],
@@ -2867,6 +2889,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([])
@@ -2897,6 +2920,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/m4/virt-smack.m4 b/m4/virt-smack.m4
new file mode 100644
index 0000000..f23ffdc
--- /dev/null
+++ b/m4/virt-smack.m4
@@ -0,0 +1,48 @@
+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([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/src/Makefile.am b/src/Makefile.am
index aa5ab69..d367954 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)
@@ -1005,6 +1009,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 \
@@ -1734,6 +1741,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)
@@ -1865,6 +1876,7 @@ EXTRA_DIST += \
$(NWFILTER_DRIVER_SOURCES) \
$(SECURITY_DRIVER_SELINUX_SOURCES) \
$(SECURITY_DRIVER_APPARMOR_SOURCES) \
+ $(SECURITY_DRIVER_SMACK_SOURCES) \
$(SECRET_DRIVER_SOURCES) \
$(VBOX_DRIVER_EXTRA_DIST) \
$(VMWARE_DRIVER_SOURCES) \
diff --git a/src/libvirt-lxc.c b/src/libvirt-lxc.c
index 8553570..4a26e80 100644
--- a/src/libvirt-lxc.c
+++ b/src/libvirt-lxc.c
@@ -3,6 +3,7 @@
* APIs.
*
* Copyright (C) 2012-2014 Red Hat, Inc.
+ * 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
@@ -18,7 +19,9 @@
* License along with this library. If not, see
* <http://www.gnu.org/licenses/>.
*
- * Author: Daniel P. Berrange <berrange(a)redhat.com>
+ * Authors: Daniel P. Berrange <berrange(a)redhat.com>
+ * Raghuram S. Sudhaakar <rssudhaakar(a)gmail.com>
+ * Randy Aybar <raybar(a)cisco.com>
*/
#include <config.h>
@@ -36,6 +39,9 @@
#ifdef WITH_APPARMOR
# include <sys/apparmor.h>
#endif
+#ifdef WITH_SMACK
+# include <sys/smack.h>
+#endif
#define VIR_FROM_THIS VIR_FROM_NONE
@@ -256,6 +262,20 @@ virDomainLxcEnterSecurityLabel(virSecurityModelPtr model,
_("Support for AppArmor is not enabled"));
goto error;
#endif
+ } else if (STREQ(model->model, "smack")) {
+#ifdef WITH_SMACK
+ if (smack_set_label_for_self(label->label) < 0) {
+ virReportError(errno,
+ _("unable to set security label '%s'"),
+ label->label);
+
+ goto error;
+ }
+#else
+ virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
+ _("Support for Smack is not enabled"));
+ goto error;
+#endif
} else {
virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED,
_("Security model %s cannot be entered"),
diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c
index c5a70a1..71203aa 100644
--- a/src/lxc/lxc_container.c
+++ b/src/lxc/lxc_container.c
@@ -1,13 +1,16 @@
/*
* Copyright (C) 2008-2015 Red Hat, Inc.
* Copyright (C) 2008 IBM Corp.
- * Copyright (c) 2015 SUSE LINUX Products GmbH, Nuernberg, Germany.
+ * Copyright (C) 2015 SUSE LINUX Products GmbH, Nuernberg, Germany.
+ * Copyright (C) 2015 Cisco Systems, Inc.
*
* lxc_container.c: file description
*
* Authors:
* David L. Leskovec <dlesko at linux.vnet.ibm.com>
* Daniel P. Berrange <berrange(a)redhat.com>
+ * Raghuram S. Sudhaakar <rssudhaakar(a)gmail.com>
+ * Randy Aybar <raybar(a)cisco.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -2206,6 +2209,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 +2261,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 +2274,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);
@@ -2389,6 +2392,16 @@ int lxcContainerStart(virDomainDefPtr def,
if (userns_supported()) {
VIR_DEBUG("Enable user namespace");
cflags |= CLONE_NEWUSER;
+#ifdef WITH_SMACK
+ if(STREQ(virSecurityManagerGetModel(securityDriver),"smack") &&
+ virSecurityManagerSetChildProcessLabel(securityDriver,
+ def,
+ NULL) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("Failed to send label to relabel interface."));
+ return -1;
+ }
+#endif
} else {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("Kernel doesn't support user namespace"));
diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c
index 438103a..37080b8 100644
--- a/src/lxc/lxc_controller.c
+++ b/src/lxc/lxc_controller.c
@@ -1,11 +1,14 @@
/*
* Copyright (C) 2010-2015 Red Hat, Inc.
- * Copyright IBM Corp. 2008
- *
+ * Copyright (C) 2008 IBM Corp.
+ * Copyright (C) 2015 Cisco Systems, Inc.
+ *
* lxc_controller.c: linux container process controller
*
* Authors:
* David L. Leskovec <dlesko at linux.vnet.ibm.com>
+ * Raghuram S. Sudhaakar <rssudhaakar(a)gmail.com>
+ * Randy Aybar <raybar(a)cisco.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -1476,6 +1479,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:
@@ -1525,6 +1531,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);
}
@@ -2183,6 +2194,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:
@@ -2227,6 +2246,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 2cf333d..c013443 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 a09aba5..1af5175 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 784b0de..c477f93 100644
--- a/src/security/security_driver.h
+++ b/src/security/security_driver.h
@@ -1,6 +1,7 @@
/*
* Copyright (C) 2008, 2010-2013 Red Hat, Inc.
- *
+ * Copyright (C) 2015 Cisco System, 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
@@ -17,7 +18,8 @@
*
* Authors:
* James Morris <jmorris(a)namei.org>
- *
+ * Raghuram S. Sudhaakar <rssudhaakar(a)gmail.com>
+ * Randy Aybar <raybar(a)cisco.com>
*/
#ifndef __VIR_SECURITY_H__
# define __VIR_SECURITY_H__
@@ -104,6 +106,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 +170,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 07a0522..b782eab 100644
--- a/src/security/security_manager.c
+++ b/src/security/security_manager.c
@@ -2,6 +2,7 @@
* security_manager.c: Internal security manager API
*
* Copyright (C) 2010-2014 Red Hat, Inc.
+ * 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
@@ -17,7 +18,9 @@
* License along with this library. If not, see
* <http://www.gnu.org/licenses/>.
*
- * Author: Daniel P. Berrange <berrange(a)redhat.com>
+ * Authors: Daniel P. Berrange <berrange(a)redhat.com>
+ * Raghuram S. Sudhaakar <rssudhaakar(a)gmail.com>
+ * Randy Aybar <raybar(a)cisco.com>
*/
#include <config.h>
@@ -916,6 +919,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 e534e31..35e8a3b 100644
--- a/src/security/security_manager.h
+++ b/src/security/security_manager.h
@@ -2,7 +2,8 @@
* security_manager.h: Internal security manager API
*
* Copyright (C) 2010-2013 Red Hat, Inc.
- *
+ * 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
@@ -18,6 +19,8 @@
* <http://www.gnu.org/licenses/>.
*
* Author: Daniel P. Berrange <berrange(a)redhat.com>
+ * Raghuram S. Sudhaakar <rssudhaakar(a)gmail.com>
+ * Randy Aybar <raybar(a)cisco.com>
*/
#ifndef VIR_SECURITY_MANAGER_H__
@@ -143,6 +146,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 9e98635..4b510e1 100644
--- a/src/security/security_selinux.c
+++ b/src/security/security_selinux.c
@@ -2459,6 +2459,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)
@@ -2639,6 +2647,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..50301ad
--- /dev/null
+++ b/src/security/security_smack.c
@@ -0,0 +1,1519 @@
+/*
+ * 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 <dirent.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;
+ int fd;
+ int ret;
+ char *path;
+
+ result = calloc(SMACK_LABEL_LEN + 1, 1);
+ if (result == NULL)
+ return -1;
+ ret = virAsprintf(&path, "/proc/%d/attr/current", pid);
+ if (ret < 0)
+ return -1;
+ fd = open(path, O_RDONLY);
+ VIR_FREE(path);
+ if (fd < 0) {
+ free(result);
+ return -1;
+ }
+ ret = read(fd, result, SMACK_LABEL_LEN);
+ VIR_FORCE_CLOSE(fd);
+ if (ret < 0) {
+ free(result);
+ return -1;
+ }
+ *label = result;
+ return ret;
+
+}
+
+int
+virSecuritySmackSockCreate(const char *label, const char *attr)
+{
+ int fd;
+ int ret = -1;
+ long int tid;
+ char *path;
+ tid = syscall(SYS_gettid);
+ VIR_DEBUG("/proc/self/task/%ld/attr/%s", tid, attr);
+ ret = virAsprintf(&path, "/proc/self/task/%ld/attr/%s", tid, attr);
+ if (ret < 0)
+ return -1;
+
+ VIR_DEBUG("virSecuritySmackSockCreate 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);
+
+ if (label) {
+ fd = open(path, O_WRONLY | O_CLOEXEC);
+ VIR_DEBUG("open file %s", path);
+ VIR_FREE(path);
+ if (fd < 0) {
+ VIR_DEBUG("open fail");
+ return -1;
+ }
+ VIR_DEBUG("open success");
+ do {
+ ret = write(fd, label, strlen(label) + 1);
+ } while (ret < 0 && errno == EINTR);
+ }
+ else {
+ fd = open(path, O_TRUNC);
+ VIR_FREE(path);
+ if (fd < 0)
+ return -1;
+ ret = 0;
+ }
+
+ close(fd);
+
+ return (ret < 0) ? -1 : 0;
+
+}
+
+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)) {
+ 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)) {
+ 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:
+
+ 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)) {
+ 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)) {
+ 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);
+ free(label_name);
+ return -1;
+ }
+
+ strcpy(sec->label, label_name);
+ free(label_name);
+ /*Smack default enforced*/
+ sec->enforcing = 1;
+
+ return 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,
+ _("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(write(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..9a865cb
--- /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 00d1fa7..38551ca 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 fe7bf34..7094e89 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);
8 years, 4 months
[libvirt] Creating external snapshots with logical volumes.
by Dominique Ramaekers
Hi,
I've already asked this question on the libvirt-users mailing list but got no answer. I think because the answer to my question is not obvious. I hope I get some help here...
Currently, for making backups of my guests, I use external snapshots like this:
A) virsh snapshot-create-as --domain PCVIRTdra --disk-only --atomic --quiesce --no-metadata --diskspec vda,file=/srv/poolVMS/PCVIRTdra-ONDERHOUD
If I wanted to use a logical volume as destination behind the '--diskspec' option, can I do this like this?
B) virsh snapshot-create-as --domain PCVIRTdra --disk-only --atomic --quiesce --no-metadata --diskspec vda,file=/dev/CmsrvVH3-vg/PCVIRTdra-ONDERHOUD
I got the hit from libvirt itself. If I create a snapshot with command A and the diskspec file already exists, libvirt gives me an error like:
" external snapshot file for disk vda already exists and is not a block device: /srv/poolVMS/PCVIRTdra-ONDERHOUD"
So the 'and is not a block device' gave me the idea to use a logical volume instead of a file
It seems to work, but if this is never intended to be used like this, I would rather not...
I ask this question because it seems libvirt is actually recognizing the logical volume as a file if I use command B:
root@CmsrvVH3:~# virsh domblklist PCVIRTdra --details
Type Device Target Source
------------------------------------------------
file disk vda /dev/CmsrvVH3-vg/PCVIRTdra-ONDERHOUD
file cdrom hdb /srv/poolVMS/Windows10_x64.iso
file cdrom hdc /srv/poolVMS/virtiodrivers.iso
Is this intentional? Is there a better way of doing this?
Thanks in advance,
Dominique.
8 years, 4 months
[libvirt] [PATCH] virt-admin: Call virInitialize to fix startup crash
by Cole Robinson
Similar to what virsh and virt-login-shell do
https://bugzilla.redhat.com/show_bug.cgi?id=1350315
---
I can't actually reproduce the bug, the backtrace is similar to
97973ebb7 which added the same fix for virt-login-shell, and
that commit also mentions the randomness of reproducing...
tools/virt-admin.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/tools/virt-admin.c b/tools/virt-admin.c
index 4acac65..7bff5c3 100644
--- a/tools/virt-admin.c
+++ b/tools/virt-admin.c
@@ -1371,6 +1371,11 @@ main(int argc, char **argv)
return EXIT_FAILURE;
}
+ if (virInitialize() < 0) {
+ vshError(ctl, "%s", _("Failed to initialize libvirt"));
+ return EXIT_FAILURE;
+ }
+
virFileActivateDirOverride(argv[0]);
if (!vshInit(ctl, cmdGroups, NULL))
--
2.7.4
8 years, 4 months
[libvirt] [PATCH] qemu: Let empty default VNC password work as documented
by Jiri Denemark
Setting an empty vnc_password in qemu.conf is documented as a way to
disable VNC access, but QEMU does not seem to behave like that. Let's
enforce the behavior by setting password expiration to "now".
Note, this has no effect on setting an empty //graphics@passwd in
domain XML. Users may use //graphics@passwdValidTo to enforce the same
behavior.
https://bugzilla.redhat.com/show_bug.cgi?id=1180092
Signed-off-by: Jiri Denemark <jdenemar(a)redhat.com>
---
src/qemu/qemu_hotplug.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index e0b8230..91f48dc 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -3970,6 +3970,8 @@ qemuDomainChangeGraphicsPasswords(virQEMUDriverPtr driver,
snprintf(expire_time, sizeof(expire_time), "now");
else
snprintf(expire_time, sizeof(expire_time), "%lu", (long unsigned)auth->validTo);
+ } else if (!auth->passwd && defaultPasswd && defaultPasswd[0] == '\0') {
+ snprintf(expire_time, sizeof(expire_time), "now");
} else {
snprintf(expire_time, sizeof(expire_time), "never");
}
--
2.9.0
8 years, 4 months
[libvirt] [PATCH] qemu: Use proper async job to refresh virtio channels
by Jiri Denemark
Signed-off-by: Jiri Denemark <jdenemar(a)redhat.com>
---
src/qemu/qemu_migration.c | 3 ++-
src/qemu/qemu_process.c | 9 ++++++---
src/qemu/qemu_process.h | 3 ++-
3 files changed, 10 insertions(+), 5 deletions(-)
diff --git a/src/qemu/qemu_migration.c b/src/qemu/qemu_migration.c
index 83e1bfc..0b1770b 100644
--- a/src/qemu/qemu_migration.c
+++ b/src/qemu/qemu_migration.c
@@ -6225,7 +6225,8 @@ qemuMigrationFinish(virQEMUDriverPtr driver,
if (qemuMigrationStopNBDServer(driver, vm, mig) < 0)
goto endjob;
- if (qemuRefreshVirtioChannelState(driver, vm) < 0)
+ if (qemuRefreshVirtioChannelState(driver, vm,
+ QEMU_ASYNC_JOB_MIGRATION_IN) < 0)
goto endjob;
if ((rc = qemuConnectAgent(driver, vm)) < 0) {
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 63da600..c8ff587 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -1974,13 +1974,16 @@ qemuProcessRefreshChannelVirtioState(virQEMUDriverPtr driver,
int
qemuRefreshVirtioChannelState(virQEMUDriverPtr driver,
- virDomainObjPtr vm)
+ virDomainObjPtr vm,
+ qemuDomainAsyncJob asyncJob)
{
qemuDomainObjPrivatePtr priv = vm->privateData;
virHashTablePtr info = NULL;
int ret = -1;
- qemuDomainObjEnterMonitor(driver, vm);
+ if (qemuDomainObjEnterMonitorAsync(driver, vm, asyncJob) < 0)
+ goto cleanup;
+
ret = qemuMonitorGetChardevInfo(priv->mon, &info);
if (qemuDomainObjExitMonitor(driver, vm) < 0)
ret = -1;
@@ -3312,7 +3315,7 @@ qemuProcessReconnect(void *opaque)
if (qemuProcessRefreshDisks(driver, obj, QEMU_ASYNC_JOB_NONE) < 0)
goto error;
- if (qemuRefreshVirtioChannelState(driver, obj) < 0)
+ if (qemuRefreshVirtioChannelState(driver, obj, QEMU_ASYNC_JOB_NONE) < 0)
goto error;
/* If querying of guest's RTC failed, report error, but do not kill the domain. */
diff --git a/src/qemu/qemu_process.h b/src/qemu/qemu_process.h
index 37081ad..21f3b0c 100644
--- a/src/qemu/qemu_process.h
+++ b/src/qemu/qemu_process.h
@@ -180,7 +180,8 @@ int qemuProcessSetupIOThread(virDomainObjPtr vm,
virDomainIOThreadIDDefPtr iothread);
int qemuRefreshVirtioChannelState(virQEMUDriverPtr driver,
- virDomainObjPtr vm);
+ virDomainObjPtr vm,
+ qemuDomainAsyncJob asyncJob);
int qemuProcessRefreshBalloonState(virQEMUDriverPtr driver,
virDomainObjPtr vm,
--
2.9.0
8 years, 4 months
[libvirt] [PATCH rfc 0/2] devices: filesystem: type volume
by Olga Krishtal
In-Reply-To:
Patches introduce the new type of filesystem device.
The first patch adds the possibility to use storage pool volumes
as a backend for filesystem, that is accesed from the guest.
Such possibility allows to use volumes for container as a source of
root directory.
Usage:
<devices>
<filesystem type='volume'>
<source pool='pool_name' volume='volume_name'/>
...
<filesystem/>
The second patch adds the support of filesystem type volume
to virtuozzo containers. There is special type of volume for
virtuozzo containers, that can be manipulated via storage api.
Now, the volume of this type can be added to ct.xml description as
filesystem source.
However, there is a small issue with the pool/volume to path translation.
Usuallyi, in storage pools, virStorageTranslateDiskSourcePool is used,
but in the case of filesystem we do not have virDomainDiskDefPtr and
and code deduplication in every driver,that uses this possibility, is unavoidable.
eg. virStorageTranslatePoolLocal. Now I am looking for the way to avoid it somehow.
8 years, 4 months
[libvirt] [PATCH] util: swap After/Before clauses in virSystemdCreateMachine
by Quentin Machu
An unexpected behavior in systemd has been introduced between the versions
225 and 229: when non-existing units are specified in After/Before clauses,
systemd fails if the After clause is listed first. What is expected is that
systemd simply ignores these clauses. Because the After clause is specified
before the Before clause in virSystemdCreateMachine and because libvirt
does not tolerate missing the systemd-machined registration, it leads to
fatal boot failures, whereas instances could start properly without these
units - only the shutdown workflow could be affected.
This fixes the following error in some particular cases: `libvirtError:
Cannot set property Before, or unknown property.`.
If accepted, this bug fix should be backported.
https://bugzilla.redhat.com/show_bug.cgi?id=1350909
---
src/util/virsystemd.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/util/virsystemd.c b/src/util/virsystemd.c
index 871db7e..3a146f8 100644
--- a/src/util/virsystemd.c
+++ b/src/util/virsystemd.c
@@ -365,8 +365,8 @@ int virSystemdCreateMachine(const char *name,
nnicindexes, nicindexes,
3,
"Slice", "s", slicename,
- "After", "as", 1, "libvirtd.service",
- "Before", "as", 1, "libvirt-guests.service")
< 0)
+ "Before", "as", 1, "libvirt-guests.service",
+ "After", "as", 1, "libvirtd.service") < 0)
goto cleanup;
if (error.level == VIR_ERR_ERROR) {
@@ -406,8 +406,8 @@ int virSystemdCreateMachine(const char *name,
rootdir ? rootdir : "",
3,
"Slice", "s", slicename,
- "After", "as", 1, "libvirtd.service",
- "Before", "as", 1, "libvirt-guests.service")
< 0)
+ "Before", "as", 1, "libvirt-guests.service",
+ "After", "as", 1, "libvirtd.service") < 0)
goto cleanup;
}
--
1.8.3.1
8 years, 4 months
[libvirt] [PATCH] Fix possible invalid read in adminClientGetInfo
by Ján Tomko
virNetServerClientGetInfo returns the client's remote address
as a string, which is a part of the client object.
Use VIR_STRDUP to make a copy which can be freely accessed
even after the virNetServerClient object is unlocked.
---
daemon/admin_server.c | 3 ++-
src/rpc/virnetserverclient.c | 8 ++++++--
src/rpc/virnetserverclient.h | 2 +-
3 files changed, 9 insertions(+), 4 deletions(-)
diff --git a/daemon/admin_server.c b/daemon/admin_server.c
index cb9079c..9f24f68 100644
--- a/daemon/admin_server.c
+++ b/daemon/admin_server.c
@@ -221,7 +221,7 @@ adminClientGetInfo(virNetServerClientPtr client,
int ret = -1;
int maxparams = 0;
bool readonly;
- const char *sock_addr = NULL;
+ char *sock_addr = NULL;
const char *attr = NULL;
virTypedParameterPtr tmpparams = NULL;
virIdentityPtr identity = NULL;
@@ -300,6 +300,7 @@ adminClientGetInfo(virNetServerClientPtr client,
cleanup:
virObjectUnref(identity);
+ VIR_FREE(sock_addr);
return ret;
}
diff --git a/src/rpc/virnetserverclient.c b/src/rpc/virnetserverclient.c
index 39fe860..81da82c 100644
--- a/src/rpc/virnetserverclient.c
+++ b/src/rpc/virnetserverclient.c
@@ -1606,20 +1606,24 @@ virNetServerClientGetTransport(virNetServerClientPtr client)
int
virNetServerClientGetInfo(virNetServerClientPtr client,
- bool *readonly, const char **sock_addr,
+ bool *readonly, char **sock_addr,
virIdentityPtr *identity)
{
int ret = -1;
+ const char *addr;
virObjectLock(client);
*readonly = client->readonly;
- if (!(*sock_addr = virNetServerClientRemoteAddrStringURI(client))) {
+ if (!(addr = virNetServerClientRemoteAddrStringURI(client))) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("No network socket associated with client"));
goto cleanup;
}
+ if (VIR_STRDUP(*sock_addr, addr) < 0)
+ goto cleanup;
+
if (!client->identity) {
virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("No identity information available for client"));
diff --git a/src/rpc/virnetserverclient.h b/src/rpc/virnetserverclient.h
index c243a68..a53cc00 100644
--- a/src/rpc/virnetserverclient.h
+++ b/src/rpc/virnetserverclient.h
@@ -149,7 +149,7 @@ bool virNetServerClientNeedAuth(virNetServerClientPtr client);
int virNetServerClientGetTransport(virNetServerClientPtr client);
int virNetServerClientGetInfo(virNetServerClientPtr client,
- bool *readonly, const char **sock_addr,
+ bool *readonly, char **sock_addr,
virIdentityPtr *identity);
#endif /* __VIR_NET_SERVER_CLIENT_H__ */
--
2.7.3
8 years, 4 months
[libvirt] [PATCH 0/2] qemu: Use bootindex whenever possible
by Jiri Denemark
Jiri Denemark (2):
qemu: Use bootindex whenever possible
qemu: Drop emitBootindex parameter
src/qemu/qemu_command.c | 89 ++++++++++------------
.../qemuxml2argv-boot-menu-enable-bootindex.args | 23 ++++++
.../qemuxml2argv-boot-menu-enable-bootindex.xml | 28 +++++++
tests/qemuxml2argvtest.c | 2 +-
4 files changed, 91 insertions(+), 51 deletions(-)
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-boot-menu-enable-bootindex.args
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-boot-menu-enable-bootindex.xml
--
2.9.0
8 years, 4 months