Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Abstract out syscall numbers similarly to registers.

  • Loading branch information...
commit ed3ecb098d56943b3e4d5ed5633d38ab513f773d 1 parent 14f8754
@nelhage authored
Showing with 105 additions and 53 deletions.
  1. +32 −0 arch/default-syscalls.h
  2. +36 −51 attach.c
  3. +19 −2 ptrace.c
  4. +18 −0 ptrace.h
View
32 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
View
87 attach.c
@@ -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;
@@ -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;
@@ -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) {
@@ -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));
}
@@ -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;
@@ -184,8 +179,7 @@ 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;
@@ -193,8 +187,7 @@ int do_setsid(struct ptrace_child *child) {
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);
@@ -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;
}
@@ -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) {
@@ -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);
@@ -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.");
@@ -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;
@@ -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);
View
21 ptrace.c
@@ -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"
@@ -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;
@@ -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;
View
18 ptrace.h
@@ -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);
@@ -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);
Please sign in to comment.
Something went wrong with that request. Please try again.