[libvirt] [RFC PATCH 1/6] LXC: New XML element for user namespace

Gao feng gaofeng at cn.fujitsu.com
Mon Mar 11 06:26:47 UTC 2013


This patch introduces three new elements in <os> for
user namespace. for example
<os>
    <userns enabled='yes'/>
    <uidmap first='0' low_first='1000' count='10'/>
    <gidmap first='0' low_first='1000' count='10'/>
</os>

this new element userns is used for controlling if enable
userns for the domain.

the other two elements uidmap and gidmap are used for
setting proc files /proc/<pid>/{uid_map,gid_map}.

Since user namespace is not very complete,we need this element
to enable or disable userns manually.

Signed-off-by: Gao feng <gaofeng at cn.fujitsu.com>
---
 docs/formatdomain.html.in     | 20 +++++++++++++++++++-
 docs/schemas/domaincommon.rng | 36 ++++++++++++++++++++++++++++++++++++
 src/conf/domain_conf.c        | 36 ++++++++++++++++++++++++++++++++++++
 src/conf/domain_conf.h        | 21 +++++++++++++++++++++
 src/lxc/lxc_container.c       | 14 ++++----------
 5 files changed, 116 insertions(+), 11 deletions(-)

diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index 4cafc92..d274c64 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -264,7 +264,10 @@
       no arguments. To specify the initial argv, use the <code>initarg</code>
       element, repeated as many time as is required. The <code>cmdline</code>
       element, if set will be used to provide an equivalent to <code>/proc/cmdline</code>
-      but will not effect init argv.
+      but will not effect init argv. If you want to enable userns, use the
+      <code>userns</code> element,the <code>enabled</code> attribute can be
+      either "yes" or "no".If not specified, default is "no". <span class="since">
+      Since 1.0.4 (LXC only)</span>.
     </p>
 
     <pre>
@@ -273,9 +276,24 @@
     <init>/bin/systemd</init>
     <initarg>--unit</initarg>
     <initarg>emergency.service</initarg>
+    <userns enabled='yes'/>
+    <uidmap first='0' low_first='1000' count='10'/>
+    <gidmap first='0' low_first='1000' count='10'/>
   </os>
     </pre>
 
+    <p>
+    The uidmap and gidmap elements have three attributs:
+    </p>
+
+    <dl>
+      <dt><code>first</code></dt>
+      <dd>First user id in container</dd>
+      <dt><code>low_first</code></dt>
+      <dd>First user id in container will be mapped to this low_first user id in host</dd>
+      <dt><code>count</code></dt>
+      <dd>How many users in container being allowed to map to host's user</dd>
+    </dl>
 
     <h3><a name="elementsSysinfo">SMBIOS System Information</a></h3>
 
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index 4b60885..03886d1 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -435,6 +435,42 @@
             <text/>
           </element>
         </zeroOrMore>
+        <optional>
+          <element name="userns">
+            <attribute name="enabled">
+              <choice>
+                <value>yes</value>
+                <value>no</value>
+              </choice>
+            </attribute>
+          </element>
+        </optional>
+        <optional>
+          <element name="uidmap">
+            <attribute name="first">
+              <ref name="unsignedInt"/>
+            </attribute>
+            <attribute name="low_first">
+              <ref name="unsignedInt"/>
+            </attribute>
+            <attribute name="count">
+              <ref name="unsignedInt"/>
+            </attribute>
+          </element>
+        </optional>
+        <optional>
+          <element name="gidmap">
+            <attribute name="first">
+              <ref name="unsignedInt"/>
+            </attribute>
+            <attribute name="low_first">
+              <ref name="unsignedInt"/>
+            </attribute>
+            <attribute name="count">
+              <ref name="unsignedInt"/>
+            </attribute>
+          </element>
+        </optional>
       </interleave>
     </element>
   </define>
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index f7c8af1..7f610c3 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -158,6 +158,11 @@ VIR_ENUM_IMPL(virDomainPMState, VIR_DOMAIN_PM_STATE_LAST,
               "yes",
               "no")
 
+VIR_ENUM_IMPL(virDomainUserns, VIR_DOMAIN_USER_NS_LAST,
+              "default",
+              "yes",
+              "no")
+
 VIR_ENUM_IMPL(virDomainDevice, VIR_DOMAIN_DEVICE_LAST,
               "none",
               "disk",
@@ -10036,6 +10041,27 @@ virDomainDefParseXML(virCapsPtr caps,
         }
         def->os.cmdline = virXPathString("string(./os/cmdline[1])", ctxt);
 
+        tmp = virXPathString("string(./os/userns/@enabled)", ctxt);
+        if (tmp) {
+            def->os.userns = virDomainUsernsTypeFromString(tmp);
+            if (def->os.userns <= 0)
+                def->os.userns = VIR_DOMAIN_USER_NS_DISABLED;
+            else if (def->os.userns == VIR_DOMAIN_USER_NS_ENABLED) {
+                virXPathUInt("string(./os/uidmap/@first)", ctxt,
+                              &def->os.uidmap.first);
+                virXPathUInt("string(./os/uidmap/@low_first)", ctxt,
+                              &def->os.uidmap.low_first);
+                virXPathUInt("string(./os/uidmap/@count)", ctxt,
+                              &def->os.uidmap.count);
+                virXPathUInt("string(./os/gidmap/@first)", ctxt,
+                              &def->os.gidmap.first);
+                virXPathUInt("string(./os/gidmap/@low_first)", ctxt,
+                              &def->os.gidmap.low_first);
+                virXPathUInt("string(./os/gidmap/@count)", ctxt,
+                              &def->os.gidmap.count);
+            }
+        }
+
         if ((n = virXPathNodeSet("./os/initarg", ctxt, &nodes)) < 0) {
             goto error;
         }
@@ -14665,6 +14691,16 @@ virDomainDefFormatInternal(virDomainDefPtr def,
     for (i = 0 ; def->os.initargv && def->os.initargv[i] ; i++)
         virBufferEscapeString(buf, "    <initarg>%s</initarg>\n",
                               def->os.initargv[i]);
+    if (def->os.userns != VIR_DOMAIN_USER_NS_DEFAULT) {
+        const char *enabled = virDomainUsernsTypeToString(def->os.userns);
+        virBufferAsprintf(buf, "    <userns enabled='%s'/>\n", enabled);
+        virBufferAsprintf(buf, "    <uidmap first='%u' low_first='%u'"
+                          " count='%u'/>\n", def->os.uidmap.first,
+                          def->os.uidmap.low_first, def->os.uidmap.count);
+        virBufferAsprintf(buf, "    <gidmap first='%u' low_first='%u'"
+                          " count='%u'/>\n", def->os.gidmap.first,
+                          def->os.gidmap.low_first, def->os.gidmap.count);
+    }
     virBufferEscapeString(buf, "    <loader>%s</loader>\n",
                           def->os.loader);
     virBufferEscapeString(buf, "    <kernel>%s</kernel>\n",
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 2509193..af39290 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -1438,6 +1438,14 @@ enum virDomainBootMenu {
     VIR_DOMAIN_BOOT_MENU_LAST
 };
 
+enum virDomainUserns {
+    VIR_DOMAIN_USER_NS_DEFAULT = 0,
+    VIR_DOMAIN_USER_NS_ENABLED,
+    VIR_DOMAIN_USER_NS_DISABLED,
+
+    VIR_DOMAIN_USER_NS_LAST
+};
+
 enum virDomainFeature {
     VIR_DOMAIN_FEATURE_ACPI,
     VIR_DOMAIN_FEATURE_APIC,
@@ -1504,6 +1512,14 @@ enum virDomainPMState {
     VIR_DOMAIN_PM_STATE_LAST
 };
 
+typedef struct _virDomainIdMapDef virDomainIdMapDef;
+typedef virDomainIdMapDef *virDomainIdMapDefPtr;
+struct _virDomainIdMapDef {
+    unsigned int first;
+    unsigned int low_first;
+    unsigned int count;
+};
+
 enum virDomainBIOSUseserial {
     VIR_DOMAIN_BIOS_USESERIAL_DEFAULT = 0,
     VIR_DOMAIN_BIOS_USESERIAL_YES,
@@ -1540,8 +1556,12 @@ struct _virDomainOSDef {
     char *bootloader;
     char *bootloaderArgs;
     int smbios_mode;
+    /* enum virDomainUserns */
+    int userns;
 
     virDomainBIOSDef bios;
+    virDomainIdMapDef uidmap;
+    virDomainIdMapDef gidmap;
 };
 
 enum virDomainTimerNameType {
@@ -2272,6 +2292,7 @@ VIR_ENUM_DECL(virDomainTaint)
 VIR_ENUM_DECL(virDomainVirt)
 VIR_ENUM_DECL(virDomainBoot)
 VIR_ENUM_DECL(virDomainBootMenu)
+VIR_ENUM_DECL(virDomainUserns)
 VIR_ENUM_DECL(virDomainFeature)
 VIR_ENUM_DECL(virDomainFeatureState)
 VIR_ENUM_DECL(virDomainLifecycle)
diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c
index 497539c..1d7bc1e 100644
--- a/src/lxc/lxc_container.c
+++ b/src/lxc/lxc_container.c
@@ -2293,16 +2293,10 @@ cleanup:
     return ret;
 }
 
-static int userns_supported(void)
+static int userns_supported(virDomainDefPtr def)
 {
-#if 1
-    /*
-     * put off using userns until uid mapping is implemented
-     */
-    return 0;
-#else
-    return lxcContainerAvailable(LXC_CONTAINER_FEATURE_USER) == 0;
-#endif
+    return ((def->os.userns == VIR_DOMAIN_USER_NS_ENABLED) &&
+            lxcContainerAvailable(LXC_CONTAINER_FEATURE_USER) == 0);
 }
 
 virArch lxcContainerGetAlt32bitArch(virArch arch)
@@ -2366,7 +2360,7 @@ int lxcContainerStart(virDomainDefPtr def,
 
     cflags = CLONE_NEWPID|CLONE_NEWNS|CLONE_NEWUTS|CLONE_NEWIPC|SIGCHLD;
 
-    if (userns_supported()) {
+    if (userns_supported(def)) {
         VIR_DEBUG("Enable user namespaces");
         cflags |= CLONE_NEWUSER;
     }
-- 
1.7.11.7




More information about the libvir-list mailing list