diff options
author | Andrei Vagin <avagin@gmail.com> | 2022-08-08 02:36:15 +0300 |
---|---|---|
committer | Andrei Vagin <avagin@gmail.com> | 2022-08-15 08:23:49 +0300 |
commit | 40f5d9b4592788f9975605625cc749dea7f2bec2 (patch) | |
tree | 7534ffcc23429fe38ee09411b42cf74a3f32b0c8 | |
parent | 373281f50dfa9069058aa0bfde05c4f4a40ddd8a (diff) |
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 <avagin@gmail.com>
-rw-r--r-- | compel/src/lib/infect.c | 15 | ||||
-rw-r--r-- | 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 |