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(a)cn.fujitsu.com>
---
docs/formatdomain.html.in | 23 +++++++++++
docs/schemas/domaincommon.rng | 31 ++++++++++++++
src/conf/domain_conf.c | 95 +++++++++++++++++++++++++++++++++++++++++++
src/conf/domain_conf.h | 22 ++++++++++
4 files changed, 171 insertions(+)
diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index 3a200aa..cc0ae52 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 ad5550c..a3c5c84 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);
@@ -10057,6 +10060,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(const xmlNodePtr *node,
+ xmlXPathContextPtr ctxt,
+ ssize_t num)
+{
+ int 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
@@ -11804,6 +11841,43 @@ 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);
+
+ 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;
@@ -16008,6 +16082,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