Skip to content

Commit

Permalink
Implement ptrace
Browse files Browse the repository at this point in the history
  • Loading branch information
saagarjha committed Oct 12, 2020
1 parent 91c4ff6 commit 1d16949
Show file tree
Hide file tree
Showing 19 changed files with 483 additions and 20 deletions.
2 changes: 2 additions & 0 deletions emu/decode.h
Original file line number Diff line number Diff line change
Expand Up @@ -696,6 +696,8 @@ __no_instrument DECODER_RET glue(DECODER_NAME, OP_SIZE)(DECODER_ARGS) {
case 0xc9: TRACEI("leave");
MOV(reg_bp, reg_sp,oz); POP(reg_bp,oz); break;

case 0xcc: TRACEI("int3");
INT(INT_BREAKPOINT); break;
case 0xcd: TRACEI("int imm8\t");
READIMM8; INT(imm); break;

Expand Down
8 changes: 6 additions & 2 deletions emu/memory.c
Original file line number Diff line number Diff line change
Expand Up @@ -256,10 +256,14 @@ void *mem_ptr(struct mem *mem, addr_t addr, int type) {
entry = mem_pt(mem, page);
}

if (entry != NULL && type == MEM_WRITE) {
if (entry != NULL && (type == MEM_WRITE || type == MEM_WRITE_PTRACE)) {
// if page is unwritable, well tough luck
if (!(entry->flags & P_WRITE))
if (type != MEM_WRITE_PTRACE && !(entry->flags & P_WRITE))
return NULL;
if (type == MEM_WRITE_PTRACE) {
// TODO: Is P_WRITE really correct? The page shouldn't be writable without ptrace.
entry->flags |= P_WRITE | P_COW;
}
// if page is cow, ~~milk~~ copy it
if (entry->flags & P_COW) {
void *data = (char *) entry->data->data + entry->offset;
Expand Down
2 changes: 2 additions & 0 deletions emu/memory.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#include <stdatomic.h>
#include <unistd.h>
#include <stdbool.h>
#include "util/list.h"
#include "util/sync.h"
#include "misc.h"
Expand Down Expand Up @@ -112,6 +113,7 @@ int pt_copy_on_write(struct mem *src, struct mem *dst, page_t start, page_t page

#define MEM_READ 0
#define MEM_WRITE 1
#define MEM_WRITE_PTRACE 2
// Must call with mem read-locked.
void *mem_ptr(struct mem *mem, addr_t addr, int type);
int mem_segv_reason(struct mem *mem, addr_t addr);
Expand Down
8 changes: 7 additions & 1 deletion iSH.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,9 @@
/* Begin PBXFileReference section */
408A2639236440F8008A4E81 /* iOSFS.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = iOSFS.m; sourceTree = "<group>"; };
408A263B23644102008A4E81 /* iOSFS.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = iOSFS.h; sourceTree = "<group>"; };
49146E272490649A00514457 /* personality.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = personality.h; sourceTree = "<group>"; };
49E2B95224775D3700892BFF /* ptrace.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ptrace.h; sourceTree = "<group>"; };
49E2B95324775D3700892BFF /* ptrace.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = ptrace.c; sourceTree = "<group>"; };
650B335A22E9E46A00B4C03E /* mem.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mem.c; sourceTree = "<group>"; tabWidth = 4; };
650B335B22E9E46A00B4C03E /* mem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mem.h; sourceTree = "<group>"; tabWidth = 4; };
650B335D22E9EF9B00B4C03E /* proc.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = proc.c; sourceTree = "<group>"; };
Expand Down Expand Up @@ -633,9 +636,9 @@
BB7D93422087C2880008DA78 /* exec.c */,
BB7D93432087C2880008DA78 /* exit.c */,
BB7D93442087C2880008DA78 /* fork.c */,
BB7D93472087C2880008DA78 /* fs_info.c */,
BB7D93452087C2880008DA78 /* fs.c */,
BB7D93462087C2880008DA78 /* fs.h */,
BB7D93472087C2880008DA78 /* fs_info.c */,
BB7D93482087C2880008DA78 /* futex.c */,
BB101B5C2364EB88000A93BC /* futex.h */,
BB7D93492087C2880008DA78 /* getset.c */,
Expand All @@ -646,7 +649,10 @@
BB101B632364EB89000A93BC /* misc.c */,
BB101B602364EB88000A93BC /* mm.h */,
BB7D934D2087C2880008DA78 /* mmap.c */,
49146E272490649A00514457 /* personality.h */,
BB7D934E2087C2880008DA78 /* poll.c */,
49E2B95324775D3700892BFF /* ptrace.c */,
49E2B95224775D3700892BFF /* ptrace.h */,
BB101B5E2364EB88000A93BC /* random.c */,
BB101B612364EB88000A93BC /* random.h */,
BB7D934F2087C2880008DA78 /* resource.c */,
Expand Down
17 changes: 17 additions & 0 deletions kernel/calls.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
#include "debug.h"
#include "kernel/calls.h"
#include "emu/interrupt.h"
#include "kernel/signal.h"
#include "kernel/task.h"

dword_t syscall_stub() {
return _ENOSYS;
Expand Down Expand Up @@ -34,6 +36,7 @@ syscall_t syscall_table[] = {
[23] = (syscall_t) sys_setuid,
[24] = (syscall_t) sys_getuid,
[25] = (syscall_t) sys_stime,
[26] = (syscall_t) sys_ptrace,
[27] = (syscall_t) sys_alarm,
[29] = (syscall_t) sys_pause,
[30] = (syscall_t) sys_utime,
Expand Down Expand Up @@ -276,6 +279,20 @@ void handle_interrupt(int interrupt) {
.fault.addr = cpu->eip,
};
deliver_signal(current, SIGILL_, info);
} else if (interrupt == INT_BREAKPOINT) {
lock(&pids_lock);
send_signal(current, SIGTRAP_, (struct siginfo_) {
.sig = SIGTRAP_,
.code = SI_KERNEL_,
});
unlock(&pids_lock);
} else if (interrupt == INT_DEBUG) {
lock(&pids_lock);
send_signal(current, SIGTRAP_, (struct siginfo_) {
.sig = SIGTRAP_,
.code = TRAP_TRACE_,
});
unlock(&pids_lock);
} else if (interrupt != INT_TIMER) {
printk("%d unhandled interrupt %d\n", current->pid, interrupt);
sys_exit(interrupt);
Expand Down
1 change: 1 addition & 0 deletions kernel/calls.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "fs/sock.h"
#include "kernel/time.h"
#include "kernel/resource.h"
#include "kernel/ptrace.h"

void handle_interrupt(int interrupt);

Expand Down
13 changes: 13 additions & 0 deletions kernel/exec.c
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#include "kernel/signal.h"
#include "task.h"
#define _GNU_SOURCE
#include <unistd.h>
#include <fcntl.h>
Expand Down Expand Up @@ -614,6 +616,17 @@ int __do_execve(const char *file, struct exec_args argv, struct exec_args envp)

current->did_exec = true;
vfork_notify(current);

if (current->ptrace.traced) {
lock(&pids_lock);
send_signal(current, SIGTRAP_, (struct siginfo_) {
.code = SI_USER_,
.kill.pid = current->pid,
.kill.uid = current->uid,
});
unlock(&pids_lock);
}

return 0;
}

Expand Down
33 changes: 25 additions & 8 deletions kernel/exit.c
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
#include <pthread.h>
#include <signal.h>
#include <string.h>
#include "kernel/calls.h"
#include "kernel/mm.h"
#include "kernel/futex.h"
#include "kernel/ptrace.h"
#include "fs/fd.h"
#include "fs/tty.h"

Expand Down Expand Up @@ -178,6 +180,7 @@ dword_t sys_exit_group(dword_t status) {
#define WEXITED_ (1 << 2)
#define WCONTINUED_ (1 << 3)
#define WNOWAIT_ (1 << 24)
#define __WALL_ (1 << 30)

#define P_ALL_ 0
#define P_PID_ 1
Expand Down Expand Up @@ -233,17 +236,29 @@ static bool notify_if_stopped(struct task *task, struct siginfo_ *info_out) {

static bool reap_if_needed(struct task *task, struct siginfo_ *info_out, struct rusage_ *rusage_out, int options) {
assert(task_is_leader(task));
if (options & WUNTRACED_ && notify_if_stopped(task, info_out))
if ((options & WUNTRACED_ && notify_if_stopped(task, info_out)) ||
(options & WEXITED_ && reap_if_zombie(task, info_out, rusage_out, options))) {
info_out->sig = SIGCHLD_;
return true;
if (options & WEXITED_ && reap_if_zombie(task, info_out, rusage_out, options))
}
lock(&task->ptrace.lock);
if (task->ptrace.stopped && task->ptrace.signal) {
// I had this code here because it made something work, but it's now
// making GDB think we support events (we don't). I can't remember what
// it fixed but until then commenting it out for now.
info_out->child.status = /* task->ptrace.trap_event << 16 |*/ task->ptrace.signal << 8 | 0x7f;
task->ptrace.signal = 0;
unlock(&task->ptrace.lock);
return true;
}
unlock(&task->ptrace.lock);
return false;
}

int do_wait(int idtype, pid_t_ id, struct siginfo_ *info, struct rusage_ *rusage, int options) {
if (idtype != P_ALL_ && idtype != P_PID_ && idtype != P_PGID_)
return _EINVAL;
if (options & ~(WNOHANG_|WUNTRACED_|WEXITED_|WCONTINUED_|WNOWAIT_))
if (options & ~(WNOHANG_|WUNTRACED_|WEXITED_|WCONTINUED_|WNOWAIT_|__WALL_))
return _EINVAL;

lock(&pids_lock);
Expand All @@ -265,7 +280,7 @@ int do_wait(int idtype, pid_t_ id, struct siginfo_ *info, struct rusage_ *rusage
no_children = false;
info->child.pid = task->pid;
if (reap_if_needed(task, info, rusage, options))
goto found_zombie;
goto found_something;
}
}
err = _ECHILD;
Expand All @@ -280,14 +295,16 @@ int do_wait(int idtype, pid_t_ id, struct siginfo_ *info, struct rusage_ *rusage
task = task->group->leader;
info->child.pid = id;
if (reap_if_needed(task, info, rusage, options))
goto found_zombie;
goto found_something;
}

// WNOHANG leaves the info in an implementation-defined state. set the pid
// to 0 so wait4 can pass that along correctly.
info->child.pid = 0;
if (options & WNOHANG_)
goto found_zombie;
if (options & WNOHANG_) {
info->sig = SIGCHLD_;
goto found_something;
}

err = _EINTR;
if (got_signal)
Expand All @@ -302,8 +319,8 @@ int do_wait(int idtype, pid_t_ id, struct siginfo_ *info, struct rusage_ *rusage
}
goto retry;

found_zombie:
info->sig = SIGCHLD_;
found_something:
unlock(&pids_lock);
return 0;

Expand Down
8 changes: 8 additions & 0 deletions kernel/fork.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "kernel/calls.h"
#include "fs/tty.h"
#include "kernel/mm.h"
#include "kernel/ptrace.h"

#define CSIGNAL_ 0x000000ff
#define CLONE_VM_ 0x00000100
Expand Down Expand Up @@ -172,6 +173,12 @@ dword_t sys_clone(dword_t flags, addr_t stack, addr_t ptid, addr_t tls, addr_t c

// task might be destroyed by the time we finish, so save the pid
pid_t pid = task->pid;

if (current->ptrace.traced) {
current->ptrace.trap_event = PTRACE_EVENT_FORK_;
send_signal(current, SIGTRAP_, SIGINFO_NIL);
}

task_start(task);

if (flags & CLONE_VFORK_) {
Expand All @@ -185,6 +192,7 @@ dword_t sys_clone(dword_t flags, addr_t stack, addr_t ptid, addr_t tls, addr_t c
unlock(&task->general_lock);
cond_destroy(&vfork.cond);
}

return pid;
}

Expand Down
19 changes: 13 additions & 6 deletions kernel/getset.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
#include "kernel/calls.h"
#include "kernel/task.h"
#include "kernel/personality.h"

pid_t_ sys_getpid() {
STRACE("getpid()");
Expand Down Expand Up @@ -186,10 +188,15 @@ int_t sys_capset(addr_t header_addr, addr_t data_addr) {
}

// minimal version according to Linux sys/personality.h
int_t sys_personality(dword_t pers) {
if (pers == 0xffffffff) // get personality, return default (Linux)
return 0x00000000;
if (pers == 0x00000000) // set personality to Linux
return 0x00000000;
return _EINVAL; // otherwise return error
int_t sys_personality(dword_t persona) {
STRACE("personality(%#x)", persona);
// Get the personality
if (persona == 0xffffffff)
return current->group->personality;

// ADDR_NO_RANDOMIZE is the only thing we support, and you can't turn it off
if (persona != ADDR_NO_RANDOMIZE_)
return _EINVAL;

return current->group->personality;
}
2 changes: 2 additions & 0 deletions kernel/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "fs/tty.h"
#include "kernel/calls.h"
#include "kernel/init.h"
#include "kernel/personality.h"

int mount_root(const struct fs_ops *fs, const char *source) {
char source_realpath[MAX_PATH + 1];
Expand Down Expand Up @@ -61,6 +62,7 @@ static struct task *construct_task(struct task *parent) {
cond_init(&group->stopped_cond);
memcpy(group->limits, init_rlimits, sizeof(init_rlimits));
group->leader = task;
group->personality = ADDR_NO_RANDOMIZE_;
list_add(&group->threads, &task->group_links);
task->group = group;
task->tgid = task->pid;
Expand Down
6 changes: 6 additions & 0 deletions kernel/personality.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#ifndef KERNEL_PERSONALITY_H
#define KERNEL_PERSONALITY_H

#define ADDR_NO_RANDOMIZE_ 0x0040000

#endif /* KERNEL_PERSONALITY_H */
Loading

0 comments on commit 1d16949

Please sign in to comment.