Skip to content

Commit

Permalink
compel: when pre-dump, handle ERESTART_RESTARTBLOCK as ERESTARTNOINTR
Browse files Browse the repository at this point in the history
When pre-dump, if thread is in syscall like sleep or poll, it will
return -ERESTART_RESTARTBLOCK. In that case, if we set ax register to -EINTR,
it will break the original syscall. Instead, we can restore original
syscall.

Signed-off-by: Longjun Luo <luolongjuna@gmail.com>
  • Loading branch information
anatasluo committed Nov 4, 2024
1 parent dcc3b49 commit 860e527
Show file tree
Hide file tree
Showing 13 changed files with 23 additions and 16 deletions.
2 changes: 1 addition & 1 deletion compel/arch/aarch64/src/lib/infect.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion compel/arch/arm/src/lib/infect.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
2 changes: 1 addition & 1 deletion compel/arch/loongarch64/src/lib/infect.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion compel/arch/mips/src/lib/infect.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
2 changes: 1 addition & 1 deletion compel/arch/ppc64/src/lib/infect.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
2 changes: 1 addition & 1 deletion compel/arch/s390/src/lib/infect.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
11 changes: 8 additions & 3 deletions compel/arch/x86/src/lib/infect.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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;
}
}
Expand Down
2 changes: 1 addition & 1 deletion compel/include/infect-priv.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
1 change: 1 addition & 0 deletions compel/include/uapi/infect.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*/
Expand Down
4 changes: 2 additions & 2 deletions compel/src/lib/infect.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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)
Expand Down
4 changes: 2 additions & 2 deletions criu/cr-dump.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion criu/include/parasite-syscall.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 *);

Expand Down
3 changes: 2 additions & 1 deletion criu/parasite-syscall.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down

0 comments on commit 860e527

Please sign in to comment.