基于eBPF检测 进程生命周期

目录

tracepoint

ProcessLifeCycle.c

ebpf_prog_test_main.cpp

Android.bp

Readme

运行输出


tracepoint

"tracepoint/sched/sched_process_fork":进程创建事件 - "tracepoint/sched/sched_process_exit":进程退出事件 - "tracepoint/sched/sched_process_free":进程释放事件

ProcessLifeCycle.c

#include 
#include 


// Define some status flag
#define MAP_FALL 0b00000001
// Define data type size
#define MAX_SIZE 4096
#define VARIABLE 1

#pragma pack (1)
typedef struct
{
    pid_t ppid;
    pid_t pid;
} PidInfo;

DEFINE_BPF_MAP_GRW(process_life_map, HASH, pid_t, pid_t, MAX_SIZE, AID_SYSTEM)
DEFINE_BPF_MAP_GRO(process_life_fork_map, ARRAY, uint32_t, PidInfo, MAX_SIZE, AID_SYSTEM)
DEFINE_BPF_MAP_GRW(process_life_fork_map_status, PERCPU_ARRAY, uint32_t, uint32_t, VARIABLE, AID_SYSTEM)

DEFINE_BPF_MAP_GRO(process_life_fork_map_front, PERCPU_ARRAY, uint32_t, uint32_t, VARIABLE, AID_SYSTEM)
DEFINE_BPF_MAP_GWO(process_life_fork_map_rear, PERCPU_ARRAY, uint32_t, uint32_t, VARIABLE, AID_SYSTEM)


DEFINE_BPF_MAP_GRO(process_life_exit_map, ARRAY, uint32_t, pid_t, MAX_SIZE, AID_SYSTEM)
DEFINE_BPF_MAP_GRW(process_life_exit_map_status, PERCPU_ARRAY, uint32_t, uint32_t, VARIABLE, AID_SYSTEM)
DEFINE_BPF_MAP_GRO(process_life_exit_map_front, PERCPU_ARRAY, uint32_t, uint32_t, VARIABLE, AID_SYSTEM)
DEFINE_BPF_MAP_GWO(process_life_exit_map_rear, PERCPU_ARRAY, uint32_t, uint32_t, VARIABLE, AID_SYSTEM)


#pragma pack (1)
struct sched_process_fork_args
{
    unsigned short common_type;
    unsigned char common_flags;
    unsigned char common_preempt_count;
    int common_pid;
    char parent_comm[16];
    pid_t parent_pid;
    char child_comm[16];
    pid_t child_pid;
};

#pragma pack (1)
struct sched_process_exit_args
{
    unsigned short common_type;
    unsigned char common_flags;
    unsigned char common_preempt_count;
    int common_pid;
    char comm[16];
    pid_t pid;
    int prio;
};


DEFINE_BPF_PROG("tracepoint/sched/sched_process_fork", AID_ROOT, AID_SYSTEM, bpfser_sched_process_fork)
(struct sched_process_fork_args* args) {
    const int ALLOW = 1;
    uint32_t zero = 0;
    pid_t child_pid = args->child_pid;
    pid_t ppid = args->parent_pid;
    pid_t *pid_lookup_value = bpf_process_life_map_lookup_elem(&child_pid);
    uint32_t *front = bpf_process_life_fork_map_front_lookup_elem(&zero);
    uint32_t *rear = bpf_process_life_fork_map_rear_lookup_elem(&zero);
    if (front && rear) {
        *front = *front + 1;
        if (*front >= MAX_SIZE) *front = 0;
        if (*front == *rear) {
            // Map Full !!!
            uint32_t status = MAP_FALL;
            bpf_process_life_fork_map_status_update_elem(&zero, &status, BPF_ANY);
        } else {
            PidInfo pidInfo = {.ppid = ppid, .pid = child_pid};
            bpf_process_life_fork_map_front_update_elem(&zero, front, BPF_ANY);
            bpf_process_life_fork_map_update_elem(front, &pidInfo, BPF_ANY);
        }
    }
    if (!pid_lookup_value) {
        bpf_process_life_map_update_elem(&child_pid, &ppid, BPF_ANY);
    }
    return ALLOW;
}


DEFINE_BPF_PROG("tracepoint/sched/sched_process_exit", AID_ROOT, AID_SYSTEM, bpfser_sched_process_exit)
(struct sched_process_exit_args* args) {
    const int ALLOW = 1;
    uint32_t zero = 0;
    pid_t pid = args->pid;
    pid_t *pid_lookup_value = bpf_process_life_map_lookup_elem(&pid);
    uint32_t *front = bpf_process_life_exit_map_front_lookup_elem(&zero);
    uint32_t *rear = bpf_process_life_exit_map_rear_lookup_elem(&zero);
    if (front && rear) {
        *front = *front + 1;
        if (*front >= MAX_SIZE) *front = 0;
        if (*front == *rear) {
            // Map Full !!!
            uint32_t status = MAP_FALL;
            bpf_process_life_exit_map_status_update_elem(&zero, &status, BPF_ANY);
        } else {
            bpf_process_life_exit_map_front_update_elem(&zero, front, BPF_ANY);
            bpf_process_life_exit_map_update_elem(front, &pid, BPF_ANY);
        }
    }
    if (!pid_lookup_value) {
        return ALLOW;
    }
    bpf_process_life_map_delete_elem(&pid);
    return ALLOW;
}

DEFINE_BPF_PROG("tracepoint/sched/sched_process_free", AID_ROOT, AID_SYSTEM, bpfser_sched_process_free)
(struct sched_process_free_args* args) {
    const int ALLOW = 1;
    pid_t pid = args->pid;
    pid_t *pid_lookup_value = bpf_process_life_map_lookup_elem(&pid);
    if (!pid_lookup_value) {
        return ALLOW;
    }
    bpf_process_life_map_delete_elem(&pid);
    return ALLOW;
}



LICENSE("GPL");

ebpf_prog_test_main.cpp

#include 
#include 

#include 
#include 

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define BPF_FS_PATH "/sys/fs/bpf/"


using android::base::unique_fd;
using android::base::StringPrintf;



static int retrieveProgramFd(const std::string &eventType, const std::string& eventName) {
    std::string path = StringPrintf(BPF_FS_PATH "prog_ProcessLifeCycle_tracepoint_%s_%s",eventType.c_str(), eventName.c_str());
    
    return android::bpf::retrieveProgram(path.c_str());
}

static bool attachTracepointProgram(const std::string &eventType, const std::string& eventName) {
    int prog_fd = retrieveProgramFd(eventType, eventName);
    if (prog_fd < 0) {
        LOG(ERROR) << "retrieveProgramFd failed: " << eventType << "/" << "eventName";
        return false;
    }
    return bpf_attach_tracepoint(prog_fd, eventType.c_str(), eventName.c_str()) >= 0;
}



// Check if tracking is expected to work without activating it.
bool isTrackingProcessLifeSupported() {
    if (retrieveProgramFd("sched", "sched_process_fork") < 0) return false;
    if (retrieveProgramFd("sched", "sched_process_exit") < 0) return false;
    return true;
}

bool startTrackingProcesslife() {
    bool result = attachTracepointProgram("sched", "sched_process_fork") &&
            attachTracepointProgram("sched", "sched_process_exit");
    return result;
}

void printEbpfMap() {
    auto start = std::chrono::high_resolution_clock::now();
    unique_fd process_fd = unique_fd{bpf_obj_get(BPF_FS_PATH "map_ProcessLifeCycle_process_life_map")};
    pid_t pid;
    pid_t prevKey;
    uint8_t status;
    size_t loop = 0;
    if (android::bpf::getFirstMapKey(process_fd, &pid) != 0) {
        LOG(ERROR) << "W: No process map info!";
        return;
    }
    do {
        LOG(ERROR) << "I: pid info : " << pid;
        loop++;
        prevKey = pid;
    } while (prevKey = pid, !android::bpf::getNextMapKey(process_fd, &prevKey, &pid));
    auto end = std::chrono::high_resolution_clock::now();
    LOG(ERROR) << "printEbpfMap Count : " << loop << "  , time: " << std::chrono::duration_cast(end - start).count();
}

void printForkFrontMap() {
    const uint32_t ZERO = 0;
    uint32_t value = 0;
    unique_fd mapfd = unique_fd{bpf_obj_get(BPF_FS_PATH "map_ProcessLifeCycle_process_life_fork_map_front")};
    android::bpf::findMapEntry(mapfd, &ZERO, &value);
    LOG(INFO) << "map front: " << value;
}

void printForkRearMap() {
    const uint32_t ZERO = 0;
    uint32_t value = 0;
    unique_fd mapfd = unique_fd{bpf_obj_get(BPF_FS_PATH "map_ProcessLifeCycle_process_life_fork_map_rear")};
    android::bpf::findMapEntry(mapfd, &ZERO, &value);
    LOG(INFO) << "map rear: " << value;
}

int main(int argc, char const *argv[])
{
    if (isTrackingProcessLifeSupported()) {
        LOG(ERROR) << "Tracking Process Life Supported!";
    } else {
        LOG(ERROR) << "E: Tracking Process Life not Supported!";
    }

    if (startTrackingProcesslife()) {
        LOG(ERROR) << "Start tracking success!";
    } else {
        LOG(ERROR) << "E: Start tracking failed!";
    }

    while (true)
    {
        printEbpfMap();
        printForkFrontMap();
        printForkRearMap();
        sleep(10);
    }
    

    return 0;
}

Android.bp

cc_binary {
    name: "ebpf_test",
    srcs: [
        "ebpf_prog_test_main.cpp",
    ],
    header_libs: [
        "bpf_headers",
        "bpf_prog_headers",
        ],
    shared_libs: [
        "libbase",
        "libbpf_bcc",
        "libcutils",
        "liblog",
        "libutils",
        "libbpf_minimal",
    ],
    export_header_lib_headers: ["bpf_headers"],
    export_shared_lib_headers: ["libbase"],
    cppflags: [
        "-Wall",
        "-Werror",
        "-Wformat",
        "-Wthread-safety",
        "-Wunused",
        "-Wunreachable-code",
    ],
}

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

Readme debug

source build/envsetup.sh
lunch missi_phone_cn-user
make ProcessLifeCycle.o ebpf_test

adb root; adb remount; adb reboot
adb root; adb remount;
adb push out/target/product/missi/system/etc/bpf/ProcessLifeCycle.o /system/etc/bpf/ProcessLifeCycle.o
adb push out/target/product/missi/system/bin/ebpf_test /mnt/rescue/ebpf_test
adb shell chmod +x /mnt/rescue/ebpf_test

adb shell setenforce 0
adb shell /mnt/rescue/ebpf_test

# 另一个窗口查看日志输出
adb logcat | grep ebpf_test

运行输出

11-24 02:23:37.680 12209 12209 E ebpf_test: I: pid info : 12981
11-24 02:23:37.680 12209 12209 E ebpf_test: I: pid info : 12809
11-24 02:23:37.680 12209 12209 E ebpf_test: I: pid info : 13482
11-24 02:23:37.680 12209 12209 E ebpf_test: I: pid info : 13476
11-24 02:23:37.680 12209 12209 E ebpf_test: I: pid info : 11704
11-24 02:23:37.680 12209 12209 E ebpf_test: I: pid info : 12665
11-24 02:23:37.680 12209 12209 E ebpf_test: I: pid info : 12231
11-24 02:23:37.680 12209 12209 E ebpf_test: I: pid info : 13594
11-24 02:23:37.680 12209 12209 E ebpf_test: I: pid info : 12801
11-24 02:23:37.680 12209 12209 E ebpf_test: I: pid info : 12311
11-24 02:23:37.680 12209 12209 E ebpf_test: I: pid info : 12754
11-24 02:23:37.680 12209 12209 E ebpf_test: I: pid info : 12932
11-24 02:23:37.680 12209 12209 E ebpf_test: I: pid info : 12979
11-24 02:23:37.680 12209 12209 E ebpf_test: I: pid info : 13582
11-24 02:23:37.680 12209 12209 E ebpf_test: I: pid info : 13375
11-24 02:23:37.680 12209 12209 E ebpf_test: I: pid info : 13308
11-24 02:23:37.680 12209 12209 E ebpf_test: I: pid info : 12215
11-24 02:23:37.681 12209 12209 E ebpf_test: I: pid info : 13521
11-24 02:23:37.681 12209 12209 E ebpf_test: I: pid info : 13121
11-24 02:23:37.681 12209 12209 E ebpf_test: I: pid info : 12040
11-24 02:23:37.681 12209 12209 E ebpf_test: I: pid info : 13625
11-24 02:23:37.681 12209 12209 E ebpf_test: I: pid info : 13550
11-24 02:23:37.681 12209 12209 E ebpf_test: I: pid info : 13247
11-24 02:23:37.681 12209 12209 E ebpf_test: I: pid info : 13249
11-24 02:23:37.681 12209 12209 E ebpf_test: I: pid info : 13621
11-24 02:23:37.681 12209 12209 E ebpf_test: I: pid info : 12445
11-24 02:23:37.681 12209 12209 E ebpf_test: I: pid info : 12755
11-24 02:23:37.681 12209 12209 E ebpf_test: I: pid info : 12930
11-24 02:23:37.681 12209 12209 E ebpf_test: I: pid info : 13381
11-24 02:23:37.681 12209 12209 E ebpf_test: I: pid info : 12962
11-24 02:23:37.681 12209 12209 E ebpf_test: I: pid info : 13207
11-24 02:23:37.681 12209 12209 E ebpf_test: I: pid info : 13601
11-24 02:23:37.681 12209 12209 E ebpf_test: I: pid info : 13009
11-24 02:23:37.681 12209 12209 E ebpf_test: I: pid info : 12309
11-24 02:23:37.681 12209 12209 E ebpf_test: I: pid info : 12898
11-24 02:23:37.681 12209 12209 E ebpf_test: I: pid info : 12905
11-24 02:23:37.681 12209 12209 E ebpf_test: I: pid info : 12767
11-24 02:23:37.681 12209 12209 E ebpf_test: I: pid info : 13624
11-24 02:23:37.681 12209 12209 E ebpf_test: printEbpfMap Count : 487  , time: 16726093
11-24 02:23:37.681 12209 12209 I ebpf_test: map front: 78
11-24 02:23:37.681 12209 12209 I ebpf_test: map rear: 0

小结

使用eBPF技术实现的内核态程序,用于跟踪进程的创建和退出。

你可能感兴趣的:(eBPF,simpleperf技术,eBPF,进程生命周期)