diff options
author | Cyrill Gorcunov <gorcunov@openvz.org> | 2016-10-31 15:06:48 +0300 |
---|---|---|
committer | Andrei Vagin <avagin@virtuozzo.com> | 2017-03-15 00:06:06 +0300 |
commit | cbe24fb9c438f147fdd70c41f2a66844457ffed4 (patch) | |
tree | 375b747a15aa530d377e4be25ecfb42374d8dd61 /compel/arch/aarch64/src/lib/infect.c | |
parent | 51092282de6daca5cc8927c88b52e58314d40c00 (diff) |
compel: Move in parasite engine
This is the final patch in the series. It does a bunch
of renames and fixes headers respectively.
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: Andrei Vagin <avagin@virtuozzo.com>
Diffstat (limited to 'compel/arch/aarch64/src/lib/infect.c')
-rw-r--r-- | compel/arch/aarch64/src/lib/infect.c | 111 |
1 files changed, 111 insertions, 0 deletions
diff --git a/compel/arch/aarch64/src/lib/infect.c b/compel/arch/aarch64/src/lib/infect.c new file mode 100644 index 000000000..fceea2816 --- /dev/null +++ b/compel/arch/aarch64/src/lib/infect.c @@ -0,0 +1,111 @@ +#include <sys/ptrace.h> +#include <sys/types.h> +#include <sys/uio.h> +#include <linux/elf.h> +#include <compel/plugins/std/syscall-codes.h> +#include "uapi/compel/asm/infect-types.h" +#include "log.h" +#include "errno.h" +#include "infect.h" +#include "infect-priv.h" + +/* + * Injected syscall instruction + */ +const char code_syscall[] = { + 0x01, 0x00, 0x00, 0xd4, /* SVC #0 */ + 0x00, 0x00, 0x20, 0xd4 /* BRK #0 */ +}; + +static const int +code_syscall_aligned = round_up(sizeof(code_syscall), sizeof(long)); + +static inline void __always_unused __check_code_syscall(void) +{ + BUILD_BUG_ON(code_syscall_aligned != BUILTIN_SYSCALL_SIZE); + BUILD_BUG_ON(!is_log2(sizeof(code_syscall))); +} + +int compel_get_task_regs(pid_t pid, user_regs_struct_t regs, save_regs_t save, void *arg) +{ + struct iovec iov; + user_fpregs_struct_t fpsimd; + int ret; + + pr_info("Dumping GP/FPU registers for %d\n", pid); + + iov.iov_base = ®s; + iov.iov_len = sizeof(user_regs_struct_t); + if ((ret = ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, &iov))) { + pr_perror("Failed to obtain CPU registers for %d", pid); + goto err; + } + + iov.iov_base = &fpsimd; + iov.iov_len = sizeof(fpsimd); + if ((ret = ptrace(PTRACE_GETREGSET, pid, NT_PRFPREG, &iov))) { + pr_perror("Failed to obtain FPU registers for %d", pid); + goto err; + } + + ret = save(arg, ®s, &fpsimd); +err: + return ret; +} + +int compel_syscall(struct parasite_ctl *ctl, int nr, unsigned long *ret, + unsigned long arg1, + unsigned long arg2, + unsigned long arg3, + unsigned long arg4, + unsigned long arg5, + unsigned long arg6) +{ + user_regs_struct_t regs = ctl->orig.regs; + int err; + + regs.regs[8] = (unsigned long)nr; + regs.regs[0] = arg1; + regs.regs[1] = arg2; + regs.regs[2] = arg3; + regs.regs[3] = arg4; + regs.regs[4] = arg5; + regs.regs[5] = arg6; + regs.regs[6] = 0; + regs.regs[7] = 0; + + err = compel_execute_syscall(ctl, ®s, code_syscall); + + *ret = regs.regs[0]; + return err; +} + +void *remote_mmap(struct parasite_ctl *ctl, + void *addr, size_t length, int prot, + int flags, int fd, off_t offset) +{ + unsigned long map; + int err; + + err = compel_syscall(ctl, __NR_mmap, &map, + (unsigned long)addr, length, prot, flags, fd, offset); + if (err < 0 || (long)map < 0) + map = 0; + + return (void *)map; +} + +void parasite_setup_regs(unsigned long new_ip, void *stack, user_regs_struct_t *regs) +{ + regs->pc = new_ip; + if (stack) + regs->sp = (unsigned long)stack; +} + +bool arch_can_dump_task(struct parasite_ctl *ctl) +{ + /* + * TODO: Add proper check here + */ + return true; +} |