From 40f5d9b4592788f9975605625cc749dea7f2bec2 Mon Sep 17 00:00:00 2001 From: Andrei Vagin Date: Sun, 7 Aug 2022 16:36:15 -0700 Subject: compel: clear a breakpoint right after it's been triggered Breakpoints are used to stop as close as possible to a target system call. First, we don't need it after this point. Second, PTRACE_CONT can't pass through a breakpoint on arm64. Signed-off-by: Andrei Vagin --- compel/src/lib/infect.c | 15 +++++++++++---- criu/cr-restore.c | 21 --------------------- 2 files changed, 11 insertions(+), 25 deletions(-) diff --git a/compel/src/lib/infect.c b/compel/src/lib/infect.c index 7d7865480..6413a1860 100644 --- a/compel/src/lib/infect.c +++ b/compel/src/lib/infect.c @@ -1418,9 +1418,6 @@ static int parasite_fini_seized(struct parasite_ctl *ctl) if (compel_stop_on_syscall(1, __NR(rt_sigreturn, 0), __NR(rt_sigreturn, 1))) return -1; - if (ptrace_flush_breakpoints(pid)) - return -1; - /* * All signals are unblocked now. The kernel notifies about leaving * syscall before starting to deliver signals. All parasite code are @@ -1650,8 +1647,18 @@ int compel_stop_on_syscall(int tasks, const int sys_nr, const int sys_nr_compat) pr_debug("%d was trapped\n", pid); - if ((WSTOPSIG(status) & PTRACE_SYSCALL_TRAP) == 0) + if ((WSTOPSIG(status) & PTRACE_SYSCALL_TRAP) == 0) { + /* + * On some platforms such as ARM64, it is impossible to + * pass through a breakpoint, so let's clear it right + * after it has been triggered. + */ + if (ptrace_flush_breakpoints(pid)) { + pr_err("Unable to clear breakpoints\n"); + return -1; + } goto goon; + } if (trace == TRACE_EXIT) { trace = TRACE_ENTER; pr_debug("`- Expecting exit\n"); diff --git a/criu/cr-restore.c b/criu/cr-restore.c index 9a1b23999..9c480be78 100644 --- a/criu/cr-restore.c +++ b/criu/cr-restore.c @@ -2071,24 +2071,6 @@ static int catch_tasks(bool root_seized) return 0; } -static int clear_breakpoints(void) -{ - struct pstree_item *item; - int ret = 0, i; - - if (fault_injected(FI_NO_BREAKPOINTS)) - return 0; - - for_each_pstree_item(item) { - if (!task_alive(item)) - continue; - for (i = 0; i < item->nr_threads; i++) - ret |= ptrace_flush_breakpoints(item->threads[i].real); - } - - return ret; -} - static void finalize_restore(void) { struct pstree_item *item; @@ -2459,9 +2441,6 @@ skip_ns_bouncing: goto out_kill_network_unlocked; } - if (clear_breakpoints()) - pr_err("Unable to flush breakpoints\n"); - finalize_restore(); /* * Some external devices such as GPUs might need a very late -- cgit v1.2.3