]> xenbits.xensource.com Git - people/dariof/libvirt.git/commitdiff
LXC: Introduce New XML element for user namespace
authorGao feng <gaofeng@cn.fujitsu.com>
Fri, 7 Jun 2013 07:12:18 +0000 (15:12 +0800)
committerDaniel P. Berrange <berrange@redhat.com>
Tue, 2 Jul 2013 10:20:04 +0000 (11:20 +0100)
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@cn.fujitsu.com>
docs/formatdomain.html.in
docs/schemas/domaincommon.rng
src/conf/domain_conf.c
src/conf/domain_conf.h

index 47d91ab2e60769a9f9933c837c052d82059f5056..52a6353bd6941dfb4808af1e38c6c3c1c5ec8b2b 100644 (file)
     </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>
+  &lt;idmap&gt;
+    &lt;uid start='0' target='1000' count='10'/&gt;
+    &lt;gid start='0' target='1000' count='10'/&gt;
+  &lt;/idmap&gt;
+    </pre>
+
+
     <h3><a name="elementsSysinfo">SMBIOS System Information</a></h3>
 
     <p>
index cf82878e21ae3ac3426663b2f946d262fb829867..6fe1f96e41e8796f66c33775073995705246d791 100644 (file)
@@ -55,6 +55,9 @@
         <optional>
           <ref name="pm"/>
         </optional>
+        <optional>
+          <ref name="idmap"/>
+        </optional>
         <optional>
           <ref name="devices"/>
         </optional>
       </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.
index 011de7127a210b7911c71726c3a1075cd7e78840..5f1f3d71df5d4f95de2a0b63045cf475e90c01d6 100644 (file)
@@ -1942,6 +1942,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);
@@ -10221,6 +10224,44 @@ 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 cleanup;
+    }
+
+    for (i = 0; i < num; i++) {
+        ctxt->node = node[i];
+        if (virXPathUInt("string(./@start)", ctxt, &idmap[i].start) < 0 ||
+            virXPathUInt("string(./@target)", ctxt, &idmap[i].target) < 0 ||
+            virXPathUInt("string(./@count)", ctxt, &idmap[i].count) < 0) {
+            VIR_FREE(idmap);
+            goto cleanup;
+        }
+    }
+
+cleanup:
+    ctxt->node = save_ctxt;
+    return idmap;
+}
+
+
 /* Parse the XML definition for a vcpupin or emulatorpin.
  *
  * vcpupin has the form of
@@ -12049,6 +12090,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;
@@ -16244,6 +16317,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++) {
index 3817e37f6bc00fd1ddb2c6226cce99b169e42d99..2b55de5691d317940dab8d74d8fd0090a6811ecd 100644 (file)
@@ -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,
@@ -1845,6 +1851,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);
 
@@ -1907,6 +1928,7 @@ struct _virDomainDef {
 
     virNumaTuneDef numatune;
     virDomainResourceDefPtr resource;
+    virDomainIdMapDef idmap;
 
     /* These 3 are based on virDomainLifeCycleAction enum flags */
     int onReboot;