[libvirt] Updated James Morris patch to apply to libvirt-0.6.0 version
Daniel J Walsh
dwalsh at redhat.com
Fri Feb 20 15:31:21 UTC 2009
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
Daniel P. Berrange wrote:
> Just spotted one serious problem we need to address. The
> method 'qemudStartVMDaemon' quoted here is where we set the
> security label:
>
> On Tue, Feb 17, 2009 at 11:20:17AM -0500, Daniel J Walsh wrote:
>> @@ -1178,6 +1237,16 @@ static int qemudStartVMDaemon(virConnect
>> return -1;
>> }
>>
>> + /*
>> + * Set up the security label for the domain here, before doing
>> + * too much else.
>> + */
>> + if (qemudDomainSetSecurityLabel(conn, driver, vm) < 0) {
>> + qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
>> + _("Failed to set security label"));
>> + return -1;
>> + }
>> +
>> if (qemudExtractVersionInfo(emulator,
>> NULL,
>> &qemuCmdFlags) < 0) {
>
>
>
> Which ultimately calls the following method, which sets the context
> to use for the next exec call.
>
>> +static int
>> +SELinuxSecurityDomainSetSecurityLabel(virConnectPtr conn,
>> + virSecurityDriverPtr drv,
>> + const virSecurityLabelDefPtr secdef)
>> +{
>> + /* TODO: verify DOI */
>> +
>> + if (!STREQ(drv->name, secdef->model)) {
>> + virSecurityReportError(conn, VIR_ERR_ERROR,
>> + _("%s: security label driver mismatch: "
>> + "\'%s\' model configured for domain, but "
>> + "hypervisor driver is \'%s\'."),
>> + __func__, secdef->model, drv->name);
>> + return -1;
>> + }
>> +
>> + if (setexeccon(secdef->label) == -1) {
>> + virSecurityReportError(conn, VIR_ERR_ERROR,
>> + _("%s: unable to set security context "
>> + "'\%s\': %s."), __func__, secdef->label,
>> + strerror(errno));
>> + return -1;
>> + }
>> + return 0;
>> +}
>
> The problem is that between the point where we set the exec context,
> and the place where QEMU is finally exec'd, there is scope for several
> other programs to be exec'd. Also there are other threads running
> concurrently, and I'm under whether 'setexeccon' scope is per thread
> or per process.
>
> I think we need to move place where we set the exec context to after
> the fork() call, ideally to be the very last call made before the
> actual execve().
>
> We do not currently have an easy way todo this, but I have the exact
> same problem in my patches to integrate with cgroups - I need to add
> the new PID to the appropriate cgroup immediately before exec'ing.
> So i suggest the following patch whichs a generic callback to the
> virExec() call, so we can implant the neccessary logic after the fork()
> and just before the real execve(), and safely in the child process.
>
> To use this, we'd make qemudStartVM() pass in a virExecHook callback
> which does the call to qemudDomainSetSecurityLabel()
>
> Daniel
>
> diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
> --- a/src/libvirt_private.syms
> +++ b/src/libvirt_private.syms
> @@ -291,6 +291,7 @@ virEnumToString;
> virEventAddHandle;
> virEventRemoveHandle;
> virExec;
> +virExecWithHook;
> virSetNonBlock;
> virFormatMacAddr;
> virGetHostname;
> diff --git a/src/util.c b/src/util.c
> --- a/src/util.c
> +++ b/src/util.c
> @@ -199,7 +199,10 @@ __virExec(virConnectPtr conn,
> const fd_set *keepfd,
> pid_t *retpid,
> int infd, int *outfd, int *errfd,
> - int flags) {
> + int flags,
> + virExecHook hook,
> + void *data)
> +{
> pid_t pid;
> int null, i, openmax;
> int pipeout[2] = {-1,-1};
> @@ -411,6 +414,9 @@ __virExec(virConnectPtr conn,
> childerr != childout)
> close(childerr);
>
> + if (hook)
> + (hook)(data);
> +
> if (envp)
> execve(argv[0], (char **) argv, (char**)envp);
> else
> @@ -445,13 +451,16 @@ __virExec(virConnectPtr conn,
> }
>
> int
> -virExec(virConnectPtr conn,
> - const char *const*argv,
> - const char *const*envp,
> - const fd_set *keepfd,
> - pid_t *retpid,
> - int infd, int *outfd, int *errfd,
> - int flags) {
> +virExecWithHook(virConnectPtr conn,
> + const char *const*argv,
> + const char *const*envp,
> + const fd_set *keepfd,
> + pid_t *retpid,
> + int infd, int *outfd, int *errfd,
> + int flags,
> + virExecHook hook,
> + void *data)
> +{
> char *argv_str;
>
> if ((argv_str = virArgvToString(argv)) == NULL) {
> @@ -462,7 +471,21 @@ virExec(virConnectPtr conn,
> VIR_FREE(argv_str);
>
> return __virExec(conn, argv, envp, keepfd, retpid, infd, outfd, errfd,
> - flags);
> + flags, hook, data);
> +}
> +
> +int
> +virExec(virConnectPtr conn,
> + const char *const*argv,
> + const char *const*envp,
> + const fd_set *keepfd,
> + pid_t *retpid,
> + int infd, int *outfd, int *errfd,
> + int flags)
> +{
> + return virExecWithHook(conn, argv, envp, keepfd, retpid,
> + infd, outfd, errfd,
> + flags, NULL, NULL);
> }
>
> static int
> @@ -580,7 +603,7 @@ virRun(virConnectPtr conn,
>
> if ((execret = __virExec(conn, argv, NULL, NULL,
> &childpid, -1, &outfd, &errfd,
> - VIR_EXEC_NONE)) < 0) {
> + VIR_EXEC_NONE, NULL, NULL)) < 0) {
> ret = execret;
> goto error;
> }
> diff --git a/src/util.h b/src/util.h
> --- a/src/util.h
> +++ b/src/util.h
> @@ -40,6 +40,21 @@ enum {
>
> int virSetNonBlock(int fd);
>
> +/* This will execute in the context of the first child
> + * immediately after fork() */
> +typedef int (*virExecHook)(void *data);
> +
> +int virExecWithHook(virConnectPtr conn,
> + const char *const*argv,
> + const char *const*envp,
> + const fd_set *keepfd,
> + int *retpid,
> + int infd,
> + int *outfd,
> + int *errfd,
> + int flags,
> + virExecHook hook,
> + void *data);
> int virExec(virConnectPtr conn,
> const char *const*argv,
> const char *const*envp,
>
>
I have an update to the original patch which includes a test program and
a changelog, but I guess I need to wait for this patch to be approved.
http://people.fedoraproject.org/~dwalsh/SELinux/svirt.patch
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (GNU/Linux)
Comment: Using GnuPG with Fedora - http://enigmail.mozdev.org
iEYEARECAAYFAkmezMkACgkQrlYvE4MpobMM1ACg1TYPE0OyLzPHAohvx0LRva4Z
wXkAoLUHS+yJMx4A0C/xz7tVs2Np3NLL
=uu9y
-----END PGP SIGNATURE-----
More information about the libvir-list
mailing list