exec on a guest now returns the return value of the executed process
authorTobias Brunner <tobias@strongswan.org>
Thu, 31 Jul 2008 12:59:59 +0000 (12:59 -0000)
committerTobias Brunner <tobias@strongswan.org>
Thu, 31 Jul 2008 12:59:59 +0000 (12:59 -0000)
src/dumm/irdumm.c
src/dumm/mconsole.c
src/dumm/patches/mconsole-exec-2.6.26.patch

index f468e7c..d943740 100644 (file)
@@ -194,13 +194,14 @@ static VALUE guest_exec(VALUE self, VALUE cmd)
 {
        guest_t *guest;
        bool block;
 {
        guest_t *guest;
        bool block;
+       int ret;
        
        block = rb_block_given_p();
        Data_Get_Struct(self, guest_t, guest);
        
        block = rb_block_given_p();
        Data_Get_Struct(self, guest_t, guest);
-       if (guest->exec_str(guest, block ? (void*)exec_cb : NULL, TRUE, NULL,
-                                       "%s", StringValuePtr(cmd)) != 0)
+       if ((ret = guest->exec_str(guest, block ? (void*)exec_cb : NULL, TRUE, NULL,
+                                       "%s", StringValuePtr(cmd))) != 0)
        {
        {
-               rb_raise(rb_eRuntimeError, "executing command failed");
+               rb_raise(rb_eRuntimeError, "executing command failed (%d)", ret);
        }
        return self;
 }
        }
        return self;
 }
index b44a8e5..71062be 100644 (file)
@@ -201,11 +201,7 @@ static bool del_iface(private_mconsole_t *this, char *guest)
 static int exec(private_mconsole_t *this, void(*cb)(void*,char*,size_t),
                                void *data, char *cmd)
 {
 static int exec(private_mconsole_t *this, void(*cb)(void*,char*,size_t),
                                void *data, char *cmd)
 {
-       if (request(this, cb, data, "exec %s", cmd) != 0)
-       {
-               return -1;
-       }
-       return 0;
+       return request(this, cb, data, "exec %s", cmd);
 }
 
 /**
 }
 
 /**
index 92601cf..853b28f 100644 (file)
@@ -1,5 +1,5 @@
 --- a/arch/um/drivers/mconsole_kern.c  2008-07-13 23:51:29.000000000 +0200
 --- a/arch/um/drivers/mconsole_kern.c  2008-07-13 23:51:29.000000000 +0200
-+++ b/arch/um/drivers/mconsole_kern.c  2008-07-15 15:41:54.000000000 +0200
++++ b/arch/um/drivers/mconsole_kern.c  2008-07-31 14:04:57.000000000 +0200
 @@ -4,6 +4,7 @@
   * Licensed under the GPL
   */
 @@ -4,6 +4,7 @@
   * Licensed under the GPL
   */
@@ -8,20 +8,23 @@
  #include <linux/console.h>
  #include <linux/ctype.h>
  #include <linux/interrupt.h>
  #include <linux/console.h>
  #include <linux/ctype.h>
  #include <linux/interrupt.h>
-@@ -18,6 +19,7 @@
+@@ -18,6 +19,8 @@
  #include <linux/utsname.h>
  #include <linux/workqueue.h>
  #include <linux/mutex.h>
  #include <linux/utsname.h>
  #include <linux/workqueue.h>
  #include <linux/mutex.h>
++#include <linux/completion.h>
 +#include <linux/file.h>
  #include <asm/uaccess.h>
  
  #include "init.h"
 +#include <linux/file.h>
  #include <asm/uaccess.h>
  
  #include "init.h"
-@@ -199,6 +201,44 @@
+@@ -199,6 +202,64 @@
  }
  #endif
  
 +void mconsole_exec(struct mc_request *req)
 +{
  }
  #endif
  
 +void mconsole_exec(struct mc_request *req)
 +{
++      DECLARE_COMPLETION_ONSTACK(done);
++      struct subprocess_info *sub_info;
 +      int res, len;
 +      struct file *out;
 +      char buf[MCONSOLE_MAX_DATA];
 +      int res, len;
 +      struct file *out;
 +      char buf[MCONSOLE_MAX_DATA];
 +              req->request.data + strlen("exec "),
 +              NULL
 +      };
 +              req->request.data + strlen("exec "),
 +              NULL
 +      };
-+      res = call_usermodehelper_pipe("/bin/sh", argv, envp, NULL, &out);
 +      
 +      
++      sub_info = call_usermodehelper_setup("/bin/sh", argv, envp);
++      if (sub_info == NULL) {
++              mconsole_reply(req, "call_usermodehelper_setup failed", 1, 0);
++              return;
++      }
++      res = call_usermodehelper_stdoutpipe(sub_info, &out);
 +      if (res < 0) {
 +      if (res < 0) {
-+              mconsole_reply(req, "call_usermodehelper_pipe failed", 1, 0);
++              call_usermodehelper_freeinfo(sub_info);
++              mconsole_reply(req, "call_usermodehelper_stdoutpipe failed", 1, 0);
++              return;
++      }
++
++      call_usermodehelper_setcomplete(sub_info, &done);
++      
++      res = call_usermodehelper_exec(sub_info, UMH_WAIT_EXT); 
++      if (res < 0) {
++              mconsole_reply(req, "call_usermodehelper_exec failed", 1, 0);
 +              return;
 +      }
 +      
 +              return;
 +      }
 +      
 +                      mconsole_reply(req, "reading output failed", 1, 0);
 +                      break;
 +              }
 +                      mconsole_reply(req, "reading output failed", 1, 0);
 +                      break;
 +              }
-+              if (len == 0) {
-+                      mconsole_reply_len(req, buf, len, 0, 0);
++              if (len == 0)
 +                      break;
 +                      break;
-+              }
 +              mconsole_reply_len(req, buf, len, 0, 1);
 +      }
 +      fput(out);
 +              mconsole_reply_len(req, buf, len, 0, 1);
 +      }
 +      fput(out);
++      
++      wait_for_completion(&done);
++      res = call_usermodehelper_getretval(sub_info) >> 8;
++      call_usermodehelper_freeinfo(sub_info);
++      
++      mconsole_reply_len(req, buf, len, res, 0);
 +}
 +
  void mconsole_proc(struct mc_request *req)
  {
        char path[64];
 +}
 +
  void mconsole_proc(struct mc_request *req)
  {
        char path[64];
-@@ -270,6 +310,7 @@
+@@ -270,6 +331,7 @@
      stop - pause the UML; it will do nothing until it receives a 'go' \n\
      go - continue the UML after a 'stop' \n\
      log <string> - make UML enter <string> into the kernel log\n\
      stop - pause the UML; it will do nothing until it receives a 'go' \n\
      go - continue the UML after a 'stop' \n\
      log <string> - make UML enter <string> into the kernel log\n\
  extern void mconsole_stack(struct mc_request *req);
  
 --- a/kernel/kmod.c    2008-07-13 23:51:29.000000000 +0200
  extern void mconsole_stack(struct mc_request *req);
  
 --- a/kernel/kmod.c    2008-07-13 23:51:29.000000000 +0200
-+++ b/kernel/kmod.c    2008-07-15 15:41:54.000000000 +0200
-@@ -125,6 +125,7 @@
++++ b/kernel/kmod.c    2008-07-31 14:46:31.000000000 +0200
+@@ -118,6 +118,7 @@
+ struct subprocess_info {
+       struct work_struct work;
+       struct completion *complete;
++      struct completion *executed;
+       char *path;
+       char **argv;
+       char **envp;
+@@ -125,6 +126,7 @@
        enum umh_wait wait;
        int retval;
        struct file *stdin;
        enum umh_wait wait;
        int retval;
        struct file *stdin;
        void (*cleanup)(char **argv, char **envp);
  };
  
        void (*cleanup)(char **argv, char **envp);
  };
  
-@@ -160,8 +161,26 @@
+@@ -160,8 +162,26 @@
                FD_SET(0, fdt->open_fds);
                FD_CLR(0, fdt->close_on_exec);
                spin_unlock(&f->file_lock);
                FD_SET(0, fdt->open_fds);
                FD_CLR(0, fdt->close_on_exec);
                spin_unlock(&f->file_lock);
                current->signal->rlim[RLIMIT_CORE] = (struct rlimit){0, 0};
        }
  
                current->signal->rlim[RLIMIT_CORE] = (struct rlimit){0, 0};
        }
  
-@@ -433,6 +452,29 @@
+@@ -243,7 +263,7 @@
+       /* CLONE_VFORK: wait until the usermode helper has execve'd
+        * successfully We need the data structures to stay around
+        * until that is done.  */
+-      if (wait == UMH_WAIT_PROC || wait == UMH_NO_WAIT)
++      if (wait == UMH_WAIT_PROC || wait == UMH_NO_WAIT || wait == UMH_WAIT_EXT)
+               pid = kernel_thread(wait_for_helper, sub_info,
+                                   CLONE_FS | CLONE_FILES | SIGCHLD);
+       else
+@@ -254,6 +274,16 @@
+       case UMH_NO_WAIT:
+               break;
++      case UMH_WAIT_EXT:
++              if (pid > 0) {
++                      complete(sub_info->executed);
++                      break;
++              }
++              sub_info->retval = pid;
++              complete(sub_info->executed);
++              complete(sub_info->complete);
++              break;
++
+       case UMH_WAIT_PROC:
+               if (pid > 0)
+                       break;
+@@ -404,6 +434,19 @@
+ }
+ EXPORT_SYMBOL(call_usermodehelper_setcleanup);
++void call_usermodehelper_setcomplete(struct subprocess_info *info,
++                                  struct completion* complete)
++{
++      info->complete = complete;
++}
++EXPORT_SYMBOL(call_usermodehelper_setcomplete);
++
++int call_usermodehelper_getretval(struct subprocess_info *info)
++{
++      return info->retval;
++}
++EXPORT_SYMBOL(call_usermodehelper_getretval);
++
+ /**
+  * call_usermodehelper_stdinpipe - set up a pipe to be used for stdin
+  * @sub_info: a subprocess_info returned by call_usermodehelper_setup
+@@ -433,6 +476,29 @@
  }
  EXPORT_SYMBOL(call_usermodehelper_stdinpipe);
  
  }
  EXPORT_SYMBOL(call_usermodehelper_stdinpipe);
  
  /**
   * call_usermodehelper_exec - start a usermode application
   * @sub_info: information about the subprocessa
  /**
   * call_usermodehelper_exec - start a usermode application
   * @sub_info: information about the subprocessa
-@@ -489,7 +531,7 @@
-  * lower-level call_usermodehelper_* functions.
-  */
- int call_usermodehelper_pipe(char *path, char **argv, char **envp,
--                           struct file **filp)
-+                           struct file **in, struct file **out)
- {
-       struct subprocess_info *sub_info;
-       int ret;
-@@ -498,9 +540,17 @@
-       if (sub_info == NULL)
-               return -ENOMEM;
--      ret = call_usermodehelper_stdinpipe(sub_info, filp);
--      if (ret < 0)
--              goto out;
-+      if (in) {
-+              ret = call_usermodehelper_stdinpipe(sub_info, in);
-+              if (ret < 0)
-+                      goto out;
-+      }
+@@ -460,15 +526,22 @@
+               goto out;
+       }
+-      sub_info->complete = &done;
++      if (wait == UMH_WAIT_EXT)
++              sub_info->executed = &done;
++      else
++              sub_info->complete = &done;
 +
 +
-+      if (out) {
-+              ret = call_usermodehelper_stdoutpipe(sub_info, out);
-+              if (ret < 0)
-+                      goto out;
-+      }
+       sub_info->wait = wait;
  
  
-       return call_usermodehelper_exec(sub_info, UMH_WAIT_EXEC);
+       queue_work(khelper_wq, &sub_info->work);
+       if (wait == UMH_NO_WAIT)        /* task has freed sub_info */
+               goto unlock;
++
+       wait_for_completion(&done);
+-      retval = sub_info->retval;
  
  
++      retval = sub_info->retval;
++      if (wait == UMH_WAIT_EXT)       /* caller will free sub_info */
++              goto unlock;
+ out:
+       call_usermodehelper_freeinfo(sub_info);
+ unlock:
 --- a/include/linux/kmod.h     2008-07-13 23:51:29.000000000 +0200
 --- a/include/linux/kmod.h     2008-07-13 23:51:29.000000000 +0200
-+++ b/include/linux/kmod.h     2008-07-15 15:41:54.000000000 +0200
-@@ -93,6 +93,6 @@
++++ b/include/linux/kmod.h     2008-07-31 14:43:33.000000000 +0200
+@@ -38,6 +38,7 @@
+ struct key;
  struct file;
  struct file;
- extern int call_usermodehelper_pipe(char *path, char *argv[], char *envp[],
--                                  struct file **filp);
-+                                  struct file **in, struct file **out);
- #endif /* __LINUX_KMOD_H__ */
---- a/fs/exec.c        2008-07-13 23:51:29.000000000 +0200
-+++ b/fs/exec.c        2008-07-15 15:41:54.000000000 +0200
-@@ -1741,7 +1741,7 @@
-               /* SIGPIPE can happen, but it's just never processed */
-               if (call_usermodehelper_pipe(corename+1, helper_argv, NULL,
--                              &file)) {
-+                              &file, NULL)) {
-                       printk(KERN_INFO "Core dump to %s pipe failed\n",
-                              corename);
-                       goto fail_unlock;
+ struct subprocess_info;
++struct completion;
+ /* Allocate a subprocess_info structure */
+ struct subprocess_info *call_usermodehelper_setup(char *path,
+@@ -48,13 +49,20 @@
+                                struct key *session_keyring);
+ int call_usermodehelper_stdinpipe(struct subprocess_info *sub_info,
+                                 struct file **filp);
++int call_usermodehelper_stdoutpipe(struct subprocess_info *sub_info,
++                                 struct file **filp);
++void call_usermodehelper_setcomplete(struct subprocess_info *sub_info,
++                                   struct completion *complete);
+ void call_usermodehelper_setcleanup(struct subprocess_info *info,
+                                   void (*cleanup)(char **argv, char **envp));
++int call_usermodehelper_getretval(struct subprocess_info *sub_info);
+ enum umh_wait {
+       UMH_NO_WAIT = -1,       /* don't wait at all */
+       UMH_WAIT_EXEC = 0,      /* wait for the exec, but not the process */
+       UMH_WAIT_PROC = 1,      /* wait for the process to complete */
++      UMH_WAIT_EXT = 2,       /* wait for the exec then return and signal 
++                                 when the process is complete */
+ };
+ /* Actually execute the sub-process */
 --- a/arch/um/Makefile 2008-07-13 23:51:29.000000000 +0200
 +++ b/arch/um/Makefile 2008-07-15 16:27:02.000000000 +0200
 @@ -77,6 +77,7 @@
 --- a/arch/um/Makefile 2008-07-13 23:51:29.000000000 +0200
 +++ b/arch/um/Makefile 2008-07-15 16:27:02.000000000 +0200
 @@ -77,6 +77,7 @@