目录
tracepoint
ProcessLifeCycle.c
ebpf_prog_test_main.cpp
Android.bp
Readme
运行输出
"tracepoint/sched/sched_process_fork":进程创建事件 - "tracepoint/sched/sched_process_exit":进程退出事件 - "tracepoint/sched/sched_process_free":进程释放事件
#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");
#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;
}
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",
],
}
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技术实现的内核态程序,用于跟踪进程的创建和退出。