[libvirt] [PATCH v4 01/10] LXC: Introduce New XML element for user namespace

Gao feng gaofeng at cn.fujitsu.com
Fri Jun 7 07:12:18 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.

We don't support the semi configuation, user has to
configure uid and gid both.

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

diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index 755d084..140e098 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 3cace35..ac07407 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -56,6 +56,9 @@
           <ref name="pm"/>
         </optional>
         <optional>
+          <ref name="idmap"/>
+        </optional>
+        <optional>
           <ref name="devices"/>
         </optional>
         <zeroOrMore>
@@ -465,6 +468,34 @@
       </optional>
     </interleave>
   </define>
+  <define name="idmap">
+    <zeroOrMore>
+      <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>
+    </zeroOrMore>
+    <zeroOrMore>
+      <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>
+    </zeroOrMore>
+  </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 a16ebd1..b001938 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -1939,6 +1939,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);
@@ -10196,6 +10199,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 virDomainIdMapEntryPtr
+virDomainIdmapDefParseXML(xmlXPathContextPtr ctxt,
+                          const xmlNodePtr *node,
+                          size_t num)
+{
+    size_t i;
+    virDomainIdMapEntryPtr 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
@@ -11971,6 +12008,38 @@ virDomainDefParseXML(xmlDocPtr xml,
     }
     VIR_FREE(nodes);
 
+    /* analysis of the user namespace mapping */
+    if ((n = virXPathNodeSet("./idmap/uid", ctxt, &nodes)) < 0)
+        goto error;
+
+    if (n) {
+        def->idmap.uidmap = virDomainIdmapDefParseXML(ctxt, nodes, n);
+        if (!def->idmap.uidmap)
+            goto error;
+
+        def->idmap.nuidmap = n;
+    }
+    VIR_FREE(nodes);
+
+    if  ((n = virXPathNodeSet("./idmap/gid", ctxt, &nodes)) < 0)
+        goto error;
+
+    if (n) {
+        def->idmap.gidmap =  virDomainIdmapDefParseXML(ctxt, nodes, n);
+        if (!def->idmap.gidmap)
+            goto error;
+
+        def->idmap.ngidmap = n;
+    }
+    VIR_FREE(nodes);
+
+    if ((def->idmap.uidmap && !def->idmap.gidmap) ||
+        (!def->idmap.uidmap && def->idmap.gidmap)) {
+            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                           _("uid and gid should be mapped both"));
+            goto error;
+    }
+
     /* analysis of cpu handling */
     if ((node = virXPathNode("./cpu[1]", ctxt)) != NULL) {
         xmlNodePtr oldnode = ctxt->node;
@@ -16150,6 +16219,27 @@ virDomainDefFormatInternal(virDomainDefPtr def,
 
     virBufferAddLit(buf, "  </os>\n");
 
+
+    if (def->idmap.uidmap) {
+        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 3a71d6c..29a6d8a 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -120,6 +120,12 @@ typedef virDomainSnapshotObjList *virDomainSnapshotObjListPtr;
 typedef struct _virDomainRNGDef virDomainRNGDef;
 typedef virDomainRNGDef *virDomainRNGDefPtr;
 
+typedef struct _virDomainIdMapEntry virDomainIdMapEntry;
+typedef virDomainIdMapEntry *virDomainIdMapEntryPtr;
+
+typedef struct _virDomainIdMapDef virDomainIdMapDef;
+typedef virDomainIdMapDef *virDomainIdMapDefPtr;
+
 /* Flags for the 'type' field in virDomainDeviceDef */
 typedef enum {
     VIR_DOMAIN_DEVICE_NONE = 0,
@@ -1837,6 +1843,21 @@ struct _virDomainRNGDef {
     virDomainDeviceInfo info;
 };
 
+struct _virDomainIdMapEntry {
+    unsigned int start;
+    unsigned int target;
+    unsigned int count;
+};
+
+struct _virDomainIdMapDef {
+    size_t nuidmap;
+    virDomainIdMapEntryPtr uidmap;
+
+    size_t ngidmap;
+    virDomainIdMapEntryPtr gidmap;
+};
+
+
 void virBlkioDeviceWeightArrayClear(virBlkioDeviceWeightPtr deviceWeights,
                                     int ndevices);
 
@@ -1899,6 +1920,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