[libvirt] [PATCH v2 1/8] LXC: Introduce New XML element for user namespace

Gao feng gaofeng at cn.fujitsu.com
Fri May 10 09:58:10 UTC 2013


This patch introduces new element <idmap> for
user namespace. for example
<idmap>
    <uid start='0' target='1000' count='10'/>
    <gid start='0' target='1000' count='10'/>
</idmap>

this new element is used for setting proc files
/proc/<pid>/{uid_map,gid_map}.

This patch also supports multiple uid/gid elements
setting in XML configuration.

Signed-off-by: Gao feng <gaofeng at cn.fujitsu.com>
---
 docs/formatdomain.html.in     | 23 +++++++++++
 docs/schemas/domaincommon.rng | 28 ++++++++++++++
 src/conf/domain_conf.c        | 88 +++++++++++++++++++++++++++++++++++++++++++
 src/conf/domain_conf.h        | 19 ++++++++++
 4 files changed, 158 insertions(+)

diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index 572d7ee..7a5c1ed 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -285,6 +285,29 @@
     </pre>
 
 
+    <p>
+      If you want to enable user namespace,set the <code>idmap</code> element.
+      the <code>uid</code> and <code>gid</code> elements have three attributes:
+    </p>
+
+    <dl>
+      <dt><code>start</code></dt>
+      <dd>First user id in container.</dd>
+      <dt><code>target</code></dt>
+      <dd>The first user id in container will be mapped to this target 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>
+
+    <pre>
+  <idmap>
+    <uid start='0' target='1000' count='10'/>
+    <gid start='0' target='1000' count='10'/>
+  </idmap>
+    </pre>
+
+
     <h3><a name="elementsSysinfo">SMBIOS System Information</a></h3>
 
     <p>
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index 10596dc..dffb103 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -465,6 +465,34 @@
       </optional>
     </interleave>
   </define>
+  <define name="map">
+    <optional>
+      <element name="idmap">
+        <element name="uid">
+          <attribute name="start">
+            <ref name="unsignedInt"/>
+          </attribute>
+          <attribute name="target">
+            <ref name="unsignedInt"/>
+          </attribute>
+          <attribute name="count">
+            <ref name="unsignedInt"/>
+          </attribute>
+        </element>
+        <element name="gid">
+          <attribute name="start">
+            <ref name="unsignedInt"/>
+          </attribute>
+          <attribute name="target">
+            <ref name="unsignedInt"/>
+          </attribute>
+          <attribute name="count">
+            <ref name="unsignedInt"/>
+          </attribute>
+        </element>
+      </element>
+    </optional>
+  </define>
   <!--
       Resources usage defines the amount of memory (maximum and possibly
       current usage) and number of virtual CPUs used by that domain.
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index b7e253e..46be458 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -1944,6 +1944,9 @@ void virDomainDefFree(virDomainDefPtr def)
 
     virDomainTPMDefFree(def->tpm);
 
+    VIR_FREE(def->idmap.uidmap);
+    VIR_FREE(def->idmap.gidmap);
+
     VIR_FREE(def->os.type);
     VIR_FREE(def->os.machine);
     VIR_FREE(def->os.init);
@@ -9798,6 +9801,40 @@ cleanup:
     return ret;
 }
 
+
+/* Parse the XML definition for user namespace id map.
+ *
+ * idmap has the form of
+ *
+ *   <uid start='0' target='1000' count='10'/>
+ *   <gid start='0' target='1000' count='10'/>
+ */
+static struct idmap *
+virDomainIdmapDefParseXML(const xmlNodePtr *node,
+                          xmlXPathContextPtr ctxt,
+                          ssize_t num)
+{
+    int i;
+    struct idmap *idmap = NULL;
+    xmlNodePtr save_ctxt = ctxt->node;
+
+    if (VIR_ALLOC_N(idmap, num) < 0) {
+        virReportOOMError();
+        goto error;
+    }
+
+    for (i = 0; i < num ; i++) {
+        ctxt->node = node[i];
+        virXPathUInt("string(./@start)", ctxt, &idmap[i].start);
+        virXPathUInt("string(./@target)", ctxt, &idmap[i].target);
+        virXPathUInt("string(./@count)", ctxt, &idmap[i].count);
+    }
+ error:
+    ctxt->node = save_ctxt;
+    return idmap;
+}
+
+
 /* Parse the XML definition for a vcpupin or emulatorpin.
  *
  * vcpupin has the form of
@@ -11544,6 +11581,36 @@ virDomainDefParseXML(xmlDocPtr xml,
     }
     VIR_FREE(nodes);
 
+    /* analysis of the user namespace mapping */
+    def->idmap.nuidmap = 0;
+    def->idmap.uidmap = NULL;
+    if ((n = virXPathNodeSet("./idmap/uid", ctxt, &nodes)) < 0)
+        goto error;
+
+    if (n) {
+        def->idmap.uidmap = virDomainIdmapDefParseXML(nodes, ctxt, n);
+        if (!def->idmap.uidmap)
+            goto error;
+
+        def->idmap.nuidmap = n;
+    }
+    VIR_FREE(nodes);
+
+    def->idmap.ngidmap = 0;
+    def->idmap.gidmap = NULL;
+
+    if  ((n = virXPathNodeSet("./idmap/gid", ctxt, &nodes)) < 0)
+        goto error;
+
+    if (n) {
+        def->idmap.gidmap =  virDomainIdmapDefParseXML(nodes, ctxt, n);
+        if (!def->idmap.gidmap)
+            goto error;
+
+        def->idmap.ngidmap = n;
+    }
+    VIR_FREE(nodes);
+
     /* analysis of cpu handling */
     if ((node = virXPathNode("./cpu[1]", ctxt)) != NULL) {
         xmlNodePtr oldnode = ctxt->node;
@@ -15696,6 +15763,27 @@ virDomainDefFormatInternal(virDomainDefPtr def,
 
     virBufferAddLit(buf, "  </os>\n");
 
+
+    if (def->idmap.uidmap || def->idmap.gidmap) {
+        virBufferAddLit(buf, "  <idmap>\n");
+        for (i = 0 ; i < def->idmap.nuidmap; i++) {
+            virBufferAsprintf(buf,
+                              "    <uid start='%u' target='%u' count='%u'/>\n",
+                              def->idmap.uidmap[i].start,
+                              def->idmap.uidmap[i].target,
+                              def->idmap.uidmap[i].count);
+        }
+        for (i = 0 ; i < def->idmap.ngidmap; i++) {
+            virBufferAsprintf(buf,
+                              "    <gid start='%u' target='%u' count='%u'/>\n",
+                              def->idmap.gidmap[i].start,
+                              def->idmap.gidmap[i].target,
+                              def->idmap.gidmap[i].count);
+        }
+        virBufferAddLit(buf, "  </idmap>\n");
+    }
+
+
     if (def->features) {
         virBufferAddLit(buf, "  <features>\n");
         for (i = 0 ; i < VIR_DOMAIN_FEATURE_LAST ; i++) {
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 21f7ce2..b21d567 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -120,6 +120,9 @@ typedef virDomainSnapshotObjList *virDomainSnapshotObjListPtr;
 typedef struct _virDomainRNGDef virDomainRNGDef;
 typedef virDomainRNGDef *virDomainRNGDefPtr;
 
+typedef struct _virDomainIdmapDef virDomainIdmapDef;
+typedef virDomainIdmapDef *virDomainIdmapDefPtr;
+
 /* Flags for the 'type' field in virDomainDeviceDef */
 typedef enum {
     VIR_DOMAIN_DEVICE_NONE = 0,
@@ -1803,6 +1806,21 @@ struct _virDomainRNGDef {
     virDomainDeviceInfo info;
 };
 
+struct idmap {
+    unsigned int start;
+    unsigned int target;
+    unsigned int count;
+};
+
+struct _virDomainIdmapDef {
+    size_t nuidmap;
+    struct idmap *uidmap;
+
+    size_t ngidmap;
+    struct idmap *gidmap;
+};
+
+
 void virBlkioDeviceWeightArrayClear(virBlkioDeviceWeightPtr deviceWeights,
                                     int ndevices);
 
@@ -1863,6 +1881,7 @@ struct _virDomainDef {
 
     virNumaTuneDef numatune;
     virDomainResourceDefPtr resource;
+    virDomainIdmapDef idmap;
 
     /* These 3 are based on virDomainLifeCycleAction enum flags */
     int onReboot;
-- 
1.8.1.4




More information about the libvir-list mailing list