Skip to content

Commit

Permalink
Abstract out syscall numbers similarly to registers.
Browse files Browse the repository at this point in the history
  • Loading branch information
nelhage committed Apr 15, 2011
1 parent 14f8754 commit ed3ecb0
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 53 deletions.
32 changes: 32 additions & 0 deletions arch/default-syscalls.h
@@ -0,0 +1,32 @@
#define SC(name) .nr_##name = __NR_##name

{
#ifdef __NR_mmap
SC(mmap),
#else
.nr_mmap = -1,
#endif
#ifdef __NR_mmap2
SC(mmap2),
#else
.nr_mmap2 = -1,
#endif
SC(munmap),
SC(getsid),
SC(setsid),
SC(setpgid),
SC(fork),
SC(wait4),
#ifdef __NR_signal
SC(signal),
#else
.nr_signal = -1,
#endif
SC(rt_sigaction),
SC(open),
SC(close),
SC(ioctl),
SC(dup2),
},

#undef SC
87 changes: 36 additions & 51 deletions attach.c
Expand Up @@ -40,12 +40,6 @@
#include "ptrace.h"
#include "reptyr.h"

#ifdef __NR_mmap2
#define mmap_syscall __NR_mmap2
#else
#define mmap_syscall __NR_mmap
#endif

#define TASK_COMM_LENGTH 16
struct proc_stat {
pid_t pid;
Expand All @@ -55,6 +49,10 @@ struct proc_stat {
dev_t ctty;
};

#define do_syscall(child, name, a0, a1, a2, a3, a4, a5) \
ptrace_remote_syscall((child), ptrace_syscall_numbers((child))->nr_##name, \
a0, a1, a2, a3, a4, a5)

int parse_proc_stat(int statfd, struct proc_stat *out) {
char buf[1024];
int n;
Expand All @@ -78,7 +76,7 @@ int parse_proc_stat(int statfd, struct proc_stat *out) {
static void do_unmap(struct ptrace_child *child, child_addr_t addr, unsigned long len) {
if (addr == (unsigned long)-1)
return;
ptrace_remote_syscall(child, __NR_munmap, addr, len, 0, 0, 0, 0);
do_syscall(child, munmap, addr, len, 0, 0, 0, 0);
}

int *get_child_tty_fds(struct ptrace_child *child, int statfd, int *count) {
Expand Down Expand Up @@ -152,9 +150,7 @@ void move_process_group(struct ptrace_child *child, pid_t from, pid_t to) {
if (*p) continue;
if (getpgid(pid) == from) {
debug("Change pgid for pid %d", pid);
err = ptrace_remote_syscall(child, __NR_setpgid,
pid, to,
0, 0, 0, 0);
err = do_syscall(child, setpgid, pid, to, 0, 0, 0, 0);
if (err < 0)
error(" failed: %s", strerror(-err));
}
Expand All @@ -166,8 +162,7 @@ int do_setsid(struct ptrace_child *child) {
int err = 0;
struct ptrace_child dummy;

err = ptrace_remote_syscall(child, __NR_fork,
0, 0, 0, 0, 0, 0);
err = do_syscall(child, fork, 0, 0, 0, 0, 0, 0);
if (err < 0)
return err;

Expand All @@ -184,17 +179,15 @@ int do_setsid(struct ptrace_child *child) {
goto out_kill;
}

err = ptrace_remote_syscall(&dummy, __NR_setpgid,
0, 0, 0, 0, 0, 0);
err = do_syscall(&dummy, setpgid, 0, 0, 0, 0, 0, 0);
if (err < 0) {
error("Failed to setpgid: %s", strerror(-err));
goto out_kill;
}

move_process_group(child, child->pid, dummy.pid);

err = ptrace_remote_syscall(child, __NR_setsid,
0, 0, 0, 0, 0, 0);
err = do_syscall(child, setsid, 0, 0, 0, 0, 0, 0);
if (err < 0) {
error("Failed to setsid: %s", strerror(-err));
move_process_group(child, dummy.pid, child->pid);
Expand All @@ -207,30 +200,26 @@ int do_setsid(struct ptrace_child *child) {
kill(dummy.pid, SIGKILL);
ptrace_detach_child(&dummy);
ptrace_wait(&dummy);
ptrace_remote_syscall(child, __NR_wait4,
dummy.pid, 0, WNOHANG,
0, 0, 0);
do_syscall(child, wait4, dummy.pid, 0, WNOHANG, 0, 0, 0);
return err;
}

int ignore_hup(struct ptrace_child *child, unsigned long scratch_page) {
int err;
#ifdef __NR_signal
err = ptrace_remote_syscall(child, __NR_signal,
SIGHUP, (unsigned long)SIG_IGN,
0, 0, 0, 0);
#else
struct sigaction act = {
.sa_handler = SIG_IGN,
};
err = ptrace_memcpy_to_child(child, scratch_page,
&act, sizeof act);
if (err < 0)
return err;
err = ptrace_remote_syscall(child, __NR_rt_sigaction,
SIGHUP, scratch_page,
0, 8, 0, 0);
#endif
if (ptrace_syscall_numbers(child)->nr_signal != -1) {
err = do_syscall(child, signal, SIGHUP, (unsigned long)SIG_IGN, 0, 0, 0, 0);
} else {
struct sigaction act = {
.sa_handler = SIG_IGN,
};
err = ptrace_memcpy_to_child(child, scratch_page,
&act, sizeof act);
if (err < 0)
return err;
err = do_syscall(child, rt_sigaction,
SIGHUP, scratch_page,
0, 8, 0, 0);
}
return err;
}

Expand Down Expand Up @@ -319,6 +308,7 @@ int attach_child(pid_t pid, const char *pty, int force_stdio) {
int err = 0;
long page_size = sysconf(_SC_PAGE_SIZE);
char stat_path[PATH_MAX];
long mmap_syscall;

if ((err = copy_tty_state(pid, pty))) {
if (err == ENOTTY && !force_stdio) {
Expand Down Expand Up @@ -352,6 +342,9 @@ int attach_child(pid_t pid, const char *pty, int force_stdio) {
goto out_detach;
}

mmap_syscall = ptrace_syscall_numbers(&child)->nr_mmap2;
if (mmap_syscall == -1)
mmap_syscall = ptrace_syscall_numbers(&child)->nr_mmap;
scratch_page = ptrace_remote_syscall(&child, mmap_syscall, 0,
page_size, PROT_READ|PROT_WRITE,
MAP_ANONYMOUS|MAP_PRIVATE, 0, 0);
Expand Down Expand Up @@ -387,9 +380,9 @@ int attach_child(pid_t pid, const char *pty, int force_stdio) {
goto out_free_fds;
}

child_fd = ptrace_remote_syscall(&child, __NR_open,
scratch_page, O_RDWR|O_NOCTTY,
0, 0, 0, 0);
child_fd = do_syscall(&child, open,
scratch_page, O_RDWR|O_NOCTTY,
0, 0, 0, 0);
if (child_fd < 0) {
err = child_fd;
error("Unable to open the tty in the child.");
Expand All @@ -402,22 +395,17 @@ int attach_child(pid_t pid, const char *pty, int force_stdio) {
if (err < 0)
goto out_close;

err = ptrace_remote_syscall(&child, __NR_getsid,
0, 0, 0, 0, 0, 0);
err = do_syscall(&child, getsid, 0, 0, 0, 0, 0, 0);
if (err != child.pid) {
debug("Target is not a session leader, attempting to setsid.");
err = do_setsid(&child);
} else {
ptrace_remote_syscall(&child, __NR_ioctl,
child_tty_fds[0], TIOCNOTTY,
0, 0, 0, 0);
do_syscall(&child, ioctl, child_tty_fds[0], TIOCNOTTY, 0, 0, 0, 0);
}
if (err < 0)
goto out_close;

err = ptrace_remote_syscall(&child, __NR_ioctl,
child_fd, TIOCSCTTY,
0, 0, 0, 0);
err = do_syscall(&child, ioctl, child_fd, TIOCSCTTY, 0, 0, 0, 0);
if (err < 0) {
error("Unable to set controlling terminal.");
goto out_close;
Expand All @@ -426,16 +414,13 @@ int attach_child(pid_t pid, const char *pty, int force_stdio) {
debug("Set the controlling tty");

for (i = 0; i < n_fds; i++)
ptrace_remote_syscall(&child, __NR_dup2,
child_fd, child_tty_fds[i],
0, 0, 0, 0);
do_syscall(&child, dup2, child_fd, child_tty_fds[i], 0, 0, 0, 0);


err = 0;

out_close:
ptrace_remote_syscall(&child, __NR_close, child_fd,
0, 0, 0, 0, 0);
do_syscall(&child, close, child_fd, 0, 0, 0, 0, 0);
out_free_fds:
free(child_tty_fds);

Expand Down
21 changes: 19 additions & 2 deletions ptrace.c
Expand Up @@ -76,7 +76,7 @@ struct ptrace_personality {
size_t reg_ip;
};

struct ptrace_personality *personality(struct ptrace_child *child);
static struct ptrace_personality *personality(struct ptrace_child *child);

#if defined(__amd64__)
#include "arch/amd64.h"
Expand All @@ -88,10 +88,24 @@ struct ptrace_personality *personality(struct ptrace_child *child);
#error Unsupported architecture.
#endif

struct ptrace_personality *personality(struct ptrace_child *child) {
#ifndef ARCH_HAVE_MULTIPLE_PERSONALITIES
int arch_get_personality(struct ptrace_child *child) {
return 0;
}

struct syscall_numbers arch_syscall_numbers[] = {
#include "arch/default-syscalls.h"
};
#endif

static struct ptrace_personality *personality(struct ptrace_child *child) {
return &arch_personality[child->personality];
}

struct syscall_numbers *ptrace_syscall_numbers(struct ptrace_child *child) {
return &arch_syscall_numbers[child->personality];
}

int ptrace_attach_child(struct ptrace_child *child, pid_t pid) {
memset(child, 0, sizeof *child);
child->pid = pid;
Expand All @@ -109,6 +123,9 @@ int ptrace_finish_attach(struct ptrace_child *child, pid_t pid) {
if (ptrace_wait(child) < 0)
goto detach;

if (arch_get_personality(child))
goto detach;

if (ptrace_command(child, PTRACE_SETOPTIONS, 0,
PTRACE_O_TRACESYSGOOD|PTRACE_O_TRACEFORK) < 0)
goto detach;
Expand Down
18 changes: 18 additions & 0 deletions ptrace.h
Expand Up @@ -43,6 +43,23 @@ struct ptrace_child {
unsigned long saved_syscall;
};

struct syscall_numbers {
long nr_mmap;
long nr_mmap2;
long nr_munmap;
long nr_getsid;
long nr_setsid;
long nr_setpgid;
long nr_fork;
long nr_wait4;
long nr_signal;
long nr_rt_sigaction;
long nr_open;
long nr_close;
long nr_ioctl;
long nr_dup2;
};

typedef unsigned long child_addr_t;

int ptrace_wait(struct ptrace_child *child);
Expand All @@ -62,3 +79,4 @@ unsigned long ptrace_remote_syscall(struct ptrace_child *child,

int ptrace_memcpy_to_child(struct ptrace_child *, child_addr_t, const void*, size_t);
int ptrace_memcpy_from_child(struct ptrace_child *, void*, child_addr_t, size_t);
struct syscall_numbers *ptrace_syscall_numbers(struct ptrace_child *child);

0 comments on commit ed3ecb0

Please sign in to comment.