Android Kprobe使用

发布时间 2023-12-19 19:47:18作者: 梦过无声

搜索了好久都没有找到关于Android中使用kprobe的例子,基本都是用tracepoint .于是自己摸索了下,记录下

首先是prog程序

#include <linux/bpf.h>
#include <stdbool.h>
#include <stdint.h>
#include <bpf_helpers.h>
#include <string.h>

struct switch_args {
    unsigned long long ignore;
    char prev_comm[16];
    int prev_pid;
    int prev_prio;
    long long prev_state;
    char next_comm[16];
    int next_pid;
    int next_prio;
};

struct data {
    char str[16];
    void *ptr;
};


DEFINE_BPF_MAP(do_faccessat_map, ARRAY, int, struct data, 1024);

DEFINE_BPF_PROG("kprobe/do_faccessat", AID_ROOT, AID_NET_ADMIN, kp_do_faccessat)
//(struct pt_regs *ctx, int dirfd, const char __user *pathname, int mode) {
//(void *ctx, int dirfd, const char __user *pathname, int mode) {
(struct switch_args *ctx) {  //参数这里暂时还不知道怎么获取传递过去,因为中途忙其他的去了
    int key = 100;

    struct data data_t;
    data_t.ptr = ctx;
    memcpy(data_t.str, "hello world", 16);
 
    bpf_do_faccessat_map_update_elem(&key, &data_t, BPF_ANY);
    return 0;
}

LICENSE("Apache 2.0");

测试程序

// bpf_kprobe_test_cli.cpp
#include <android-base/macros.h>
#include <stdlib.h>
#include <unistd.h>
#include <iostream>
#include <bpf/BpfMap.h> // system/bpf/libbpf_android/include/bpf/BpfMap.h
#include <bpf/BpfUtils.h>
#include <libbpf_android.h>

struct data {
    char str[16];
    void *ptr;
};

int main() {
    constexpr const char tp_prog_path[] = "/sys/fs/bpf/prog_bpf_kprobe_test_kprobe_do_faccessat";
    constexpr const char tp_map_path[] = "/sys/fs/bpf/map_bpf_kprobe_test_do_faccessat_map";

    // Attach tracepoint and wait for 4 seconds
    int mProgFd = bpf_obj_get(tp_prog_path);
    // int mMapFd = bpf_obj_get(tp_map_path);

    /**
     * int bpf_attach_kprobe(int progfd, enum bpf_probe_attach_type attach_type,
     *                     const char *ev_name, const char *fn_name, uint64_t fn_offset)
     * 打开 /sys/kernel/tracing/kprobe_events
     * 写入对应事件 'echo 'p:kprobes/do_faccessat_bcc_pid_ do_faccessat'
     * 参考: https://www.kernel.org/doc/html/latest/trace/kprobetrace.html
     */
    int pfd = bpf_attach_kprobe(mProgFd, BPF_PROBE_ENTRY, 
            "myprobe"/*probe name*/, "do_faccessat" /*函数符号*/, 0);
    if (pfd < 0) {
        printf("bpf_attach_kprobe error!\n");
        exit(0);
    }

    sleep(1);
    // 高版本使用fd构造BpfMap
    android::bpf::BpfMap<int, struct data> myMap(tp_map_path);
 
    pid_t pid = getpid();
    printf("pid: %d\n", pid);

    while(1) {
        usleep(40000);
        // android::base::Result<Value> 类型
        data data_t = myMap.readValue(100).value();
        printf("kprobe do_faccessat %s map addr %p\n", data_t.str, data_t.ptr);
    }

    exit(0);
}

Android.bp

bpf {
    name: "bpf_kprobe_test.o",
    srcs: ["bpf_kprobe_test.c"],
    cflags: [
        "-Wall",
        "-Werror",
    ],
}


cc_binary {
    name: "bpf_kprobe_test_cli",

    cflags: [
        "-Wall",
        "-Werror",
        "-Wthread-safety",
    ], 
    clang: true,
    shared_libs: [
        "libcutils",
        "libbpf_android",
        "libbase",
        "liblog",
        "libnetdutils",
        "libbpf",
    ],
    srcs: [
        "bpf_kprobe_test_cli.cpp",
    ],
}

运行效果