mirror of
https://github.com/radareorg/radare2.git
synced 2024-12-13 16:18:33 +00:00
c7cced5c67
* Fix startup segfault in r_reg doublefree
157 lines
3.7 KiB
C
157 lines
3.7 KiB
C
/* radare - LGPL - Copyright 2010-2011 pancake<nopcode.org> */
|
|
|
|
#include <r_userconf.h>
|
|
|
|
#include <r_io.h>
|
|
#include <r_lib.h>
|
|
#include <r_cons.h>
|
|
|
|
// XXX: maybe it works on other OS
|
|
#if __linux__
|
|
|
|
#include <sys/ptrace.h>
|
|
#include <sys/types.h>
|
|
#include <sys/wait.h>
|
|
#include <errno.h>
|
|
|
|
//static int fd;
|
|
//static int pid;
|
|
|
|
typedef struct {
|
|
int fd;
|
|
int pid;
|
|
} RIOProcpid;
|
|
|
|
#define RIOPROCPID_PID(x) (((RIOProcpid*)x->data)->pid)
|
|
#define RIOPROCPID_FD(x) (((RIOProcpid*)x->data)->fd)
|
|
|
|
static int __waitpid(int pid) {
|
|
int st = 0;
|
|
return (waitpid(pid, &st, 0) != -1);
|
|
}
|
|
|
|
static int debug_os_read_at(int fdn, void *buf, int sz, ut64 addr) {
|
|
lseek (fdn, addr, 0);
|
|
return read (fdn, buf, sz);
|
|
}
|
|
|
|
static int __read(struct r_io_t *io, RIODesc *fd, ut8 *buf, int len) {
|
|
ut64 addr = io->off;
|
|
memset (buf, '\xff', len); // TODO: only memset the non-readed bytes
|
|
return debug_os_read_at (RIOPROCPID_FD (fd), buf, len, addr);
|
|
}
|
|
|
|
static int procpid_write_at(int fd, const ut8 *buf, int sz, ut64 addr) {
|
|
lseek (fd, addr, 0);
|
|
return write (fd, buf, sz);
|
|
}
|
|
|
|
static int __write(struct r_io_t *io, RIODesc *fd, const ut8 *buf, int len) {
|
|
return procpid_write_at (RIOPROCPID_FD (fd), buf, len, io->off);
|
|
}
|
|
|
|
static int __plugin_open(struct r_io_t *io, const char *file) {
|
|
return (!memcmp (file, "procpid://", 10));
|
|
}
|
|
|
|
static RIODesc *__open(struct r_io_t *io, const char *file, int rw, int mode) {
|
|
char procpidpath[64];
|
|
int fd, ret = -1;
|
|
if (__plugin_open (io, file)) {
|
|
int pid = atoi (file+10);
|
|
if (file[0]=='a') {
|
|
ret = ptrace (PTRACE_ATTACH, pid, 0, 0);
|
|
if (ret == -1) {
|
|
switch (errno) {
|
|
case EPERM:
|
|
ret = pid;
|
|
eprintf ("Operation not permitted\n");
|
|
break;
|
|
case EINVAL:
|
|
perror ("ptrace: Cannot attach");
|
|
eprintf ("ERRNO: %d (EINVAL)\n", errno);
|
|
break;
|
|
}
|
|
} else
|
|
if (__waitpid(pid))
|
|
ret = pid;
|
|
else eprintf ("Error in waitpid\n");
|
|
} else ret = pid;
|
|
fd = ret;//TODO: use r_io_fd api
|
|
snprintf (procpidpath, sizeof (procpidpath), "/proc/%d/mem", pid);
|
|
fd = open (procpidpath, O_RDWR);
|
|
if (fd != -1) {
|
|
RIOProcpid *riop = R_NEW (RIOProcpid);
|
|
riop->pid = pid;
|
|
riop->fd = fd;
|
|
return r_io_desc_new (&r_io_plugin_procpid, -1, file, R_TRUE, 0, riop);
|
|
}
|
|
/* kill children */
|
|
eprintf ("Cannot open /proc/%d/mem of already attached process\n", pid);
|
|
ptrace (PTRACE_DETACH, pid, 0, 0);
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
static ut64 __lseek(struct r_io_t *io, RIODesc *fd, ut64 offset, int whence) {
|
|
return offset;
|
|
}
|
|
|
|
static int __close(RIODesc *fd) {
|
|
int ret = ptrace (PTRACE_DETACH, RIOPROCPID_PID (fd), 0, 0);
|
|
free (fd->data);
|
|
fd->data = NULL;
|
|
return ret;
|
|
}
|
|
|
|
static int __system(struct r_io_t *io, RIODesc *fd, const char *cmd) {
|
|
RIOProcpid *iop = (RIOProcpid*)fd->data;
|
|
//printf("ptrace io command (%s)\n", cmd);
|
|
/* XXX ugly hack for testing purposes */
|
|
if (!strcmp (cmd, "pid")) {
|
|
int pid = atoi (cmd+4);
|
|
if (pid != 0)
|
|
iop->pid = pid;
|
|
io->printf ("%d\n", iop->pid);
|
|
return 0;
|
|
} else eprintf ("Try: '=!pid'\n");
|
|
return R_TRUE;
|
|
}
|
|
|
|
static int __init(struct r_io_t *io) {
|
|
return R_TRUE;
|
|
}
|
|
|
|
// TODO: rename ptrace to io_ptrace .. err io.ptrace ??
|
|
struct r_io_plugin_t r_io_plugin_procpid = {
|
|
//void *plugin;
|
|
.name = "procpid",
|
|
.desc = "proc/pid/mem io",
|
|
.open = __open,
|
|
.close = __close,
|
|
.read = __read,
|
|
.plugin_open = __plugin_open,
|
|
.lseek = __lseek,
|
|
.system = __system,
|
|
.init = __init,
|
|
.write = __write,
|
|
//void *widget;
|
|
/*
|
|
struct debug_t *debug;
|
|
ut32 (*write)(int fd, const ut8 *buf, ut32 count);
|
|
int fds[R_IO_NFDS];
|
|
*/
|
|
};
|
|
#else
|
|
struct r_io_plugin_t r_io_plugin_procpid = {
|
|
.name = NULL
|
|
};
|
|
#endif
|
|
|
|
#ifndef CORELIB
|
|
struct r_lib_struct_t radare_plugin = {
|
|
.type = R_LIB_TYPE_IO,
|
|
.data = &r_io_plugin_procpid
|
|
};
|
|
#endif
|