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(a)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