Android Kprobe使用

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

手写例子

echo 'p:kprobes/myretprobe do_sys_openat2 dfd=$arg1:u32 filename=+0($arg2):string' > /sys/kernel/tracing/kprobe_events
echo 1 > /sys/kernel/tracing/events/kprobes/myretprobe/enable
echo 1 > /sys/kernel/tracing/tracing_on
cat /sys/kernel/tracing/trace_pipe

首先是prog程序

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

#include <linux/ptrace.h>
#include "bpf_kprobe_test.h"

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

// 定义了函数kp_do_faccessat, 目前来看名字可以随便起没什么作用
DEFINE_BPF_PROG("kprobe/do_faccessat", AID_ROOT, AID_NET_ADMIN, kp_do_faccessat)
//(struct user_pt_regs *regs, int dirfd, const char *pathname, int mode) {
(struct user_pt_regs *regs) { // 这里aosp头文件叫做user_pt_regs, bcc中是pt_regs
    int key = 100;
    struct data data_t;
    data_t.pid = bpf_get_current_pid_tgid() >> 32; 
    
    // aosp中本身不支持此函数,bcc支持,直接给aosp加上
    // system/bpf/progs/include/bpf_helpers.h
    bpf_get_current_comm(data_t.comm, sizeof(data_t.comm));

    // 测试1
    // 2-20 16:38:19.882   887   887 W LibBpfLoader: bpf_prog_load - BEGIN log_buf contents:
    // 12-20 16:38:19.882   887   887 W LibBpfLoader: 0: (bf) r6 = r3
    // 12-20 16:38:19.882   887   887 W LibBpfLoader: R3 !read_ok
    // bpfload Permission denied, 可能是用户空间地址无法访问
    
    //if (pathname)
    //  bpf_probe_read_str(&data_t.log, sizeof(data_t.log), (void *)pathname);

    // 测试2 强行拷贝 bpfload 还是加载prog失败,不过这次没有R3 !read_ok
    // memcpy(data_t.log, pathname, sizeof(data_t.log));

    // 测试3 通过寄存器访问.测试OK  可以获取到pathname
    //    systemd-journal-338 do_faccessat /run/systemd/jo
    //    systemd-journal-338 do_faccessat /run/systemd/jo
    //    systemd-journal-338 do_faccessat /run/systemd/jo
    //    systemd-journal-338 do_faccessat /run/systemd/jo
    bpf_probe_read_str(&data_t.log, sizeof(data_t.log), (void *)regs->regs[1]);

    bpf_do_faccessat_map_update_elem(&key, &data_t, BPF_ANY);
    return 0;
}

LICENSE("GPL");

头文件

// bpf_kprobe_test.h
#ifndef _BPF_KPROBE_TEST_H
#define _BPF_KPROBE_TEST_H

#include <linux/sched.h>
#ifndef TASK_COMM_LEN
#define TASK_COMM_LEN 16 // linux/sched.h 
#endif

struct data {
    pid_t pid;
    char comm[TASK_COMM_LEN];
    char log[16];
};
#endif // _BPF_KPROBE_TEST_H

测试程序

// 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>

#include "bpf_kprobe_test.h"

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);

    // 打开对应的id 文件
    // /sys/kernel/tracing/events/task/task_rename/id

    /**
     * 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("%s-%d do_faccessat %s\n", data_t.comm, data_t.pid, data_t.log);
    }

    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",
    ],
}

运行效果

posted @ 2023-12-19 19:44  梦过无声  阅读(337)  评论(1编辑  收藏  举报