>From e231257274c4716ea69a630b5613b91e04ebc813 Mon Sep 17 00:00:00 2001
From: Dan Walsh <dwalsh@redhat.com>
Date: Tue, 22 Jan 2013 17:27:31 -0500
Subject: [PATCH 6/6] Set the label by default when entering a namespace, when
 using SELinux.

Any lxc process that runs within the namespace should be running with the
context of the namespace.

I also added a --nolabel qualifier to virsh so you can run an unconfined_t
label in the namespace and not transition.
---
 include/libvirt/libvirt-lxc.h |  4 ++++
 src/libvirt-lxc.c             | 44 ++++++++++++++++++++++++++++++++++++++++++-
 tools/virsh-domain.c          |  8 +++++++-
 3 files changed, 54 insertions(+), 2 deletions(-)

diff --git a/include/libvirt/libvirt-lxc.h b/include/libvirt/libvirt-lxc.h
index f2c87fb..2fad400 100644
--- a/include/libvirt/libvirt-lxc.h
+++ b/include/libvirt/libvirt-lxc.h
@@ -32,6 +32,10 @@
 extern "C" {
 # endif
 
+typedef enum {
+    SECURITY_LABEL = 1
+} NamespaceFlags;
+
 int virDomainLxcOpenNamespace(virDomainPtr domain,
                               int **fdlist,
                               unsigned int flags);
diff --git a/src/libvirt-lxc.c b/src/libvirt-lxc.c
index f580c3c..2972721 100644
--- a/src/libvirt-lxc.c
+++ b/src/libvirt-lxc.c
@@ -29,6 +29,9 @@
 #include "virlog.h"
 #include "virprocess.h"
 #include "datatypes.h"
+#ifdef WITH_SELINUX
+#include <selinux/selinux.h>
+#endif
 
 #define VIR_FROM_THIS VIR_FROM_NONE
 
@@ -103,6 +106,36 @@ error:
     return -1;
 }
 
+static int
+virDomainSetDefaultSecurityLabel(virDomainPtr domain)
+{
+    int rc = 0;
+    virSecurityLabelPtr seclabel;
+    if (VIR_ALLOC(seclabel) < 0)
+        return -1;
+
+    if (virDomainGetSecurityLabel(domain, seclabel))
+        return -1;
+
+#ifdef WITH_SELINUX
+    VIR_DEBUG("setexeccon %s", seclabel->label);
+    rc = setexeccon(seclabel->label);
+    if (rc)
+        VIR_ERROR(_("Failed to set security context to %s"), seclabel->label);
+#endif
+
+    VIR_FREE(seclabel);
+
+    return rc;
+}
+
+static void
+virDomainResetSecurityLabel(void)
+{
+#ifdef WITH_SELINUX
+    (void) setexeccon(NULL);
+#endif
+}
 
 /**
  * virDomainLxcEnterNamespace:
@@ -135,7 +168,12 @@ virDomainLxcEnterNamespace(virDomainPtr domain,
 {
     int i;
 
-    virCheckFlags(0, -1);
+    virCheckFlags(SECURITY_LABEL, -1);
+
+    if (flags & SECURITY_LABEL) {
+        if (virDomainSetDefaultSecurityLabel(domain) < 0)
+            goto error;
+    }
 
     if (noldfdlist && oldfdlist) {
         size_t nfds;
@@ -160,6 +198,10 @@ virDomainLxcEnterNamespace(virDomainPtr domain,
     return 0;
 
 error:
+    if (flags & SECURITY_LABEL) {
+        virDomainResetSecurityLabel();
+    }
+
     virDispatchError(domain->conn);
     return -1;
 }
diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c
index f4b6622..5b99c94 100644
--- a/tools/virsh-domain.c
+++ b/tools/virsh-domain.c
@@ -7677,6 +7677,7 @@ static const vshCmdInfo info_lxc_enter_namespace[] = {
 
 static const vshCmdOptDef opts_lxc_enter_namespace[] = {
     {"domain", VSH_OT_DATA, VSH_OFLAG_REQ, N_("domain name, id or uuid")},
+    {"nolabel", VSH_OT_BOOL, 0, N_("Do Not Change Process Label ")},
     {"cmd", VSH_OT_ARGV, VSH_OFLAG_REQ, N_("namespace")},
     {NULL, 0, 0, NULL}
 };
@@ -7693,6 +7694,7 @@ cmdLxcEnterNamespace(vshControl *ctl, const vshCmd *cmd)
     int nfdlist;
     int *fdlist;
     size_t i;
+    int flags=0;
 
     dom = vshCommandOptDomain(ctl, cmd, NULL);
     if (dom == NULL)
@@ -7719,13 +7721,17 @@ cmdLxcEnterNamespace(vshControl *ctl, const vshCmd *cmd)
      */
     if (virFork(&pid) < 0)
         goto cleanup;
+
+    if (!vshCommandOptBool(cmd, "nolabel"))
+        flags |= SECURITY_LABEL;
+
     if (pid == 0) {
         if (virDomainLxcEnterNamespace(dom,
                                        nfdlist,
                                        fdlist,
                                        NULL,
                                        NULL,
-                                       0) < 0)
+                                       flags) < 0)
             _exit(255);
 
         /* Fork a second time because entering the
-- 
1.8.1



