From a9c33766dc5fa50ebad7bbbe00fc72af1098ab1f Mon Sep 17 00:00:00 2001 From: Longjun Luo Date: Tue, 19 Sep 2023 20:54:15 +0800 Subject: [PATCH] upatch: init for upatch monitor Signed-off-by: Longjun Luo --- upatch/upatch-manage/ebpf/CMakeLists.txt | 68 +++++++++++++++ .../upatch-manage/ebpf/upatch-manager.bpf.c | 41 +++++++++ upatch/upatch-manage/ebpf/upatch-manager.c | 84 +++++++++++++++++++ upatch/upatch-manage/ebpf/upatch-manager.h | 13 +++ 4 files changed, 206 insertions(+) create mode 100644 upatch/upatch-manage/ebpf/CMakeLists.txt create mode 100644 upatch/upatch-manage/ebpf/upatch-manager.bpf.c create mode 100644 upatch/upatch-manage/ebpf/upatch-manager.c create mode 100644 upatch/upatch-manage/ebpf/upatch-manager.h diff --git a/upatch/upatch-manage/ebpf/CMakeLists.txt b/upatch/upatch-manage/ebpf/CMakeLists.txt new file mode 100644 index 00000000..bc08f0f7 --- /dev/null +++ b/upatch/upatch-manage/ebpf/CMakeLists.txt @@ -0,0 +1,68 @@ +# SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause +cmake_minimum_required(VERSION 3.22) +project(upatch-manager) + +find_program(BASH bash HINTS /bin) +find_package(ZLIB) + +if(NOT DEFINED BPFTOOL_PATH) + set(BPFTOOL_PATH "bpftool") +endif() + +if(NOT DEFINED CLANG_PATH) + set(CLANG_PATH "clang") +endif() + +if(NOT DEFINED LLVM_STRIP_PATH) + set(LLVM_STRIP_PATH "llvm-strip") +endif() + +if(${CMAKE_SYSTEM_PROCESSOR} MATCHES "x86_64") + set(ARCH "x86") +elseif(${CMAKE_SYSTEM_PROCESSOR} MATCHES "arm") + set(ARCH "arm") +elseif(${CMAKE_SYSTEM_PROCESSOR} MATCHES "aarch64") + set(ARCH "arm64") +elseif(${CMAKE_SYSTEM_PROCESSOR} MATCHES "ppc64le") + set(ARCH "powerpc") +elseif(${CMAKE_SYSTEM_PROCESSOR} MATCHES "mips") + set(ARCH "mips") +elseif(${CMAKE_SYSTEM_PROCESSOR} MATCHES "riscv64") + set(ARCH "riscv") +elseif(${CMAKE_SYSTEM_PROCESSOR} MATCHES "loongarch64") + set(ARCH "loongarch") +endif() + +function(generate_bpf_skel bpf_source bpf_headers bpf_object skel_output) + add_custom_command(OUTPUT ${bpf_headers} + COMMAND ${BPFTOOL_PATH} btf dump file + /sys/kernel/btf/vmlinux format c > ${bpf_headers} + ) + add_custom_command(OUTPUT ${bpf_object} + COMMAND ${CLANG_PATH} -g -O2 -target bpf -D__TARGET_ARCH_${ARCH} + -I ${CMAKE_CURRENT_BINARY_DIR} + -c ${bpf_source} + -o ${bpf_object} + COMMAND ${LLVM_STRIP_PATH} -g ${bpf_object} + MAIN_DEPENDENCY ${bpf_source} + DEPENDS ${bpf_headers} + ) + add_custom_command(OUTPUT ${skel_output} + COMMAND ${CMAKE_COMMAND} -E env ${BASH} -c + "${BPFTOOL_PATH} gen skeleton ${bpf_object} > ${skel_output}" + VERBATIM + MAIN_DEPENDENCY ${bpf_object} + ) +endfunction(generate_bpf_skel) + +set(_skel_output "${CMAKE_PROJECT_NAME}.skel.h") +generate_bpf_skel( + "${CMAKE_CURRENT_SOURCE_DIR}/${CMAKE_PROJECT_NAME}.bpf.c" + "vmlinux.h" + "${CMAKE_PROJECT_NAME}.bpf.o" + "${_skel_output}" +) +add_compile_options(-g -Wall) +include_directories(${CMAKE_CURRENT_BINARY_DIR}) +add_executable(${CMAKE_PROJECT_NAME} ${CMAKE_PROJECT_NAME}.c ${_skel_output}) +target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE libbpf.a elf ZLIB::ZLIB) \ No newline at end of file diff --git a/upatch/upatch-manage/ebpf/upatch-manager.bpf.c b/upatch/upatch-manage/ebpf/upatch-manager.bpf.c new file mode 100644 index 00000000..d91a4469 --- /dev/null +++ b/upatch/upatch-manage/ebpf/upatch-manager.bpf.c @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause +/* Copyright (c) 2023 Longjun Luo. */ +#include "vmlinux.h" + +#include +#include +#include + +#include "upatch-manager.h" + +unsigned int _version SEC("version") = 1; +char LICENSE[] SEC("license") = "Dual BSD/GPL"; + +struct { + __uint(type, BPF_MAP_TYPE_HASH); + __uint(max_entries, UPATCH_MAX_PATCH_ENTITY); + __type(key, struct elf_process); + __type(value, int); +} elf_process_maps SEC(".maps"); + +static int initial_entry = 0; + +SEC("uprobe") +/* used for find releated process, need check it when using pid */ +int upatch_empty_handler(struct pt_regs *ctx) +{ + return 0; +} + +SEC("kprobe") +/* ATTENTION: install_breakpoint is a local function and it may repeat */ +int BPF_KPROBE(install_breakpoint, struct uprobe *uprobe, struct mm_struct *mm, + struct vm_area_struct *vma, unsigned long vaddr) +{ + struct elf_process ep; + ep.ino = BPF_CORE_READ(uprobe, inode, i_ino); + ep.pid = BPF_CORE_READ(mm, owner, pid); + bpf_map_update_elem(&elf_process_maps, &ep, &initial_entry, BPF_ANY); + bpf_printk("ino %lu works for pid %d in addr 0x%lx \n", ep.ino, ep.pid, vaddr); + return 0; +} \ No newline at end of file diff --git a/upatch/upatch-manage/ebpf/upatch-manager.c b/upatch/upatch-manage/ebpf/upatch-manager.c new file mode 100644 index 00000000..71ac89cd --- /dev/null +++ b/upatch/upatch-manage/ebpf/upatch-manager.c @@ -0,0 +1,84 @@ +// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) +/* Copyright (c) 2023 Longjun Luo. */ +#include +#include +#include + +#include +#include +#include + +#include "upatch-manager.h" +#include "upatch-manager.skel.h" + +static int libbpf_print_fn(enum libbpf_print_level level, const char *format, va_list args) +{ + return vfprintf(stderr, format, args); +} + +static int attach_elf(struct upatch_manager_bpf *skel, const char *path) +{ + struct bpf_link *link; + int ret; + + /* find entry point and attach it */ + link = bpf_program__attach_uprobe(skel->progs.upatch_empty_handler, false, -1, path, 0x1126); + if (!link) { + ret = -errno; + fprintf(stderr, "Failed to attach 1 uprobe: %d\n", ret); + return ret; + } + return 0; +} + +/* TODO: find all pids and handle them */ +static int upatch_manage_daemon() +{ + sleep(1); + return 0; +} + +int main(int argc, char **argv) +{ + int err; + struct upatch_manager_bpf *skel; + + libbpf_set_print(libbpf_print_fn); + + skel = upatch_manager_bpf__open_and_load(); + if (!skel) { + fprintf(stderr, "Failed to open and load BPF skeleton\n"); + return 1; + } + + skel->links.install_breakpoint = bpf_program__attach_kprobe( + skel->progs.install_breakpoint, false, "install_breakpoint.isra.0"); + if (!skel->links.install_breakpoint && errno == ENOENT) + skel->links.install_breakpoint = bpf_program__attach_kprobe( + skel->progs.install_breakpoint, false, "install_breakpoint"); + if (!skel->links.install_breakpoint) { + err = -errno; + fprintf(stderr, "Failed to attach kprobe for install_breakpoint: %d \n", err); + goto cleanup; + } + + err = upatch_manager_bpf__attach(skel); + if (err) { + fprintf(stderr, "Failed to auto-attach BPF skeleton: %d\n", err); + goto cleanup; + } + + // err = attach_elf(skel, "./a.out"); + // if (err) { + // fprintf(stderr, "Attach elf failed - %d \n", err); + // goto cleanup; + // } + + while(1) { + upatch_manage_daemon(); + } + +cleanup: + upatch_manager_bpf__destroy(skel); + return -err; +} diff --git a/upatch/upatch-manage/ebpf/upatch-manager.h b/upatch/upatch-manage/ebpf/upatch-manager.h new file mode 100644 index 00000000..a5217a93 --- /dev/null +++ b/upatch/upatch-manage/ebpf/upatch-manager.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */ +/* Copyright (c) 2023 Longjun Luo. */ +#ifndef _UPATCH_MANAGER_H +#define _UPATCH_MANAGER_H + +#define UPATCH_MAX_PATCH_ENTITY 10240 + +struct elf_process { + unsigned long ino; + int pid; +}; + +#endif /* _UPATCH_MANAGER_H */ -- Gitee