mirror of
https://github.com/radareorg/radare2.git
synced 2024-12-15 09:21:00 +00:00
xnu: change logic handle exception
instead of a thread waiting for incoming messages, i've implemented wait functionality above mach_msg, now i have to make it work with r2 and avoid while (1) in the code, understand better the references and start thinking about edge cases
This commit is contained in:
parent
29d8456013
commit
feea7f4d17
@ -271,9 +271,9 @@ static int r_debug_native_wait (RDebug *dbg, int pid) {
|
||||
if (pid == -1) {
|
||||
status = R_DEBUG_REASON_UNKNOWN;
|
||||
} else {
|
||||
#if __APPLE__ && (__arm__ || __arm64__ || __aarch64__)
|
||||
#if __APPLE__
|
||||
// eprintf ("No waitpid here :D\n");
|
||||
status = R_DEBUG_REASON_UNKNOWN;
|
||||
status = xnu_wait (dbg, pid);
|
||||
#else
|
||||
// XXX: this is blocking, ^C will be ignored
|
||||
int ret = waitpid (pid, &status, 0);
|
||||
|
@ -18,7 +18,7 @@
|
||||
#include <mach/mach_host.h>
|
||||
#include <mach/host_priv.h>
|
||||
|
||||
static task_t task_dbg = -1;
|
||||
static task_t task_dbg = 0;
|
||||
#include "xnu_debug.h"
|
||||
#include "xnu_threads.c"
|
||||
#if XNU_USE_EXCTHR
|
||||
@ -107,6 +107,10 @@ static task_t task_for_pid_workaround(int Pid) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int xnu_wait(RDebug *dbg, int pid) {
|
||||
return __xnu_wait (dbg, pid);
|
||||
}
|
||||
|
||||
bool xnu_step(RDebug *dbg) {
|
||||
#if XNU_USE_PTRACE
|
||||
int ret = ptrace (PT_STEP, dbg->pid, (caddr_t)1, 0) == 0; //SIGINT
|
||||
@ -151,14 +155,6 @@ int xnu_attach(RDebug *dbg, int pid) {
|
||||
eprintf ("error setting up exception thread\n");
|
||||
return -1;
|
||||
}
|
||||
//task_suspend (pid_to_task (pid));
|
||||
#if 0
|
||||
if (ptrace (PT_ATTACHEXC, pid, 0, 0) == -1) {
|
||||
perror ("ptrace (PT_ATTACHEXC)");
|
||||
return -1;
|
||||
}
|
||||
usleep(250000);
|
||||
#endif
|
||||
return pid;
|
||||
#endif
|
||||
}
|
||||
@ -177,7 +173,7 @@ int xnu_detach(RDebug *dbg, int pid) {
|
||||
__FILE__, __LINE__);
|
||||
}
|
||||
//we mark the task as not longer available since we deallocated the ref
|
||||
task_dbg = -2;
|
||||
task_dbg = 0;
|
||||
r_list_free (dbg->threads);
|
||||
#endif
|
||||
}
|
||||
@ -192,6 +188,7 @@ int xnu_continue(RDebug *dbg, int pid, int tid, int sig) {
|
||||
task_t task = pid_to_task (pid);
|
||||
if (!task)
|
||||
return false;
|
||||
//TODO free refs count threads
|
||||
xnu_thread_t *th = get_xnu_thread (dbg, getcurthread (dbg));
|
||||
if (!th) {
|
||||
eprintf ("failed to get thread in xnu_continue\n");
|
||||
@ -394,15 +391,23 @@ int xnu_map_protect (RDebug *dbg, ut64 addr, int size, int perms) {
|
||||
|
||||
task_t pid_to_task (int pid) {
|
||||
static int old_pid = -1;
|
||||
kern_return_t kr;
|
||||
task_t task = -1;
|
||||
int err;
|
||||
|
||||
/* it means that we are done with the task*/
|
||||
if (task_dbg == -2)
|
||||
return 0;
|
||||
if (task_dbg != -1 && old_pid == pid)
|
||||
if (task_dbg != 0 && old_pid == pid) {
|
||||
return task_dbg;
|
||||
} else if (task_dbg != 0 && old_pid != pid) {
|
||||
//we changed the process pid so deallocate a ref from the old_task
|
||||
//since we are going to get a new task
|
||||
kr = mach_port_deallocate (mach_task_self (), task_dbg);
|
||||
if (kr != KERN_SUCCESS) {
|
||||
eprintf ("fail to deallocate port %s:%d\n", __FILE__, __LINE__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
err = task_for_pid (mach_task_self (), (pid_t)pid, &task);
|
||||
if ((err != KERN_SUCCESS) || !MACH_PORT_VALID (task)) {
|
||||
task = task_for_pid_workaround (pid);
|
||||
|
@ -228,9 +228,11 @@ static bool xnu_restore_exception_ports (int pid) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//TODO review more closely we are failing here
|
||||
static void encode_reply(mig_reply_error_t *reply, mach_msg_header_t *hdr, int code) {
|
||||
mach_msg_header_t *rh = &reply->Head;
|
||||
rh->msgh_bits = MACH_MSGH_BITS (MACH_MSGH_BITS_REMOTE (hdr->msgh_bits), 0);
|
||||
rh->msgh_bits = MACH_MSGH_BITS (MACH_MSGH_BITS_REMOTE(hdr->msgh_bits), 0);
|
||||
rh->msgh_remote_port = hdr->msgh_remote_port;
|
||||
rh->msgh_size = (mach_msg_size_t) sizeof (mig_reply_error_t);
|
||||
rh->msgh_local_port = MACH_PORT_NULL;
|
||||
@ -266,7 +268,7 @@ static void decode_exception_type(int exception) {
|
||||
|
||||
}
|
||||
static bool validate_mach_message (RDebug *dbg, exc_msg *msg) {
|
||||
kern_return_t kret;
|
||||
kern_return_t kr;
|
||||
/*check if the message is for us*/
|
||||
if (msg->hdr.msgh_local_port != ex.exception_port)
|
||||
return false;
|
||||
@ -290,8 +292,8 @@ static bool validate_mach_message (RDebug *dbg, exc_msg *msg) {
|
||||
msg->NDR.float_rep != NDR_record.float_rep)
|
||||
return false;
|
||||
/*we got new rights to the task, get rid of it.*/
|
||||
kret = mach_port_deallocate (mach_task_self (), msg->task.name);
|
||||
if (kret != KERN_SUCCESS) {
|
||||
kr = mach_port_deallocate (mach_task_self (), msg->task.name);
|
||||
if (kr != KERN_SUCCESS) {
|
||||
eprintf ("failed to deallocate task port %s-%d\n",
|
||||
__FILE__, __LINE__);
|
||||
}
|
||||
@ -299,8 +301,8 @@ static bool validate_mach_message (RDebug *dbg, exc_msg *msg) {
|
||||
//we receive a exception from an unknown process this could
|
||||
//happen if the child fork, as the created process will inherit
|
||||
//its exception port
|
||||
kret = mach_port_deallocate (mach_task_self (), msg->thread.name);
|
||||
if (kret != KERN_SUCCESS) {
|
||||
kr = mach_port_deallocate (mach_task_self (), msg->thread.name);
|
||||
if (kr != KERN_SUCCESS) {
|
||||
eprintf ("failed to deallocated task port %s-%d\n",
|
||||
__FILE__, __LINE__);
|
||||
}
|
||||
@ -309,61 +311,97 @@ static bool validate_mach_message (RDebug *dbg, exc_msg *msg) {
|
||||
return true;
|
||||
}
|
||||
static bool handle_exception_message (RDebug *dbg, exc_msg *msg) {
|
||||
kern_return_t kret;
|
||||
decode_exception_type (msg->exception);
|
||||
kret = mach_port_deallocate (mach_task_self (), msg->thread.name);
|
||||
if (kret != KERN_SUCCESS) {
|
||||
kern_return_t kr;
|
||||
int ret = R_DEBUG_REASON_UNKNOWN;
|
||||
switch (msg->exception) {
|
||||
case EXC_BAD_ACCESS:
|
||||
eprintf ("EXC_BAD_ACCESS\n");
|
||||
break;
|
||||
case EXC_BAD_INSTRUCTION:
|
||||
eprintf ("EXC_BAD_INSTRUCTION\n");
|
||||
break;
|
||||
case EXC_ARITHMETIC:
|
||||
eprintf ("EXC_ARITHMETIC\n");
|
||||
break;
|
||||
case EXC_EMULATION:
|
||||
eprintf ("EXC_EMULATION\n");
|
||||
break;
|
||||
case EXC_SOFTWARE:
|
||||
eprintf ("EXC_SOFTWARE\n");
|
||||
break;
|
||||
case EXC_BREAKPOINT:
|
||||
ret = R_DEBUG_REASON_BREAKPOINT;
|
||||
eprintf ("EXC_BREAKPOINT\n");
|
||||
break;
|
||||
default:
|
||||
eprintf ("UNKNOWN\n");
|
||||
break;
|
||||
}
|
||||
|
||||
kr = mach_port_deallocate (mach_task_self (), msg->thread.name);
|
||||
if (kr != KERN_SUCCESS) {
|
||||
eprintf ("failed to deallocated task port %s-%d\n",
|
||||
__FILE__, __LINE__);
|
||||
}
|
||||
return KERN_SUCCESS;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void *xnu_exception_thread (void *arg) {
|
||||
static int __xnu_wait (RDebug *dbg, int pid) {
|
||||
// here comes the important thing
|
||||
RDebug *dbg;
|
||||
kern_return_t kret;
|
||||
kern_return_t kr;
|
||||
int reason = R_DEBUG_REASON_UNKNOWN;
|
||||
mig_reply_error_t reply;
|
||||
bool ret;
|
||||
exc_msg msg;
|
||||
if (!arg)
|
||||
if (!dbg)
|
||||
return NULL;
|
||||
dbg = (RDebug *)arg;
|
||||
for (;;) {
|
||||
//wait for a incoming messages
|
||||
//XXX what to do on failure; do we continue processing or stop ?
|
||||
//XXX some layer for error handling and review ports leak
|
||||
kret = mach_msg (&msg.hdr, MACH_RCV_MSG | MACH_RCV_INTERRUPT, 0,
|
||||
sizeof (exc_msg), ex.exception_port, 0,
|
||||
MACH_PORT_NULL);
|
||||
if (kret != KERN_SUCCESS) {
|
||||
eprintf ("fail to retrieve message exception thread\n");
|
||||
kr = mach_msg (
|
||||
&msg.hdr,
|
||||
MACH_RCV_MSG | MACH_RCV_INTERRUPT, 0,
|
||||
sizeof (exc_msg), ex.exception_port, 1, MACH_PORT_NULL);
|
||||
if (kr == MACH_RCV_INTERRUPTED ) {
|
||||
eprintf ("message interrupted\n");
|
||||
break;
|
||||
}
|
||||
if (kr == MACH_RCV_TIMED_OUT) {
|
||||
eprintf ("message timed out\n");
|
||||
break;
|
||||
}
|
||||
if (kr == MACH_MSG_SUCCESS) {
|
||||
eprintf ("message interrupted\n");
|
||||
break;
|
||||
}
|
||||
|
||||
eprintf ("Received exception\n");
|
||||
ret = validate_mach_message (dbg, &msg);
|
||||
if (!ret || msg.hdr.msgh_id != 2405 || msg.hdr.msgh_id != 2401) {
|
||||
if (!ret && (msg.hdr.msgh_id != 2405 || msg.hdr.msgh_id != 2401)) {
|
||||
encode_reply (&reply, &msg.hdr, KERN_FAILURE);
|
||||
kret = mach_msg (&reply.Head, MACH_SEND_MSG | MACH_SEND_INTERRUPT,
|
||||
kr = mach_msg (&reply.Head, MACH_SEND_MSG | MACH_SEND_INTERRUPT,
|
||||
reply.Head.msgh_size, 0,
|
||||
MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE,
|
||||
MACH_PORT_NULL);
|
||||
if (kret != KERN_SUCCESS)
|
||||
eprintf ("failed to reply mach_msg %s-%d\n", __FILE__, __LINE__);
|
||||
if (kr != KERN_SUCCESS)
|
||||
eprintf ("failed to reply mach_msg %s:%d\n", __FILE__, __LINE__);
|
||||
continue;
|
||||
}
|
||||
|
||||
kret = handle_exception_message (dbg, &msg);
|
||||
if (kret == KERN_FAILURE)
|
||||
eprintf ("failed to handle exception");
|
||||
encode_reply (&reply, &msg.hdr, kret);
|
||||
kret = mach_msg (&reply.Head, MACH_SEND_MSG | MACH_SEND_INTERRUPT,
|
||||
reply.Head.msgh_size, 0,
|
||||
MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE,
|
||||
MACH_PORT_NULL);
|
||||
if (kret != KERN_SUCCESS)
|
||||
eprintf ("failed to reply mach_msg %s-%d\n", __FILE__, __LINE__);
|
||||
reason = handle_exception_message (dbg, &msg);
|
||||
if (reason == R_DEBUG_REASON_BREAKPOINT) {
|
||||
encode_reply (&reply, &msg.hdr, KERN_SUCCESS);
|
||||
kr = mach_msg (&reply.Head, MACH_SEND_MSG | MACH_SEND_INTERRUPT,
|
||||
reply.Head.msgh_size, 0,
|
||||
MACH_PORT_NULL, 0,
|
||||
MACH_PORT_NULL);
|
||||
eprintf ("REPLIED\n");
|
||||
if (kr != MACH_MSG_SUCCESS)
|
||||
eprintf ("failed to reply mach_msg %s:%d\n", __FILE__, __LINE__);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@ -404,12 +442,14 @@ bool xnu_create_exception_thread(RDebug *dbg) {
|
||||
EXCEPTION_DEFAULT | MACH_EXCEPTION_CODES,
|
||||
THREAD_STATE_NONE);
|
||||
RETURN_ON_MACH_ERROR ("error to set port to receive exceptions\n", R_FALSE);
|
||||
#if 0
|
||||
// Create the exception thread
|
||||
ret = pthread_create (&ex.thread, NULL, &xnu_exception_thread, dbg);
|
||||
if (ret) {
|
||||
perror ("pthread_create");
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
ex.exception_port = exception_port;
|
||||
return true;
|
||||
}
|
||||
|
@ -115,6 +115,7 @@ static task_t pid_to_task(int pid) {
|
||||
}
|
||||
}
|
||||
old_task = task;
|
||||
old_pid = pid;
|
||||
return task;
|
||||
}
|
||||
|
||||
@ -186,7 +187,7 @@ static int __read(RIO *io, RIODesc *fd, ut8 *buf, int len) {
|
||||
}
|
||||
|
||||
copied = getNextValid(io, fd, io->off) - io->off;
|
||||
if (copied<0) copied = 0;
|
||||
if (copied < 0) copied = 0;
|
||||
|
||||
while (copied < len) {
|
||||
blen = R_MIN ((len - copied), blocksize);
|
||||
@ -225,95 +226,111 @@ static int __read(RIO *io, RIODesc *fd, ut8 *buf, int len) {
|
||||
return len;
|
||||
}
|
||||
|
||||
static vm_address_t tsk_getpagebase(ut64 addr) {
|
||||
vm_address_t a = addr;
|
||||
a >>= 12;
|
||||
a <<= 12;
|
||||
return a;
|
||||
|
||||
static int tsk_getperm(RIO *io, task_t task, vm_address_t addr) {
|
||||
kern_return_t kr;
|
||||
mach_port_t object;
|
||||
int prot;
|
||||
|
||||
if (io->bits == 32) {
|
||||
vm_region_flavor_t flavor = VM_REGION_BASIC_INFO;
|
||||
mach_msg_type_number_t info_count = VM_REGION_BASIC_INFO_COUNT;
|
||||
vm_region_basic_info_data_t info;
|
||||
mach_vm_size_t vmsize;
|
||||
kr = mach_vm_region (task, &addr, &vmsize, flavor, (vm_region_info_t)&info, &info_count, &object);
|
||||
return (kr != KERN_SUCCESS ? 0 : info.protection);
|
||||
} else {
|
||||
mach_msg_type_number_t info_count = VM_REGION_BASIC_INFO_COUNT_64;
|
||||
vm_region_flavor_t flavor = VM_REGION_BASIC_INFO_64;
|
||||
vm_region_basic_info_data_64_t info;
|
||||
vm_size_t vmsize;
|
||||
kr = vm_region_64 (task, &addr, &vmsize, flavor, (vm_region_info_t)&info, &info_count, &object);
|
||||
return (kr != KERN_SUCCESS ? 0 : info.protection);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static int tsk_getperm(task_t task, vm_address_t addr) {
|
||||
vm_size_t pagesize = 1;
|
||||
int _basic64[VM_REGION_BASIC_INFO_COUNT_64];
|
||||
vm_region_basic_info_64_t basic64 = (vm_region_basic_info_64_t)_basic64;
|
||||
mach_msg_type_number_t infocnt = VM_REGION_BASIC_INFO_COUNT_64;
|
||||
mach_port_t objname;
|
||||
kern_return_t rc;
|
||||
|
||||
rc = vm_region_64 (task, &addr, &pagesize, VM_REGION_BASIC_INFO,
|
||||
(vm_region_info_t)basic64, &infocnt, &objname);
|
||||
if (rc == KERN_SUCCESS) {
|
||||
return basic64[0].protection;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tsk_pagesize(RIO *io, int len) {
|
||||
#if __arm__ || __arm64__ || __aarch64__
|
||||
int is_arm64 = (io && io->bits == 64);
|
||||
int pagesize = is_arm64? 16384: 4096;
|
||||
#else
|
||||
int pagesize = getpagesize();
|
||||
#endif
|
||||
if (pagesize<1) pagesize = 4096;
|
||||
if (len > pagesize) {
|
||||
pagesize *= (1 + (len / pagesize));
|
||||
}
|
||||
static int tsk_pagesize(RIOMach *riom) {
|
||||
//cache the pagesize
|
||||
static ut64 pagesize = 0;
|
||||
kern_return_t kr;
|
||||
task_vm_info_data_t task_vm_info;
|
||||
mach_msg_type_number_t count = TASK_VM_INFO_COUNT;
|
||||
if (pagesize)
|
||||
return pagesize;
|
||||
kr = task_info (riom->task, TASK_VM_INFO, (task_info_t)&task_vm_info, &count);
|
||||
if (kr != KERN_SUCCESS)
|
||||
perror ("task_info");
|
||||
pagesize = task_vm_info.page_size;
|
||||
return pagesize;
|
||||
}
|
||||
|
||||
static vm_address_t tsk_getpagebase(RIOMach *riom, ut64 addr) {
|
||||
vm_address_t pagesize = tsk_pagesize (riom);
|
||||
return (addr & ~(pagesize - 1));
|
||||
}
|
||||
|
||||
|
||||
static bool tsk_setperm(RIO *io, task_t task, vm_address_t addr, int len, int perm) {
|
||||
mach_msg_type_number_t info_count = VM_REGION_BASIC_INFO_COUNT;
|
||||
vm_region_flavor_t flavor = VM_REGION_BASIC_INFO;
|
||||
vm_address_t region = (vm_address_t)addr;
|
||||
vm_region_basic_info_data_t info;
|
||||
vm_size_t region_size = tsk_pagesize(io, len);
|
||||
#if 1
|
||||
task_t t;
|
||||
vm_region_64 (task, ®ion, ®ion_size, flavor, (vm_region_info_t)&info,
|
||||
(mach_msg_type_number_t*)&info_count, (mach_port_t*)&t);
|
||||
#endif
|
||||
return vm_protect (task, region, region_size, FALSE, perm) == KERN_SUCCESS;
|
||||
kern_return_t kr;
|
||||
kr = vm_protect (task, addr, len, 0, perm);
|
||||
if (kr != KERN_SUCCESS) {
|
||||
eprintf ("failed to change perm %s:%d\n", __FILE__, __LINE__);
|
||||
perror ("tsk_setperm");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool tsk_write(task_t task, vm_address_t addr, const ut8 *buf, int len) {
|
||||
kern_return_t kr;
|
||||
mach_msg_type_number_t _len = len;
|
||||
vm_offset_t _buf = (vm_offset_t)buf;
|
||||
return vm_write (task, addr, _buf, _len) == KERN_SUCCESS;
|
||||
unsigned int count = 0;
|
||||
kr = mach_port_get_refs (mach_task_self(), task, MACH_PORT_RIGHT_SEND, &count);
|
||||
if (kr != KERN_SUCCESS)
|
||||
perror ("get refs");
|
||||
eprintf ("refs = %d\n", count);
|
||||
kr = vm_write (task, addr, _buf, _len);
|
||||
if (kr != KERN_SUCCESS)
|
||||
//the memory is not mapped
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static int mach_write_at(RIO *io, RIOMach *riom, const void *buf, int len, ut64 addr) {
|
||||
vm_address_t vaddr = addr;
|
||||
vm_address_t pageaddr;
|
||||
vm_size_t pagesize;
|
||||
vm_size_t total_size;
|
||||
int operms = 0;
|
||||
task_t task;
|
||||
|
||||
if (!riom || len <1) {
|
||||
if (!riom || len < 1) {
|
||||
return 0;
|
||||
}
|
||||
task = riom->task;
|
||||
pageaddr = tsk_getpagebase (riom, addr);
|
||||
pagesize = tsk_pagesize (riom);
|
||||
if (len > pagesize)
|
||||
total_size = pagesize * (1 + (len / pagesize));
|
||||
else
|
||||
total_size = pagesize;
|
||||
|
||||
pageaddr = tsk_getpagebase (addr);
|
||||
pagesize = tsk_pagesize (io, len);
|
||||
|
||||
if (tsk_write (task, vaddr, buf, len)) {
|
||||
if (tsk_write (task, vaddr, buf, len))
|
||||
return len;
|
||||
}
|
||||
operms = tsk_getperm (task, pageaddr);
|
||||
if (!tsk_setperm (io, task, pageaddr, pagesize, VM_PROT_READ | VM_PROT_WRITE | VM_PROT_COPY)) {
|
||||
perror ("setperm");
|
||||
operms = tsk_getperm (io, task, pageaddr);
|
||||
if (!tsk_setperm (io, task, pageaddr, total_size, VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE)) {
|
||||
eprintf ("io.mach: Cannot set page perms for %d bytes at 0x%08"
|
||||
PFMT64x"\n", (int)pagesize, (ut64)pageaddr);
|
||||
//return -1;
|
||||
return -1;
|
||||
}
|
||||
if (!tsk_write (task, vaddr, buf, len)) {
|
||||
perror ("write");
|
||||
eprintf ("io.mach: Cannot write on memory\n");
|
||||
len = -1;
|
||||
}
|
||||
if (operms) {
|
||||
if (!tsk_setperm (io, task, pageaddr, pagesize, operms)) {
|
||||
if (!tsk_setperm (io, task, pageaddr, total_size, operms)) {
|
||||
eprintf ("io.mach: Cannot restore page perms\n");
|
||||
return -1;
|
||||
}
|
||||
@ -377,13 +394,12 @@ static RIODesc *__open(RIO *io, const char *file, int rw, int mode) {
|
||||
riom->pid = pid;
|
||||
riom->task = task;
|
||||
// sleep 1s to get proper path (program name instead of ls) (racy)
|
||||
if (pid == 0) {
|
||||
if (!pid)
|
||||
pidpath = strdup ("kernel");
|
||||
} else {
|
||||
else
|
||||
pidpath = r_sys_pid_to_path (pid);
|
||||
}
|
||||
ret = r_io_desc_new (&r_io_plugin_mach, riom->pid,
|
||||
pidpath, rw | R_IO_EXEC, mode, riom);
|
||||
pidpath, rw | R_IO_EXEC, mode, riom);
|
||||
free (pidpath);
|
||||
return ret;
|
||||
}
|
||||
@ -404,19 +420,22 @@ static ut64 __lseek(RIO *io, RIODesc *fd, ut64 offset, int whence) {
|
||||
}
|
||||
|
||||
static int __close(RIODesc *fd) {
|
||||
int pid = RIOMACH_PID (fd->data);
|
||||
RIOMach *riom= (RIOMach*)fd->data;
|
||||
kern_return_t kr;
|
||||
kr = mach_port_deallocate (mach_task_self (), riom->task);
|
||||
if (kr != KERN_SUCCESS)
|
||||
perror ("__close io_mach");
|
||||
R_FREE (fd->data);
|
||||
return ptrace (PT_DETACH, pid, 0, 0);
|
||||
return kr == KERN_SUCCESS;
|
||||
}
|
||||
|
||||
static int __system(RIO *io, RIODesc *fd, const char *cmd) {
|
||||
RIOMach *riom = (RIOMach*)fd->data;
|
||||
//printf("ptrace io command (%s)\n", cmd);
|
||||
/* XXX ugly hack for testing purposes */
|
||||
if (!strncmp (cmd, "perm", 4)) {
|
||||
int perm = r_str_rwx (cmd+4);
|
||||
int perm = r_str_rwx (cmd + 4);
|
||||
if (perm) {
|
||||
int pagesize = tsk_pagesize(io, 1);
|
||||
int pagesize = tsk_pagesize(riom);
|
||||
tsk_setperm (io, riom->task, io->off, pagesize, perm);
|
||||
} else {
|
||||
eprintf ("Usage: =!perm [rwx]\n");
|
||||
@ -447,8 +466,9 @@ static int __system(RIO *io, RIODesc *fd, const char *cmd) {
|
||||
}
|
||||
}
|
||||
eprintf ("io_mach_system: Invalid pid %d\n", pid);
|
||||
} else
|
||||
} else {
|
||||
eprintf ("Try: '=!pid' or '=!perm'\n");
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user