[libvirt] [PATCH v2] Introduce Smack security driver for Libvirt

Randy Aybar (raybar) raybar at cisco.com
Thu Jun 30 10:06:44 UTC 2016


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 at 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 at bupt.edu.cn>
+ *   Changyao Han <changyao at bupt.edu.cn>
+ *
+ * Updated to libvirt v1.2.15: (Original was written for libvirt v1.1.4)
+ *   Raghuram S. Sudhaakar <rsudhaak at cisco.com>
+ *   Randy Aybar <raybar at cisco.com>
+ *
+ *   Based on security_selinux.c by James Morris <jmorris at namei.org>
+ *   and security_apparmor.c by Jamie Strandboge <jamie at 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 at bupt.edu,cn>
+ *   Changyao Han <changyao at bupt.edu.cn>
+ *   Raghuram S. Sudhaakar <rssudhaakar at gmail.com>
+ *   Randy Aybar <raybar at 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






More information about the libvir-list mailing list