From 9fa4f0083a698429cdd3461d7581107c7ebc14c1 Mon Sep 17 00:00:00 2001 From: Roman Rashchupkin Date: Fri, 2 Mar 2018 11:06:37 +0300 Subject: [PATCH] Don't fail if some thread exit during attach. --- src/kpatch_process.c | 32 +++++++++++++++++++------------- src/kpatch_ptrace.c | 33 +++++++++++++++++++++------------ 2 files changed, 40 insertions(+), 25 deletions(-) diff --git a/src/kpatch_process.c b/src/kpatch_process.c index 2f85373..36347a2 100644 --- a/src/kpatch_process.c +++ b/src/kpatch_process.c @@ -12,6 +12,11 @@ #include #include +#include +#include +#include +#include + #include #include #include @@ -641,6 +646,7 @@ kpatch_process_attach(kpatch_process_t *proc) { int *pids = NULL, ret; size_t i, npids = 0, alloc = 0, prevnpids = 0, nattempts; + struct kpatch_ptrace_ctx *pctx; if (kpatch_process_mem_open(proc, MEM_WRITE) < 0) return -1; @@ -653,16 +659,11 @@ kpatch_process_attach(kpatch_process_t *proc) if (nattempts == 0) { kpdebug("Found %lu thread(s), attaching...\n", npids); } else { - /* - * FIXME(pboldin): This is wrong, amount of threads can - * be the same because some new spawned and some old - * died - */ if (prevnpids == npids) break; kpdebug("Found %lu new thread(s), attaching...\n", - prevnpids - npids); + npids - prevnpids); } if (proc->is_just_started && npids > 1 && proc->send_fd == -1) { @@ -683,7 +684,9 @@ kpatch_process_attach(kpatch_process_t *proc) goto detach; } - prevnpids = npids; + prevnpids = 0; + list_for_each_entry(pctx, &proc->ptrace.pctxs, list) + prevnpids++; } if (nattempts == max_attach_attempts) { @@ -691,12 +694,14 @@ kpatch_process_attach(kpatch_process_t *proc) goto detach; } - kpinfo("attached to %lu thread(s): %d", npids, pids[0]); - for (i = 1; i < npids; i++) - kpinfo(", %d", pids[i]); - kpinfo("\n"); - - free(pids); + kpinfo("Attached to %lu thread(s):", npids); + list_for_each_entry(pctx, &proc->ptrace.pctxs, list) { + kpinfo(" %d", pctx->pid); + if (pctx->list.next != &proc->ptrace.pctxs) + kpinfo(","); + else + kpinfo("\n"); + } if (proc->ptrace.unwd == NULL) { proc->ptrace.unwd = unw_create_addr_space(&_UPT_accessors, @@ -707,6 +712,7 @@ kpatch_process_attach(kpatch_process_t *proc) } } + free(pids); return 0; detach: diff --git a/src/kpatch_ptrace.c b/src/kpatch_ptrace.c index f91b80e..80e89cb 100644 --- a/src/kpatch_ptrace.c +++ b/src/kpatch_ptrace.c @@ -1126,21 +1126,18 @@ int kpatch_ptrace_attach_thread(kpatch_process_t *proc, int status; struct kpatch_ptrace_ctx *pctx; - pctx = kpatch_ptrace_ctx_alloc(proc); - if (pctx == NULL) { - kperr("Can't alloc kpatch_ptrace_ctx"); - return -1; - } - - pctx->pid = tid; - kpdebug("Attaching to %d...", pctx->pid); - - ret = ptrace(PTRACE_ATTACH, pctx->pid, NULL, NULL); + ret = ptrace(PTRACE_ATTACH, tid, NULL, NULL); if (ret < 0) { - kplogerror("can't attach to %d\n", pctx->pid); + if (errno == ESRCH) { + kpinfo("Thread %d exited before attach.\n", tid); + return 0; + } + kplogerror("can't attach to %d\n", tid); return -1; } + kpdebug("Attaching to %d...", tid); + do { ret = waitpid(tid, &status, __WALL); if (ret < 0) { @@ -1148,6 +1145,11 @@ int kpatch_ptrace_attach_thread(kpatch_process_t *proc, return -1; } + if (WIFEXITED(status)) { + kpinfo("Thread %d exited during attach.\n", tid); + return 0; + } + /* We are expecting SIGSTOP */ if (WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP) break; @@ -1162,7 +1164,7 @@ int kpatch_ptrace_attach_thread(kpatch_process_t *proc, status = WTERMSIG(status); - ret = ptrace(PTRACE_CONT, pctx->pid, NULL, + ret = ptrace(PTRACE_CONT, tid, NULL, (void *)(uintptr_t)status); if (ret < 0) { kplogerror("can't cont tracee\n"); @@ -1170,6 +1172,13 @@ int kpatch_ptrace_attach_thread(kpatch_process_t *proc, } } while (1); + pctx = kpatch_ptrace_ctx_alloc(proc); + if (pctx == NULL) { + kperr("Can't alloc kpatch_ptrace_ctx"); + return -1; + } + + pctx->pid = tid; pctx->running = 0; kpdebug("OK\n");