mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-22 05:35:25 +00:00
lxc: add possibility to define init uid/gid
Users may want to run the init command of a container as a special user / group. This is achieved by adding <inituser> and <initgroup> elements. Note that the user can either provide a name or an ID to specify the user / group to be used. This commit also fixes a side effect of being able to run the command as a non-root user: the user needs rights on the tty to allow shell job control. Reviewed-by: Daniel P. Berrange <berrange@redhat.com>
This commit is contained in:
parent
552f7c139a
commit
426929aea9
@ -334,6 +334,13 @@
|
|||||||
To set a custom work directory for the init, use the <code>initdir</code>
|
To set a custom work directory for the init, use the <code>initdir</code>
|
||||||
element.
|
element.
|
||||||
</p>
|
</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>
|
<pre>
|
||||||
<os>
|
<os>
|
||||||
@ -343,6 +350,8 @@
|
|||||||
<initarg>emergency.service</initarg>
|
<initarg>emergency.service</initarg>
|
||||||
<initenv name='MYENV'>some value</initenv>
|
<initenv name='MYENV'>some value</initenv>
|
||||||
<initdir>/my/custom/cwd</initdir>
|
<initdir>/my/custom/cwd</initdir>
|
||||||
|
<inituser>tester</inituser>
|
||||||
|
<initgroup>1000</initgroup>
|
||||||
</os>
|
</os>
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
|
@ -400,6 +400,20 @@
|
|||||||
<ref name="absFilePath"/>
|
<ref name="absFilePath"/>
|
||||||
</element>
|
</element>
|
||||||
</optional>
|
</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>
|
</interleave>
|
||||||
</element>
|
</element>
|
||||||
</define>
|
</define>
|
||||||
|
@ -2877,6 +2877,8 @@ void virDomainDefFree(virDomainDefPtr def)
|
|||||||
for (i = 0; def->os.initenv && def->os.initenv[i]; i++)
|
for (i = 0; def->os.initenv && def->os.initenv[i]; i++)
|
||||||
VIR_FREE(def->os.initenv[i]);
|
VIR_FREE(def->os.initenv[i]);
|
||||||
VIR_FREE(def->os.initdir);
|
VIR_FREE(def->os.initdir);
|
||||||
|
VIR_FREE(def->os.inituser);
|
||||||
|
VIR_FREE(def->os.initgroup);
|
||||||
VIR_FREE(def->os.initenv);
|
VIR_FREE(def->os.initenv);
|
||||||
VIR_FREE(def->os.kernel);
|
VIR_FREE(def->os.kernel);
|
||||||
VIR_FREE(def->os.initrd);
|
VIR_FREE(def->os.initrd);
|
||||||
@ -17070,6 +17072,8 @@ virDomainDefParseBootOptions(virDomainDefPtr def,
|
|||||||
def->os.init = virXPathString("string(./os/init[1])", ctxt);
|
def->os.init = virXPathString("string(./os/init[1])", ctxt);
|
||||||
def->os.cmdline = virXPathString("string(./os/cmdline[1])", ctxt);
|
def->os.cmdline = virXPathString("string(./os/cmdline[1])", ctxt);
|
||||||
def->os.initdir = virXPathString("string(./os/initdir[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)
|
if ((n = virXPathNodeSet("./os/initarg", ctxt, &nodes)) < 0)
|
||||||
goto error;
|
goto error;
|
||||||
@ -24958,6 +24962,11 @@ virDomainDefFormatInternal(virDomainDefPtr def,
|
|||||||
if (def->os.initdir)
|
if (def->os.initdir)
|
||||||
virBufferEscapeString(buf, "<initdir>%s</initdir>\n",
|
virBufferEscapeString(buf, "<initdir>%s</initdir>\n",
|
||||||
def->os.initdir);
|
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)
|
if (def->os.loader)
|
||||||
virDomainLoaderDefFormat(buf, def->os.loader);
|
virDomainLoaderDefFormat(buf, def->os.loader);
|
||||||
virBufferEscapeString(buf, "<kernel>%s</kernel>\n",
|
virBufferEscapeString(buf, "<kernel>%s</kernel>\n",
|
||||||
|
@ -1870,6 +1870,8 @@ struct _virDomainOSDef {
|
|||||||
char **initargv;
|
char **initargv;
|
||||||
virDomainOSEnvPtr *initenv;
|
virDomainOSEnvPtr *initenv;
|
||||||
char *initdir;
|
char *initdir;
|
||||||
|
char *inituser;
|
||||||
|
char *initgroup;
|
||||||
char *kernel;
|
char *kernel;
|
||||||
char *initrd;
|
char *initrd;
|
||||||
char *cmdline;
|
char *cmdline;
|
||||||
|
@ -2110,6 +2110,55 @@ static int lxcAttachNS(int *ns_fd)
|
|||||||
return 0;
|
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:
|
* lxcContainerChild:
|
||||||
@ -2208,6 +2257,9 @@ static int lxcContainerChild(void *data)
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (lxcContainerSetUserGroup(cmd, vmDef, argv->ttyPaths[0]) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
/* rename and enable interfaces */
|
/* rename and enable interfaces */
|
||||||
if (lxcContainerRenameAndEnableInterfaces(vmDef,
|
if (lxcContainerRenameAndEnableInterfaces(vmDef,
|
||||||
argv->nveths,
|
argv->nveths,
|
||||||
|
31
tests/lxcxml2xmldata/lxc-inituser.xml
Normal file
31
tests/lxcxml2xmldata/lxc-inituser.xml
Normal file
@ -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>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>
|
@ -100,6 +100,7 @@ mymain(void)
|
|||||||
VIR_DOMAIN_DEF_PARSE_SKIP_OSTYPE_CHECKS);
|
VIR_DOMAIN_DEF_PARSE_SKIP_OSTYPE_CHECKS);
|
||||||
DO_TEST("initenv");
|
DO_TEST("initenv");
|
||||||
DO_TEST("initdir");
|
DO_TEST("initdir");
|
||||||
|
DO_TEST("inituser");
|
||||||
|
|
||||||
virObjectUnref(caps);
|
virObjectUnref(caps);
|
||||||
virObjectUnref(xmlopt);
|
virObjectUnref(xmlopt);
|
||||||
|
Loading…
Reference in New Issue
Block a user