On Fri, Feb 20, 2009 at 02:38:05PM +0000, Daniel P. Berrange wrote:
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()
I've committed this patch to CVS now.
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,
Daniel
--
|: Red Hat, Engineering, London -o-
http://people.redhat.com/berrange/ :|
|:
http://libvirt.org -o-
http://virt-manager.org -o-
http://ovirt.org :|
|:
http://autobuild.org -o-
http://search.cpan.org/~danberr/ :|
|: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|