libcareplus/0046-kpatch_ptrace-Split-function-kpatch_ptrace_kickstart.patch
Jiajie Li 2b0fff2855 AArch64 support: add aarch64 support for libcareplus
Add related code which make libcareplus can run basic demo on aarch64.

Signed-off-by: Jiajie Li <lijiajie11@huawei.com>
2021-02-10 09:18:56 +08:00

402 lines
10 KiB
Diff

From f53cbbe63cbe16b2b0eb0466b5c85ea35f68da2b Mon Sep 17 00:00:00 2001
From: Jiajie Li <lijiajie11@huawei.com>
Date: Tue, 13 Oct 2020 11:22:27 +0800
Subject: [PATCH 46/89] kpatch_ptrace: Split function
kpatch_ptrace_kickstart_execve_wrapper
The function kpatch_ptrace_kickstart_execve_wrapper is arch related,
first rename it with kpatch_arch_ptrace_kickstart_execve_wrapper,
and then make separate definations in arch/x86/arch_ptrace.c and
arch/aarch64/arch_ptrace.c
Signed-off-by: Jiajie Li <lijiajie11@huawei.com>
Signed-off-by: Ying Fang <fangying1@huawei.com>
---
src/arch/aarch64/arch_ptrace.c | 99 +++++++++++++++++++++++++++++++
src/arch/x86/arch_ptrace.c | 99 +++++++++++++++++++++++++++++++
src/include/kpatch_ptrace.h | 5 +-
src/kpatch_process.c | 2 +-
src/kpatch_ptrace.c | 103 +--------------------------------
5 files changed, 205 insertions(+), 103 deletions(-)
diff --git a/src/arch/aarch64/arch_ptrace.c b/src/arch/aarch64/arch_ptrace.c
index b21189e..9f87d10 100644
--- a/src/arch/aarch64/arch_ptrace.c
+++ b/src/arch/aarch64/arch_ptrace.c
@@ -22,6 +22,105 @@
#include <gelf.h>
+/**
+ * This is rather tricky since we are accounting for the non-main
+ * thread calling for execve(). See `ptrace(2)` for details.
+ *
+ * FIXME(pboldin): this is broken for multi-threaded calls
+ * to execve. Sight.
+ */
+int
+kpatch_arch_ptrace_kickstart_execve_wrapper(kpatch_process_t *proc)
+{
+ int ret, pid = 0;
+ struct kpatch_ptrace_ctx *pctx, *ptmp, *execve_pctx = NULL;
+ long rv;
+
+ kpdebug("kpatch_arch_ptrace_kickstart_execve_wrapper\n");
+
+ list_for_each_entry(pctx, &proc->ptrace.pctxs, list) {
+ /* proc->pid equals to THREAD ID of the thread
+ * executing execve.so's version of execve
+ */
+ if (pctx->pid != proc->pid)
+ continue;
+ execve_pctx = pctx;
+ break;
+ }
+
+ if (execve_pctx == NULL) {
+ kperr("can't find thread executing execve");
+ return -1;
+ }
+
+ /* Send a message to our `execve` wrapper so it will continue
+ * execution
+ */
+ ret = send(proc->send_fd, &ret, sizeof(ret), 0);
+ if (ret < 0) {
+ kplogerror("send failed\n");
+ return ret;
+ }
+
+ /* Wait for it to reach BRKN instruction just before real execve */
+ while (1) {
+ ret = wait_for_stop(execve_pctx, NULL);
+ if (ret < 0) {
+ kplogerror("wait_for_stop\n");
+ return ret;
+ }
+
+ rv = ptrace(PTRACE_PEEKUSER, execve_pctx->pid,
+ offsetof(struct user_regs_struct, pc),
+ NULL);
+ if (rv == -1)
+ return rv;
+
+ rv = ptrace(PTRACE_PEEKTEXT, execve_pctx->pid,
+ rv - 1, NULL);
+ if (rv == -1)
+ return rv;
+ if ((unsigned char)rv == 0xcc)
+ break;
+ }
+
+ /* Wait for SIGTRAP from the execve. It happens from the thread
+ * group ID, so find it if thread doing execve() is not it. */
+ if (execve_pctx != proc2pctx(proc)) {
+ pid = get_threadgroup_id(proc->pid);
+ if (pid < 0)
+ return -1;
+
+ proc->pid = pid;
+ }
+
+ ret = wait_for_stop(execve_pctx, (void *)(uintptr_t)pid);
+ if (ret < 0) {
+ kplogerror("waitpid\n");
+ return ret;
+ }
+
+ list_for_each_entry_safe(pctx, ptmp, &proc->ptrace.pctxs, list) {
+ if (pctx->pid == proc->pid)
+ continue;
+ kpatch_ptrace_detach(pctx);
+ kpatch_ptrace_ctx_destroy(pctx);
+ }
+
+ /* Suddenly, /proc/pid/mem gets invalidated */
+ {
+ char buf[128];
+ close(proc->memfd);
+
+ snprintf(buf, sizeof(buf), "/proc/%d/mem", proc->pid);
+ proc->memfd = open(buf, O_RDWR);
+ }
+
+ kpdebug("...done\n");
+
+ return 0;
+}
+
int
wait_for_mmap(struct kpatch_ptrace_ctx *pctx,
unsigned long *pbase)
diff --git a/src/arch/x86/arch_ptrace.c b/src/arch/x86/arch_ptrace.c
index 0032cbd..ef0f460 100644
--- a/src/arch/x86/arch_ptrace.c
+++ b/src/arch/x86/arch_ptrace.c
@@ -22,6 +22,105 @@
#include <gelf.h>
+/**
+ * This is rather tricky since we are accounting for the non-main
+ * thread calling for execve(). See `ptrace(2)` for details.
+ *
+ * FIXME(pboldin): this is broken for multi-threaded calls
+ * to execve. Sight.
+ */
+int
+kpatch_arch_ptrace_kickstart_execve_wrapper(kpatch_process_t *proc)
+{
+ int ret, pid = 0;
+ struct kpatch_ptrace_ctx *pctx, *ptmp, *execve_pctx = NULL;
+ long rv;
+
+ kpdebug("kpatch_arch_ptrace_kickstart_execve_wrapper\n");
+
+ list_for_each_entry(pctx, &proc->ptrace.pctxs, list) {
+ /* proc->pid equals to THREAD ID of the thread
+ * executing execve.so's version of execve
+ */
+ if (pctx->pid != proc->pid)
+ continue;
+ execve_pctx = pctx;
+ break;
+ }
+
+ if (execve_pctx == NULL) {
+ kperr("can't find thread executing execve");
+ return -1;
+ }
+
+ /* Send a message to our `execve` wrapper so it will continue
+ * execution
+ */
+ ret = send(proc->send_fd, &ret, sizeof(ret), 0);
+ if (ret < 0) {
+ kplogerror("send failed\n");
+ return ret;
+ }
+
+ /* Wait for it to reach BRKN instruction just before real execve */
+ while (1) {
+ ret = wait_for_stop(execve_pctx, NULL);
+ if (ret < 0) {
+ kplogerror("wait_for_stop\n");
+ return ret;
+ }
+
+ rv = ptrace(PTRACE_PEEKUSER, execve_pctx->pid,
+ offsetof(struct user_regs_struct, rip),
+ NULL);
+ if (rv == -1)
+ return rv;
+
+ rv = ptrace(PTRACE_PEEKTEXT, execve_pctx->pid,
+ rv - 1, NULL);
+ if (rv == -1)
+ return rv;
+ if ((unsigned char)rv == 0xcc)
+ break;
+ }
+
+ /* Wait for SIGTRAP from the execve. It happens from the thread
+ * group ID, so find it if thread doing execve() is not it. */
+ if (execve_pctx != proc2pctx(proc)) {
+ pid = get_threadgroup_id(proc->pid);
+ if (pid < 0)
+ return -1;
+
+ proc->pid = pid;
+ }
+
+ ret = wait_for_stop(execve_pctx, (void *)(uintptr_t)pid);
+ if (ret < 0) {
+ kplogerror("waitpid\n");
+ return ret;
+ }
+
+ list_for_each_entry_safe(pctx, ptmp, &proc->ptrace.pctxs, list) {
+ if (pctx->pid == proc->pid)
+ continue;
+ kpatch_ptrace_detach(pctx);
+ kpatch_ptrace_ctx_destroy(pctx);
+ }
+
+ /* Suddenly, /proc/pid/mem gets invalidated */
+ {
+ char buf[128];
+ close(proc->memfd);
+
+ snprintf(buf, sizeof(buf), "/proc/%d/mem", proc->pid);
+ proc->memfd = open(buf, O_RDWR);
+ }
+
+ kpdebug("...done\n");
+
+ return 0;
+}
+
int
wait_for_mmap(struct kpatch_ptrace_ctx *pctx,
unsigned long *pbase)
diff --git a/src/include/kpatch_ptrace.h b/src/include/kpatch_ptrace.h
index 5abcf26..f0e83c0 100644
--- a/src/include/kpatch_ptrace.h
+++ b/src/include/kpatch_ptrace.h
@@ -55,7 +55,10 @@ int kpatch_ptrace_detach(struct kpatch_ptrace_ctx *pctx);
int kpatch_ptrace_handle_ld_linux(kpatch_process_t *proc,
unsigned long *pentry_point);
-int kpatch_ptrace_kickstart_execve_wrapper(kpatch_process_t *proc);
+
+int wait_for_stop(struct kpatch_ptrace_ctx *pctx, void *data);
+int get_threadgroup_id(int tid);
+int kpatch_arch_ptrace_kickstart_execve_wrapper(kpatch_process_t *proc);
int kpatch_ptrace_get_entry_point(struct kpatch_ptrace_ctx *pctx,
unsigned long *pentry_point);
diff --git a/src/kpatch_process.c b/src/kpatch_process.c
index 9561962..f987b7e 100644
--- a/src/kpatch_process.c
+++ b/src/kpatch_process.c
@@ -856,7 +856,7 @@ kpatch_process_kickstart_execve_wrapper(kpatch_process_t *proc)
{
int ret;
- ret = kpatch_ptrace_kickstart_execve_wrapper(proc);
+ ret = kpatch_arch_ptrace_kickstart_execve_wrapper(proc);
if (ret < 0)
return -1;
diff --git a/src/kpatch_ptrace.c b/src/kpatch_ptrace.c
index 7ab550c..d0bfbdd 100644
--- a/src/kpatch_ptrace.c
+++ b/src/kpatch_ptrace.c
@@ -413,7 +413,7 @@ poke_back:
return ret;
}
-static int
+int
wait_for_stop(struct kpatch_ptrace_ctx *pctx,
void *data)
{
@@ -463,7 +463,7 @@ kpatch_execute_remote(struct kpatch_ptrace_ctx *pctx,
}
/* FIXME(pboldin) buf might be too small */
-static int
+int
get_threadgroup_id(int tid)
{
FILE *fh;
@@ -486,105 +486,6 @@ get_threadgroup_id(int tid)
return pid;
}
-/**
- * This is rather tricky since we are accounting for the non-main
- * thread calling for execve(). See `ptrace(2)` for details.
- *
- * FIXME(pboldin): this is broken for multi-threaded calls
- * to execve. Sight.
- */
-int
-kpatch_ptrace_kickstart_execve_wrapper(kpatch_process_t *proc)
-{
- int ret, pid = 0;
- struct kpatch_ptrace_ctx *pctx, *ptmp, *execve_pctx = NULL;
- long rv;
-
- kpdebug("kpatch_ptrace_kickstart_execve_wrapper\n");
-
- list_for_each_entry(pctx, &proc->ptrace.pctxs, list) {
- /* proc->pid equals to THREAD ID of the thread
- * executing execve.so's version of execve
- */
- if (pctx->pid != proc->pid)
- continue;
- execve_pctx = pctx;
- break;
- }
-
- if (execve_pctx == NULL) {
- kperr("can't find thread executing execve");
- return -1;
- }
-
- /* Send a message to our `execve` wrapper so it will continue
- * execution
- */
- ret = send(proc->send_fd, &ret, sizeof(ret), 0);
- if (ret < 0) {
- kplogerror("send failed\n");
- return ret;
- }
-
- /* Wait for it to reach BRKN instruction just before real execve */
- while (1) {
- ret = wait_for_stop(execve_pctx, NULL);
- if (ret < 0) {
- kplogerror("wait_for_stop\n");
- return ret;
- }
-
- rv = ptrace(PTRACE_PEEKUSER, execve_pctx->pid,
- offsetof(struct user_regs_struct, rip),
- NULL);
- if (rv == -1)
- return rv;
-
- rv = ptrace(PTRACE_PEEKTEXT, execve_pctx->pid,
- rv - 1, NULL);
- if (rv == -1)
- return rv;
- if ((unsigned char)rv == 0xcc)
- break;
- }
-
- /* Wait for SIGTRAP from the execve. It happens from the thread
- * group ID, so find it if thread doing execve() is not it. */
- if (execve_pctx != proc2pctx(proc)) {
- pid = get_threadgroup_id(proc->pid);
- if (pid < 0)
- return -1;
-
- proc->pid = pid;
- }
-
- ret = wait_for_stop(execve_pctx, (void *)(uintptr_t)pid);
- if (ret < 0) {
- kplogerror("waitpid\n");
- return ret;
- }
-
- list_for_each_entry_safe(pctx, ptmp, &proc->ptrace.pctxs, list) {
- if (pctx->pid == proc->pid)
- continue;
- kpatch_ptrace_detach(pctx);
- kpatch_ptrace_ctx_destroy(pctx);
- }
-
- /* Suddenly, /proc/pid/mem gets invalidated */
- {
- char buf[128];
- close(proc->memfd);
-
- snprintf(buf, sizeof(buf), "/proc/%d/mem", proc->pid);
- proc->memfd = open(buf, O_RDWR);
- }
-
- kpdebug("...done\n");
-
- return 0;
-}
-
unsigned long
kpatch_mmap_remote(struct kpatch_ptrace_ctx *pctx,
unsigned long addr,
--
2.23.0