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@xxxxxxxxxxxxxx> --- 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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list