ptrace: POKEDATA, permission fixes for PEEKDATA
This commit is contained in:
parent
5825bf0c9e
commit
c8a37456ec
17
apps/dbg.c
17
apps/dbg.c
@ -403,6 +403,23 @@ static void show_commandline(pid_t pid, int status, struct regs * regs) {
|
||||
if (signum == SIGINT) signum = 0;
|
||||
ptrace(PTRACE_CONT, pid, NULL, (void*)(uintptr_t)signum);
|
||||
return;
|
||||
} else if (!strcmp(buf, "poke")) {
|
||||
char * addr = arg;
|
||||
char * data = strstr(addr, " ");
|
||||
if (!data) {
|
||||
fprintf(stderr, "usage: poke addr byte\n");
|
||||
continue;
|
||||
}
|
||||
*data = '\0'; data++;
|
||||
|
||||
uintptr_t addr_ = strtoul(addr, NULL, 0);
|
||||
uintptr_t data_ = strtoul(data, NULL, 0);
|
||||
|
||||
if (ptrace(PTRACE_POKEDATA, pid, (void*)addr_, (void*)&data_) != 0) {
|
||||
fprintf(stderr, "poke: %s\n", strerror(errno));
|
||||
continue;
|
||||
}
|
||||
|
||||
} else if (!strcmp(buf, "print") || !strcmp(buf,"p")) {
|
||||
char * fmt = arg;
|
||||
char * sp = strstr(arg, " ");
|
||||
|
@ -12,7 +12,8 @@ enum __ptrace_request {
|
||||
PTRACE_TRACEME,
|
||||
PTRACE_GETREGS,
|
||||
PTRACE_PEEKDATA,
|
||||
PTRACE_SIGNALS_ONLY_PLZ
|
||||
PTRACE_SIGNALS_ONLY_PLZ,
|
||||
PTRACE_POKEDATA
|
||||
};
|
||||
|
||||
enum __ptrace_event {
|
||||
|
@ -194,6 +194,43 @@ void * mmu_map_from_physical(uintptr_t frameaddress) {
|
||||
return (void*)(frameaddress | HIGH_MAP_REGION);
|
||||
}
|
||||
|
||||
union PML * mmu_get_page_other(union PML * root, uintptr_t virtAddr) {
|
||||
uintptr_t realBits = virtAddr & CANONICAL_MASK;
|
||||
uintptr_t pageAddr = realBits >> PAGE_SHIFT;
|
||||
unsigned int pml4_entry = (pageAddr >> 27) & ENTRY_MASK;
|
||||
unsigned int pdp_entry = (pageAddr >> 18) & ENTRY_MASK;
|
||||
unsigned int pd_entry = (pageAddr >> 9) & ENTRY_MASK;
|
||||
unsigned int pt_entry = (pageAddr) & ENTRY_MASK;
|
||||
|
||||
/* Get the PML4 entry for this address */
|
||||
if (!root[pml4_entry].bits.present) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
union PML * pdp = mmu_map_from_physical((uintptr_t)root[pml4_entry].bits.page << PAGE_SHIFT);
|
||||
|
||||
if (!pdp[pdp_entry].bits.present) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (pdp[pdp_entry].bits.size) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
union PML * pd = mmu_map_from_physical((uintptr_t)pdp[pdp_entry].bits.page << PAGE_SHIFT);
|
||||
|
||||
if (!pd[pd_entry].bits.present) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (pd[pd_entry].bits.size) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
union PML * pt = mmu_map_from_physical((uintptr_t)pd[pd_entry].bits.page << PAGE_SHIFT);
|
||||
return (union PML *)&pt[pt_entry];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Find the physical address at a given virtual address.
|
||||
*
|
||||
|
@ -75,14 +75,17 @@ long ptrace_getregs(pid_t pid, void * data) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern union PML * mmu_get_page_other(union PML * root, uintptr_t virtAddr);
|
||||
long ptrace_peek(pid_t pid, void * addr, void * data) {
|
||||
if (!data || ptr_validate(data, "ptrace")) return -EFAULT;
|
||||
process_t * tracee = process_from_pid(pid);
|
||||
if (!tracee || (tracee->tracer != this_core->current_process->id) || !(tracee->flags & PROC_FLAG_SUSPENDED)) return -ESRCH;
|
||||
|
||||
/* Figure out where *addr is...
|
||||
* TODO: We don't ever really page things to disk, and we don't have file
|
||||
* mappings that may be not-present, so this is fairly straightforward for now... */
|
||||
union PML * page_entry = mmu_get_page_other(tracee->thread.page_directory->directory, (uintptr_t)addr);
|
||||
|
||||
if (!page_entry) return -EFAULT;
|
||||
if (!page_entry->bits.present || !page_entry->bits.user) return -EFAULT;
|
||||
|
||||
uintptr_t mapped_address = mmu_map_to_physical(tracee->thread.page_directory->directory, (uintptr_t)addr);
|
||||
|
||||
if ((intptr_t)mapped_address < 0 && (intptr_t)mapped_address > -10) return -EFAULT;
|
||||
@ -95,6 +98,28 @@ long ptrace_peek(pid_t pid, void * addr, void * data) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
long ptrace_poke(pid_t pid, void * addr, void * data) {
|
||||
if (!data || ptr_validate(data, "ptrace")) return -EFAULT;
|
||||
process_t * tracee = process_from_pid(pid);
|
||||
if (!tracee || (tracee->tracer != this_core->current_process->id) || !(tracee->flags & PROC_FLAG_SUSPENDED)) return -ESRCH;
|
||||
|
||||
union PML * page_entry = mmu_get_page_other(tracee->thread.page_directory->directory, (uintptr_t)addr);
|
||||
|
||||
if (!page_entry) return -EFAULT;
|
||||
if (!page_entry->bits.present || !page_entry->bits.user || !page_entry->bits.writable) return -EFAULT;
|
||||
|
||||
uintptr_t mapped_address = mmu_map_to_physical(tracee->thread.page_directory->directory, (uintptr_t)addr);
|
||||
|
||||
if ((intptr_t)mapped_address < 0 && (intptr_t)mapped_address > -10) return -EFAULT;
|
||||
|
||||
uintptr_t blarg = (uintptr_t)mmu_map_from_physical(mapped_address);
|
||||
|
||||
/* Yeah, uh, one byte. That works. */
|
||||
*(char*)blarg = *(char*)data;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
long ptrace_signals_only(pid_t pid) {
|
||||
process_t * tracee = process_from_pid(pid);
|
||||
if (!tracee || (tracee->tracer != this_core->current_process->id) || !(tracee->flags & PROC_FLAG_SUSPENDED)) return -ESRCH;
|
||||
@ -102,7 +127,6 @@ long ptrace_signals_only(pid_t pid) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
long ptrace_handle(long request, pid_t pid, void * addr, void * data) {
|
||||
switch (request) {
|
||||
case PTRACE_ATTACH:
|
||||
@ -115,6 +139,8 @@ long ptrace_handle(long request, pid_t pid, void * addr, void * data) {
|
||||
return ptrace_continue(pid,(uintptr_t)data);
|
||||
case PTRACE_PEEKDATA:
|
||||
return ptrace_peek(pid,addr,data);
|
||||
case PTRACE_POKEDATA:
|
||||
return ptrace_poke(pid,addr,data);
|
||||
case PTRACE_SIGNALS_ONLY_PLZ:
|
||||
return ptrace_signals_only(pid);
|
||||
default:
|
||||
|
Loading…
Reference in New Issue
Block a user