2005-04-16 18:20:36 -04:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org)
|
|
|
|
* Copyright (C) 2001 - 2003 Jeff Dike (jdike@addtoit.com)
|
|
|
|
* Licensed under the GPL
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <signal.h>
|
|
|
|
#include <sys/socket.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/uio.h>
|
|
|
|
#include <sys/un.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include "user.h"
|
2006-10-24 06:15:29 -04:00
|
|
|
#include "sysdep/ptrace.h"
|
2005-04-16 18:20:36 -04:00
|
|
|
#include "mconsole.h"
|
2007-02-10 04:44:25 -05:00
|
|
|
#include "os.h"
|
2006-09-26 02:33:00 -04:00
|
|
|
#include "user_util.h"
|
2005-04-16 18:20:36 -04:00
|
|
|
|
|
|
|
static struct mconsole_command commands[] = {
|
2006-07-10 07:45:16 -04:00
|
|
|
/* With uts namespaces, uts information becomes process-specific, so
|
|
|
|
* we need a process context. If we try handling this in interrupt
|
|
|
|
* context, we may hit an exiting process without a valid uts
|
|
|
|
* namespace.
|
|
|
|
*/
|
|
|
|
{ "version", mconsole_version, MCONSOLE_PROC },
|
2005-04-16 18:20:36 -04:00
|
|
|
{ "halt", mconsole_halt, MCONSOLE_PROC },
|
|
|
|
{ "reboot", mconsole_reboot, MCONSOLE_PROC },
|
|
|
|
{ "config", mconsole_config, MCONSOLE_PROC },
|
|
|
|
{ "remove", mconsole_remove, MCONSOLE_PROC },
|
2005-09-30 14:59:00 -04:00
|
|
|
{ "sysrq", mconsole_sysrq, MCONSOLE_INTR },
|
2005-04-16 18:20:36 -04:00
|
|
|
{ "help", mconsole_help, MCONSOLE_INTR },
|
|
|
|
{ "cad", mconsole_cad, MCONSOLE_INTR },
|
|
|
|
{ "stop", mconsole_stop, MCONSOLE_PROC },
|
|
|
|
{ "go", mconsole_go, MCONSOLE_INTR },
|
|
|
|
{ "log", mconsole_log, MCONSOLE_INTR },
|
|
|
|
{ "proc", mconsole_proc, MCONSOLE_PROC },
|
[PATCH] uml: breakpoint an arbitrary thread
This patch implements a stack trace for a thread, not unlike sysrq-t does.
The advantage to this is that a break point can be placed on showreqs, so that
upon showing the stack, you jump immediately into the debugger. While sysrq-t
does the same thing, sysrq-t shows *all* threads stacks. It also doesn't work
right now. In the future, I thought it might be acceptable to make this show
all pids stacks, but perhaps leaving well enough alone and just using sysrq-t
would be okay. For now, upon receiving the stack command, UML switches
context to that thread, dumps its registers, and then switches context back to
the original thread. Since UML compacts all threads into one of 4 host
threads, this sort of mechanism could be expanded in the future to include
other debugging helpers that sysrq does not cover.
Note by jdike - The main benefit to this is that it brings an arbitrary thread
back into context, where it can be examined by gdb. The fact that it dumps it
stack is secondary. This provides the capability to examine a sleeping
thread, which has existed in tt mode, but not in skas mode until now.
Also, the other threads, that sysrq doesn't cover, can be gdb-ed directly
anyway.
Signed-off-by: Allan Graves<allan.graves@gmail.com>
Signed-off-by: Jeff Dike <jdike@addtoit.com>
Cc: Paolo Giarrusso <blaisorblade@yahoo.it>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2005-09-16 22:27:46 -04:00
|
|
|
{ "stack", mconsole_stack, MCONSOLE_INTR },
|
2005-04-16 18:20:36 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
/* Initialized in mconsole_init, which is an initcall */
|
|
|
|
char mconsole_socket_name[256];
|
|
|
|
|
|
|
|
int mconsole_reply_v0(struct mc_request *req, char *reply)
|
|
|
|
{
|
|
|
|
struct iovec iov;
|
|
|
|
struct msghdr msg;
|
|
|
|
|
|
|
|
iov.iov_base = reply;
|
|
|
|
iov.iov_len = strlen(reply);
|
|
|
|
|
|
|
|
msg.msg_name = &(req->origin);
|
|
|
|
msg.msg_namelen = req->originlen;
|
|
|
|
msg.msg_iov = &iov;
|
|
|
|
msg.msg_iovlen = 1;
|
|
|
|
msg.msg_control = NULL;
|
|
|
|
msg.msg_controllen = 0;
|
|
|
|
msg.msg_flags = 0;
|
|
|
|
|
|
|
|
return sendmsg(req->originating_fd, &msg, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct mconsole_command *mconsole_parse(struct mc_request *req)
|
|
|
|
{
|
|
|
|
struct mconsole_command *cmd;
|
|
|
|
int i;
|
|
|
|
|
2006-09-26 02:33:00 -04:00
|
|
|
for(i = 0; i < ARRAY_SIZE(commands); i++){
|
2005-04-16 18:20:36 -04:00
|
|
|
cmd = &commands[i];
|
|
|
|
if(!strncmp(req->request.data, cmd->command,
|
|
|
|
strlen(cmd->command))){
|
2006-09-26 02:33:00 -04:00
|
|
|
return cmd;
|
2005-04-16 18:20:36 -04:00
|
|
|
}
|
|
|
|
}
|
2006-09-26 02:33:00 -04:00
|
|
|
return NULL;
|
2005-04-16 18:20:36 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
#define MIN(a,b) ((a)<(b) ? (a):(b))
|
|
|
|
|
|
|
|
#define STRINGX(x) #x
|
|
|
|
#define STRING(x) STRINGX(x)
|
|
|
|
|
|
|
|
int mconsole_get_request(int fd, struct mc_request *req)
|
|
|
|
{
|
|
|
|
int len;
|
|
|
|
|
|
|
|
req->originlen = sizeof(req->origin);
|
|
|
|
req->len = recvfrom(fd, &req->request, sizeof(req->request), 0,
|
|
|
|
(struct sockaddr *) req->origin, &req->originlen);
|
|
|
|
if (req->len < 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
req->originating_fd = fd;
|
|
|
|
|
|
|
|
if(req->request.magic != MCONSOLE_MAGIC){
|
|
|
|
/* Unversioned request */
|
|
|
|
len = MIN(sizeof(req->request.data) - 1,
|
|
|
|
strlen((char *) &req->request));
|
|
|
|
memmove(req->request.data, &req->request, len);
|
|
|
|
req->request.data[len] = '\0';
|
|
|
|
|
|
|
|
req->request.magic = MCONSOLE_MAGIC;
|
|
|
|
req->request.version = 0;
|
|
|
|
req->request.len = len;
|
|
|
|
|
|
|
|
mconsole_reply_v0(req, "ERR Version 0 mconsole clients are "
|
|
|
|
"not supported by this driver");
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(req->request.len >= MCONSOLE_MAX_DATA){
|
|
|
|
mconsole_reply(req, "Request too large", 1, 0);
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
if(req->request.version != MCONSOLE_VERSION){
|
|
|
|
mconsole_reply(req, "This driver only supports version "
|
|
|
|
STRING(MCONSOLE_VERSION) " clients", 1, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
req->request.data[req->request.len] = '\0';
|
|
|
|
req->cmd = mconsole_parse(req);
|
|
|
|
if(req->cmd == NULL){
|
|
|
|
mconsole_reply(req, "Unknown command", 1, 0);
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
return(1);
|
|
|
|
}
|
|
|
|
|
2006-01-06 03:19:03 -05:00
|
|
|
int mconsole_reply_len(struct mc_request *req, const char *str, int total,
|
|
|
|
int err, int more)
|
2005-04-16 18:20:36 -04:00
|
|
|
{
|
2006-09-29 04:58:52 -04:00
|
|
|
/* XXX This is a stack consumption problem. It'd be nice to
|
|
|
|
* make it global and serialize access to it, but there are a
|
|
|
|
* ton of callers to this function.
|
|
|
|
*/
|
2005-04-16 18:20:36 -04:00
|
|
|
struct mconsole_reply reply;
|
2006-01-06 03:19:03 -05:00
|
|
|
int len, n;
|
2005-04-16 18:20:36 -04:00
|
|
|
|
|
|
|
do {
|
|
|
|
reply.err = err;
|
|
|
|
|
|
|
|
/* err can only be true on the first packet */
|
|
|
|
err = 0;
|
|
|
|
|
|
|
|
len = MIN(total, MCONSOLE_MAX_DATA - 1);
|
|
|
|
|
|
|
|
if(len == total) reply.more = more;
|
|
|
|
else reply.more = 1;
|
|
|
|
|
|
|
|
memcpy(reply.data, str, len);
|
|
|
|
reply.data[len] = '\0';
|
|
|
|
total -= len;
|
|
|
|
str += len;
|
|
|
|
reply.len = len + 1;
|
|
|
|
|
|
|
|
len = sizeof(reply) + reply.len - sizeof(reply.data);
|
|
|
|
|
|
|
|
n = sendto(req->originating_fd, &reply, len, 0,
|
|
|
|
(struct sockaddr *) req->origin, req->originlen);
|
|
|
|
|
|
|
|
if(n < 0) return(-errno);
|
|
|
|
} while(total > 0);
|
|
|
|
return(0);
|
|
|
|
}
|
|
|
|
|
2006-01-06 03:19:03 -05:00
|
|
|
int mconsole_reply(struct mc_request *req, const char *str, int err, int more)
|
|
|
|
{
|
|
|
|
return mconsole_reply_len(req, str, strlen(str), err, more);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-04-16 18:20:36 -04:00
|
|
|
int mconsole_unlink_socket(void)
|
|
|
|
{
|
|
|
|
unlink(mconsole_socket_name);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int notify_sock = -1;
|
|
|
|
|
|
|
|
int mconsole_notify(char *sock_name, int type, const void *data, int len)
|
|
|
|
{
|
|
|
|
struct sockaddr_un target;
|
|
|
|
struct mconsole_notify packet;
|
|
|
|
int n, err = 0;
|
|
|
|
|
|
|
|
lock_notify();
|
|
|
|
if(notify_sock < 0){
|
|
|
|
notify_sock = socket(PF_UNIX, SOCK_DGRAM, 0);
|
|
|
|
if(notify_sock < 0){
|
|
|
|
err = -errno;
|
[PATCH] uml: preserve errno in error paths
The poster child for this patch is the third tuntap_user hunk. When an ioctl
fails, it properly closes the opened file descriptor and returns. However,
the close resets errno to 0, and the 'return errno' that follows returns 0
rather than the value that ioctl set. This caused the caller to believe that
the device open succeeded and had opened file descriptor 0, which caused no
end of interesting behavior.
The rest of this patch is a pass through the UML sources looking for places
where errno could be reset before being passed back out. A common culprit is
printk, which could call write, being called before errno is returned.
In some cases, where the code ends up being much smaller, I just deleted the
printk.
There was another case where a caller of run_helper looked at errno after a
failure, rather than the return value of run_helper, which was the errno value
that it wanted.
Signed-off-by: Jeff Dike <jdike@addtoit.com>
Cc: Paolo Giarrusso <blaisorblade@yahoo.it>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2005-09-16 22:27:49 -04:00
|
|
|
printk("mconsole_notify - socket failed, errno = %d\n",
|
|
|
|
err);
|
2005-04-16 18:20:36 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
unlock_notify();
|
|
|
|
|
|
|
|
if(err)
|
|
|
|
return(err);
|
|
|
|
|
|
|
|
target.sun_family = AF_UNIX;
|
|
|
|
strcpy(target.sun_path, sock_name);
|
|
|
|
|
|
|
|
packet.magic = MCONSOLE_MAGIC;
|
|
|
|
packet.version = MCONSOLE_VERSION;
|
|
|
|
packet.type = type;
|
|
|
|
len = (len > sizeof(packet.data)) ? sizeof(packet.data) : len;
|
|
|
|
packet.len = len;
|
|
|
|
memcpy(packet.data, data, len);
|
|
|
|
|
|
|
|
err = 0;
|
|
|
|
len = sizeof(packet) + packet.len - sizeof(packet.data);
|
|
|
|
n = sendto(notify_sock, &packet, len, 0, (struct sockaddr *) &target,
|
|
|
|
sizeof(target));
|
|
|
|
if(n < 0){
|
|
|
|
err = -errno;
|
[PATCH] uml: preserve errno in error paths
The poster child for this patch is the third tuntap_user hunk. When an ioctl
fails, it properly closes the opened file descriptor and returns. However,
the close resets errno to 0, and the 'return errno' that follows returns 0
rather than the value that ioctl set. This caused the caller to believe that
the device open succeeded and had opened file descriptor 0, which caused no
end of interesting behavior.
The rest of this patch is a pass through the UML sources looking for places
where errno could be reset before being passed back out. A common culprit is
printk, which could call write, being called before errno is returned.
In some cases, where the code ends up being much smaller, I just deleted the
printk.
There was another case where a caller of run_helper looked at errno after a
failure, rather than the return value of run_helper, which was the errno value
that it wanted.
Signed-off-by: Jeff Dike <jdike@addtoit.com>
Cc: Paolo Giarrusso <blaisorblade@yahoo.it>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2005-09-16 22:27:49 -04:00
|
|
|
printk("mconsole_notify - sendto failed, errno = %d\n", errno);
|
2005-04-16 18:20:36 -04:00
|
|
|
}
|
|
|
|
return(err);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Overrides for Emacs so that we follow Linus's tabbing style.
|
|
|
|
* Emacs will notice this stuff at the end of the file and automatically
|
|
|
|
* adjust the settings for this buffer only. This must remain at the end
|
|
|
|
* of the file.
|
|
|
|
* ---------------------------------------------------------------------------
|
|
|
|
* Local variables:
|
|
|
|
* c-file-style: "linux"
|
|
|
|
* End:
|
|
|
|
*/
|