[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

Re: [libvirt] [PATCH] Apply security label when entering LXC namespaces



-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On 03/12/2013 03:06 PM, Eric Blake wrote:
> On 03/12/2013 11:28 AM, Daniel P. Berrange wrote:
>> From: "Daniel P. Berrange" <berrange redhat com>
>> 
>> Add a new virDomainLxcEnterSecurityLabel() function as a counterpart to
>> virDomainLxcEnterNamespaces(), which can change the current calling
>> process to have a new security context. This call runs client side, not
>> in libvirtd so we can't use the security driver infrastructure.
>> 
>> When entering a namespace, the process spawned from virsh will default to
>> running with the security label of virsh. The actual desired behaviour is
>> to run with the security label of the container most of the time. So this
>> changes virsh lxc-enter-namespace command to invoke the 
>> virDomainLxcEnterSecurityLabel method.
>> 
> 
>> include/libvirt/libvirt-lxc.h |  4 ++ python/generator.py           |  1
>> + src/libvirt-lxc.c             | 96
>> +++++++++++++++++++++++++++++++++++++++++++ tools/virsh-domain.c
>> | 32 +++++++++++++++ 4 files changed, 133 insertions(+)
> 
> Missing an entry in src/libvirt_lxc.syms to actually expose the new 
> function in the .so.
> 
>> +++ 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
> 
> Will fail 'make syntax-check' if cppi is installed.
> 
>> @@ -8029,12 +8036,35 @@ cmdLxcEnterNamespace(vshControl *ctl, const
>> vshCmd *cmd) if ((nfdlist = virDomainLxcOpenNamespace(dom, &fdlist, 0)) <
>> 0) goto cleanup;
>> 
>> +    if (setlabel) { +        fprintf(stderr, "Getr sec\n");
> 
> Spurious debug message?
> 
> ACK with those things addressed.
> 

Here is my current patch for this, with a fix for the syms file.
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.13 (GNU/Linux)
Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/

iEYEARECAAYFAlE/hLoACgkQrlYvE4MpobPImgCggDyVpwbhsy4lMd2nZmTGavCF
qkIAn0gJT1xc2487N8HP081M1ydC02rn
=VTUO
-----END PGP SIGNATURE-----
diff --git a/include/libvirt/libvirt-lxc.h b/include/libvirt/libvirt-lxc.h
index f2c87fb..257637b 100644
--- a/include/libvirt/libvirt-lxc.h
+++ b/include/libvirt/libvirt-lxc.h
@@ -43,6 +43,9 @@ int virDomainLxcEnterNamespace(virDomainPtr domain,
                                int **oldfdlist,
                                unsigned int flags);
 
+int virDomainLxcGetSecurityLabel(virDomainPtr domain,
+                                 virSecurityLabelPtr seclabel);
+
 # ifdef __cplusplus
 }
 # endif
diff --git a/python/generator.py b/python/generator.py
index 8236bd2..308b776 100755
--- a/python/generator.py
+++ b/python/generator.py
@@ -557,6 +557,7 @@ skip_function = (
 
 lxc_skip_function = (
   "virDomainLxcEnterNamespace",
+  "virDomainLxcGetSecurityLabel",
 )
 qemu_skip_function = (
     #"virDomainQemuAttach",
diff --git a/src/libvirt-lxc.c b/src/libvirt-lxc.c
index f580c3c..a4aff59 100644
--- a/src/libvirt-lxc.c
+++ b/src/libvirt-lxc.c
@@ -41,6 +41,57 @@
                          __LINE__, info)
 
 /**
+ * virDomainLxcGetSecurityLabel:
+ * @domain: a domain object
+ * @seclabel: pointer to a virSecurityLabel structure
+ *
+ * This API is LXC specific, so it will only work with hypervisor
+ * connections to the LXC driver.
+ *
+ * Get the security label associated with the container @domain.
+ *
+ * Returns 0 on success, or -1 on error
+ */
+int
+virDomainLxcGetSecurityLabel(virDomainPtr domain,
+				 virSecurityLabelPtr seclabel)
+{
+    virConnectPtr conn;
+
+    VIR_DEBUG("domain=%p", domain);
+
+    virResetLastError();
+
+    if (!VIR_IS_CONNECTED_DOMAIN(domain)) {
+	virLibDomainError(NULL, VIR_ERR_INVALID_DOMAIN, __FUNCTION__);
+	virDispatchError(NULL);
+	return -1;
+    }
+
+    conn = domain->conn;
+
+    if (conn->flags & VIR_CONNECT_RO) {
+	virLibDomainError(domain, VIR_ERR_OPERATION_DENIED, __FUNCTION__);
+	goto error;
+    }
+
+    if (conn->driver->domainGetSecurityLabel) {
+
+	if (conn->driver->domainGetSecurityLabel(domain,
+						 seclabel) < 0)
+	    goto error;
+
+	return 0;
+    }
+
+    virLibConnError(conn, VIR_ERR_NO_SUPPORT, __FUNCTION__);
+
+error:
+    virDispatchError(conn);
+    return -1;
+}
+
+/**
  * virDomainLxcOpenNamespace:
  * @domain: a domain object
  * @fdlist: pointer to an array to be filled with FDs
diff --git a/src/libvirt_lxc.syms b/src/libvirt_lxc.syms
index b5be18b..3ef4eb8 100644
--- a/src/libvirt_lxc.syms
+++ b/src/libvirt_lxc.syms
@@ -14,4 +14,5 @@ LIBVIRT_LXC_1.0.2 {
     global:
         virDomainLxcEnterNamespace;
         virDomainLxcOpenNamespace;
+        virDomainLxcGetSecurityLabel;
 };
diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c
index f136df2..89f87f2 100644
--- a/src/lxc/lxc_driver.c
+++ b/src/lxc/lxc_driver.c
@@ -1125,6 +1125,7 @@ static int lxcDomainGetSecurityLabel(virDomainPtr dom, virSecurityLabelPtr secla
 {
     virLXCDriverPtr driver = dom->conn->privateData;
     virDomainObjPtr vm;
+    virLXCDomainObjPrivatePtr priv;
     int ret = -1;
 
     lxcDriverLock(driver);
@@ -1162,8 +1163,14 @@ static int lxcDomainGetSecurityLabel(virDomainPtr dom, virSecurityLabelPtr secla
      *   LXC monitor hasn't seen SIGHUP/ERR on poll().
      */
     if (virDomainObjIsActive(vm)) {
+	priv = vm->privateData;
+	if (!priv->initpid) {
+	    virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+			   _("Init pid is not yet available"));
+	    goto cleanup;
+	}
         if (virSecurityManagerGetProcessLabel(driver->securityManager,
-                                              vm->def, vm->pid, seclabel) < 0) {
+                                              vm->def, priv->initpid, seclabel) < 0) {
             virReportError(VIR_ERR_INTERNAL_ERROR,
                            "%s", _("Failed to get security label"));
             goto cleanup;
diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c
index c272688..b6203e2 100644
--- a/tools/virsh-domain.c
+++ b/tools/virsh-domain.c
@@ -56,6 +56,10 @@
 #include "virtypedparam.h"
 #include "virxml.h"
 
+#ifdef WITH_SELINUX
+# include <selinux/selinux.h>
+#endif
+
 /* libxml2 in RHEL4 has this symbol in the binary but it
  * is commented out in the header, despite apparently
  * working fine. This hacks around that header problem
@@ -8003,6 +8007,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}
 };
@@ -8011,6 +8016,7 @@ static bool
 cmdLxcEnterNamespace(vshControl *ctl, const vshCmd *cmd)
 {
     virDomainPtr dom = NULL;
+    virSecurityLabelPtr seclabel;
     bool ret = false;
     const vshCmdOpt *opt = NULL;
     char **cmdargv = NULL;
@@ -8019,6 +8025,7 @@ cmdLxcEnterNamespace(vshControl *ctl, const vshCmd *cmd)
     int nfdlist;
     int *fdlist;
     size_t i;
+    int label = false;
 
     dom = vshCommandOptDomain(ctl, cmd, NULL);
     if (dom == NULL)
@@ -8040,12 +8047,33 @@ cmdLxcEnterNamespace(vshControl *ctl, const vshCmd *cmd)
     if ((nfdlist = virDomainLxcOpenNamespace(dom, &fdlist, 0)) < 0)
         goto cleanup;
 
+#ifdef WITH_SELINUX
+    if ((is_selinux_enabled() > 0) && 
+        (! vshCommandOptBool(cmd, "nolabel"))) {
+        if (VIR_ALLOC(seclabel) < 0)
+            goto cleanup;
+        label = true;
+        if (virDomainGetSecurityLabel(dom, seclabel) < 0)
+            goto cleanup;
+    }
+#endif
+
     /* Fork once because we don't want to affect
      * virsh's namespace itself
      */
     if (virFork(&pid) < 0)
         goto cleanup;
     if (pid == 0) {
+#ifdef WITH_SELINUX
+        if (label) {
+            vshDebug(ctl, VSH_ERR_INFO, "setexeccon %s", seclabel->label);
+            ret = setexeccon(seclabel->label);
+            if (ret < 0) {
+                vshError(ctl, _("Failed to set security context to %s"), seclabel->label);
+                _exit(255);
+            }
+        }
+#endif
         if (virDomainLxcEnterNamespace(dom,
                                        nfdlist,
                                        fdlist,
@@ -8078,6 +8106,8 @@ cmdLxcEnterNamespace(vshControl *ctl, const vshCmd *cmd)
     ret = true;
 
 cleanup:
+    if (label)
+        VIR_FREE(seclabel);
     if (dom)
         virDomainFree(dom);
     VIR_FREE(cmdargv);

[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]