From c587052624be4219d869e38f45b9f00a4db3b4e9 Mon Sep 17 00:00:00 2001 From: Martin Willi Date: Thu, 5 Mar 2009 14:32:15 +0000 Subject: [PATCH] added updated mconsole-exec patch for 2.6.28 --- src/dumm/patches/mconsole-exec-2.6.28.patch | 302 ++++++++++++++++++++++++++++ 1 file changed, 302 insertions(+) create mode 100644 src/dumm/patches/mconsole-exec-2.6.28.patch diff --git a/src/dumm/patches/mconsole-exec-2.6.28.patch b/src/dumm/patches/mconsole-exec-2.6.28.patch new file mode 100644 index 0000000..2f400b3 --- /dev/null +++ b/src/dumm/patches/mconsole-exec-2.6.28.patch @@ -0,0 +1,302 @@ +--- a/arch/um/drivers/line.c ++++ b/arch/um/drivers/line.c +@@ -866,6 +866,6 @@ char *add_xterm_umid(char *base) + return base; + } + +- snprintf(title, len, "%s (%s)", base, umid); ++ snprintf(title, len, "%s (%s)", umid, base); + return title; + } +--- a/arch/um/drivers/mconsole_kern.c ++++ b/arch/um/drivers/mconsole_kern.c +@@ -4,6 +4,7 @@ + * Licensed under the GPL + */ + ++#include "linux/kmod.h" + #include + #include + #include +@@ -20,6 +21,8 @@ + #include + #include + #include ++#include ++#include + #include + + #include "init.h" +@@ -201,6 +204,65 @@ void mconsole_proc(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]; ++ ++ char *envp[] = { ++ "HOME=/", "TERM=linux", ++ "PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin", ++ NULL ++ }; ++ char *argv[] = { ++ "/bin/sh", "-c", ++ req->request.data + strlen("exec "), ++ NULL ++ }; ++ ++ sub_info = call_usermodehelper_setup("/bin/sh", argv, envp, GFP_ATOMIC); ++ if (sub_info == NULL) { ++ mconsole_reply(req, "call_usermodehelper_setup failed", 1, 0); ++ return; ++ } ++ res = call_usermodehelper_stdoutpipe(sub_info, &out); ++ if (res < 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) { ++ call_usermodehelper_freeinfo(sub_info); ++ mconsole_reply(req, "call_usermodehelper_exec failed", 1, 0); ++ return; ++ } ++ ++ for (;;) { ++ len = out->f_op->read(out, buf, sizeof(buf), 0); ++ if (len < 0) { ++ mconsole_reply(req, "reading output failed", 1, 0); ++ break; ++ } ++ if (len == 0) ++ break; ++ 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]; +@@ -272,6 +334,7 @@ void mconsole_proc(struct mc_request *req) + stop - pause the UML; it will do nothing until it receives a 'go' \n\ + go - continue the UML after a 'stop' \n\ + log - make UML enter into the kernel log\n\ ++ exec - pass to /bin/sh -c synchronously\n\ + proc - returns the contents of the UML's /proc/\n\ + stack - returns the stack of the specified pid\n\ + " +--- a/arch/um/drivers/mconsole_user.c ++++ b/arch/um/drivers/mconsole_user.c +@@ -32,6 +32,7 @@ static struct mconsole_command commands[] = { + { "stop", mconsole_stop, MCONSOLE_PROC }, + { "go", mconsole_go, MCONSOLE_INTR }, + { "log", mconsole_log, MCONSOLE_INTR }, ++ { "exec", mconsole_exec, MCONSOLE_PROC }, + { "proc", mconsole_proc, MCONSOLE_PROC }, + { "stack", mconsole_stack, MCONSOLE_INTR }, + }; +--- a/arch/um/include/shared/mconsole.h ++++ b/arch/um/include/shared/mconsole.h +@@ -85,6 +85,7 @@ extern void mconsole_cad(struct mc_request *req); + extern void mconsole_stop(struct mc_request *req); + extern void mconsole_go(struct mc_request *req); + extern void mconsole_log(struct mc_request *req); ++extern void mconsole_exec(struct mc_request *req); + extern void mconsole_proc(struct mc_request *req); + extern void mconsole_stack(struct mc_request *req); + +--- a/include/linux/kmod.h ++++ b/include/linux/kmod.h +@@ -40,6 +40,7 @@ static inline int request_module(const char * name, ...) { return -ENOSYS; } + struct key; + struct file; + struct subprocess_info; ++struct completion; + + /* Allocate a subprocess_info structure */ + struct subprocess_info *call_usermodehelper_setup(char *path, char **argv, +@@ -50,13 +51,20 @@ void call_usermodehelper_setkeys(struct subprocess_info *info, + 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/kernel/kmod.c ++++ b/kernel/kmod.c +@@ -118,6 +118,7 @@ EXPORT_SYMBOL(request_module); + struct subprocess_info { + struct work_struct work; + struct completion *complete; ++ struct completion *executed; + char *path; + char **argv; + char **envp; +@@ -125,6 +126,7 @@ struct subprocess_info { + enum umh_wait wait; + int retval; + struct file *stdin; ++ struct file *stdout; + void (*cleanup)(char **argv, char **envp); + }; + +@@ -160,8 +162,26 @@ static int ____call_usermodehelper(void *data) + FD_SET(0, fdt->open_fds); + FD_CLR(0, fdt->close_on_exec); + spin_unlock(&f->file_lock); +- +- /* and disallow core files too */ ++ } ++ if (sub_info->stdout) { ++ struct files_struct *f = current->files; ++ struct fdtable *fdt; ++ ++ sys_close(1); ++ sys_close(2); ++ get_file(sub_info->stdout); ++ fd_install(1, sub_info->stdout); ++ fd_install(2, sub_info->stdout); ++ spin_lock(&f->file_lock); ++ fdt = files_fdtable(f); ++ FD_SET(1, fdt->open_fds); ++ FD_CLR(1, fdt->close_on_exec); ++ FD_SET(2, fdt->open_fds); ++ FD_CLR(2, fdt->close_on_exec); ++ spin_unlock(&f->file_lock); ++ } ++ if (sub_info->stdin || sub_info->stdout) { ++ /* disallow core files */ + current->signal->rlim[RLIMIT_CORE] = (struct rlimit){0, 0}; + } + +@@ -243,7 +263,7 @@ static void __call_usermodehelper(struct work_struct *work) + /* 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 @@ static void __call_usermodehelper(struct work_struct *work) + 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; +@@ -397,6 +427,19 @@ void call_usermodehelper_setcleanup(struct subprocess_info *info, + } + 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 +@@ -426,6 +469,29 @@ int call_usermodehelper_stdinpipe(struct subprocess_info *sub_info, + } + EXPORT_SYMBOL(call_usermodehelper_stdinpipe); + ++int call_usermodehelper_stdoutpipe(struct subprocess_info *sub_info, ++ struct file **filp) ++{ ++ struct file *f; ++ ++ f = create_write_pipe(0); ++ if (IS_ERR(f)) ++ return PTR_ERR(f); ++ sub_info->stdout = f; ++ ++ f = create_read_pipe(f, 0); ++ if (IS_ERR(f)) { ++ free_write_pipe(sub_info->stdout); ++ sub_info->stdout = NULL; ++ return PTR_ERR(f); ++ } ++ *filp = f; ++ ++ return 0; ++} ++EXPORT_SYMBOL(call_usermodehelper_stdoutpipe); ++ ++ + /** + * call_usermodehelper_exec - start a usermode application + * @sub_info: information about the subprocessa +@@ -453,15 +519,22 @@ int call_usermodehelper_exec(struct subprocess_info *sub_info, + goto out; + } + +- sub_info->complete = &done; ++ if (wait == UMH_WAIT_EXT) ++ sub_info->executed = &done; ++ else ++ sub_info->complete = &done; ++ + sub_info->wait = wait; + + 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: -- 2.7.4