[libvirt] [PATCH] lxc: add possibility to define init uid/gid

Cédric Bosdonnat cbosdonnat at suse.com
Tue Jun 6 14:11:24 UTC 2017


Users may want to run the init command of a container as a special
user / group. Allow doing it using <inituser uid=""/> and <initgroup
gid=""/> elements.
---
 docs/formatdomain.html.in             |  6 ++++++
 docs/schemas/domaincommon.rng         | 12 ++++++++++++
 src/conf/domain_conf.c                | 19 +++++++++++++++++++
 src/conf/domain_conf.h                |  2 ++
 src/lxc/lxc_container.c               | 13 +++++++++++++
 tests/lxcxml2xmldata/lxc-inituser.xml | 31 +++++++++++++++++++++++++++++++
 tests/lxcxml2xmltest.c                |  1 +
 7 files changed, 84 insertions(+)
 create mode 100644 tests/lxcxml2xmldata/lxc-inituser.xml

diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index 7627fd0d0..85d5f4539 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -334,6 +334,10 @@
       To set a custom work directory for the init, use the <code>initdir</code>
       element.
     </p>
+    <p>
+      To run the init command as a given user or group, use the <code>inituser</code>
+      or <code>initgroup</code> elements respectively.
+    </p>
 
     <pre>
 <os>
@@ -343,6 +347,8 @@
   <initarg>emergency.service</initarg>
   <initenv name='MYENV'>some value</initenv>
   <initdir>/my/custom/cwd</initdir>
+  <inituser uid="1000"/>
+  <initgroup gid="1000"/>
 </os>
     </pre>
 
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index 5a4c4ecf1..385e937e9 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -400,6 +400,18 @@
             <ref name="absFilePath"/>
           </element>
         </optional>
+        <optional>
+          <element name="inituser">
+            <attribute name="uid">
+              <ref name="unsignedInt"/>
+            </attribute>
+          </element>
+          <element name="initgroup">
+            <attribute name="gid">
+              <ref name="unsignedInt"/>
+            </attribute>
+          </element>
+        </optional>
       </interleave>
     </element>
   </define>
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 3c2a81f52..21bb104a9 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -16806,6 +16806,18 @@ virDomainDefParseBootOptions(virDomainDefPtr def,
         def->os.cmdline = virXPathString("string(./os/cmdline[1])", ctxt);
         def->os.initdir = virXPathString("string(./os/initdir[1])", ctxt);
 
+        if (virXPathUInt("string(./os/inituser[1]/@uid)", ctxt, &def->os.inituid) == -2) {
+            virReportError(VIR_ERR_XML_ERROR, "%s",
+                           _("Failed to parse inituser uid"));
+            goto error;
+        }
+
+        if (virXPathUInt("string(./os/initgroup[1]/@gid)", ctxt, &def->os.initgid) == -2) {
+            virReportError(VIR_ERR_XML_ERROR, "%s",
+                           _("Failed to parse initgroup gid"));
+            goto error;
+        }
+
         if ((n = virXPathNodeSet("./os/initarg", ctxt, &nodes)) < 0)
             goto error;
 
@@ -24593,6 +24605,13 @@ virDomainDefFormatInternal(virDomainDefPtr def,
     if (def->os.initdir)
         virBufferEscapeString(buf, "<initdir>%s</initdir>\n",
                               def->os.initdir);
+    if (def->os.inituid)
+        virBufferAsprintf(buf, "<inituser uid='%u'/>\n",
+                          def->os.inituid);
+    if (def->os.initgid)
+        virBufferAsprintf(buf, "<initgroup gid='%u'/>\n",
+                          def->os.initgid);
+
     if (def->os.loader)
         virDomainLoaderDefFormat(buf, def->os.loader);
     virBufferEscapeString(buf, "<kernel>%s</kernel>\n",
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index d6b8429c3..6e1997324 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -1842,6 +1842,8 @@ struct _virDomainOSDef {
     char **initargv;
     virDomainOSEnvPtr *initenv;
     char *initdir;
+    uid_t inituid;
+    gid_t initgid;
     char *kernel;
     char *initrd;
     char *cmdline;
diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c
index 8d8e1a735..42bcd25c4 100644
--- a/src/lxc/lxc_container.c
+++ b/src/lxc/lxc_container.c
@@ -247,6 +247,10 @@ static virCommandPtr lxcContainerBuildInitCmd(virDomainDefPtr vmDef,
         virCommandAddEnvPair(cmd, "LIBVIRT_LXC_CMDLINE", vmDef->os.cmdline);
     if (vmDef->os.initdir)
         virCommandSetWorkingDirectory(cmd, vmDef->os.initdir);
+    if (vmDef->os.inituid)
+        virCommandSetUID(cmd, vmDef->os.inituid);
+    if (vmDef->os.initgid)
+        virCommandSetGID(cmd, vmDef->os.initgid);
 
     for (i = 0; vmDef->os.initenv[i]; i++) {
         virCommandAddEnvPair(cmd, vmDef->os.initenv[i]->name,
@@ -2192,6 +2196,15 @@ static int lxcContainerChild(void *data)
         goto cleanup;
     }
 
+    /* Change the newly created tty owner to the inituid for
+     * shells to have job control */
+    if (vmDef->os.inituid && chown(ttyPath, vmDef->os.inituid, -1) < 0) {
+        virReportSystemError(errno,
+                             _("Failed to change ownership of tty %s"),
+                             ttyPath);
+        goto cleanup;
+    }
+
     if (lxcContainerResolveAllSymlinks(vmDef) < 0)
         goto cleanup;
 
diff --git a/tests/lxcxml2xmldata/lxc-inituser.xml b/tests/lxcxml2xmldata/lxc-inituser.xml
new file mode 100644
index 000000000..61b5db4af
--- /dev/null
+++ b/tests/lxcxml2xmldata/lxc-inituser.xml
@@ -0,0 +1,31 @@
+<domain type='lxc'>
+  <name>jessie</name>
+  <uuid>e21987a5-e98e-9c99-0e35-803e4d9ad1fe</uuid>
+  <memory unit='KiB'>1048576</memory>
+  <currentMemory unit='KiB'>1048576</currentMemory>
+  <vcpu placement='static'>1</vcpu>
+  <resource>
+    <partition>/machine</partition>
+  </resource>
+  <os>
+    <type arch='x86_64'>exe</type>
+    <init>/sbin/sh</init>
+    <inituser uid='1000'/>
+    <initgroup gid='1234'/>
+  </os>
+  <clock offset='utc'/>
+  <on_poweroff>destroy</on_poweroff>
+  <on_reboot>restart</on_reboot>
+  <on_crash>restart</on_crash>
+  <devices>
+    <emulator>/usr/libexec/libvirt_lxc</emulator>
+    <filesystem type='mount' accessmode='passthrough'>
+      <source dir='/mach/jessie'/>
+      <target dir='/'/>
+    </filesystem>
+    <console type='pty'>
+      <target type='lxc' port='0'/>
+    </console>
+  </devices>
+  <seclabel type='none'/>
+</domain>
diff --git a/tests/lxcxml2xmltest.c b/tests/lxcxml2xmltest.c
index c81b0eace..9b9314cf8 100644
--- a/tests/lxcxml2xmltest.c
+++ b/tests/lxcxml2xmltest.c
@@ -100,6 +100,7 @@ mymain(void)
                  VIR_DOMAIN_DEF_PARSE_SKIP_OSTYPE_CHECKS);
     DO_TEST("initenv");
     DO_TEST("initdir");
+    DO_TEST("inituser");
 
     virObjectUnref(caps);
     virObjectUnref(xmlopt);
-- 
2.12.2




More information about the libvir-list mailing list