diff options
29 files changed, 198 insertions, 165 deletions
diff --git a/compel/arch/aarch64/src/lib/include/ptrace.h b/compel/arch/aarch64/src/lib/include/ptrace.h new file mode 100644 index 000000000..9cf7d460d --- /dev/null +++ b/compel/arch/aarch64/src/lib/include/ptrace.h @@ -0,0 +1,4 @@ +#ifndef __COMPEL_PTRACE_H__ +#define __COMPEL_PTRACE_H__ +#define ARCH_SI_TRAP TRAP_BRKPT +#endif diff --git a/compel/arch/aarch64/src/lib/include/syscall.h b/compel/arch/aarch64/src/lib/include/syscall.h new file mode 100644 index 000000000..e2ec1272e --- /dev/null +++ b/compel/arch/aarch64/src/lib/include/syscall.h @@ -0,0 +1,4 @@ +#ifndef __COMPEL_SYSCALL_H__ +#define __COMPEL_SYSCALL_H__ +#define __NR(syscall, compat) __NR_##syscall +#endif diff --git a/compel/arch/arm/src/lib/include/ptrace.h b/compel/arch/arm/src/lib/include/ptrace.h new file mode 100644 index 000000000..9cf7d460d --- /dev/null +++ b/compel/arch/arm/src/lib/include/ptrace.h @@ -0,0 +1,4 @@ +#ifndef __COMPEL_PTRACE_H__ +#define __COMPEL_PTRACE_H__ +#define ARCH_SI_TRAP TRAP_BRKPT +#endif diff --git a/compel/arch/arm/src/lib/include/syscall.h b/compel/arch/arm/src/lib/include/syscall.h new file mode 100644 index 000000000..e2ec1272e --- /dev/null +++ b/compel/arch/arm/src/lib/include/syscall.h @@ -0,0 +1,4 @@ +#ifndef __COMPEL_SYSCALL_H__ +#define __COMPEL_SYSCALL_H__ +#define __NR(syscall, compat) __NR_##syscall +#endif diff --git a/compel/arch/ppc64/src/lib/include/ptrace.h b/compel/arch/ppc64/src/lib/include/ptrace.h new file mode 100644 index 000000000..9cf7d460d --- /dev/null +++ b/compel/arch/ppc64/src/lib/include/ptrace.h @@ -0,0 +1,4 @@ +#ifndef __COMPEL_PTRACE_H__ +#define __COMPEL_PTRACE_H__ +#define ARCH_SI_TRAP TRAP_BRKPT +#endif diff --git a/compel/arch/ppc64/src/lib/include/syscall.h b/compel/arch/ppc64/src/lib/include/syscall.h new file mode 100644 index 000000000..e2ec1272e --- /dev/null +++ b/compel/arch/ppc64/src/lib/include/syscall.h @@ -0,0 +1,4 @@ +#ifndef __COMPEL_SYSCALL_H__ +#define __COMPEL_SYSCALL_H__ +#define __NR(syscall, compat) __NR_##syscall +#endif diff --git a/compel/arch/x86/src/lib/include/ptrace.h b/compel/arch/x86/src/lib/include/ptrace.h new file mode 100644 index 000000000..991f1152a --- /dev/null +++ b/compel/arch/x86/src/lib/include/ptrace.h @@ -0,0 +1,4 @@ +#ifndef __COMPEL_PTRACE_H__ +#define __COMPEL_PTRACE_H__ +#define ARCH_SI_TRAP SI_KERNEL +#endif diff --git a/compel/arch/x86/src/lib/include/syscall.h b/compel/arch/x86/src/lib/include/syscall.h new file mode 100644 index 000000000..6d7df1861 --- /dev/null +++ b/compel/arch/x86/src/lib/include/syscall.h @@ -0,0 +1,4 @@ +#ifndef __COMPEL_SYSCALL_H__ +#define __COMPEL_SYSCALL_H__ +#define __NR(syscall, compat) ((compat) ? __NR32_##syscall : __NR_##syscall) +#endif diff --git a/criu/Makefile.crtools b/criu/Makefile.crtools index 04ba7b3f7..502f33133 100644 --- a/criu/Makefile.crtools +++ b/criu/Makefile.crtools @@ -5,6 +5,7 @@ ccflags-y += -iquote compel/arch/$(ARCH)/plugins/std obj-y += infect.o obj-y += infect-rpc.o +obj-y += infect-util.o obj-y += action-scripts.o obj-y += external.o obj-y += aio.o diff --git a/criu/arch/aarch64/crtools.c b/criu/arch/aarch64/crtools.c index 8a92a5f83..02205453e 100644 --- a/criu/arch/aarch64/crtools.c +++ b/criu/arch/aarch64/crtools.c @@ -19,21 +19,6 @@ #include "restorer.h" #include "infect.h" -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; -} - #define assign_reg(dst, src, e) dst->e = (__typeof__(dst->e))(src)->e int save_task_regs(void *x, user_regs_struct_t *regs, user_fpregs_struct_t *fpsimd) diff --git a/criu/arch/aarch64/include/asm/parasite-syscall.h b/criu/arch/aarch64/include/asm/parasite-syscall.h index e420ccbdc..6008c3792 100644 --- a/criu/arch/aarch64/include/asm/parasite-syscall.h +++ b/criu/arch/aarch64/include/asm/parasite-syscall.h @@ -3,10 +3,4 @@ struct parasite_ctl; -#define ARCH_SI_TRAP TRAP_BRKPT - -#define __NR(syscall, compat) __NR_##syscall - -void parasite_setup_regs(unsigned long new_ip, void *stack, user_regs_struct_t *regs); - #endif diff --git a/criu/arch/aarch64/infect.c b/criu/arch/aarch64/infect.c index 2411cd6e8..263ea5a55 100644 --- a/criu/arch/aarch64/infect.c +++ b/criu/arch/aarch64/infect.c @@ -98,3 +98,17 @@ void *mmap_re(struct parasite_ctl *ctl, 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; +} diff --git a/criu/arch/arm/crtools.c b/criu/arch/arm/crtools.c index bc63e6282..8ce1e6619 100644 --- a/criu/arch/arm/crtools.c +++ b/criu/arch/arm/crtools.c @@ -20,24 +20,6 @@ #include "kerndat.h" #include "infect.h" -void parasite_setup_regs(unsigned long new_ip, void *stack, user_regs_struct_t *regs) -{ - regs->ARM_pc = new_ip; - if (stack) - regs->ARM_sp = (unsigned long)stack; - - /* Make sure flags are in known state */ - regs->ARM_cpsr &= PSR_f | PSR_s | PSR_x | MODE32_BIT; -} - -bool arch_can_dump_task(struct parasite_ctl *ctl) -{ - /* - * TODO: Add proper check here - */ - return true; -} - #define assign_reg(dst, src, e) dst->e = (__typeof__(dst->e))((src)->ARM_##e) int save_task_regs(void *x, user_regs_struct_t *regs, user_fpregs_struct_t *fpregs) diff --git a/criu/arch/arm/include/asm/parasite-syscall.h b/criu/arch/arm/include/asm/parasite-syscall.h index e420ccbdc..6008c3792 100644 --- a/criu/arch/arm/include/asm/parasite-syscall.h +++ b/criu/arch/arm/include/asm/parasite-syscall.h @@ -3,10 +3,4 @@ struct parasite_ctl; -#define ARCH_SI_TRAP TRAP_BRKPT - -#define __NR(syscall, compat) __NR_##syscall - -void parasite_setup_regs(unsigned long new_ip, void *stack, user_regs_struct_t *regs); - #endif diff --git a/criu/arch/arm/infect.c b/criu/arch/arm/infect.c index ec84c20aa..50d1d5b68 100644 --- a/criu/arch/arm/infect.c +++ b/criu/arch/arm/infect.c @@ -105,3 +105,20 @@ void *remote_mmap(struct parasite_ctl *ctl, return (void *)map; } +void parasite_setup_regs(unsigned long new_ip, void *stack, user_regs_struct_t *regs) +{ + regs->ARM_pc = new_ip; + if (stack) + regs->ARM_sp = (unsigned long)stack; + + /* Make sure flags are in known state */ + regs->ARM_cpsr &= PSR_f | PSR_s | PSR_x | MODE32_BIT; +} + +bool arch_can_dump_task(struct parasite_ctl *ctl) +{ + /* + * TODO: Add proper check here + */ + return true; +} diff --git a/criu/arch/ppc64/crtools.c b/criu/arch/ppc64/crtools.c index 057dd8494..e634c7b71 100644 --- a/criu/arch/ppc64/crtools.c +++ b/criu/arch/ppc64/crtools.c @@ -24,27 +24,6 @@ #include "images/core.pb-c.h" #include "images/creds.pb-c.h" -void parasite_setup_regs(unsigned long new_ip, void *stack, user_regs_struct_t *regs) -{ - /* - * OpenPOWER ABI requires that r12 is set to the calling function addressi - * to compute the TOC pointer. - */ - regs->gpr[12] = new_ip; - regs->nip = new_ip; - if (stack) - regs->gpr[1] = (unsigned long) stack; - regs->trap = 0; -} - -bool arch_can_dump_task(struct parasite_ctl *ctl) -{ - /* - * TODO: We should detect 32bit task when BE support is done. - */ - return true; -} - static UserPpc64FpstateEntry *copy_fp_regs(uint64_t *fpregs) { UserPpc64FpstateEntry *fpe; diff --git a/criu/arch/ppc64/include/asm/parasite-syscall.h b/criu/arch/ppc64/include/asm/parasite-syscall.h index e420ccbdc..6008c3792 100644 --- a/criu/arch/ppc64/include/asm/parasite-syscall.h +++ b/criu/arch/ppc64/include/asm/parasite-syscall.h @@ -3,10 +3,4 @@ struct parasite_ctl; -#define ARCH_SI_TRAP TRAP_BRKPT - -#define __NR(syscall, compat) __NR_##syscall - -void parasite_setup_regs(unsigned long new_ip, void *stack, user_regs_struct_t *regs); - #endif diff --git a/criu/arch/ppc64/infect.c b/criu/arch/ppc64/infect.c index c76bef5e7..029509ee3 100644 --- a/criu/arch/ppc64/infect.c +++ b/criu/arch/ppc64/infect.c @@ -295,3 +295,24 @@ void *remote_mmap(struct parasite_ctl *ctl, return (void *)map; } + +void parasite_setup_regs(unsigned long new_ip, void *stack, user_regs_struct_t *regs) +{ + /* + * OpenPOWER ABI requires that r12 is set to the calling function addressi + * to compute the TOC pointer. + */ + regs->gpr[12] = new_ip; + regs->nip = new_ip; + if (stack) + regs->gpr[1] = (unsigned long) stack; + regs->trap = 0; +} + +bool arch_can_dump_task(struct parasite_ctl *ctl) +{ + /* + * TODO: We should detect 32bit task when BE support is done. + */ + return true; +} diff --git a/criu/arch/x86/crtools.c b/criu/arch/x86/crtools.c index 73accb13d..3484455dd 100644 --- a/criu/arch/x86/crtools.c +++ b/criu/arch/x86/crtools.c @@ -7,7 +7,6 @@ #include <sys/auxv.h> #include "types.h" -#include "asm/processor-flags.h" #include "asm/parasite-syscall.h" #include "asm/restorer.h" #include "asm/fpu.h" @@ -30,23 +29,6 @@ #include "images/core.pb-c.h" #include "images/creds.pb-c.h" -/* - * regs must be inited when calling this function from original context - */ -void parasite_setup_regs(unsigned long new_ip, void *stack, user_regs_struct_t *regs) -{ - set_user_reg(regs, ip, new_ip); - if (stack) - set_user_reg(regs, sp, (unsigned long) stack); - - /* Avoid end of syscall processing */ - set_user_reg(regs, orig_ax, -1); - - /* Make sure flags are in known state */ - set_user_reg(regs, flags, get_user_reg(regs, flags) & - ~(X86_EFLAGS_TF | X86_EFLAGS_DF | X86_EFLAGS_IF)); -} - #ifdef CONFIG_X86_64 /* Remaps 64-bit vDSO on the same addr, where it already is */ int kdat_compat_sigreturn_test(void) @@ -72,54 +54,6 @@ int kdat_compat_sigreturn_test(void) } #endif /* CONFIG_X86_64 */ -static int arch_task_compatible(struct parasite_ctl *ctl) -{ - return !user_regs_native(&ctl->orig.regs); -} - -#define USER32_CS 0x23 -#define USER_CS 0x33 - -static bool ldt_task_selectors(pid_t pid) -{ - unsigned long cs; - - errno = 0; - /* - * Offset of register must be from 64-bit set even for - * compatible tasks. Fix this to support native i386 tasks - */ - cs = ptrace(PTRACE_PEEKUSER, pid, offsetof(user_regs_struct64, cs), 0); - if (errno != 0) { - pr_perror("Can't get CS register for %d", pid); - return -1; - } - - return cs != USER_CS && cs != USER32_CS; -} - -bool arch_can_dump_task(struct parasite_ctl *ctl) -{ - pid_t pid = ctl->rpid; - int ret; - - ret = arch_task_compatible(ctl); - if (ret < 0) - return false; - - if (ret && !kdat.has_compat_sigreturn) { - pr_err("Can't dump task %d running in 32-bit mode\n", pid); - return false; - } - - if (ldt_task_selectors(pid)) { - pr_err("Can't dump task %d with LDT descriptors\n", pid); - return false; - } - - return true; -} - int save_task_regs(void *x, user_regs_struct_t *regs, user_fpregs_struct_t *fpregs) { CoreEntry *core = x; diff --git a/criu/arch/x86/include/asm/parasite-syscall.h b/criu/arch/x86/include/asm/parasite-syscall.h index 18c746f6f..fd5b26c7c 100644 --- a/criu/arch/x86/include/asm/parasite-syscall.h +++ b/criu/arch/x86/include/asm/parasite-syscall.h @@ -5,10 +5,6 @@ struct parasite_ctl; -#define ARCH_SI_TRAP SI_KERNEL - -#define __NR(syscall, compat) ((compat) ? __NR32_##syscall : __NR_##syscall) - /* * For x86_32 __NR_mmap inside the kernel represents old_mmap system * call, but since we didn't use it yet lets go further and simply @@ -18,6 +14,4 @@ struct parasite_ctl; #define __NR32_mmap __NR32_mmap2 -void parasite_setup_regs(unsigned long new_ip, void *stack, user_regs_struct_t *regs); - #endif diff --git a/criu/arch/x86/infect.c b/criu/arch/x86/infect.c index 38abde2d9..19d65d76f 100644 --- a/criu/arch/x86/infect.c +++ b/criu/arch/x86/infect.c @@ -3,14 +3,19 @@ #include <sys/uio.h> #include <sys/auxv.h> #include <sys/mman.h> + +#include "asm/processor-flags.h" #include "asm/parasite-syscall.h" #include "uapi/std/syscall-codes.h" +#include "compel/include/asm/syscall.h" #include "err.h" #include "asm/fpu.h" #include "asm/types.h" #include "errno.h" #include "asm/cpu.h" #include "parasite-syscall.h" +#include "ptrace.h" +#include "kerndat.h" #include "infect.h" #include "infect-priv.h" @@ -170,6 +175,77 @@ void *remote_mmap(struct parasite_ctl *ctl, return (void *)map; } +/* + * regs must be inited when calling this function from original context + */ +void parasite_setup_regs(unsigned long new_ip, void *stack, user_regs_struct_t *regs) +{ + set_user_reg(regs, ip, new_ip); + if (stack) + set_user_reg(regs, sp, (unsigned long) stack); + + /* Avoid end of syscall processing */ + set_user_reg(regs, orig_ax, -1); + + /* Make sure flags are in known state */ + set_user_reg(regs, flags, get_user_reg(regs, flags) & + ~(X86_EFLAGS_TF | X86_EFLAGS_DF | X86_EFLAGS_IF)); +} + +#define USER32_CS 0x23 +#define USER_CS 0x33 + +static bool ldt_task_selectors(pid_t pid) +{ + unsigned long cs; + + errno = 0; + /* + * Offset of register must be from 64-bit set even for + * compatible tasks. Fix this to support native i386 tasks + */ + cs = ptrace(PTRACE_PEEKUSER, pid, offsetof(user_regs_struct64, cs), 0); + if (errno != 0) { + pr_perror("Can't get CS register for %d", pid); + return -1; + } + + return cs != USER_CS && cs != USER32_CS; +} + +static int arch_task_compatible(pid_t pid) +{ + user_regs_struct_t r; + int ret = ptrace_get_regs(pid, &r); + + if (ret) + return -1; + + return !user_regs_native(&r); +} + +bool arch_can_dump_task(struct parasite_ctl *ctl) +{ + pid_t pid = ctl->rpid; + int ret; + + ret = arch_task_compatible(pid); + if (ret < 0) + return false; + + if (ret && !kdat.has_compat_sigreturn) { + pr_err("Can't dump task %d running in 32-bit mode\n", pid); + return false; + } + + if (ldt_task_selectors(pid)) { + pr_err("Can't dump task %d with LDT descriptors\n", pid); + return false; + } + + return true; +} + int ptrace_get_regs(pid_t pid, user_regs_struct_t *regs) { struct iovec iov; diff --git a/criu/cr-restore.c b/criu/cr-restore.c index fdceacbc2..b9e9827ee 100644 --- a/criu/cr-restore.c +++ b/criu/cr-restore.c @@ -81,6 +81,7 @@ #include "parasite-syscall.h" #include "files-reg.h" #include "uapi/std/syscall-codes.h" +#include "compel/include/asm/syscall.h" #include "protobuf.h" #include "images/sa.pb-c.h" diff --git a/criu/include/infect-priv.h b/criu/include/infect-priv.h index 3ddd1175f..c994981d1 100644 --- a/criu/include/infect-priv.h +++ b/criu/include/infect-priv.h @@ -3,6 +3,8 @@ #include <stdbool.h> +#define BUILTIN_SYSCALL_SIZE 8 + /* parasite control block */ struct parasite_ctl { int rpid; /* Real pid of the victim */ @@ -46,7 +48,10 @@ extern int compel_syscall(struct parasite_ctl *ctl, int nr, unsigned long *ret, unsigned long arg5, unsigned long arg6); +extern void parasite_setup_regs(unsigned long new_ip, void *stack, user_regs_struct_t *regs); extern void *remote_mmap(struct parasite_ctl *ctl, void *addr, size_t length, int prot, int flags, int fd, off_t offset); +extern bool arch_can_dump_task(struct parasite_ctl *ctl); + #endif diff --git a/criu/include/infect-util.h b/criu/include/infect-util.h new file mode 100644 index 000000000..bd2010c3b --- /dev/null +++ b/criu/include/infect-util.h @@ -0,0 +1,5 @@ +#ifndef __COMPEL_INFECT_UTIL_H__ +#define __COMPEL_INFECT_UTIL_H__ +struct parasite_ctl; +extern int compel_util_send_fd(struct parasite_ctl *ctl, int fd); +#endif diff --git a/criu/include/parasite-syscall.h b/criu/include/parasite-syscall.h index 30cb36b83..88318916b 100644 --- a/criu/include/parasite-syscall.h +++ b/criu/include/parasite-syscall.h @@ -6,8 +6,6 @@ #include "config.h" #include "asm/parasite-syscall.h" -#define BUILTIN_SYSCALL_SIZE 8 - struct parasite_dump_thread; struct parasite_dump_misc; struct parasite_drain_fd; @@ -31,8 +29,6 @@ struct proc_posix_timers_stat; extern int parasite_dump_posix_timers_seized(struct proc_posix_timers_stat *proc_args, struct parasite_ctl *ctl, struct pstree_item *); -extern int parasite_send_fd(struct parasite_ctl *ctl, int fd); - extern int parasite_dump_misc_seized(struct parasite_ctl *ctl, struct parasite_dump_misc *misc); extern int parasite_dump_creds(struct parasite_ctl *ctl, struct _CredsEntry *ce); extern int parasite_dump_thread_leader_seized(struct parasite_ctl *ctl, int pid, struct _CoreEntry *core); @@ -59,6 +55,4 @@ extern struct parasite_tty_args *parasite_dump_tty(struct parasite_ctl *ctl, int extern int parasite_init_threads_seized(struct parasite_ctl *ctl, struct pstree_item *item); extern int parasite_fini_threads_seized(struct parasite_ctl *ctl); -extern bool arch_can_dump_task(struct parasite_ctl *ctl); - #endif /* __CR_PARASITE_SYSCALL_H__ */ diff --git a/criu/infect-util.c b/criu/infect-util.c new file mode 100644 index 000000000..8db32afdf --- /dev/null +++ b/criu/infect-util.c @@ -0,0 +1,20 @@ +#include "int.h" +#include "log.h" +#include "common/bug.h" +#include "lock.h" +#include "util-pie.h" +#include "infect-rpc.h" +#include "infect-util.h" + +int compel_util_send_fd(struct parasite_ctl *ctl, int fd) +{ + int sk; + + sk = compel_rpc_sock(ctl); + if (send_fd(sk, NULL, 0, fd) < 0) { + pr_perror("Can't send file descriptor"); + return -1; + } + return 0; +} + diff --git a/criu/infect.c b/criu/infect.c index 62ec77c36..48ad1effd 100644 --- a/criu/infect.c +++ b/criu/infect.c @@ -6,16 +6,18 @@ #include <signal.h> #include <linux/seccomp.h> +#include "compel/include/asm/ptrace.h" +#include "compel/include/asm/syscall.h" #include "infect.h" #include "ptrace.h" #include "restorer.h" -#include "parasite-syscall.h" #include "pie-relocs.h" #include "parasite-blob.h" #include "sigframe.h" #include "criu-log.h" #include "infect-rpc.h" #include "infect-priv.h" +#include "infect-util.h" #define UNIX_PATH_MAX (sizeof(struct sockaddr_un) - \ (size_t)((struct sockaddr_un *) 0)->sun_path) @@ -556,7 +558,7 @@ static int parasite_init_daemon(struct parasite_ctl *ctl) if (accept_tsock(ctl) < 0) goto err; - if (parasite_send_fd(ctl, log_get_fd())) + if (compel_util_send_fd(ctl, log_get_fd())) goto err; pr_info("Wait for parasite being daemonized...\n"); diff --git a/criu/mem.c b/criu/mem.c index 46389d3cc..757e13668 100644 --- a/criu/mem.c +++ b/criu/mem.c @@ -27,6 +27,7 @@ #include "fault-injection.h" #include "infect.h" #include "infect-rpc.h" +#include "infect-util.h" #include "protobuf.h" #include "images/pagemap.pb-c.h" @@ -236,7 +237,7 @@ static int drain_pages(struct page_pipe *pp, struct parasite_ctl *ctl, ret = compel_rpc_call(PARASITE_CMD_DUMPPAGES, ctl); if (ret < 0) return -1; - ret = parasite_send_fd(ctl, ppb->p[1]); + ret = compel_util_send_fd(ctl, ppb->p[1]); if (ret) return -1; diff --git a/criu/parasite-syscall.c b/criu/parasite-syscall.c index 80a28e420..26cd9afa6 100644 --- a/criu/parasite-syscall.c +++ b/criu/parasite-syscall.c @@ -68,18 +68,6 @@ unsigned long get_exec_start(struct vm_area_list *vmas) return 0; } -int parasite_send_fd(struct parasite_ctl *ctl, int fd) -{ - int sk; - - sk = compel_rpc_sock(ctl); - if (send_fd(sk, NULL, 0, fd) < 0) { - pr_perror("Can't send file descriptor"); - return -1; - } - return 0; -} - /* * We need to detect parasite crashes not to hang on socket operations. * Since CRIU holds parasite with ptrace, it will receive SIGCHLD if the |