Skip to content

Commit

Permalink
Support aarch64 on Linux.
Browse files Browse the repository at this point in the history
  • Loading branch information
lopsided98 committed Dec 1, 2018
1 parent 40aad4c commit ceef05a
Show file tree
Hide file tree
Showing 14 changed files with 225 additions and 103 deletions.
4 changes: 2 additions & 2 deletions Makefile
Expand Up @@ -24,8 +24,8 @@ reptyr: $(OBJS)

ifeq ($(DISABLE_TESTS),)
test: reptyr test/victim PHONY
python test/basic.py
python test/tty-steal.py
python2 test/basic.py
python2 test/tty-steal.py
else
test: all
endif
Expand Down
37 changes: 30 additions & 7 deletions attach.c
Expand Up @@ -69,11 +69,19 @@ static void do_unmap(struct ptrace_child *child, child_addr_t addr, unsigned lon
do_syscall(child, munmap, (unsigned long)addr, len, 0, 0, 0, 0);
}

static int do_fork(struct ptrace_child *child) {
if (ptrace_syscall_numbers(child)->nr_fork != -1) {
return do_syscall(child, fork, 0, 0, 0, 0, 0, 0);
} else {
return do_syscall(child, clone, SIGCHLD, 0, 0, 0, 0, 0);
}
}

int do_setsid(struct ptrace_child *child) {
int err = 0;
struct ptrace_child dummy;

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

Expand Down Expand Up @@ -115,6 +123,21 @@ int do_setsid(struct ptrace_child *child) {
return err;
}

static int do_dup2(struct ptrace_child *child, int oldfd, int newfd) {
if (ptrace_syscall_numbers(child)->nr_dup2 != -1) {
return do_syscall(child, dup2, oldfd, newfd, 0, 0, 0, 0);
} else {
int err = do_syscall(child, dup3, oldfd, newfd, 0, 0, 0, 0);
// dup3 returns EINVAL when the fds are the same, while dup2 ignores it
if (child->error == EINVAL){
child->error = 0;
return 0;
} else {
return err;
}
}
}

int ignore_hup(struct ptrace_child *child, child_addr_t scratch_page) {
int err;

Expand Down Expand Up @@ -316,9 +339,9 @@ int attach_child(pid_t pid, const char *pty, int force_stdio) {
goto out_free_fds;
}

child_fd = do_syscall(&child, open,
scratch_page, O_RDWR | O_NOCTTY,
0, 0, 0, 0);
child_fd = do_syscall(&child, openat,
-1, scratch_page, O_RDWR | O_NOCTTY,
0, 0, 0);
if (child_fd < 0) {
err = child_fd;
error("Unable to open the tty in the child.");
Expand Down Expand Up @@ -350,7 +373,7 @@ int attach_child(pid_t pid, const char *pty, int force_stdio) {
debug("Set the controlling tty");

for (i = 0; i < n_fds; i++) {
err = do_syscall(&child, dup2, child_fd, child_tty_fds[i], 0, 0, 0, 0);
err = do_dup2(&child, child_fd, child_tty_fds[i]);
if (err < 0)
error("Problem moving child fd number %d to new tty: %s", child_tty_fds[i], strerror(errno));
}
Expand Down Expand Up @@ -522,14 +545,14 @@ int steal_cleanup_child(struct steal_pty_state *steal) {
return steal->child.error;
}

int nullfd = do_syscall(&steal->child, open, steal->child_scratch, O_RDWR, 0, 0, 0, 0);
int nullfd = do_syscall(&steal->child, openat, -1, steal->child_scratch, O_RDWR, 0, 0, 0);
if (nullfd < 0) {
return steal->child.error;
}

int i;
for (i = 0; i < steal->master_fds.n; ++i) {
do_syscall(&steal->child, dup2, nullfd, steal->master_fds.fds[i], 0, 0, 0, 0);
do_dup2(&steal->child, nullfd, steal->master_fds.fds[i]);
}

do_syscall(&steal->child, close, nullfd, 0, 0, 0, 0, 0);
Expand Down
11 changes: 5 additions & 6 deletions platform/freebsd/arch/default-syscalls.h
@@ -1,32 +1,31 @@
#define SC(name) .nr_##name = SYS_##name

{
#ifdef SYS_mmap
SC(mmap),
#else
.nr_mmap = -1,
#endif
#ifdef SYS_mmap2
.nr_mmap = -1,
SC(mmap2),
#else
SC(mmap),
.nr_mmap2 = -1,
#endif
SC(munmap),
SC(getsid),
SC(setsid),
SC(setpgid),
SC(fork),
.nr_clone = -1,
SC(wait4),
#ifdef SYS_signal
SC(signal),
#else
.nr_signal = -1,
#endif
.nr_rt_sigaction = SYS_sigaction,
SC(open),
SC(openat),
SC(close),
SC(ioctl),
SC(dup2),
.nr_dup3 = -1,
#ifdef SYS_socketcall
SC(socketcall),
#else
Expand Down
2 changes: 1 addition & 1 deletion platform/freebsd/arch/x86_common.h
Expand Up @@ -34,7 +34,7 @@ static inline void arch_fixup_regs(struct ptrace_child *child) {
struct x86_personality *x86pers = x86_pers(child);
struct ptrace_personality *pers = personality(child);
struct reg *regs = &child->regs;
#define ptr(user, off) ((unsigned long*)((void*)(user)+(off)))
#define ptr(regs, off) ((unsigned long*)((void*)(regs)+(off)))
*ptr(regs, pers->reg_ip) -= 2;
*ptr(regs, x86pers->ax) = child->saved_syscall;
//*ptr(user, x86pers->ax) = *ptr(user, x86pers->orig_ax);
Expand Down
64 changes: 64 additions & 0 deletions platform/linux/arch/aarch64.h
@@ -0,0 +1,64 @@
/*
* Copyright (C) 2011 by Nelson Elhage
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
static struct ptrace_personality arch_personality[1] = {
{
offsetof(struct user_regs_struct, regs[0]),
offsetof(struct user_regs_struct, regs[0]),
offsetof(struct user_regs_struct, regs[1]),
offsetof(struct user_regs_struct, regs[2]),
offsetof(struct user_regs_struct, regs[3]),
offsetof(struct user_regs_struct, regs[4]),
offsetof(struct user_regs_struct, regs[5]),
offsetof(struct user_regs_struct, pc),
}
};

static inline void arch_fixup_regs(struct ptrace_child *child) {
child->regs.pc -= 4;
}

static inline int arch_set_syscall(struct ptrace_child *child,
unsigned long sysno) {
int syscall_reg = sysno;
struct iovec reg_iovec = {
.iov_base = &syscall_reg,
.iov_len = sizeof(syscall_reg)
};
return ptrace_command(child, PTRACE_SETREGSET, NT_ARM_SYSTEM_CALL, &reg_iovec);
}

static inline int arch_save_syscall(struct ptrace_child *child) {
int syscall_reg;
struct iovec reg_iovec = {
.iov_base = &syscall_reg,
.iov_len = sizeof(syscall_reg)
};
if (ptrace_command(child, PTRACE_GETREGSET, NT_ARM_SYSTEM_CALL, &reg_iovec) < 0)
return -1;

child->saved_syscall = syscall_reg;
return 0;
}

static inline int arch_restore_syscall(struct ptrace_child *child) {
return arch_set_syscall(child, child->saved_syscall);
}
44 changes: 22 additions & 22 deletions platform/linux/arch/amd64.h
Expand Up @@ -25,35 +25,35 @@

static struct ptrace_personality arch_personality[2] = {
{
offsetof(struct user, regs.rax),
offsetof(struct user, regs.rdi),
offsetof(struct user, regs.rsi),
offsetof(struct user, regs.rdx),
offsetof(struct user, regs.r10),
offsetof(struct user, regs.r8),
offsetof(struct user, regs.r9),
offsetof(struct user, regs.rip),
offsetof(struct user_regs_struct, rax),
offsetof(struct user_regs_struct, rdi),
offsetof(struct user_regs_struct, rsi),
offsetof(struct user_regs_struct, rdx),
offsetof(struct user_regs_struct, r10),
offsetof(struct user_regs_struct, r8),
offsetof(struct user_regs_struct, r9),
offsetof(struct user_regs_struct, rip),
},
{
offsetof(struct user, regs.rax),
offsetof(struct user, regs.rbx),
offsetof(struct user, regs.rcx),
offsetof(struct user, regs.rdx),
offsetof(struct user, regs.rsi),
offsetof(struct user, regs.rdi),
offsetof(struct user, regs.rbp),
offsetof(struct user, regs.rip),
offsetof(struct user_regs_struct, rax),
offsetof(struct user_regs_struct, rbx),
offsetof(struct user_regs_struct, rcx),
offsetof(struct user_regs_struct, rdx),
offsetof(struct user_regs_struct, rsi),
offsetof(struct user_regs_struct, rdi),
offsetof(struct user_regs_struct, rbp),
offsetof(struct user_regs_struct, rip),
},
};

struct x86_personality x86_personality[2] = {
{
offsetof(struct user, regs.orig_rax),
offsetof(struct user, regs.rax),
offsetof(struct user_regs_struct, orig_rax),
offsetof(struct user_regs_struct, rax),
},
{
offsetof(struct user, regs.orig_rax),
offsetof(struct user, regs.rax),
offsetof(struct user_regs_struct, orig_rax),
offsetof(struct user_regs_struct, rax),
},
};

Expand All @@ -77,7 +77,7 @@ struct syscall_numbers arch_syscall_numbers[2] = {
.nr_wait4 = 114,
.nr_signal = 48,
.nr_rt_sigaction = 174,
.nr_open = 5,
.nr_openat = 295,
.nr_close = 6,
.nr_ioctl = 54,
.nr_dup2 = 63,
Expand All @@ -89,7 +89,7 @@ int arch_get_personality(struct ptrace_child *child) {
unsigned long cs;

cs = ptrace_command(child, PTRACE_PEEKUSER,
offsetof(struct user, regs.cs));
offsetof(struct user_regs_struct, cs));
if (child->error)
return -1;
if (cs == 0x23)
Expand Down
22 changes: 11 additions & 11 deletions platform/linux/arch/arm.h
Expand Up @@ -21,19 +21,19 @@
*/
static struct ptrace_personality arch_personality[1] = {
{
offsetof(struct user, regs.uregs[0]),
offsetof(struct user, regs.uregs[0]),
offsetof(struct user, regs.uregs[1]),
offsetof(struct user, regs.uregs[2]),
offsetof(struct user, regs.uregs[3]),
offsetof(struct user, regs.uregs[4]),
offsetof(struct user, regs.uregs[5]),
offsetof(struct user, regs.ARM_pc),
offsetof(struct user_regs, uregs[0]),
offsetof(struct user_regs, uregs[0]),
offsetof(struct user_regs, uregs[1]),
offsetof(struct user_regs, uregs[2]),
offsetof(struct user_regs, uregs[3]),
offsetof(struct user_regs, uregs[4]),
offsetof(struct user_regs, uregs[5]),
offsetof(struct user_regs, ARM_pc),
}
};

static inline void arch_fixup_regs(struct ptrace_child *child) {
child->user.regs.ARM_pc -= 4;
child->regs.ARM_pc -= 4;
}

static inline int arch_set_syscall(struct ptrace_child *child,
Expand All @@ -43,11 +43,11 @@ static inline int arch_set_syscall(struct ptrace_child *child,

static inline int arch_save_syscall(struct ptrace_child *child) {
unsigned long swi;
swi = ptrace_command(child, PTRACE_PEEKTEXT, child->user.regs.ARM_pc);
swi = ptrace_command(child, PTRACE_PEEKTEXT, child->regs.ARM_pc);
if (child->error)
return -1;
if (swi == 0xef000000)
child->saved_syscall = child->user.regs.uregs[7];
child->saved_syscall = child->regs.uregs[7];
else
child->saved_syscall = (swi & 0x000fffff);
return 0;
Expand Down
21 changes: 15 additions & 6 deletions platform/linux/arch/default-syscalls.h
@@ -1,32 +1,41 @@
#define SC(name) .nr_##name = __NR_##name

{
#ifdef __NR_mmap
SC(mmap),
#else
.nr_mmap = -1,
#endif
#ifdef __NR_mmap2
.nr_mmap = -1,
SC(mmap2),
#else
SC(mmap),
.nr_mmap2 = -1,
#endif
SC(munmap),
SC(getsid),
SC(setsid),
SC(setpgid),
#ifdef __NR_fork
SC(fork),
.nr_clone = -1,
#else
.nr_fork = -1,
SC(clone),
#endif
SC(wait4),
#ifdef __NR_signal
SC(signal),
#else
.nr_signal = -1,
#endif
SC(rt_sigaction),
SC(open),
SC(openat),
SC(close),
SC(ioctl),
#ifdef __NR_dup2
SC(dup2),
.nr_dup3 = -1,
#else
.nr_dup2 = -1,
SC(dup3),
#endif
#ifdef __NR_socketcall
SC(socketcall),
#else
Expand Down

0 comments on commit ceef05a

Please sign in to comment.