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. Both elements can be provided
+ either a user (resp. group) id or a name. Prefixing the user or group id with
+ a <code>+</code> will force it to be considered like a numeric value. Without
+ this, it will be first tried as a user or group name.
+ </p>
<pre>
<os>
<initarg>emergency.service</initarg>
<initenv name='MYENV'>some value</initenv>
<initdir>/my/custom/cwd</initdir>
+ <inituser>tester</inituser>
+ <initgroup>1000</initgroup>
</os>
</pre>
<ref name="absFilePath"/>
</element>
</optional>
+ <optional>
+ <element name="inituser">
+ <choice>
+ <ref name="unsignedInt"/>
+ <ref name="genericName"/>
+ </choice>
+ </element>
+ <element name="initgroup">
+ <choice>
+ <ref name="unsignedInt"/>
+ <ref name="genericName"/>
+ </choice>
+ </element>
+ </optional>
</interleave>
</element>
</define>
for (i = 0; def->os.initenv && def->os.initenv[i]; i++)
VIR_FREE(def->os.initenv[i]);
VIR_FREE(def->os.initdir);
+ VIR_FREE(def->os.inituser);
+ VIR_FREE(def->os.initgroup);
VIR_FREE(def->os.initenv);
VIR_FREE(def->os.kernel);
VIR_FREE(def->os.initrd);
def->os.init = virXPathString("string(./os/init[1])", ctxt);
def->os.cmdline = virXPathString("string(./os/cmdline[1])", ctxt);
def->os.initdir = virXPathString("string(./os/initdir[1])", ctxt);
+ def->os.inituser = virXPathString("string(./os/inituser[1])", ctxt);
+ def->os.initgroup = virXPathString("string(./os/initgroup[1])", ctxt);
if ((n = virXPathNodeSet("./os/initarg", ctxt, &nodes)) < 0)
goto error;
if (def->os.initdir)
virBufferEscapeString(buf, "<initdir>%s</initdir>\n",
def->os.initdir);
+ if (def->os.inituser)
+ virBufferAsprintf(buf, "<inituser>%s</inituser>\n", def->os.inituser);
+ if (def->os.initgroup)
+ virBufferAsprintf(buf, "<initgroup>%s</initgroup>\n", def->os.initgroup);
+
if (def->os.loader)
virDomainLoaderDefFormat(buf, def->os.loader);
virBufferEscapeString(buf, "<kernel>%s</kernel>\n",
char **initargv;
virDomainOSEnvPtr *initenv;
char *initdir;
+ char *inituser;
+ char *initgroup;
char *kernel;
char *initrd;
char *cmdline;
return 0;
}
+/**
+ * lxcContainerSetUserGroup:
+ * @cmd: command to update
+ * @vmDef: domain definition for the container
+ * @ttyPath: guest path to the tty
+ *
+ * Set the command UID and GID. As this function attempts at
+ * converting the user/group name into uid/gid, it needs to
+ * be called after the pivot root is done.
+ *
+ * The owner of the tty is also changed to the given user.
+ */
+static int lxcContainerSetUserGroup(virCommandPtr cmd,
+ virDomainDefPtr vmDef,
+ const char *ttyPath)
+{
+ uid_t uid;
+ gid_t gid;
+
+ if (vmDef->os.inituser) {
+ if (virGetUserID(vmDef->os.inituser, &uid) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, _("User %s doesn't exist"),
+ vmDef->os.inituser);
+ return -1;
+ }
+ virCommandSetUID(cmd, uid);
+
+ /* Change the newly created tty owner to the inituid for
+ * shells to have job control. */
+ if (chown(ttyPath, uid, -1) < 0) {
+ virReportSystemError(errno,
+ _("Failed to change ownership of tty %s"),
+ ttyPath);
+ return -1;
+ }
+ }
+
+ if (vmDef->os.initgroup) {
+ if (virGetGroupID(vmDef->os.initgroup, &gid) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR, _("Group %s doesn't exist"),
+ vmDef->os.initgroup);
+ return -1;
+ }
+ virCommandSetGID(cmd, gid);
+ }
+
+ return 0;
+}
+
/**
* lxcContainerChild:
goto cleanup;
}
+ if (lxcContainerSetUserGroup(cmd, vmDef, argv->ttyPaths[0]) < 0)
+ goto cleanup;
+
/* rename and enable interfaces */
if (lxcContainerRenameAndEnableInterfaces(vmDef,
argv->nveths,
--- /dev/null
+<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>tester</inituser>
+ <initgroup>1234</initgroup>
+ </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>
VIR_DOMAIN_DEF_PARSE_SKIP_OSTYPE_CHECKS);
DO_TEST("initenv");
DO_TEST("initdir");
+ DO_TEST("inituser");
virObjectUnref(caps);
virObjectUnref(xmlopt);