From 47412ba0d9ce6283071973387bf5b34bf876bb9a Mon Sep 17 00:00:00 2001 From: "fu.lin" Date: Wed, 1 Dec 2021 09:44:07 +0800 Subject: [PATCH 54/72] ptrace: trace specific syscall criu use `ptrace(PTRACE_SYSCALL)` to watch whether the tracee steps in correct status, it isn't necessory to stop tracee at every syscall. Therefore, customizing `ptrace(PTRACE_SYSCALL_NR)` to make tracee stop at the specific syscall can save time (1000 threads consume about 140ms). ptrace syntax: long ptrace(PTRACE_SYSCALL_NR, pid_t pid, void *addr, void *data); The argument `addr` is unused in original `ptrace(PTRACE_SYSCALL)`, Here `ptrace(PTRACE_SYSCALL_NR)` use `addr` parameter to give the specific sysno which is wanted to trace. use `criu check` to generate `/run/criu.kdat` before the first usage of criu, or auto-check during `criu {dump, restore}`. Conflict:NA Reference:https://gitee.com/src-openeuler/criu/pulls/25 Signed-off-by: fu.lin --- compel/Makefile | 1 + compel/include/uapi/bisect.h | 30 +++++++ compel/include/uapi/infect.h | 15 +++- compel/src/lib/bisect.c | 92 +++++++++++++++++++ compel/src/lib/infect.c | 167 ++++++++++++++++++++++++++++++++--- criu/cr-dump.c | 2 +- criu/cr-restore.c | 97 +++++++++++++++++++- criu/include/kerndat.h | 1 + criu/kerndat.c | 61 +++++++++++++ 9 files changed, 450 insertions(+), 16 deletions(-) create mode 100644 compel/include/uapi/bisect.h create mode 100644 compel/src/lib/bisect.c diff --git a/compel/Makefile b/compel/Makefile index b79aee6..2168a26 100644 --- a/compel/Makefile +++ b/compel/Makefile @@ -27,6 +27,7 @@ lib-y += src/lib/infect-rpc.o lib-y += src/lib/infect-util.o lib-y += src/lib/infect.o lib-y += src/lib/ptrace.o +lib-y += src/lib/bisect.o ifeq ($(ARCH),x86) lib-y += arch/$(ARCH)/src/lib/thread_area.o diff --git a/compel/include/uapi/bisect.h b/compel/include/uapi/bisect.h new file mode 100644 index 0000000..55ebcbd --- /dev/null +++ b/compel/include/uapi/bisect.h @@ -0,0 +1,30 @@ +#ifndef __COMPEL_BISECT_H__ +#define __COMPEL_BISECT_H__ + +#include + +enum tf { + TRACE_INTERRUPT, + TRACE_SYSCALL_ENTER, + TRACE_SYSCALL_EXIT, +}; + +struct trace_flag { + pid_t key; + enum tf flag; +}; + +struct bisect_meta { + int size; + int used; + void *data; /* data pointer array */ + void *__data; /* data array */ +}; + +struct trace_flag *tf_bisect(struct bisect_meta *meta, pid_t key); +struct trace_flag *tf_insert(struct bisect_meta *meta, pid_t key); +int tf_create(struct bisect_meta *meta, int len); +void tf_destroy(struct bisect_meta *meta); +void tf_clear(struct bisect_meta *meta); + +#endif /* __COMPEL_BISECT_H__ */ diff --git a/compel/include/uapi/infect.h b/compel/include/uapi/infect.h index 389878e..a23782e 100644 --- a/compel/include/uapi/infect.h +++ b/compel/include/uapi/infect.h @@ -8,11 +8,16 @@ #include #include #include +#include #include "common/compiler.h" #define PARASITE_START_AREA_MIN (4096) +#ifndef PTRACE_SYSCALL_NR +# define PTRACE_SYSCALL_NR 0xff00 +#endif + extern int __must_check compel_interrupt_task(int pid); struct seize_task_status { @@ -41,7 +46,7 @@ extern int __must_check compel_infect(struct parasite_ctl *ctl, unsigned long nr extern struct parasite_thread_ctl __must_check *compel_prepare_thread(struct parasite_ctl *ctl, int pid); extern void compel_release_thread(struct parasite_thread_ctl *); -extern int __must_check compel_stop_daemon(struct parasite_ctl *ctl); +extern int __must_check compel_stop_daemon(struct parasite_ctl *ctl, bool customize); extern int __must_check compel_cure_remote(struct parasite_ctl *ctl); extern int __must_check compel_cure_local(struct parasite_ctl *ctl); extern int __must_check compel_cure(struct parasite_ctl *ctl); @@ -83,6 +88,14 @@ extern int __must_check compel_stop_pie(pid_t pid, void *addr, enum trace_flags extern int __must_check compel_unmap(struct parasite_ctl *ctl, unsigned long addr); +extern int __must_check compel_stop_on_syscall_customize(int tasks, + const int sys_nr, const int exit_sys_nr, struct bisect_meta *meta); + +extern int __must_check compel_stop_pie_customize(pid_t pid, + const int sys_nr, struct trace_flag *tf); + +extern int __must_check compel_unmap_customize(struct parasite_ctl *ctl, unsigned long addr); + extern int compel_mode_native(struct parasite_ctl *ctl); extern k_rtsigset_t *compel_task_sigmask(struct parasite_ctl *ctl); diff --git a/compel/src/lib/bisect.c b/compel/src/lib/bisect.c new file mode 100644 index 0000000..807a5a9 --- /dev/null +++ b/compel/src/lib/bisect.c @@ -0,0 +1,92 @@ +#include + +#include "log.h" +#include "common/xmalloc.h" +#include "bisect.h" + +struct trace_flag *tf_bisect(struct bisect_meta *meta, pid_t key) +{ + struct trace_flag **tfs = meta->data; + int lo = 0, hi = meta->used, mid; + + if (meta->used <= 0) + return NULL; + + while (lo < hi) { + mid = (int)((lo + hi) / 2); + if (tfs[mid]->key == key) { + return tfs[mid]; + } else if (tfs[mid]->key > key) { + hi = mid; + } else { + lo = mid + 1; + } + } + + return NULL; +} + +/* used in cr-restore */ +struct trace_flag *tf_insert(struct bisect_meta *meta, pid_t key) +{ + struct trace_flag **tfs = meta->data; + struct trace_flag *tf = &((struct trace_flag *)meta->__data)[meta->used]; + int i = 0, j = 0; + + if (meta->used == meta->size) + return NULL; + + for (i = 0; i < meta->used; i++) { + if (tfs[i]->key >= key) /* impossible condition: `tfs[i]->key == key` */ + break; + } + + j = meta->used; + meta->used += 1; + + while (j > i) { + tfs[j] = tfs[j-1]; + j -= 1; + } + + tfs[i] = tf; + tf->key = key; + + return tf; +} + +int tf_create(struct bisect_meta *meta, int len) +{ + struct trace_flag *tfs; + struct trace_flag **tfs_ptr; + + tfs = xzalloc(sizeof(*tfs) * len); + if (tfs == NULL) + return -1; + + tfs_ptr = xmalloc(sizeof(*tfs_ptr) * len); + if (tfs_ptr == NULL) + goto err; + + meta->size = len; + meta->used = 0; + meta->__data = tfs; + meta->data = tfs_ptr; + + return 0; +err: + xfree(tfs); + return -1; +} + +void tf_destroy(struct bisect_meta *meta) +{ + xfree(meta->__data); + xfree(meta->data); +} + +void tf_clear(struct bisect_meta *meta) +{ + meta->used = 0; + __builtin_memset(meta->data, 0, sizeof(struct trace_flag **)*meta->size); +} diff --git a/compel/src/lib/infect.c b/compel/src/lib/infect.c index 6a13cc1..f9b8832 100644 --- a/compel/src/lib/infect.c +++ b/compel/src/lib/infect.c @@ -449,7 +449,7 @@ static int restore_child_handler(struct parasite_ctl *ctl) } static int parasite_run(pid_t pid, int cmd, unsigned long ip, void *stack, user_regs_struct_t *regs, - struct thread_ctx *octx) + struct thread_ctx *octx, void *addr) { k_rtsigset_t block; @@ -470,7 +470,7 @@ static int parasite_run(pid_t pid, int cmd, unsigned long ip, void *stack, user_ goto err_regs; } - if (ptrace(cmd, pid, NULL, NULL)) { + if (ptrace(cmd, pid, addr, NULL)) { pr_perror("Can't run parasite at %d", pid); goto err_cont; } @@ -575,7 +575,7 @@ int compel_execute_syscall(struct parasite_ctl *ctl, user_regs_struct_t *regs, c return -1; } - err = parasite_run(pid, PTRACE_CONT, ctl->ictx.syscall_ip, 0, regs, &ctl->orig); + err = parasite_run(pid, PTRACE_CONT, ctl->ictx.syscall_ip, 0, regs, &ctl->orig, NULL); if (!err) err = parasite_trap(ctl, pid, regs, &ctl->orig, false); @@ -592,7 +592,7 @@ int compel_run_at(struct parasite_ctl *ctl, unsigned long ip, user_regs_struct_t user_regs_struct_t regs = ctl->orig.regs; int ret; - ret = parasite_run(ctl->rpid, PTRACE_CONT, ip, 0, ®s, &ctl->orig); + ret = parasite_run(ctl->rpid, PTRACE_CONT, ip, 0, ®s, &ctl->orig, NULL); if (!ret) ret = parasite_trap(ctl, ctl->rpid, ret_regs ? ret_regs : ®s, &ctl->orig, false); return ret; @@ -641,7 +641,7 @@ static int parasite_init_daemon(struct parasite_ctl *ctl) goto err; regs = ctl->orig.regs; - if (parasite_run(pid, PTRACE_CONT, ctl->parasite_ip, ctl->rstack, ®s, &ctl->orig)) + if (parasite_run(pid, PTRACE_CONT, ctl->parasite_ip, ctl->rstack, ®s, &ctl->orig, NULL)) goto err; futex_wait_while_eq(&args->daemon_connected, 0); @@ -1303,7 +1303,7 @@ static bool task_in_parasite(struct parasite_ctl *ctl, user_regs_struct_t *regs) return addr >= ctl->remote_map && addr < ctl->remote_map + ctl->map_length; } -static int parasite_fini_seized(struct parasite_ctl *ctl) +static int parasite_fini_seized(struct parasite_ctl *ctl, bool customize) { pid_t pid = ctl->rpid; user_regs_struct_t regs; @@ -1348,6 +1348,34 @@ static int parasite_fini_seized(struct parasite_ctl *ctl) if (ret) return -1; + /* use customize ptrace */ + if (customize) { + struct trace_flag tf = { .key = pid, .flag = TRACE_SYSCALL_ENTER }; + struct trace_flag *tf_ptr[] = { &tf }; + struct bisect_meta meta = { + .size = 1, + .used = 1, + .__data = &tf, + .data = tf_ptr, + }; + + ret = compel_stop_pie_customize(pid, __NR(rt_sigreturn, 0), &tf); + if (ret < 0) + return ret; + + /* The process is going to execute the required syscall, the + * original syscall should be forgot(set `-1`) in + * `syscall_trace_enter()` handler in kernel when no other + * else operation in tracer. + * + * Note: -1 means NO_SYSCALL which is defined in + * `arch/arm64/include/asm/ptrace.h`. + */ + return compel_stop_on_syscall_customize(1, + __NR(rt_sigreturn, 0), + -1, &meta); + } + /* Go to sigreturn as closer as we can */ ret = compel_stop_pie(pid, ctl->sigreturn_addr, &flag, ctl->ictx.flags & INFECT_NO_BREAKPOINTS); if (ret < 0) @@ -1368,7 +1396,7 @@ static int parasite_fini_seized(struct parasite_ctl *ctl) return 0; } -int compel_stop_daemon(struct parasite_ctl *ctl) +int compel_stop_daemon(struct parasite_ctl *ctl, bool customize) { if (ctl->daemonized) { /* @@ -1378,7 +1406,7 @@ int compel_stop_daemon(struct parasite_ctl *ctl) if (ctl->tsock < 0) return -1; - if (parasite_fini_seized(ctl)) { + if (parasite_fini_seized(ctl, customize)) { close_safe(&ctl->tsock); return -1; } @@ -1394,7 +1422,7 @@ int compel_cure_remote(struct parasite_ctl *ctl) long ret; int err; - if (compel_stop_daemon(ctl)) + if (compel_stop_daemon(ctl, false)) return -1; if (!ctl->remote_map) @@ -1461,7 +1489,7 @@ int compel_run_in_thread(struct parasite_thread_ctl *tctl, unsigned int cmd) *ctl->cmd = cmd; - ret = parasite_run(pid, PTRACE_CONT, ctl->parasite_ip, stack, ®s, octx); + ret = parasite_run(pid, PTRACE_CONT, ctl->parasite_ip, stack, ®s, octx, NULL); if (ret == 0) ret = parasite_trap(ctl, pid, ®s, octx, true); if (ret == 0) @@ -1484,7 +1512,7 @@ int compel_unmap(struct parasite_ctl *ctl, unsigned long addr) pid_t pid = ctl->rpid; int ret = -1; - ret = parasite_run(pid, PTRACE_SYSCALL, addr, ctl->rstack, ®s, &ctl->orig); + ret = parasite_run(pid, PTRACE_SYSCALL, addr, ctl->rstack, ®s, &ctl->orig, NULL); if (ret) goto err; @@ -1500,6 +1528,45 @@ err: return ret; } +int compel_unmap_customize(struct parasite_ctl *ctl, unsigned long addr) +{ + user_regs_struct_t regs = ctl->orig.regs; + pid_t pid = ctl->rpid; + int ret = -1; + struct trace_flag tf = { .key = pid, .flag = TRACE_SYSCALL_ENTER }; + struct trace_flag *tf_ptr[] = { &tf }; + struct bisect_meta meta = { + .size = 1, + .used = 1, + .__data = &tf, + .data = tf_ptr, + }; + + /* + * Here it parasite code. Unlike trap code `compel_stop_pie()`, it + * won't let tracee forget the original syscall. In such way, tracer + * just trace the syscall called by tracee. The log likes the following + * if tracee forget syscall: + * + * [ 817.638332] set pid 1877 ptrace sysno 215 + * [ 817.638343] syscall_trace_enter: pid 1877 ptrace_sysno 0 current_sysno 215 + * [ 817.638363] (00.006280) Error (compel/src/lib/infect.c:1582): 1877 (native) is going to execute the syscall 215, required is 215 + * [ 817.638368] set pid 1877 ptrace sysno 0 + * [ 817.638402] syscall_trace_exit: pid 1877 ptrace_sysno 0 current_sysno 215 + */ + ret = parasite_run(pid, PTRACE_SYSCALL_NR, addr, ctl->rstack, ®s, + &ctl->orig, (void *)(long)__NR(munmap, 0)); + if (ret) + goto err; + + ret = compel_stop_on_syscall_customize(1, __NR(munmap, 0), 0, &meta); + + if (restore_thread_ctx(pid, &ctl->orig, false)) + ret = -1; +err: + return ret; +} + int compel_stop_pie(pid_t pid, void *addr, enum trace_flags *tf, bool no_bp) { int ret; @@ -1535,6 +1602,17 @@ int compel_stop_pie(pid_t pid, void *addr, enum trace_flags *tf, bool no_bp) return 0; } +int compel_stop_pie_customize(pid_t pid, const int sys_nr, struct trace_flag *tf) +{ + if (ptrace(PTRACE_SYSCALL_NR, pid, sys_nr, NULL)) { + pr_perror("Unable to restart the %d process", pid); + return -1; + } + + tf->flag = TRACE_SYSCALL_ENTER; + return 0; +} + static bool task_is_trapped(int status, pid_t pid) { if (WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP) @@ -1642,6 +1720,73 @@ int compel_stop_on_syscall(int tasks, const int sys_nr, const int sys_nr_compat, return 0; } +int compel_stop_on_syscall_customize(int tasks, const int sys_nr, + const int exit_sys_nr, struct bisect_meta *meta) +{ + struct trace_flag *tf; + user_regs_struct_t regs; + int status, ret; + pid_t pid; + + while (tasks) { + pid = wait4(-1, &status, __WALL, NULL); + if (pid == -1) { + pr_perror("wait4 failed"); + return -1; + } + + tf = tf_bisect(meta, pid); + if (tf == NULL) { + pr_warn("Unexpected task %d, state %d signal %d: %s\n", + pid, WEXITSTATUS(status), + WTERMSIG(status), strsignal(WTERMSIG(status))); + continue; + } + + if (!task_is_trapped(status, pid)) + return -1; + + switch (tf->flag) { + case TRACE_SYSCALL_ENTER: + pr_debug("%d was trapped\n", pid); + pr_debug("`- Expecting exit\n"); + + ret = ptrace_get_regs(pid, ®s); + if (ret) { + pr_perror("ptrace"); + return -1; + } + + if (is_required_syscall(®s, pid, sys_nr, sys_nr)) { + ret = ptrace(PTRACE_SYSCALL_NR, pid, exit_sys_nr, NULL); + if (ret) { + pr_perror("ptrace"); + return -1; + } + tf->flag = TRACE_SYSCALL_EXIT; + } else { + pr_warn("Impossible condition, check the system, try our best to restore...\n"); + ret = ptrace(PTRACE_SYSCALL_NR, pid, sys_nr, NULL); + if (ret) { + pr_perror("ptrace"); + return -1; + } + } + break; + case TRACE_SYSCALL_EXIT: + pr_debug("%d was stopped\n", pid); + tasks--; + break; + + default: + pr_err("pid %d invalid status: %d\n", pid, tf->flag); + return -1; + } + } + + return 0; +} + int compel_mode_native(struct parasite_ctl *ctl) { return user_regs_native(&ctl->orig.regs); diff --git a/criu/cr-dump.c b/criu/cr-dump.c index ee826c0..9253e91 100644 --- a/criu/cr-dump.c +++ b/criu/cr-dump.c @@ -1708,7 +1708,7 @@ static int dump_one_task(struct pstree_item *item, InventoryEntry *parent_ie) goto err_cure; } - ret = compel_stop_daemon(parasite_ctl); + ret = compel_stop_daemon(parasite_ctl, kdat.has_customize_ptrace); if (ret) { pr_err("Can't stop daemon in parasite (pid: %d)\n", pid); goto err_cure; diff --git a/criu/cr-restore.c b/criu/cr-restore.c index d19768d..b0b3d30 100644 --- a/criu/cr-restore.c +++ b/criu/cr-restore.c @@ -2181,6 +2181,64 @@ static int catch_tasks(bool root_seized, enum trace_flags *flag) return 0; } +static int cache_tasks_customize(bool root_seized, struct bisect_meta *meta) +{ + struct pstree_item *item; + struct trace_flag *tf; + + for_each_pstree_item(item) { + int status, i, ret; + pid_t pid; + + if (!task_alive(item)) + continue; + + if (item->nr_threads == 1) { + item->threads[0].real = item->pid->real; + } else { + if (parse_threads(item->pid->real, &item->threads, &item->nr_threads)) + return -1; + } + + for (i = 0; i < item->nr_threads; i++) { + pid = item->threads[i].real; + + if (ptrace(PTRACE_INTERRUPT, pid, 0, 0)) { + pr_perror("Can't interrupt the %d task", pid); + return -1; + } + + tf = tf_insert(meta, pid); + if (tf == NULL) { + pr_err("Can't find trace flag for %d, used %d\n", + pid, meta->used); + return -1; + } + tf->flag = TRACE_INTERRUPT; + } + + for (i = 0; i < item->nr_threads; i++) { + pid = wait4(-1, &status, __WALL, NULL); + + tf = tf_bisect(meta, pid); + if (tf == NULL) { + pr_err("Can't find trace flag for %d, used %d\n", + pid, meta->used); + return -1; + } + + ret = compel_stop_pie_customize(pid, + __NR(rt_sigreturn, 0), + tf); + if (ret < 0) + return -1; + + } + } + + return 0; +} + static int clear_breakpoints(void) { struct pstree_item *item; @@ -2207,6 +2265,7 @@ static void finalize_restore(void) pid_t pid = item->pid->real; struct parasite_ctl *ctl; unsigned long restorer_addr; + int retval; if (!task_alive(item)) continue; @@ -2217,7 +2276,12 @@ static void finalize_restore(void) continue; restorer_addr = (unsigned long)rsti(item)->munmap_restorer; - if (compel_unmap(ctl, restorer_addr)) + if (!kdat.has_customize_ptrace) + retval = compel_unmap(ctl, restorer_addr); + else + retval = compel_unmap_customize(ctl, restorer_addr); + + if (retval) pr_err("Failed to unmap restorer from %d\n", pid); xfree(ctl); @@ -2333,11 +2397,18 @@ static void reap_zombies(void) static int restore_root_task(struct pstree_item *init) { + struct bisect_meta tfs_meta; enum trace_flags flag = TRACE_ALL; int ret, fd, mnt_ns_fd = -1; int root_seized = 0; struct pstree_item *item; + if (kdat.has_customize_ptrace + && tf_create(&tfs_meta, task_entries->nr_threads) != 0) { + pr_err("Can't alloc memory, tf_create failed\n"); + return -1; + } + ret = run_scripts(ACT_PRE_RESTORE); if (ret != 0) { pr_err("Aborting restore due to pre-restore script ret code %d\n", ret); @@ -2551,7 +2622,12 @@ skip_ns_bouncing: timing_stop(TIME_RESTORE); - if (catch_tasks(root_seized, &flag)) { + if (!kdat.has_customize_ptrace) + ret = catch_tasks(root_seized, &flag); + else + ret = cache_tasks_customize(root_seized, &tfs_meta); + + if (ret) { pr_err("Can't catch all tasks\n"); goto out_kill_network_unlocked; } @@ -2561,7 +2637,15 @@ skip_ns_bouncing: __restore_switch_stage(CR_STATE_COMPLETE); - ret = compel_stop_on_syscall(task_entries->nr_threads, __NR(rt_sigreturn, 0), __NR(rt_sigreturn, 1), flag); + if (!kdat.has_customize_ptrace) { + ret = compel_stop_on_syscall(task_entries->nr_threads, + __NR(rt_sigreturn, 0), + __NR(rt_sigreturn, 1), flag); + } else { + ret = compel_stop_on_syscall_customize(task_entries->nr_threads, + __NR(rt_sigreturn, 0), + -1, &tfs_meta); + } if (ret) { pr_err("Can't stop all tasks on rt_sigreturn\n"); goto out_kill_network_unlocked; @@ -2600,6 +2684,9 @@ skip_ns_bouncing: reap_zombies(); } + if (kdat.has_customize_ptrace) + tf_destroy(&tfs_meta); + return 0; out_kill_network_unlocked: @@ -2631,6 +2718,10 @@ out: stop_usernsd(); __restore_switch_stage(CR_STATE_FAIL); pr_err("Restoring FAILED.\n"); + + if (kdat.has_customize_ptrace) + tf_destroy(&tfs_meta); + return -1; } diff --git a/criu/include/kerndat.h b/criu/include/kerndat.h index 3979939..8034db9 100644 --- a/criu/include/kerndat.h +++ b/criu/include/kerndat.h @@ -77,6 +77,7 @@ struct kerndat_s { bool has_rseq; bool has_ptrace_get_rseq_conf; bool has_unix_sk_repair; + bool has_customize_ptrace; }; extern struct kerndat_s kdat; diff --git a/criu/kerndat.c b/criu/kerndat.c index 6d6aac1..630814e 100644 --- a/criu/kerndat.c +++ b/criu/kerndat.c @@ -1289,6 +1289,66 @@ static void kerndat_has_unix_sk_repair(void) return; } +static void kerndat_has_customize_ptrace(void) +{ + pid_t tracee = fork(); + int status; + int retval; + + if (tracee == 0) { + /* ensure */ + prctl(PR_SET_PDEATHSIG, SIGKILL); + + while (true) + sleep(1); + } else if (tracee > 0) { + pr_debug("fork task %d as tracee\n", tracee); + retval = ptrace(PTRACE_ATTACH, tracee, 0, 0); + if (retval < 0) { + pr_perror("Unexpect error from ptrace(PTRACE_ATTACH)"); + return; + } + + retval = wait4(-1, &status, __WALL, NULL); + if (retval == -1) + pr_perror("Unexpect error from wait"); + else if (retval != tracee || !(WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP)) + pr_err("Task %d (expect %d) is unexpect, status: %d," + " stoped: %d signal: %d(%s)\n", + retval, tracee, status, + WIFSTOPPED(status), WSTOPSIG(status), + strsignal(WTERMSIG(status))); + else { + retval = ptrace(PTRACE_SYSCALL_NR, tracee, 0, 0); + if (retval == 0) + kdat.has_customize_ptrace = true; + else + pr_perror("Unexpect error from ptrace(PTRACE_SYSCALL_NR)"); + } + + if (kill(tracee, SIGKILL) != 0) { + pr_perror("kill tracee %d failed", tracee); + return; + } + + /* + * To prevent wait4 unexpect task when criu.kdat is generated + * in dump process. + */ + retval = waitpid(tracee, &status, 0); + if (retval == -1) + pr_err("waitpid() failed"); + else + pr_debug("tracee %d exited, status %d, signal %d(%s)\n", + WEXITSTATUS(status), WTERMSIG(status), + WTERMSIG(status), strsignal(WTERMSIG(status))); + } else { + pr_perror("Unexpected error from fork\n"); + } + + return; +} + int kerndat_init(void) { int ret; @@ -1451,6 +1511,7 @@ int kerndat_init(void) } kerndat_has_unix_sk_repair(); + kerndat_has_customize_ptrace(); kerndat_lsm(); kerndat_mmap_min_addr(); -- 2.34.1