diff --git a/compel/arch/aarch64/src/lib/infect.c b/compel/arch/aarch64/src/lib/infect.c index 812ba34a37..170a29b33c 100644 --- a/compel/arch/aarch64/src/lib/infect.c +++ b/compel/arch/aarch64/src/lib/infect.c @@ -60,7 +60,7 @@ int sigreturn_prep_fpu_frame_plain(struct rt_sigframe *sigframe, struct rt_sigfr } int compel_get_task_regs(pid_t pid, user_regs_struct_t *regs, user_fpregs_struct_t *fpsimd, save_regs_t save, - void *arg, __maybe_unused unsigned long flags) + void *arg, __maybe_unused unsigned long flags, __maybe_unused bool pre_dump) { struct iovec iov; int ret; diff --git a/compel/arch/arm/src/lib/infect.c b/compel/arch/arm/src/lib/infect.c index 8b810a88f5..f0b45a9862 100644 --- a/compel/arch/arm/src/lib/infect.c +++ b/compel/arch/arm/src/lib/infect.c @@ -66,7 +66,7 @@ int sigreturn_prep_fpu_frame_plain(struct rt_sigframe *sigframe, struct rt_sigfr #define PTRACE_GETVFPREGS 27 int compel_get_task_regs(pid_t pid, user_regs_struct_t *regs, user_fpregs_struct_t *vfp, save_regs_t save, - void *arg, __maybe_unused unsigned long flags) + void *arg, __maybe_unused unsigned long flags, __maybe_unused bool pre_dump) { int ret = -1; diff --git a/compel/arch/loongarch64/src/lib/infect.c b/compel/arch/loongarch64/src/lib/infect.c index 8e3c19aff2..c67455b24e 100644 --- a/compel/arch/loongarch64/src/lib/infect.c +++ b/compel/arch/loongarch64/src/lib/infect.c @@ -49,7 +49,7 @@ int sigreturn_prep_fpu_frame_plain(struct rt_sigframe *sigframe, struct rt_sigfr } int compel_get_task_regs(pid_t pid, user_regs_struct_t *regs, user_fpregs_struct_t *ext_regs, save_regs_t save, - void *arg, __maybe_unused unsigned long flags) + void *arg, __maybe_unused unsigned long flags, __maybe_unused bool pre_dump) { user_fpregs_struct_t tmp, *fpregs = ext_regs ? ext_regs : &tmp; struct iovec iov; diff --git a/compel/arch/mips/src/lib/infect.c b/compel/arch/mips/src/lib/infect.c index 0e98aaee3f..a5b1e9e967 100644 --- a/compel/arch/mips/src/lib/infect.c +++ b/compel/arch/mips/src/lib/infect.c @@ -120,7 +120,7 @@ int sigreturn_prep_fpu_frame_plain(struct rt_sigframe *sigframe, struct rt_sigfr } int compel_get_task_regs(pid_t pid, user_regs_struct_t *regs, user_fpregs_struct_t *xs, save_regs_t save, - void *arg, __maybe_unused unsigned long flags) + void *arg, __maybe_unused unsigned long flags, __maybe_unused bool pre_dump) { int ret = -1; diff --git a/compel/arch/ppc64/src/lib/infect.c b/compel/arch/ppc64/src/lib/infect.c index 84c2b1d7c3..72502fc527 100644 --- a/compel/arch/ppc64/src/lib/infect.c +++ b/compel/arch/ppc64/src/lib/infect.c @@ -392,7 +392,7 @@ static int __get_task_regs(pid_t pid, user_regs_struct_t *regs, user_fpregs_stru } int compel_get_task_regs(pid_t pid, user_regs_struct_t *regs, user_fpregs_struct_t *fpregs, save_regs_t save, - void *arg, __maybe_unused unsigned long flags) + void *arg, __maybe_unused unsigned long flags, __maybe_unused bool pre_dump) { int ret; diff --git a/compel/arch/s390/src/lib/infect.c b/compel/arch/s390/src/lib/infect.c index 85dfc3a4d4..abeebcfc12 100644 --- a/compel/arch/s390/src/lib/infect.c +++ b/compel/arch/s390/src/lib/infect.c @@ -294,7 +294,7 @@ static int s390_disable_ri_bit(pid_t pid, user_regs_struct_t *regs) * Prepare task registers for restart */ int compel_get_task_regs(pid_t pid, user_regs_struct_t *regs, user_fpregs_struct_t *fpregs, save_regs_t save, - void *arg, __maybe_unused unsigned long flags) + void *arg, __maybe_unused unsigned long flags, __maybe_unused bool pre_dump) { struct iovec iov; int rewind; diff --git a/compel/arch/x86/src/lib/infect.c b/compel/arch/x86/src/lib/infect.c index a07b1c9f37..2bd4bb4607 100644 --- a/compel/arch/x86/src/lib/infect.c +++ b/compel/arch/x86/src/lib/infect.c @@ -398,7 +398,7 @@ static int corrupt_extregs(pid_t pid) } int compel_get_task_regs(pid_t pid, user_regs_struct_t *regs, user_fpregs_struct_t *xs, save_regs_t save, - void *arg, unsigned long flags) + void *arg, unsigned long flags, bool pre_dump) { int ret = -1; @@ -415,8 +415,13 @@ int compel_get_task_regs(pid_t pid, user_regs_struct_t *regs, user_fpregs_struct set_user_reg(regs, ip, get_user_reg(regs, ip) - 2); break; case -ERESTART_RESTARTBLOCK: - pr_warn("Will restore %d with interrupted system call\n", pid); - set_user_reg(regs, ax, -EINTR); + if (pre_dump) { + set_user_reg(regs, ax, get_user_reg(regs, orig_ax)); + set_user_reg(regs, ip, get_user_reg(regs, ip) - 2); + } else { + pr_warn("Will restore %d with interrupted system call\n", pid); + set_user_reg(regs, ax, -EINTR); + } break; } } diff --git a/compel/include/infect-priv.h b/compel/include/infect-priv.h index 9d34428393..cdc6a96cf2 100644 --- a/compel/include/infect-priv.h +++ b/compel/include/infect-priv.h @@ -70,7 +70,7 @@ extern bool arch_can_dump_task(struct parasite_ctl *ctl); * @pid: mystery */ extern int compel_get_task_regs(pid_t pid, user_regs_struct_t *regs, user_fpregs_struct_t *ext_regs, save_regs_t save, - void *arg, unsigned long flags); + void *arg, unsigned long flags, bool pre_dum); extern int compel_set_task_ext_regs(pid_t pid, user_fpregs_struct_t *ext_regs); extern int arch_fetch_sas(struct parasite_ctl *ctl, struct rt_sigframe *s); extern int sigreturn_prep_regs_plain(struct rt_sigframe *sigframe, user_regs_struct_t *regs, diff --git a/compel/include/uapi/infect.h b/compel/include/uapi/infect.h index 7e6134f4bc..383b004561 100644 --- a/compel/include/uapi/infect.h +++ b/compel/include/uapi/infect.h @@ -103,6 +103,7 @@ typedef int (*make_sigframe_t)(void *, struct rt_sigframe *, struct rt_sigframe struct infect_ctx { int sock; + bool pre_dump; /* * Regs manipulation context. */ diff --git a/compel/src/lib/infect.c b/compel/src/lib/infect.c index 1e3ffb9670..09d62ac989 100644 --- a/compel/src/lib/infect.c +++ b/compel/src/lib/infect.c @@ -747,7 +747,7 @@ static int parasite_start_daemon(struct parasite_ctl *ctl) * while in daemon it is not such. */ - if (compel_get_task_regs(pid, &ctl->orig.regs, &ext_regs, ictx->save_regs, ictx->regs_arg, ictx->flags)) { + if (compel_get_task_regs(pid, &ctl->orig.regs, &ext_regs, ictx->save_regs, ictx->regs_arg, ictx->flags, ictx->pre_dump)) { pr_err("Can't obtain regs for thread %d\n", pid); return -1; } @@ -1751,7 +1751,7 @@ k_rtsigset_t *compel_task_sigmask(struct parasite_ctl *ctl) int compel_get_thread_regs(struct parasite_thread_ctl *tctl, save_regs_t save, void *arg) { - return compel_get_task_regs(tctl->tid, &tctl->th.regs, &tctl->th.ext_regs, save, arg, tctl->ctl->ictx.flags); + return compel_get_task_regs(tctl->tid, &tctl->th.regs, &tctl->th.ext_regs, save, arg, tctl->ctl->ictx.flags, tctl->ctl->ictx.pre_dump); } struct infect_ctx *compel_infect_ctx(struct parasite_ctl *ctl) diff --git a/criu/cr-dump.c b/criu/cr-dump.c index 1bc5d934f5..598b8ef773 100644 --- a/criu/cr-dump.c +++ b/criu/cr-dump.c @@ -1488,7 +1488,7 @@ static int pre_dump_one_task(struct pstree_item *item, InventoryEntry *parent_ie } ret = -1; - parasite_ctl = parasite_infect_seized(pid, item, &vmas); + parasite_ctl = parasite_infect_seized(pid, item, &vmas, true); if (!parasite_ctl) { pr_err("Can't infect (pid: %d) with parasite\n", pid); goto err_free; @@ -1605,7 +1605,7 @@ static int dump_one_task(struct pstree_item *item, InventoryEntry *parent_ie) goto err; } - parasite_ctl = parasite_infect_seized(pid, item, &vmas); + parasite_ctl = parasite_infect_seized(pid, item, &vmas, false); if (!parasite_ctl) { pr_err("Can't infect (pid: %d) with parasite\n", pid); goto err; diff --git a/criu/include/parasite-syscall.h b/criu/include/parasite-syscall.h index 4a8ec2fee6..3753f8eb9d 100644 --- a/criu/include/parasite-syscall.h +++ b/criu/include/parasite-syscall.h @@ -33,7 +33,7 @@ extern int parasite_drain_fds_seized(struct parasite_ctl *ctl, struct parasite_d extern int parasite_get_proc_fd_seized(struct parasite_ctl *ctl); extern struct parasite_ctl *parasite_infect_seized(pid_t pid, struct pstree_item *item, - struct vm_area_list *vma_area_list); + struct vm_area_list *vma_area_list, bool pre_dump); extern void parasite_ensure_args_size(unsigned long sz); extern unsigned long get_exec_start(struct vm_area_list *); diff --git a/criu/parasite-syscall.c b/criu/parasite-syscall.c index a88f8a66f2..971d1671fc 100644 --- a/criu/parasite-syscall.c +++ b/criu/parasite-syscall.c @@ -375,7 +375,7 @@ static int parasite_prepare_threads(struct parasite_ctl *ctl, struct pstree_item return -1; } -struct parasite_ctl *parasite_infect_seized(pid_t pid, struct pstree_item *item, struct vm_area_list *vma_area_list) +struct parasite_ctl *parasite_infect_seized(pid_t pid, struct pstree_item *item, struct vm_area_list *vma_area_list, bool pre_dump) { struct parasite_ctl *ctl; struct infect_ctx *ictx; @@ -400,6 +400,7 @@ struct parasite_ctl *parasite_infect_seized(pid_t pid, struct pstree_item *item, ictx = compel_infect_ctx(ctl); + ictx->pre_dump = pre_dump; ictx->open_proc = do_open_proc; ictx->child_handler = sigchld_handler; ictx->orig_handler.sa_handler = SIG_DFL;