uml "exec" writes stdout/stderr back to mconsole
guest->exec() accepts a callback for output sligtly refactored mconsole.c
This commit is contained in:
+6
-5
@@ -328,9 +328,10 @@ static bool load_template(private_guest_t *this, char *path)
|
|||||||
/**
|
/**
|
||||||
* Implementation of gues_t.exec
|
* Implementation of gues_t.exec
|
||||||
*/
|
*/
|
||||||
static int exec(private_guest_t *this, char *cmd, ...)
|
static int exec(private_guest_t *this, void(*cb)(void*,char*), void *data,
|
||||||
|
char *cmd, ...)
|
||||||
{
|
{
|
||||||
char buf[512];
|
char buf[1024];
|
||||||
size_t len;
|
size_t len;
|
||||||
va_list args;
|
va_list args;
|
||||||
|
|
||||||
@@ -342,10 +343,10 @@ static int exec(private_guest_t *this, char *cmd, ...)
|
|||||||
|
|
||||||
if (len > 0 && len < sizeof(buf))
|
if (len > 0 && len < sizeof(buf))
|
||||||
{
|
{
|
||||||
return this->mconsole->exec(this->mconsole, buf);
|
return this->mconsole->exec(this->mconsole, cb, data, buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return FALSE;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -472,7 +473,7 @@ static private_guest_t *guest_create_generic(char *parent, char *name,
|
|||||||
this->public.start = (void*)start;
|
this->public.start = (void*)start;
|
||||||
this->public.stop = (void*)stop;
|
this->public.stop = (void*)stop;
|
||||||
this->public.load_template = (bool(*)(guest_t*, char *path))load_template;
|
this->public.load_template = (bool(*)(guest_t*, char *path))load_template;
|
||||||
this->public.exec = (bool(*)(guest_t*, char *cmd, ...))exec;
|
this->public.exec = (int(*)(guest_t*, void(*cb)(void*,char*,size_t), void *data, char *cmd, ...))exec;
|
||||||
this->public.sigchild = (void(*)(guest_t*))sigchild;
|
this->public.sigchild = (void(*)(guest_t*))sigchild;
|
||||||
this->public.destroy = (void*)destroy;
|
this->public.destroy = (void*)destroy;
|
||||||
|
|
||||||
|
|||||||
+5
-2
@@ -144,11 +144,14 @@ struct guest_t {
|
|||||||
/**
|
/**
|
||||||
* Execute a command in the guest.
|
* Execute a command in the guest.
|
||||||
*
|
*
|
||||||
|
* @param cb callback to call for each read block
|
||||||
|
* @param data data to pass to callback
|
||||||
* @param cmd command to execute
|
* @param cmd command to execute
|
||||||
* @param ... printf style argument list for cmd
|
* @param ... printf style argument list for cmd
|
||||||
* @return TRUE if command executed
|
* @return return value
|
||||||
*/
|
*/
|
||||||
bool (*exec)(guest_t *this, char *cmd, ...);
|
int (*exec)(guest_t *this, void(*cb)(void*,char*,size_t), void *data,
|
||||||
|
char *cmd, ...);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Called whenever a SIGCHILD for the guests PID is received.
|
* @brief Called whenever a SIGCHILD for the guests PID is received.
|
||||||
|
|||||||
+8
-6
@@ -105,8 +105,8 @@ static char* get_hostif(private_iface_t *this)
|
|||||||
*/
|
*/
|
||||||
static bool add_address(private_iface_t *this, host_t *addr)
|
static bool add_address(private_iface_t *this, host_t *addr)
|
||||||
{
|
{
|
||||||
if (this->guest->exec(this->guest, "ip addr add %H dev %s",
|
if (this->guest->exec(this->guest, NULL, NULL, "ip addr add %H dev %s",
|
||||||
addr, this->guestif))
|
addr, this->guestif) == 0)
|
||||||
{
|
{
|
||||||
this->addresses->insert_last(this->addresses, addr);
|
this->addresses->insert_last(this->addresses, addr);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@@ -137,8 +137,8 @@ static bool delete_address(private_iface_t *this, host_t *addr)
|
|||||||
{
|
{
|
||||||
if (current->ip_equals(current, addr))
|
if (current->ip_equals(current, addr))
|
||||||
{
|
{
|
||||||
if (this->guest->exec(this->guest, "ip addr del %H dev %s",
|
if (this->guest->exec(this->guest, NULL, NULL,
|
||||||
current, this->guestif))
|
"ip addr del %H dev %s", current, this->guestif) == 0)
|
||||||
{
|
{
|
||||||
this->addresses->remove_at(this->addresses, enumerator);
|
this->addresses->remove_at(this->addresses, enumerator);
|
||||||
success = TRUE;
|
success = TRUE;
|
||||||
@@ -157,11 +157,13 @@ static void set_bridge(private_iface_t *this, bridge_t *bridge)
|
|||||||
{
|
{
|
||||||
if (this->bridge == NULL && bridge)
|
if (this->bridge == NULL && bridge)
|
||||||
{
|
{
|
||||||
this->guest->exec(this->guest, "ip link set %s up", this->guestif);
|
this->guest->exec(this->guest, NULL, NULL,
|
||||||
|
"ip link set %s up", this->guestif);
|
||||||
}
|
}
|
||||||
else if (this->bridge && bridge == NULL)
|
else if (this->bridge && bridge == NULL)
|
||||||
{
|
{
|
||||||
this->guest->exec(this->guest, "ip link set %s down", this->guestif);
|
this->guest->exec(this->guest, NULL, NULL,
|
||||||
|
"ip link set %s down", this->guestif);
|
||||||
}
|
}
|
||||||
this->bridge = bridge;
|
this->bridge = bridge;
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-2
@@ -123,7 +123,6 @@ static VALUE guest_each(int argc, VALUE *argv, VALUE class)
|
|||||||
|
|
||||||
static VALUE guest_new(VALUE class, VALUE name, VALUE kernel,
|
static VALUE guest_new(VALUE class, VALUE name, VALUE kernel,
|
||||||
VALUE master, VALUE mem)
|
VALUE master, VALUE mem)
|
||||||
|
|
||||||
{
|
{
|
||||||
guest_t *guest;
|
guest_t *guest;
|
||||||
|
|
||||||
@@ -170,12 +169,17 @@ static VALUE guest_stop(VALUE self)
|
|||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void cb(void *data, char *buf, size_t len)
|
||||||
|
{
|
||||||
|
printf("%.*s", len, buf);
|
||||||
|
}
|
||||||
|
|
||||||
static VALUE guest_exec(VALUE self, VALUE cmd)
|
static VALUE guest_exec(VALUE self, VALUE cmd)
|
||||||
{
|
{
|
||||||
guest_t *guest;
|
guest_t *guest;
|
||||||
|
|
||||||
Data_Get_Struct(self, guest_t, guest);
|
Data_Get_Struct(self, guest_t, guest);
|
||||||
if (!guest->exec(guest, StringValuePtr(cmd)))
|
if (guest->exec(guest, cb, NULL, "%s", StringValuePtr(cmd)) != 0)
|
||||||
{
|
{
|
||||||
rb_raise(rb_eRuntimeError, "executing command failed");
|
rb_raise(rb_eRuntimeError, "executing command failed");
|
||||||
}
|
}
|
||||||
|
|||||||
+39
-51
@@ -88,20 +88,20 @@ struct mconsole_notify {
|
|||||||
/**
|
/**
|
||||||
* send a request to UML using mconsole
|
* send a request to UML using mconsole
|
||||||
*/
|
*/
|
||||||
static int request(private_mconsole_t *this, char *command,
|
static int request(private_mconsole_t *this, void(*cb)(void*,char*,size_t),
|
||||||
char buf[], size_t *size)
|
void *data, char *command, ...)
|
||||||
{
|
{
|
||||||
mconsole_request request;
|
mconsole_request request;
|
||||||
mconsole_reply reply;
|
mconsole_reply reply;
|
||||||
int len, total = 0, flags = 0;
|
int len, flags = 0;
|
||||||
|
va_list args;
|
||||||
|
|
||||||
memset(&request, 0, sizeof(request));
|
memset(&request, 0, sizeof(request));
|
||||||
request.magic = MCONSOLE_MAGIC;
|
request.magic = MCONSOLE_MAGIC;
|
||||||
request.version = MCONSOLE_VERSION;
|
request.version = MCONSOLE_VERSION;
|
||||||
request.len = min(strlen(command), sizeof(reply.data) - 1);
|
va_start(args, command);
|
||||||
strncpy(request.data, command, request.len);
|
request.len = vsnprintf(request.data, sizeof(request.data), command, args);
|
||||||
*buf = '\0';
|
va_end(args);
|
||||||
(*size)--;
|
|
||||||
|
|
||||||
if (this->idle)
|
if (this->idle)
|
||||||
{
|
{
|
||||||
@@ -120,7 +120,7 @@ static int request(private_mconsole_t *this, char *command,
|
|||||||
|
|
||||||
if (len < 0)
|
if (len < 0)
|
||||||
{
|
{
|
||||||
snprintf(buf, *size, "sending mconsole command to UML failed: %m");
|
DBG1("sending mconsole command to UML failed: %m");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
do
|
do
|
||||||
@@ -136,44 +136,50 @@ static int request(private_mconsole_t *this, char *command,
|
|||||||
}
|
}
|
||||||
if (len < 0)
|
if (len < 0)
|
||||||
{
|
{
|
||||||
snprintf(buf, *size, "receiving from mconsole failed: %m");
|
DBG1("receiving from mconsole failed: %m");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (len > 0)
|
if (len > 0)
|
||||||
{
|
{
|
||||||
strncat(buf, reply.data, min(reply.len, *size - total));
|
if (cb)
|
||||||
total += reply.len;
|
{
|
||||||
|
cb(data, reply.data, reply.len);
|
||||||
|
}
|
||||||
|
else if (reply.err)
|
||||||
|
{
|
||||||
|
DBG1("received mconsole error %d: %*.s",
|
||||||
|
reply.err, reply.len, reply.data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while (reply.more);
|
while (reply.more);
|
||||||
|
|
||||||
*size = total;
|
|
||||||
return reply.err;
|
return reply.err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ignore error message
|
||||||
|
*/
|
||||||
|
static void ignore(void *data, char *buf, size_t len)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of mconsole_t.add_iface.
|
* Implementation of mconsole_t.add_iface.
|
||||||
*/
|
*/
|
||||||
static bool add_iface(private_mconsole_t *this, char *guest, char *host)
|
static bool add_iface(private_mconsole_t *this, char *guest, char *host)
|
||||||
{
|
{
|
||||||
char in[128], out[128];
|
int tries = 0;
|
||||||
int len, tries = 0;
|
|
||||||
|
|
||||||
len = snprintf(in, sizeof(in), "config %s=tuntap,%s", guest, host);
|
while (tries++ < 5)
|
||||||
if (len < 0 || len >= sizeof(in))
|
|
||||||
{
|
{
|
||||||
return FALSE;
|
if (request(this, ignore, NULL, "config %s=tuntap,%s", guest, host) == 0)
|
||||||
}
|
|
||||||
while (tries++ < 10)
|
|
||||||
{
|
|
||||||
len = sizeof(in);
|
|
||||||
if (request(this, in, out, &len) == 0)
|
|
||||||
{
|
{
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
usleep(10000 * tries);
|
usleep(10000 * tries * tries);
|
||||||
}
|
}
|
||||||
DBG1("adding interface failed: %.*s", len, out);
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -182,15 +188,7 @@ static bool add_iface(private_mconsole_t *this, char *guest, char *host)
|
|||||||
*/
|
*/
|
||||||
static bool del_iface(private_mconsole_t *this, char *guest)
|
static bool del_iface(private_mconsole_t *this, char *guest)
|
||||||
{
|
{
|
||||||
char buf[128];
|
if (request(this, NULL, NULL, "remove %s", guest) != 0)
|
||||||
int len;
|
|
||||||
|
|
||||||
len = snprintf(buf, sizeof(buf), "remove %s", guest);
|
|
||||||
if (len < 0 || len >= sizeof(buf))
|
|
||||||
{
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
if (request(this, buf, buf, &len) != 0)
|
|
||||||
{
|
{
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
@@ -200,22 +198,14 @@ static bool del_iface(private_mconsole_t *this, char *guest)
|
|||||||
/**
|
/**
|
||||||
* Implementation of mconsole_t.exec
|
* Implementation of mconsole_t.exec
|
||||||
*/
|
*/
|
||||||
static bool exec(private_mconsole_t *this, char *cmd)
|
static int exec(private_mconsole_t *this, void(*cb)(void*,char*,size_t),
|
||||||
|
void *data, char *cmd)
|
||||||
{
|
{
|
||||||
char buf[512];
|
if (request(this, cb, data, "exec %s", cmd) != 0)
|
||||||
int len;
|
|
||||||
|
|
||||||
len = snprintf(buf, sizeof(buf), "exec %s", cmd);
|
|
||||||
if (len < 0 || len >= sizeof(buf))
|
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (request(this, buf, buf, &len) != 0)
|
return 0;
|
||||||
{
|
|
||||||
DBG1("exec failed: %.*s", len, buf);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -223,20 +213,18 @@ static bool exec(private_mconsole_t *this, char *cmd)
|
|||||||
*/
|
*/
|
||||||
static bool wait_bootup(private_mconsole_t *this)
|
static bool wait_bootup(private_mconsole_t *this)
|
||||||
{
|
{
|
||||||
char buf[128];
|
int res;
|
||||||
int len, res;
|
|
||||||
|
|
||||||
while (TRUE)
|
while (TRUE)
|
||||||
{
|
{
|
||||||
len = sizeof(buf);
|
res = request(this, ignore, NULL, "config eth9=mcast");
|
||||||
res = request(this, "config eth9=mcast", buf, &len);
|
|
||||||
if (res < 0)
|
if (res < 0)
|
||||||
{
|
{
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
if (res == 0)
|
if (res == 0)
|
||||||
{
|
{
|
||||||
while (request(this, "remove eth9", buf, &len) != 0)
|
while (request(this, ignore, NULL, "remove eth9") != 0)
|
||||||
{
|
{
|
||||||
usleep(50000);
|
usleep(50000);
|
||||||
}
|
}
|
||||||
@@ -359,7 +347,7 @@ mconsole_t *mconsole_create(char *notify, void(*idle)(void))
|
|||||||
|
|
||||||
this->public.add_iface = (bool(*)(mconsole_t*, char *guest, char *host))add_iface;
|
this->public.add_iface = (bool(*)(mconsole_t*, char *guest, char *host))add_iface;
|
||||||
this->public.del_iface = (bool(*)(mconsole_t*, char *guest))del_iface;
|
this->public.del_iface = (bool(*)(mconsole_t*, char *guest))del_iface;
|
||||||
this->public.exec = (bool(*)(mconsole_t*, char *cmd))exec;
|
this->public.exec = (int(*)(mconsole_t*, void(*cb)(void*,char*,size_t), void *data, char *cmd))exec;
|
||||||
this->public.destroy = (void*)destroy;
|
this->public.destroy = (void*)destroy;
|
||||||
|
|
||||||
this->idle = idle;
|
this->idle = idle;
|
||||||
|
|||||||
+7
-1
@@ -44,8 +44,14 @@ struct mconsole_t {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Execute a command in the UML host.
|
* Execute a command in the UML host.
|
||||||
|
*
|
||||||
|
* @param cb callback function to invoke for each line
|
||||||
|
* @param data data to pass to callback
|
||||||
|
* @param cmd command to invoke
|
||||||
|
* @return return value of command
|
||||||
*/
|
*/
|
||||||
bool (*exec)(mconsole_t *this, char *cmd);
|
int (*exec)(mconsole_t *this, void(*cb)(void*,char*,size_t), void *data,
|
||||||
|
char *cmd);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Destroy the mconsole instance
|
* @brief Destroy the mconsole instance
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
--- a/arch/um/drivers/mconsole_kern.c 2008-04-17 04:49:44.000000000 +0200
|
--- linux-2.6.26rc5-orig/arch/um/drivers/mconsole_kern.c 2008-04-17 04:49:44.000000000 +0200
|
||||||
+++ b/arch/um/drivers/mconsole_kern.c 2008-07-07 13:55:48.000000000 +0200
|
+++ uml-2.6.26rc5/arch/um/drivers/mconsole_kern.c 2008-07-08 16:00:07.000000000 +0200
|
||||||
@@ -4,6 +4,7 @@
|
@@ -4,6 +4,7 @@
|
||||||
* Licensed under the GPL
|
* Licensed under the GPL
|
||||||
*/
|
*/
|
||||||
@@ -8,41 +8,61 @@
|
|||||||
#include <linux/console.h>
|
#include <linux/console.h>
|
||||||
#include <linux/ctype.h>
|
#include <linux/ctype.h>
|
||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
@@ -199,6 +200,24 @@
|
@@ -18,6 +19,7 @@
|
||||||
|
#include <linux/utsname.h>
|
||||||
|
#include <linux/workqueue.h>
|
||||||
|
#include <linux/mutex.h>
|
||||||
|
+#include <linux/file.h>
|
||||||
|
#include <asm/uaccess.h>
|
||||||
|
|
||||||
|
#include "init.h"
|
||||||
|
@@ -199,6 +201,36 @@
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
+void mconsole_exec(struct mc_request *req)
|
+void mconsole_exec(struct mc_request *req)
|
||||||
+{
|
+{
|
||||||
+ int res;
|
+ int res, len;
|
||||||
|
+ struct file *out;
|
||||||
|
+ char buf[MCONSOLE_MAX_DATA];
|
||||||
+
|
+
|
||||||
+ char *envp[] = { "HOME=/", "TERM=linux", "PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL };
|
+ char *envp[] = { "HOME=/", "TERM=linux", "PATH=/sbin:/usr/sbin:/bin:/usr/bin", NULL };
|
||||||
+ char *argv[] = { "/bin/sh", "-c", req->request.data + strlen("exec "), NULL };
|
+ char *argv[] = { "/bin/sh", "-c", req->request.data + strlen("exec "), NULL };
|
||||||
+ res = call_usermodehelper("/bin/sh", argv, envp, 0);
|
+ res = call_usermodehelper_pipe("/bin/sh", argv, envp, NULL, &out);
|
||||||
+
|
+
|
||||||
+ if (res < 0) {
|
+ if (res < 0) {
|
||||||
+ char buf[60];
|
+ mconsole_reply(req, "call_usermodehelper_pipe failed", 1, 0);
|
||||||
+ snprintf(buf, 60, "call_usermodehelper failed in mconsole_exec with error code: %d", -res);
|
|
||||||
+ mconsole_reply(req, buf, 1, 0);
|
|
||||||
+ return;
|
+ return;
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
+ mconsole_reply(req, "The command has been started successfully.", 0, 0);
|
+ 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) {
|
||||||
|
+ mconsole_reply_len(req, buf, len, 0, 0);
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ mconsole_reply_len(req, buf, len, 0, 1);
|
||||||
|
+ }
|
||||||
|
+ fput(out);
|
||||||
+}
|
+}
|
||||||
+
|
+
|
||||||
void mconsole_proc(struct mc_request *req)
|
void mconsole_proc(struct mc_request *req)
|
||||||
{
|
{
|
||||||
char path[64];
|
char path[64];
|
||||||
@@ -270,6 +289,7 @@
|
@@ -270,6 +302,7 @@
|
||||||
stop - pause the UML; it will do nothing until it receives a 'go' \n\
|
stop - pause the UML; it will do nothing until it receives a 'go' \n\
|
||||||
go - continue the UML after a 'stop' \n\
|
go - continue the UML after a 'stop' \n\
|
||||||
log <string> - make UML enter <string> into the kernel log\n\
|
log <string> - make UML enter <string> into the kernel log\n\
|
||||||
+ exec <string> - pass <string> to /bin/sh -c in guest\n\
|
+ exec <string> - pass <string> to /bin/sh -c synchronously\n\
|
||||||
proc <file> - returns the contents of the UML's /proc/<file>\n\
|
proc <file> - returns the contents of the UML's /proc/<file>\n\
|
||||||
stack <pid> - returns the stack of the specified pid\n\
|
stack <pid> - returns the stack of the specified pid\n\
|
||||||
"
|
"
|
||||||
--- a/arch/um/drivers/mconsole_user.c 2008-05-21 18:34:47.000000000 +0200
|
--- linux-2.6.26rc5-orig/arch/um/drivers/mconsole_user.c 2008-05-21 18:34:47.000000000 +0200
|
||||||
+++ b/arch/um/drivers/mconsole_user.c 2008-07-07 13:47:13.000000000 +0200
|
+++ uml-2.6.26rc5/arch/um/drivers/mconsole_user.c 2008-07-07 13:47:13.000000000 +0200
|
||||||
@@ -32,6 +32,7 @@
|
@@ -32,6 +32,7 @@
|
||||||
{ "stop", mconsole_stop, MCONSOLE_PROC },
|
{ "stop", mconsole_stop, MCONSOLE_PROC },
|
||||||
{ "go", mconsole_go, MCONSOLE_INTR },
|
{ "go", mconsole_go, MCONSOLE_INTR },
|
||||||
@@ -51,8 +71,8 @@
|
|||||||
{ "proc", mconsole_proc, MCONSOLE_PROC },
|
{ "proc", mconsole_proc, MCONSOLE_PROC },
|
||||||
{ "stack", mconsole_stack, MCONSOLE_INTR },
|
{ "stack", mconsole_stack, MCONSOLE_INTR },
|
||||||
};
|
};
|
||||||
--- a/arch/um/include/mconsole.h 2008-04-17 04:49:44.000000000 +0200
|
--- linux-2.6.26rc5-orig/arch/um/include/mconsole.h 2008-04-17 04:49:44.000000000 +0200
|
||||||
+++ b/arch/um/include/mconsole.h 2008-07-07 13:46:56.000000000 +0200
|
+++ uml-2.6.26rc5/arch/um/include/mconsole.h 2008-07-07 13:46:56.000000000 +0200
|
||||||
@@ -85,6 +85,7 @@
|
@@ -85,6 +85,7 @@
|
||||||
extern void mconsole_stop(struct mc_request *req);
|
extern void mconsole_stop(struct mc_request *req);
|
||||||
extern void mconsole_go(struct mc_request *req);
|
extern void mconsole_go(struct mc_request *req);
|
||||||
@@ -61,3 +81,123 @@
|
|||||||
extern void mconsole_proc(struct mc_request *req);
|
extern void mconsole_proc(struct mc_request *req);
|
||||||
extern void mconsole_stack(struct mc_request *req);
|
extern void mconsole_stack(struct mc_request *req);
|
||||||
|
|
||||||
|
--- linux-2.6.26rc5-orig/kernel/kmod.c 2008-05-21 18:34:56.000000000 +0200
|
||||||
|
+++ uml-2.6.26rc5/kernel/kmod.c 2008-07-08 13:50:37.000000000 +0200
|
||||||
|
@@ -125,6 +125,7 @@
|
||||||
|
enum umh_wait wait;
|
||||||
|
int retval;
|
||||||
|
struct file *stdin;
|
||||||
|
+ struct file *stdout;
|
||||||
|
void (*cleanup)(char **argv, char **envp);
|
||||||
|
};
|
||||||
|
|
||||||
|
@@ -160,8 +161,26 @@
|
||||||
|
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};
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -433,6 +452,29 @@
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(call_usermodehelper_stdinpipe);
|
||||||
|
|
||||||
|
+int call_usermodehelper_stdoutpipe(struct subprocess_info *sub_info,
|
||||||
|
+ struct file **filp)
|
||||||
|
+{
|
||||||
|
+ struct file *f;
|
||||||
|
+
|
||||||
|
+ f = create_write_pipe();
|
||||||
|
+ if (IS_ERR(f))
|
||||||
|
+ return PTR_ERR(f);
|
||||||
|
+ sub_info->stdout = f;
|
||||||
|
+
|
||||||
|
+ f = create_read_pipe(f);
|
||||||
|
+ 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
|
||||||
|
@@ -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;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (out) {
|
||||||
|
+ ret = call_usermodehelper_stdoutpipe(sub_info, out);
|
||||||
|
+ if (ret < 0)
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
return call_usermodehelper_exec(sub_info, UMH_WAIT_EXEC);
|
||||||
|
|
||||||
|
--- linux-2.6.26rc5-orig/include/linux/kmod.h 2008-04-17 04:49:44.000000000 +0200
|
||||||
|
+++ uml-2.6.26rc5/include/linux/kmod.h 2008-07-08 10:29:29.000000000 +0200
|
||||||
|
@@ -93,6 +93,6 @@
|
||||||
|
|
||||||
|
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__ */
|
||||||
|
--- linux-2.6.26rc5-orig/fs/exec.c 2008-06-05 14:00:42.000000000 +0200
|
||||||
|
+++ uml-2.6.26rc5/fs/exec.c 2008-07-08 10:28:33.000000000 +0200
|
||||||
|
@@ -1737,7 +1737,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;
|
||||||
|
|||||||
Reference in New Issue
Block a user