From cab989eb99d07fff28caa1417a69ff712b1f46b9 Mon Sep 17 00:00:00 2001 From: sy03 <1370724210@qq.com> Date: Sun, 22 Dec 2024 02:10:44 +0800 Subject: [PATCH 01/12] feat:Prevent segmentation fault in probe_read & probe_write --- runtime/src/bpf_helper.cpp | 154 +++++++++++++++++++++++++++++-- runtime/unit-test/CMakeLists.txt | 1 + runtime/unit-test/test_probe.cpp | 87 +++++++++++++++++ 3 files changed, 232 insertions(+), 10 deletions(-) create mode 100644 runtime/unit-test/test_probe.cpp diff --git a/runtime/src/bpf_helper.cpp b/runtime/src/bpf_helper.cpp index 981cddaf..47b07fe7 100644 --- a/runtime/src/bpf_helper.cpp +++ b/runtime/src/bpf_helper.cpp @@ -35,6 +35,9 @@ #include #include #include +#include +#include +#include #define PATH_MAX 4096 @@ -64,20 +67,151 @@ long bpftime_strncmp(const char *s1, uint64_t s1_sz, const char *s2) return strncmp(s1, s2, s1_sz); } -uint64_t bpftime_probe_read(uint64_t dst, uint64_t size, uint64_t ptr, uint64_t, - uint64_t) +extern void jump_point_read(); +extern void jump_point_write(); +/* +status instruction for probe_read and probe_write + -1 = not running + 0 = running but no error + 1 = running with error +*/ +thread_local int status_probe_write = -1; +thread_local int status_probe_read = -1; +/* +origin handler exist for probe_read and probe_write + -1 = not checked + 0 = not exist + 1 = exist +*/ +thread_local int origin_handler_exist_read = -1; +thread_local int origin_handler_exist_write = -1; +thread_local void (*origin_segv_read_handler)(int, siginfo_t *, + void *) = nullptr; +thread_local void (*origin_segv_write_handler)(int, siginfo_t *, + void *) = nullptr; + +static void segv_read_handler(int sig, siginfo_t *siginfo, void *ctx) { - memcpy((void *)(uintptr_t)dst, (void *)(uintptr_t)ptr, - (size_t)(uint32_t)(size)); - return 0; + // SPDLOG_TRACE("segv_handler for probe_read called"); + if (status_probe_read == -1) { + if (origin_segv_read_handler) { + origin_segv_read_handler(sig, siginfo, ctx); + } else { + abort(); + } + } else if (status_probe_read == 0) { + auto uctx = (ucontext_t *)ctx; + auto *rip = (uintptr_t *)(&uctx->uc_mcontext.gregs[REG_RIP]); + status_probe_read = 1; + *rip = (uintptr_t)&jump_point_read; + } } -uint64_t bpftime_probe_write_user(uint64_t dst, uint64_t src, uint64_t len, - uint64_t, uint64_t) +int64_t +// __attribute__((optimize("O0"))) +bpftime_probe_read(uint64_t dst, uint64_t size, uint64_t ptr, uint64_t, + uint64_t) { - memcpy((void *)(uintptr_t)dst, (void *)(uintptr_t)src, - (size_t)(uint32_t)(len)); - return 0; + int64_t ret = 0; + status_probe_read = 0; + + struct sigaction sa, original_sa; + // set up the signal handler + if (origin_handler_exist_read == -1) { + sigaction(SIGSEGV, NULL, &original_sa); + if (original_sa.sa_sigaction == nullptr) { + origin_handler_exist_read = 0; + } else { + origin_handler_exist_read = 1; + origin_segv_read_handler = original_sa.sa_sigaction; + } + } + + if (original_sa.sa_sigaction != segv_read_handler) { + sa.sa_flags = SA_SIGINFO; + sigemptyset(&sa.sa_mask); + sa.sa_sigaction = segv_read_handler; + sigaction(SIGSEGV, &sa, NULL); + } + unsigned char *dst_p = (unsigned char *)dst; + unsigned char *src_p = (unsigned char *)ptr; + while (size--) { + *((unsigned char *)dst_p) = *((unsigned char *)src_p); + dst_p++; + src_p++; + } + + __asm__("jump_point_read:"); + if (status_probe_read) { + ret = -EFAULT; + } + + status_probe_read = -1; + + return ret; +} + +static void segv_write_handler(int sig, siginfo_t *siginfo, void *ctx) +{ + // SPDLOG_TRACE("segv_handler for probe_write called"); + if (status_probe_write == -1) { + if (origin_segv_write_handler) { + origin_segv_write_handler(sig, siginfo, ctx); + } else { + abort(); + } + } else if (status_probe_write == 0) { + auto uctx = (ucontext_t *)ctx; + auto *rip = (uintptr_t *)(&uctx->uc_mcontext.gregs[REG_RIP]); + status_probe_write = 1; + *rip = (uintptr_t)&jump_point_write; + } +} + +int64_t +// __attribute__((optimize("O0"))) +bpftime_probe_write_user(uint64_t dst, uint64_t src, uint64_t len, uint64_t, + uint64_t) +{ + int64_t ret = 0; + + status_probe_write = 0; + // set up the signal handler + struct sigaction sa, original_sa; + // set up the signal handler + if (origin_handler_exist_write == -1) { + sigaction(SIGSEGV, NULL, &original_sa); + if (original_sa.sa_sigaction == nullptr) { + origin_handler_exist_write = 0; + } else { + origin_handler_exist_write = 1; + origin_segv_write_handler = original_sa.sa_sigaction; + } + } + + if (original_sa.sa_sigaction != segv_write_handler) { + sa.sa_flags = SA_SIGINFO; + sigemptyset(&sa.sa_mask); + sa.sa_sigaction = segv_write_handler; + sigaction(SIGSEGV, &sa, NULL); + } + + unsigned char *dst_p = (unsigned char *)dst; + unsigned char *src_p = (unsigned char *)src; + while (len--) { + *((unsigned char *)dst_p) = *((unsigned char *)src_p); + dst_p++; + src_p++; + } + + __asm__("jump_point_write:"); + if (status_probe_write) { + ret = -EFAULT; + } + + status_probe_write = -1; + + return ret; } uint64_t bpftime_get_prandom_u32() diff --git a/runtime/unit-test/CMakeLists.txt b/runtime/unit-test/CMakeLists.txt index b84a3d9a..5fa78a20 100644 --- a/runtime/unit-test/CMakeLists.txt +++ b/runtime/unit-test/CMakeLists.txt @@ -22,6 +22,7 @@ set(TEST_SOURCES maps/kernel_unit_tests.cpp test_bpftime_shm_json.cpp + test_probe.cpp attach_with_ebpf/test_attach_filter_with_ebpf.cpp attach_with_ebpf/test_attach_uprobe_with_ebpf.cpp attach_with_ebpf/test_helpers.cpp diff --git a/runtime/unit-test/test_probe.cpp b/runtime/unit-test/test_probe.cpp new file mode 100644 index 00000000..7ca7a73b --- /dev/null +++ b/runtime/unit-test/test_probe.cpp @@ -0,0 +1,87 @@ +#include "catch2/catch_test_macros.hpp" +#include "spdlog/spdlog.h" +#include +#include +#include + +extern "C" { + +uint64_t bpftime_probe_read(uint64_t dst, uint64_t size, uint64_t ptr, uint64_t, + uint64_t); +uint64_t bpftime_probe_write_user(uint64_t dst, uint64_t src, uint64_t len, + uint64_t, uint64_t); + +// prepare for future use +long bpftime_strncmp(const char *s1, uint64_t s1_sz, const char *s2); +uint64_t bpftime_get_prandom_u32(void); +uint64_t bpftime_ktime_get_coarse_ns(uint64_t, uint64_t, uint64_t, uint64_t, + uint64_t); +uint64_t bpf_ktime_get_coarse_ns(uint64_t, uint64_t, uint64_t, uint64_t, + uint64_t); +uint64_t bpftime_ktime_get_ns(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t); +uint64_t bpftime_get_current_pid_tgid(uint64_t, uint64_t, uint64_t, uint64_t, + uint64_t); +uint64_t bpf_get_current_uid_gid(uint64_t, uint64_t, uint64_t, uint64_t, + uint64_t); +uint64_t bpftime_get_current_comm(uint64_t buf, uint64_t size, uint64_t, + uint64_t, uint64_t); +uint64_t bpf_probe_read_str(uint64_t buf, uint64_t bufsz, uint64_t ptr, + uint64_t, uint64_t); +uint64_t bpftime_get_smp_processor_id(); +uint64_t bpftime_get_attach_cookie(uint64_t ctx, uint64_t, uint64_t, uint64_t, + uint64_t); + +uint64_t bpftime_get_smp_processor_id(); +} + +TEST_CASE("Test bpftime_probe_read") // test for bpftime_probe_read +{ + int dst[4] = { 0 }; + int src[4] = { 1, 2, 3, 4 }; + uint64_t size = sizeof(src); + int64_t ret = + bpftime_probe_read((uint64_t)dst, size, (uint64_t)src, 0, 0); + REQUIRE(ret == 0); + size_t len = sizeof(src) / sizeof(src[0]); + for (size_t i = 0; i < len; i++) { + REQUIRE(dst[i] == src[i]); + } + ret = bpftime_probe_read((uint64_t)dst, size, (uint64_t)(NULL), 0, 0); + REQUIRE(ret == -EFAULT); + + ret = 0; + ret = bpftime_probe_read((uint64_t)(NULL), size, (uint64_t)(NULL), 0, 0); + REQUIRE(ret == -EFAULT); +} + +TEST_CASE("Test bpftime_probe_write_user") // test for bpftime_probe_write_user +{ + int dst[4] = { 0 }; + int src[4] = { 1, 2, 3, 4 }; + uint64_t size = sizeof(src); + int64_t ret = bpftime_probe_write_user((uint64_t)dst, (uint64_t)src, size, + 0, 0); + REQUIRE(ret == 0); + size_t len = 4; + for (size_t i = 0; i < len; i++) { + REQUIRE(dst[i] == src[i]); + } + + ret = bpftime_probe_write_user((uint64_t)(NULL), (uint64_t)(src), size, + 0, 0); + REQUIRE(ret == -EFAULT); + + ret = bpftime_probe_write_user((uint64_t)dst, (uint64_t)(NULL), size, 0, + 0); + SPDLOG_INFO("ret = {}", ret); + REQUIRE(ret == -EFAULT); + + void *dst1 = (void *)(dst); + void *src1 = (void *)(src); + ret = bpftime_probe_write_user((uint64_t)dst1, (uint64_t)src1, size, 0, + 0); + REQUIRE(ret == 0); + for (size_t i = 0; i < len; i++) { + REQUIRE(((int *)dst1)[i] == ((int *)src1)[i]); + } +} \ No newline at end of file From 1f4634e1b811080efb5d75ef989cd1b0cfa935e7 Mon Sep 17 00:00:00 2001 From: sy03 <1370724210@qq.com> Date: Sun, 22 Dec 2024 14:59:03 +0800 Subject: [PATCH 02/12] update: update status & probe_test_case --- runtime/src/bpf_helper.cpp | 83 +++++++++++++++++--------------- runtime/unit-test/test_probe.cpp | 9 ++-- 2 files changed, 49 insertions(+), 43 deletions(-) diff --git a/runtime/src/bpf_helper.cpp b/runtime/src/bpf_helper.cpp index 47b07fe7..c87e9bb9 100644 --- a/runtime/src/bpf_helper.cpp +++ b/runtime/src/bpf_helper.cpp @@ -69,22 +69,31 @@ long bpftime_strncmp(const char *s1, uint64_t s1_sz, const char *s2) extern void jump_point_read(); extern void jump_point_write(); + /* status instruction for probe_read and probe_write - -1 = not running - 0 = running but no error - 1 = running with error */ -thread_local int status_probe_write = -1; -thread_local int status_probe_read = -1; +enum PROBE_STATUS { + PROBE_NOT_RUNNING = -1, + PROBE_RUNNING_NO_ERROR = 0, + PROBE_RUNNING_ERROR = 1 +}; + +thread_local static PROBE_STATUS status_probe_write = PROBE_NOT_RUNNING; +thread_local static PROBE_STATUS status_probe_read = PROBE_NOT_RUNNING; /* -origin handler exist for probe_read and probe_write - -1 = not checked - 0 = not exist - 1 = exist +origin handler exist flag for probe_read and probe_write */ -thread_local int origin_handler_exist_read = -1; -thread_local int origin_handler_exist_write = -1; +enum ORIGIN_HANDLER_EXIST_FLAG { + ORIGIN_HANDLER_NOT_CHECKED = -1, + ORIGIN_HANDLER_NOT_EXIST = 0, + ORIGIN_HANDLER_EXIST = 1 +}; +thread_local static ORIGIN_HANDLER_EXIST_FLAG origin_handler_exist_read = + ORIGIN_HANDLER_NOT_CHECKED; +thread_local static ORIGIN_HANDLER_EXIST_FLAG origin_handler_exist_write = + ORIGIN_HANDLER_NOT_CHECKED; + thread_local void (*origin_segv_read_handler)(int, siginfo_t *, void *) = nullptr; thread_local void (*origin_segv_write_handler)(int, siginfo_t *, @@ -92,37 +101,36 @@ thread_local void (*origin_segv_write_handler)(int, siginfo_t *, static void segv_read_handler(int sig, siginfo_t *siginfo, void *ctx) { - // SPDLOG_TRACE("segv_handler for probe_read called"); - if (status_probe_read == -1) { + SPDLOG_TRACE("segv_handler for probe_read called"); + if (status_probe_read == PROBE_NOT_RUNNING) { if (origin_segv_read_handler) { origin_segv_read_handler(sig, siginfo, ctx); } else { abort(); } - } else if (status_probe_read == 0) { + } else if (status_probe_read == PROBE_RUNNING_NO_ERROR) { + // set status to error auto uctx = (ucontext_t *)ctx; auto *rip = (uintptr_t *)(&uctx->uc_mcontext.gregs[REG_RIP]); - status_probe_read = 1; + status_probe_read = PROBE_RUNNING_ERROR; *rip = (uintptr_t)&jump_point_read; } } -int64_t -// __attribute__((optimize("O0"))) -bpftime_probe_read(uint64_t dst, uint64_t size, uint64_t ptr, uint64_t, - uint64_t) +int64_t bpftime_probe_read(uint64_t dst, uint64_t size, uint64_t ptr, uint64_t, + uint64_t) { int64_t ret = 0; - status_probe_read = 0; + status_probe_read = PROBE_RUNNING_NO_ERROR; struct sigaction sa, original_sa; // set up the signal handler - if (origin_handler_exist_read == -1) { + if (origin_handler_exist_read == ORIGIN_HANDLER_NOT_CHECKED) { sigaction(SIGSEGV, NULL, &original_sa); if (original_sa.sa_sigaction == nullptr) { - origin_handler_exist_read = 0; + origin_handler_exist_read = ORIGIN_HANDLER_NOT_EXIST; } else { - origin_handler_exist_read = 1; + origin_handler_exist_read = ORIGIN_HANDLER_EXIST; origin_segv_read_handler = original_sa.sa_sigaction; } } @@ -146,45 +154,44 @@ bpftime_probe_read(uint64_t dst, uint64_t size, uint64_t ptr, uint64_t, ret = -EFAULT; } - status_probe_read = -1; + status_probe_read = PROBE_NOT_RUNNING; return ret; } static void segv_write_handler(int sig, siginfo_t *siginfo, void *ctx) { - // SPDLOG_TRACE("segv_handler for probe_write called"); - if (status_probe_write == -1) { + SPDLOG_TRACE("segv_handler for probe_write called"); + if (status_probe_write == PROBE_NOT_RUNNING) { if (origin_segv_write_handler) { origin_segv_write_handler(sig, siginfo, ctx); } else { abort(); } - } else if (status_probe_write == 0) { + } else if (status_probe_write == PROBE_RUNNING_NO_ERROR) { + // set status to error auto uctx = (ucontext_t *)ctx; auto *rip = (uintptr_t *)(&uctx->uc_mcontext.gregs[REG_RIP]); - status_probe_write = 1; + status_probe_write = PROBE_RUNNING_ERROR; *rip = (uintptr_t)&jump_point_write; } } -int64_t -// __attribute__((optimize("O0"))) -bpftime_probe_write_user(uint64_t dst, uint64_t src, uint64_t len, uint64_t, - uint64_t) +int64_t bpftime_probe_write_user(uint64_t dst, uint64_t src, uint64_t len, + uint64_t, uint64_t) { int64_t ret = 0; - status_probe_write = 0; - // set up the signal handler + status_probe_write = PROBE_RUNNING_NO_ERROR; + struct sigaction sa, original_sa; // set up the signal handler - if (origin_handler_exist_write == -1) { + if (origin_handler_exist_write == ORIGIN_HANDLER_NOT_CHECKED) { sigaction(SIGSEGV, NULL, &original_sa); if (original_sa.sa_sigaction == nullptr) { - origin_handler_exist_write = 0; + origin_handler_exist_write = ORIGIN_HANDLER_NOT_EXIST; } else { - origin_handler_exist_write = 1; + origin_handler_exist_write = ORIGIN_HANDLER_EXIST; origin_segv_write_handler = original_sa.sa_sigaction; } } @@ -209,7 +216,7 @@ bpftime_probe_write_user(uint64_t dst, uint64_t src, uint64_t len, uint64_t, ret = -EFAULT; } - status_probe_write = -1; + status_probe_write = PROBE_NOT_RUNNING; return ret; } diff --git a/runtime/unit-test/test_probe.cpp b/runtime/unit-test/test_probe.cpp index 7ca7a73b..9ba129a4 100644 --- a/runtime/unit-test/test_probe.cpp +++ b/runtime/unit-test/test_probe.cpp @@ -46,11 +46,11 @@ TEST_CASE("Test bpftime_probe_read") // test for bpftime_probe_read for (size_t i = 0; i < len; i++) { REQUIRE(dst[i] == src[i]); } - ret = bpftime_probe_read((uint64_t)dst, size, (uint64_t)(NULL), 0, 0); + ret = bpftime_probe_read((uint64_t)dst, size, (uint64_t)(nullptr), 0, 0); REQUIRE(ret == -EFAULT); ret = 0; - ret = bpftime_probe_read((uint64_t)(NULL), size, (uint64_t)(NULL), 0, 0); + ret = bpftime_probe_read((uint64_t)(nullptr), size, (uint64_t)(nullptr), 0, 0); REQUIRE(ret == -EFAULT); } @@ -67,13 +67,12 @@ TEST_CASE("Test bpftime_probe_write_user") // test for bpftime_probe_write_user REQUIRE(dst[i] == src[i]); } - ret = bpftime_probe_write_user((uint64_t)(NULL), (uint64_t)(src), size, + ret = bpftime_probe_write_user((uint64_t)(nullptr), (uint64_t)(src), size, 0, 0); REQUIRE(ret == -EFAULT); - ret = bpftime_probe_write_user((uint64_t)dst, (uint64_t)(NULL), size, 0, + ret = bpftime_probe_write_user((uint64_t)dst, (uint64_t)(nullptr), size, 0, 0); - SPDLOG_INFO("ret = {}", ret); REQUIRE(ret == -EFAULT); void *dst1 = (void *)(dst); From fb09804eb4063b17e83e9f6b50ee95c56f52ef11 Mon Sep 17 00:00:00 2001 From: sy03 <1370724210@qq.com> Date: Sun, 22 Dec 2024 17:06:13 +0800 Subject: [PATCH 03/12] bug fix: return value for syscall & nullptr --- runtime/src/bpf_helper.cpp | 44 +++++++++++++++++++++++++++++++------- 1 file changed, 36 insertions(+), 8 deletions(-) diff --git a/runtime/src/bpf_helper.cpp b/runtime/src/bpf_helper.cpp index c87e9bb9..4d9aa037 100644 --- a/runtime/src/bpf_helper.cpp +++ b/runtime/src/bpf_helper.cpp @@ -94,9 +94,9 @@ thread_local static ORIGIN_HANDLER_EXIST_FLAG origin_handler_exist_read = thread_local static ORIGIN_HANDLER_EXIST_FLAG origin_handler_exist_write = ORIGIN_HANDLER_NOT_CHECKED; -thread_local void (*origin_segv_read_handler)(int, siginfo_t *, +thread_local static void (*origin_segv_read_handler)(int, siginfo_t *, void *) = nullptr; -thread_local void (*origin_segv_write_handler)(int, siginfo_t *, +thread_local static void (*origin_segv_write_handler)(int, siginfo_t *, void *) = nullptr; static void segv_read_handler(int sig, siginfo_t *siginfo, void *ctx) @@ -126,7 +126,11 @@ int64_t bpftime_probe_read(uint64_t dst, uint64_t size, uint64_t ptr, uint64_t, struct sigaction sa, original_sa; // set up the signal handler if (origin_handler_exist_read == ORIGIN_HANDLER_NOT_CHECKED) { - sigaction(SIGSEGV, NULL, &original_sa); + int err = sigaction(SIGSEGV, nullptr, &original_sa); + if (err) { + SPDLOG_ERROR("Failed to get signal handler: {}", errno); + return -EFAULT; + } if (original_sa.sa_sigaction == nullptr) { origin_handler_exist_read = ORIGIN_HANDLER_NOT_EXIST; } else { @@ -137,9 +141,18 @@ int64_t bpftime_probe_read(uint64_t dst, uint64_t size, uint64_t ptr, uint64_t, if (original_sa.sa_sigaction != segv_read_handler) { sa.sa_flags = SA_SIGINFO; - sigemptyset(&sa.sa_mask); + int err = 0; + err = sigemptyset(&sa.sa_mask); + if(err){ + SPDLOG_ERROR("Failed to set signal handler: {}", errno); + return -EFAULT; + } sa.sa_sigaction = segv_read_handler; - sigaction(SIGSEGV, &sa, NULL); + err = sigaction(SIGSEGV, &sa, nullptr); + if (err) { + SPDLOG_ERROR("Failed to set signal handler: {}", errno); + return -EFAULT; + } } unsigned char *dst_p = (unsigned char *)dst; unsigned char *src_p = (unsigned char *)ptr; @@ -187,7 +200,12 @@ int64_t bpftime_probe_write_user(uint64_t dst, uint64_t src, uint64_t len, struct sigaction sa, original_sa; // set up the signal handler if (origin_handler_exist_write == ORIGIN_HANDLER_NOT_CHECKED) { - sigaction(SIGSEGV, NULL, &original_sa); + int err = sigaction(SIGSEGV, nullptr, &original_sa); + if (err) { + SPDLOG_ERROR("Failed to get signal handler: {}", errno); + return -EFAULT; + } + if (original_sa.sa_sigaction == nullptr) { origin_handler_exist_write = ORIGIN_HANDLER_NOT_EXIST; } else { @@ -198,9 +216,19 @@ int64_t bpftime_probe_write_user(uint64_t dst, uint64_t src, uint64_t len, if (original_sa.sa_sigaction != segv_write_handler) { sa.sa_flags = SA_SIGINFO; - sigemptyset(&sa.sa_mask); + int err = 0 ; + err = sigemptyset(&sa.sa_mask); + if(err){ + SPDLOG_ERROR("Failed to set signal handler: {}", errno); + return -EFAULT; + } + sa.sa_sigaction = segv_write_handler; - sigaction(SIGSEGV, &sa, NULL); + err = sigaction(SIGSEGV, &sa, nullptr); + if (err) { + SPDLOG_ERROR("Failed to set signal handler: {}", errno); + return -EFAULT; + } } unsigned char *dst_p = (unsigned char *)dst; From 8d6197d30ce9dc5781b1401f9e7f77719bfecba8 Mon Sep 17 00:00:00 2001 From: sy03 <1370724210@qq.com> Date: Sun, 22 Dec 2024 21:09:08 +0800 Subject: [PATCH 04/12] update enum class & fix error of compile flag --- CMakeLists.txt | 9 ++++ runtime/src/bpf_helper.cpp | 94 +++++++++++++++++++++----------------- 2 files changed, 60 insertions(+), 43 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 364e06d8..17769cc0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -86,6 +86,15 @@ endif() message(STATUS "Started CMake for ${PROJECT_NAME} v${PROJECT_VERSION}...\n") +# option to use probe read/write checks +if(DEFINED ENABLE_PROBE_READ_CHECK) + add_compile_definitions(ENABLE_PROBE_READ_CHECK=1) +endif() + +if(DEFINED ENABLE_PROBE_WRITE_CHECK) + add_compile_definitions(ENABLE_PROBE_WRITE_CHECK=1) +endif() + # if option to build without libbpf is set if(${BPFTIME_BUILD_WITH_LIBBPF}) add_definitions(-DBPFTIME_BUILD_WITH_LIBBPF=1) diff --git a/runtime/src/bpf_helper.cpp b/runtime/src/bpf_helper.cpp index 4d9aa037..9c82a2a0 100644 --- a/runtime/src/bpf_helper.cpp +++ b/runtime/src/bpf_helper.cpp @@ -67,52 +67,53 @@ long bpftime_strncmp(const char *s1, uint64_t s1_sz, const char *s2) return strncmp(s1, s2, s1_sz); } -extern void jump_point_read(); -extern void jump_point_write(); +extern "C" void jump_point_read(); +extern "C" void jump_point_write(); /* status instruction for probe_read and probe_write */ -enum PROBE_STATUS { - PROBE_NOT_RUNNING = -1, - PROBE_RUNNING_NO_ERROR = 0, - PROBE_RUNNING_ERROR = 1 +enum class PROBE_STATUS { + NOT_RUNNING = -1, + RUNNING_NO_ERROR = 0, + RUNNING_ERROR = 1 }; -thread_local static PROBE_STATUS status_probe_write = PROBE_NOT_RUNNING; -thread_local static PROBE_STATUS status_probe_read = PROBE_NOT_RUNNING; +thread_local static PROBE_STATUS status_probe_write = PROBE_STATUS::NOT_RUNNING; +thread_local static PROBE_STATUS status_probe_read = PROBE_STATUS::NOT_RUNNING; /* origin handler exist flag for probe_read and probe_write */ -enum ORIGIN_HANDLER_EXIST_FLAG { - ORIGIN_HANDLER_NOT_CHECKED = -1, - ORIGIN_HANDLER_NOT_EXIST = 0, - ORIGIN_HANDLER_EXIST = 1 +enum class ORIGIN_HANDLER_EXIST_FLAG { + NOT_CHECKED = -1, + NOT_EXIST = 0, + EXIST = 1 }; -thread_local static ORIGIN_HANDLER_EXIST_FLAG origin_handler_exist_read = - ORIGIN_HANDLER_NOT_CHECKED; -thread_local static ORIGIN_HANDLER_EXIST_FLAG origin_handler_exist_write = - ORIGIN_HANDLER_NOT_CHECKED; +thread_local static ORIGIN_HANDLER_EXIST_FLAG exist_read = + ORIGIN_HANDLER_EXIST_FLAG::NOT_CHECKED; +thread_local static ORIGIN_HANDLER_EXIST_FLAG exist_write = + ORIGIN_HANDLER_EXIST_FLAG::NOT_CHECKED; thread_local static void (*origin_segv_read_handler)(int, siginfo_t *, - void *) = nullptr; + void *) = nullptr; thread_local static void (*origin_segv_write_handler)(int, siginfo_t *, - void *) = nullptr; + void *) = nullptr; + static void segv_read_handler(int sig, siginfo_t *siginfo, void *ctx) { SPDLOG_TRACE("segv_handler for probe_read called"); - if (status_probe_read == PROBE_NOT_RUNNING) { + if (status_probe_read == PROBE_STATUS::NOT_RUNNING) { if (origin_segv_read_handler) { origin_segv_read_handler(sig, siginfo, ctx); } else { abort(); } - } else if (status_probe_read == PROBE_RUNNING_NO_ERROR) { + } else if (status_probe_read == PROBE_STATUS::RUNNING_NO_ERROR) { // set status to error auto uctx = (ucontext_t *)ctx; auto *rip = (uintptr_t *)(&uctx->uc_mcontext.gregs[REG_RIP]); - status_probe_read = PROBE_RUNNING_ERROR; + status_probe_read = PROBE_STATUS::RUNNING_ERROR; *rip = (uintptr_t)&jump_point_read; } } @@ -121,20 +122,22 @@ int64_t bpftime_probe_read(uint64_t dst, uint64_t size, uint64_t ptr, uint64_t, uint64_t) { int64_t ret = 0; - status_probe_read = PROBE_RUNNING_NO_ERROR; + +#ifdef ENABLE_PROBE_READ_CHECK + status_probe_read = PROBE_STATUS::RUNNING_NO_ERROR; struct sigaction sa, original_sa; // set up the signal handler - if (origin_handler_exist_read == ORIGIN_HANDLER_NOT_CHECKED) { + if (exist_read == ORIGIN_HANDLER_EXIST_FLAG::NOT_CHECKED) { int err = sigaction(SIGSEGV, nullptr, &original_sa); if (err) { SPDLOG_ERROR("Failed to get signal handler: {}", errno); return -EFAULT; } if (original_sa.sa_sigaction == nullptr) { - origin_handler_exist_read = ORIGIN_HANDLER_NOT_EXIST; + exist_read = ORIGIN_HANDLER_EXIST_FLAG::NOT_EXIST; } else { - origin_handler_exist_read = ORIGIN_HANDLER_EXIST; + exist_read = ORIGIN_HANDLER_EXIST_FLAG::EXIST; origin_segv_read_handler = original_sa.sa_sigaction; } } @@ -143,7 +146,7 @@ int64_t bpftime_probe_read(uint64_t dst, uint64_t size, uint64_t ptr, uint64_t, sa.sa_flags = SA_SIGINFO; int err = 0; err = sigemptyset(&sa.sa_mask); - if(err){ + if (err) { SPDLOG_ERROR("Failed to set signal handler: {}", errno); return -EFAULT; } @@ -154,6 +157,7 @@ int64_t bpftime_probe_read(uint64_t dst, uint64_t size, uint64_t ptr, uint64_t, return -EFAULT; } } +#endif unsigned char *dst_p = (unsigned char *)dst; unsigned char *src_p = (unsigned char *)ptr; while (size--) { @@ -161,31 +165,32 @@ int64_t bpftime_probe_read(uint64_t dst, uint64_t size, uint64_t ptr, uint64_t, dst_p++; src_p++; } - __asm__("jump_point_read:"); - if (status_probe_read) { + +#ifdef ENABLE_PROBE_READ_CHECK + if (status_probe_read == PROBE_STATUS::RUNNING_ERROR) { ret = -EFAULT; } - status_probe_read = PROBE_NOT_RUNNING; - + status_probe_read = PROBE_STATUS::NOT_RUNNING; +#endif return ret; } static void segv_write_handler(int sig, siginfo_t *siginfo, void *ctx) { SPDLOG_TRACE("segv_handler for probe_write called"); - if (status_probe_write == PROBE_NOT_RUNNING) { + if (status_probe_write == PROBE_STATUS::NOT_RUNNING) { if (origin_segv_write_handler) { origin_segv_write_handler(sig, siginfo, ctx); } else { abort(); } - } else if (status_probe_write == PROBE_RUNNING_NO_ERROR) { + } else if (status_probe_write == PROBE_STATUS::RUNNING_NO_ERROR) { // set status to error auto uctx = (ucontext_t *)ctx; auto *rip = (uintptr_t *)(&uctx->uc_mcontext.gregs[REG_RIP]); - status_probe_write = PROBE_RUNNING_ERROR; + status_probe_write = PROBE_STATUS::RUNNING_ERROR; *rip = (uintptr_t)&jump_point_write; } } @@ -195,11 +200,12 @@ int64_t bpftime_probe_write_user(uint64_t dst, uint64_t src, uint64_t len, { int64_t ret = 0; - status_probe_write = PROBE_RUNNING_NO_ERROR; +#ifdef ENABLE_PROBE_WRITE_CHECK + status_probe_write = PROBE_STATUS::RUNNING_NO_ERROR; struct sigaction sa, original_sa; // set up the signal handler - if (origin_handler_exist_write == ORIGIN_HANDLER_NOT_CHECKED) { + if (exist_write == ORIGIN_HANDLER_EXIST_FLAG::NOT_CHECKED) { int err = sigaction(SIGSEGV, nullptr, &original_sa); if (err) { SPDLOG_ERROR("Failed to get signal handler: {}", errno); @@ -207,22 +213,22 @@ int64_t bpftime_probe_write_user(uint64_t dst, uint64_t src, uint64_t len, } if (original_sa.sa_sigaction == nullptr) { - origin_handler_exist_write = ORIGIN_HANDLER_NOT_EXIST; + exist_write = ORIGIN_HANDLER_EXIST_FLAG::NOT_EXIST; } else { - origin_handler_exist_write = ORIGIN_HANDLER_EXIST; + exist_write = ORIGIN_HANDLER_EXIST_FLAG::EXIST; origin_segv_write_handler = original_sa.sa_sigaction; } } if (original_sa.sa_sigaction != segv_write_handler) { sa.sa_flags = SA_SIGINFO; - int err = 0 ; + int err = 0; err = sigemptyset(&sa.sa_mask); - if(err){ + if (err) { SPDLOG_ERROR("Failed to set signal handler: {}", errno); return -EFAULT; } - + sa.sa_sigaction = segv_write_handler; err = sigaction(SIGSEGV, &sa, nullptr); if (err) { @@ -230,7 +236,7 @@ int64_t bpftime_probe_write_user(uint64_t dst, uint64_t src, uint64_t len, return -EFAULT; } } - +#endif unsigned char *dst_p = (unsigned char *)dst; unsigned char *src_p = (unsigned char *)src; while (len--) { @@ -240,12 +246,14 @@ int64_t bpftime_probe_write_user(uint64_t dst, uint64_t src, uint64_t len, } __asm__("jump_point_write:"); - if (status_probe_write) { +#ifdef ENABLE_PROBE_WRITE_CHECK + if (status_probe_write == PROBE_STATUS::RUNNING_ERROR) { ret = -EFAULT; } - status_probe_write = PROBE_NOT_RUNNING; + status_probe_write = PROBE_STATUS::NOT_RUNNING; +#endif return ret; } From baf0cac4ef351211d42dfee51aa1e39521bdbeb7 Mon Sep 17 00:00:00 2001 From: sy03 <1370724210@qq.com> Date: Sun, 22 Dec 2024 21:26:12 +0800 Subject: [PATCH 05/12] update CI of runtime-unit-test --- .github/workflows/test-runtime.yml | 2 +- Makefile | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/test-runtime.yml b/.github/workflows/test-runtime.yml index dd50f95c..fec26d9d 100644 --- a/.github/workflows/test-runtime.yml +++ b/.github/workflows/test-runtime.yml @@ -40,7 +40,7 @@ jobs: - name: Build run: | - cmake -DTEST_LCOV=ON -DBPFTIME_LLVM_JIT=YES -DBPFTIME_ENABLE_UNIT_TESTING=YES -DCMAKE_BUILD_TYPE=Debug -B build + cmake -DTEST_LCOV=ON -DBPFTIME_LLVM_JIT=YES -DBPFTIME_ENABLE_UNIT_TESTING=YES -DENABLE_PROBE_WRITE_CHECK=1 -DENABLE_PROBE_READ_CHECK=1 -DCMAKE_BUILD_TYPE=Debug -B build cmake --build build --config Debug --target bpftime_runtime_tests -j$(nproc) - name: Test Runtime run: ./build/runtime/unit-test/bpftime_runtime_tests diff --git a/Makefile b/Makefile index 884fd33f..94eb93c2 100644 --- a/Makefile +++ b/Makefile @@ -33,6 +33,10 @@ help: @python3 -c "$$PRINT_HELP_PYSCRIPT" < $(MAKEFILE_LIST) build-unit-test: + cmake -Bbuild -DBPFTIME_ENABLE_UNIT_TESTING=1 -DCMAKE_BUILD_TYPE:STRING=Debug -DENABLE_PROBE_WRITE_CHECK=1 -DENABLE_PROBE_READ_CHECK=1 + cmake --build build --config Debug --target bpftime_runtime_tests bpftime_daemon_tests -j$(JOBS) + +build-unit-test-without-probe-check: cmake -Bbuild -DBPFTIME_ENABLE_UNIT_TESTING=1 -DCMAKE_BUILD_TYPE:STRING=Debug cmake --build build --config Debug --target bpftime_runtime_tests bpftime_daemon_tests -j$(JOBS) From 08190f2991cc0993dcab20e9714eb08ccc1d2cf6 Mon Sep 17 00:00:00 2001 From: sy03 <1370724210@qq.com> Date: Sun, 22 Dec 2024 22:01:08 +0800 Subject: [PATCH 06/12] fix error of CI in build runtime with mpk enable --- .github/workflows/test-runtime.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test-runtime.yml b/.github/workflows/test-runtime.yml index fec26d9d..ddfb9a7f 100644 --- a/.github/workflows/test-runtime.yml +++ b/.github/workflows/test-runtime.yml @@ -69,7 +69,7 @@ jobs: - name: build runtime with mpk enable run: | rm -rf build - cmake -Bbuild -DTEST_LCOV=ON -DBPFTIME_LLVM_JIT=YES -DBPFTIME_ENABLE_UNIT_TESTING=YES -DBPFTIME_ENABLE_MPK=YES -DCMAKE_BUILD_TYPE=Debug + cmake -Bbuild -DTEST_LCOV=ON -DBPFTIME_LLVM_JIT=YES -DBPFTIME_ENABLE_UNIT_TESTING=YES -DBPFTIME_ENABLE_MPK=YES -DCMAKE_BUILD_TYPE=Debug -DENABLE_PROBE_WRITE_CHECK=1 -DENABLE_PROBE_READ_CHECK=1 cmake --build build --config Debug --target bpftime_runtime_tests -j$(nproc) - name: test runtime with mpk run: ./build/runtime/unit-test/bpftime_runtime_tests From 4d7245907ab5a41b3eb69012523ea667f3869e73 Mon Sep 17 00:00:00 2001 From: sy03 <1370724210@qq.com> Date: Mon, 23 Dec 2024 16:44:50 +0800 Subject: [PATCH 07/12] update compile settings --- CMakeLists.txt | 18 +++++++++--------- cmake/StandardSettings.cmake | 8 +++++++- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 17769cc0..f1fe2e42 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -86,15 +86,6 @@ endif() message(STATUS "Started CMake for ${PROJECT_NAME} v${PROJECT_VERSION}...\n") -# option to use probe read/write checks -if(DEFINED ENABLE_PROBE_READ_CHECK) - add_compile_definitions(ENABLE_PROBE_READ_CHECK=1) -endif() - -if(DEFINED ENABLE_PROBE_WRITE_CHECK) - add_compile_definitions(ENABLE_PROBE_WRITE_CHECK=1) -endif() - # if option to build without libbpf is set if(${BPFTIME_BUILD_WITH_LIBBPF}) add_definitions(-DBPFTIME_BUILD_WITH_LIBBPF=1) @@ -169,6 +160,15 @@ add_subdirectory(attach) add_subdirectory(runtime) +# option to use probe read/write checks +if(DEFINED ENABLE_PROBE_READ_CHECK) + target_compile_definitions(runtime PRIVATE ENABLE_PROBE_READ_CHECK=1) +endif() + +if(DEFINED ENABLE_PROBE_WRITE_CHECK) + target_compile_definitions(runtime PRIVATE ENABLE_PROBE_WRITE_CHECK=1) +endif() + # add to single archive if option is enabled if(${BPFTIME_BUILD_STATIC_LIB}) set(UBPF_BUILD_DIR ${CMAKE_CURRENT_BINARY_DIR}/vm/ubpf-vm/ubpf) diff --git a/cmake/StandardSettings.cmake b/cmake/StandardSettings.cmake index 95f29580..1f126f84 100644 --- a/cmake/StandardSettings.cmake +++ b/cmake/StandardSettings.cmake @@ -87,4 +87,10 @@ option(BPFTIME_BUILD_KERNEL_BPF "Whether to build with bpf share maps" ON) option(BPFTIME_BUILD_STATIC_LIB "Whether to build a single static library for different archive files" OFF) # whether to build bpftime with libbpf and other linux headers -option(BPFTIME_BUILD_WITH_LIBBPF "Whether to build with libbpf and other linux headers" ON) \ No newline at end of file +option(BPFTIME_BUILD_WITH_LIBBPF "Whether to build with libbpf and other linux headers" ON) + +# whether to enable probe write check +option(ENABLE_PROBE_WRITE_CHECK "Whether to enable probe write check" OFF) + +# whether to enable probe read check +option(ENABLE_PROBE_READ_CHECK "Whether to enable probe read check" OFF) \ No newline at end of file From 7b435298547c6699cabe32441fc2c5cfebd1657d Mon Sep 17 00:00:00 2001 From: sy03 <1370724210@qq.com> Date: Mon, 23 Dec 2024 17:22:38 +0800 Subject: [PATCH 08/12] fix benchmark docs errors and update more instructions --- benchmark/README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/benchmark/README.md b/benchmark/README.md index 71ad1d1c..77f7ca6c 100644 --- a/benchmark/README.md +++ b/benchmark/README.md @@ -30,6 +30,8 @@ cmake -Bbuild -DLLVM_DIR=/usr/lib/llvm-15/cmake -DCMAKE_BUILD_TYPE:STRING=RelWit cmake --build build --config RelWithDebInfo --target install -j ``` +If you fail to build , notice LLVM version. + ## build and run at a click Build the agent first. In project root: @@ -195,7 +197,7 @@ Tested on `kernel version 6.2` and `Intel(R) Xeon(R) Gold 5418Y` CPU. ### Uprobe and read/write with `bpf_probe_write_user` and `bpf_probe_read_user` -Userspace: +Kernelspace: ```txt Benchmarking __bench_uprobe_uretprobe in thread 1 @@ -233,6 +235,8 @@ Benchmarking __bench_write in thread 1 Average time usage 389.037170 ns, iter 100000 times ``` +noted that the performance of `bpf_probe_read_user` and `bpf_probe_write_user` will be influenced by the option of `ENABLE_PROBE_WRITE_USER` and `ENABLE_PROBE_READ_USER`. + ### maps operations Run the map op 1000 times in one function. Userspace map op is also faster than the kernel in the current version. Current version is 10x faster than stupid old version. From c703c5d89e6d95d341ec622eb96eb506cd8cea2e Mon Sep 17 00:00:00 2001 From: sy03 <1370724210@qq.com> Date: Mon, 23 Dec 2024 17:31:43 +0800 Subject: [PATCH 09/12] fix bug of probe size < 0 --- runtime/src/bpf_helper.cpp | 32 +++++++++++------ runtime/unit-test/test_probe.cpp | 60 ++++++++++++++++---------------- 2 files changed, 52 insertions(+), 40 deletions(-) diff --git a/runtime/src/bpf_helper.cpp b/runtime/src/bpf_helper.cpp index 9c82a2a0..efd94fb8 100644 --- a/runtime/src/bpf_helper.cpp +++ b/runtime/src/bpf_helper.cpp @@ -3,6 +3,8 @@ * Copyright (c) 2022, eunomia-bpf org * All rights reserved. */ +#include +#include #if __APPLE__ #include #include @@ -99,28 +101,34 @@ thread_local static void (*origin_segv_read_handler)(int, siginfo_t *, thread_local static void (*origin_segv_write_handler)(int, siginfo_t *, void *) = nullptr; - static void segv_read_handler(int sig, siginfo_t *siginfo, void *ctx) { - SPDLOG_TRACE("segv_handler for probe_read called"); + SPDLOG_INFO("segv_handler for probe_read called"); if (status_probe_read == PROBE_STATUS::NOT_RUNNING) { - if (origin_segv_read_handler) { + SPDLOG_INFO("segv_handler for probe_read called 2"); + if (origin_segv_read_handler != nullptr) { origin_segv_read_handler(sig, siginfo, ctx); } else { - abort(); + SPDLOG_INFO("segv_handler for probe_read called 3"); + throw std::runtime_error( + "segv_handler for probe_read called"); } } else if (status_probe_read == PROBE_STATUS::RUNNING_NO_ERROR) { // set status to error auto uctx = (ucontext_t *)ctx; - auto *rip = (uintptr_t *)(&uctx->uc_mcontext.gregs[REG_RIP]); + auto *rip = (greg_t *)(&uctx->uc_mcontext.gregs[REG_RIP]); status_probe_read = PROBE_STATUS::RUNNING_ERROR; - *rip = (uintptr_t)&jump_point_read; + *rip = (greg_t)&jump_point_read; } } -int64_t bpftime_probe_read(uint64_t dst, uint64_t size, uint64_t ptr, uint64_t, +int64_t bpftime_probe_read(uint64_t dst, int64_t size, uint64_t ptr, uint64_t, uint64_t) { + if (size < 0) { + SPDLOG_ERROR("Invalid size: {}", size); + return -EFAULT; + } int64_t ret = 0; #ifdef ENABLE_PROBE_READ_CHECK @@ -189,15 +197,19 @@ static void segv_write_handler(int sig, siginfo_t *siginfo, void *ctx) } else if (status_probe_write == PROBE_STATUS::RUNNING_NO_ERROR) { // set status to error auto uctx = (ucontext_t *)ctx; - auto *rip = (uintptr_t *)(&uctx->uc_mcontext.gregs[REG_RIP]); + auto *rip = (greg_t *)(&uctx->uc_mcontext.gregs[REG_RIP]); status_probe_write = PROBE_STATUS::RUNNING_ERROR; - *rip = (uintptr_t)&jump_point_write; + *rip = (greg_t)&jump_point_write; } } -int64_t bpftime_probe_write_user(uint64_t dst, uint64_t src, uint64_t len, +int64_t bpftime_probe_write_user(uint64_t dst, uint64_t src, int64_t len, uint64_t, uint64_t) { + if (len < 0) { + SPDLOG_ERROR("Invalid len: {}", len); + return -EFAULT; + } int64_t ret = 0; #ifdef ENABLE_PROBE_WRITE_CHECK diff --git a/runtime/unit-test/test_probe.cpp b/runtime/unit-test/test_probe.cpp index 9ba129a4..32544ebd 100644 --- a/runtime/unit-test/test_probe.cpp +++ b/runtime/unit-test/test_probe.cpp @@ -3,6 +3,7 @@ #include #include #include +#include extern "C" { @@ -10,28 +11,6 @@ uint64_t bpftime_probe_read(uint64_t dst, uint64_t size, uint64_t ptr, uint64_t, uint64_t); uint64_t bpftime_probe_write_user(uint64_t dst, uint64_t src, uint64_t len, uint64_t, uint64_t); - -// prepare for future use -long bpftime_strncmp(const char *s1, uint64_t s1_sz, const char *s2); -uint64_t bpftime_get_prandom_u32(void); -uint64_t bpftime_ktime_get_coarse_ns(uint64_t, uint64_t, uint64_t, uint64_t, - uint64_t); -uint64_t bpf_ktime_get_coarse_ns(uint64_t, uint64_t, uint64_t, uint64_t, - uint64_t); -uint64_t bpftime_ktime_get_ns(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t); -uint64_t bpftime_get_current_pid_tgid(uint64_t, uint64_t, uint64_t, uint64_t, - uint64_t); -uint64_t bpf_get_current_uid_gid(uint64_t, uint64_t, uint64_t, uint64_t, - uint64_t); -uint64_t bpftime_get_current_comm(uint64_t buf, uint64_t size, uint64_t, - uint64_t, uint64_t); -uint64_t bpf_probe_read_str(uint64_t buf, uint64_t bufsz, uint64_t ptr, - uint64_t, uint64_t); -uint64_t bpftime_get_smp_processor_id(); -uint64_t bpftime_get_attach_cookie(uint64_t ctx, uint64_t, uint64_t, uint64_t, - uint64_t); - -uint64_t bpftime_get_smp_processor_id(); } TEST_CASE("Test bpftime_probe_read") // test for bpftime_probe_read @@ -46,11 +25,13 @@ TEST_CASE("Test bpftime_probe_read") // test for bpftime_probe_read for (size_t i = 0; i < len; i++) { REQUIRE(dst[i] == src[i]); } - ret = bpftime_probe_read((uint64_t)dst, size, (uint64_t)(nullptr), 0, 0); + ret = bpftime_probe_read((uint64_t)dst, size, (uint64_t)(nullptr), 0, + 0); REQUIRE(ret == -EFAULT); ret = 0; - ret = bpftime_probe_read((uint64_t)(nullptr), size, (uint64_t)(nullptr), 0, 0); + ret = bpftime_probe_read((uint64_t)(nullptr), size, (uint64_t)(nullptr), + 0, 0); REQUIRE(ret == -EFAULT); } @@ -59,20 +40,20 @@ TEST_CASE("Test bpftime_probe_write_user") // test for bpftime_probe_write_user int dst[4] = { 0 }; int src[4] = { 1, 2, 3, 4 }; uint64_t size = sizeof(src); - int64_t ret = bpftime_probe_write_user((uint64_t)dst, (uint64_t)src, size, - 0, 0); + int64_t ret = bpftime_probe_write_user((uint64_t)dst, (uint64_t)src, + size, 0, 0); REQUIRE(ret == 0); size_t len = 4; for (size_t i = 0; i < len; i++) { REQUIRE(dst[i] == src[i]); } - ret = bpftime_probe_write_user((uint64_t)(nullptr), (uint64_t)(src), size, - 0, 0); + ret = bpftime_probe_write_user((uint64_t)(nullptr), (uint64_t)(src), + size, 0, 0); REQUIRE(ret == -EFAULT); - ret = bpftime_probe_write_user((uint64_t)dst, (uint64_t)(nullptr), size, 0, - 0); + ret = bpftime_probe_write_user((uint64_t)dst, (uint64_t)(nullptr), size, + 0, 0); REQUIRE(ret == -EFAULT); void *dst1 = (void *)(dst); @@ -83,4 +64,23 @@ TEST_CASE("Test bpftime_probe_write_user") // test for bpftime_probe_write_user for (size_t i = 0; i < len; i++) { REQUIRE(((int *)dst1)[i] == ((int *)src1)[i]); } +} + +TEST_CASE("Test Probe read/write size valid or not ") +{ + int dst[4] = { 0 }; + int src[4] = { 1, 2, 3, 4 }; + uint64_t size = sizeof(src); + int64_t ret = + bpftime_probe_read((uint64_t)dst, -1, (uint64_t)src, 0, 0); + REQUIRE(ret == -EFAULT); + ret = bpftime_probe_write_user((uint64_t)dst, (uint64_t)src, -1, 0, 0); + REQUIRE(ret == -EFAULT); + ret = bpftime_probe_read((uint64_t)dst, -1, (uint64_t)(nullptr), 0, 0); + REQUIRE(ret == -EFAULT); + ret = bpftime_probe_read((uint64_t)dst, size, (uint64_t)(src), 0, 0); + REQUIRE(ret == 0); + for (size_t i = 0; i < 4; i++) { + REQUIRE(dst[i] == src[i]); + } } \ No newline at end of file From ca3efdeb1e728331057b54884f3dd8ed5424b99c Mon Sep 17 00:00:00 2001 From: sy03 <1370724210@qq.com> Date: Mon, 23 Dec 2024 18:32:54 +0800 Subject: [PATCH 10/12] update unit-test --- runtime/src/bpf_helper.cpp | 8 ++++---- runtime/unit-test/test_probe.cpp | 24 ++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/runtime/src/bpf_helper.cpp b/runtime/src/bpf_helper.cpp index efd94fb8..49285484 100644 --- a/runtime/src/bpf_helper.cpp +++ b/runtime/src/bpf_helper.cpp @@ -103,13 +103,11 @@ thread_local static void (*origin_segv_write_handler)(int, siginfo_t *, static void segv_read_handler(int sig, siginfo_t *siginfo, void *ctx) { - SPDLOG_INFO("segv_handler for probe_read called"); if (status_probe_read == PROBE_STATUS::NOT_RUNNING) { - SPDLOG_INFO("segv_handler for probe_read called 2"); if (origin_segv_read_handler != nullptr) { origin_segv_read_handler(sig, siginfo, ctx); } else { - SPDLOG_INFO("segv_handler for probe_read called 3"); + SPDLOG_ERROR("no origin handler for probe_read"); throw std::runtime_error( "segv_handler for probe_read called"); } @@ -192,7 +190,9 @@ static void segv_write_handler(int sig, siginfo_t *siginfo, void *ctx) if (origin_segv_write_handler) { origin_segv_write_handler(sig, siginfo, ctx); } else { - abort(); + SPDLOG_ERROR("no origin handler for probe_write"); + throw std::runtime_error( + "segv_handler for probe_write called"); } } else if (status_probe_write == PROBE_STATUS::RUNNING_NO_ERROR) { // set status to error diff --git a/runtime/unit-test/test_probe.cpp b/runtime/unit-test/test_probe.cpp index 32544ebd..dab0ef1d 100644 --- a/runtime/unit-test/test_probe.cpp +++ b/runtime/unit-test/test_probe.cpp @@ -1,5 +1,6 @@ #include "catch2/catch_test_macros.hpp" #include "spdlog/spdlog.h" +#include #include #include #include @@ -83,4 +84,27 @@ TEST_CASE("Test Probe read/write size valid or not ") for (size_t i = 0; i < 4; i++) { REQUIRE(dst[i] == src[i]); } +} + + +TEST_CASE("Test origin handler is null") +{ + struct sigaction original_sa, sa; + int dst[4] = { 0 }; + int src[4] = { 1, 2, 3, 4 }; + sa.sa_flags = SA_SIGINFO; + sigemptyset(&sa.sa_mask); + sa.sa_sigaction = nullptr; + if (sigaction(SIGSEGV, &sa, nullptr) < 0) { + REQUIRE(false); + } + uint64_t size = sizeof(src); + + int ret = bpftime_probe_read((uint64_t)(dst), size, (uint64_t)(src), 0, + 0); + REQUIRE(ret == 0); + + sigaction(SIGSEGV, nullptr, &original_sa); + auto handler = original_sa.sa_sigaction; + REQUIRE(handler != nullptr); } \ No newline at end of file From 1b21ee253c37bfc9f2254104bc9ece41b8970c6a Mon Sep 17 00:00:00 2001 From: sy03 <1370724210@qq.com> Date: Mon, 23 Dec 2024 19:21:20 +0800 Subject: [PATCH 11/12] add macro definition --- runtime/src/bpf_helper.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/runtime/src/bpf_helper.cpp b/runtime/src/bpf_helper.cpp index 49285484..782c5b73 100644 --- a/runtime/src/bpf_helper.cpp +++ b/runtime/src/bpf_helper.cpp @@ -101,6 +101,8 @@ thread_local static void (*origin_segv_read_handler)(int, siginfo_t *, thread_local static void (*origin_segv_write_handler)(int, siginfo_t *, void *) = nullptr; + +#ifdef ENABLE_PROBE_READ_CHECK static void segv_read_handler(int sig, siginfo_t *siginfo, void *ctx) { if (status_probe_read == PROBE_STATUS::NOT_RUNNING) { @@ -119,6 +121,7 @@ static void segv_read_handler(int sig, siginfo_t *siginfo, void *ctx) *rip = (greg_t)&jump_point_read; } } +#endif int64_t bpftime_probe_read(uint64_t dst, int64_t size, uint64_t ptr, uint64_t, uint64_t) @@ -183,6 +186,8 @@ int64_t bpftime_probe_read(uint64_t dst, int64_t size, uint64_t ptr, uint64_t, return ret; } + +#ifdef ENABLE_PROBE_WRITE_CHECK static void segv_write_handler(int sig, siginfo_t *siginfo, void *ctx) { SPDLOG_TRACE("segv_handler for probe_write called"); @@ -202,6 +207,7 @@ static void segv_write_handler(int sig, siginfo_t *siginfo, void *ctx) *rip = (greg_t)&jump_point_write; } } +#endif int64_t bpftime_probe_write_user(uint64_t dst, uint64_t src, int64_t len, uint64_t, uint64_t) From e69e427301e99f9e41cd8e86bcfc6b4f72199a96 Mon Sep 17 00:00:00 2001 From: sy03 <1370724210@qq.com> Date: Mon, 23 Dec 2024 19:59:24 +0800 Subject: [PATCH 12/12] supplement the macro definitions --- runtime/src/bpf_helper.cpp | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/runtime/src/bpf_helper.cpp b/runtime/src/bpf_helper.cpp index 782c5b73..4c33aad9 100644 --- a/runtime/src/bpf_helper.cpp +++ b/runtime/src/bpf_helper.cpp @@ -69,8 +69,8 @@ long bpftime_strncmp(const char *s1, uint64_t s1_sz, const char *s2) return strncmp(s1, s2, s1_sz); } -extern "C" void jump_point_read(); -extern "C" void jump_point_write(); + +#if defined(ENABLE_PROBE_WRITE_CHECK) || defined(ENABLE_PROBE_READ_CHECK) /* status instruction for probe_read and probe_write @@ -81,8 +81,6 @@ enum class PROBE_STATUS { RUNNING_ERROR = 1 }; -thread_local static PROBE_STATUS status_probe_write = PROBE_STATUS::NOT_RUNNING; -thread_local static PROBE_STATUS status_probe_read = PROBE_STATUS::NOT_RUNNING; /* origin handler exist flag for probe_read and probe_write */ @@ -91,16 +89,31 @@ enum class ORIGIN_HANDLER_EXIST_FLAG { NOT_EXIST = 0, EXIST = 1 }; + +#endif + +#ifdef ENABLE_PROBE_READ_CHECK +extern "C" void jump_point_read(); + +thread_local static PROBE_STATUS status_probe_write = PROBE_STATUS::NOT_RUNNING; + thread_local static ORIGIN_HANDLER_EXIST_FLAG exist_read = ORIGIN_HANDLER_EXIST_FLAG::NOT_CHECKED; -thread_local static ORIGIN_HANDLER_EXIST_FLAG exist_write = - ORIGIN_HANDLER_EXIST_FLAG::NOT_CHECKED; thread_local static void (*origin_segv_read_handler)(int, siginfo_t *, void *) = nullptr; +#endif +#ifdef ENABLE_PROBE_WRITE_CHECK + +extern "C" void jump_point_write(); +thread_local static PROBE_STATUS status_probe_read = PROBE_STATUS::NOT_RUNNING; + +thread_local static ORIGIN_HANDLER_EXIST_FLAG exist_write = + ORIGIN_HANDLER_EXIST_FLAG::NOT_CHECKED; + thread_local static void (*origin_segv_write_handler)(int, siginfo_t *, void *) = nullptr; - +#endif #ifdef ENABLE_PROBE_READ_CHECK static void segv_read_handler(int sig, siginfo_t *siginfo, void *ctx) @@ -186,7 +199,6 @@ int64_t bpftime_probe_read(uint64_t dst, int64_t size, uint64_t ptr, uint64_t, return ret; } - #ifdef ENABLE_PROBE_WRITE_CHECK static void segv_write_handler(int sig, siginfo_t *siginfo, void *ctx) {