Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

kvm_watcher:修复bug #959

Merged
merged 3 commits into from
Jan 13, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 48 additions & 9 deletions eBPF_Supermarket/kvm_watcher/include/bpf/container.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@ static int trace_container_sys_entry(struct trace_event_raw_sys_enter *args){
bpf_map_update_elem(&id,&pid,&syscall_id,BPF_ANY);
return 0;
}
static int trace_container_sys_exit(struct trace_event_raw_sys_exit *args,void *rb,struct common_event *e){

static int trace_container_sys_exit(struct trace_event_raw_sys_exit *args){
u64 exit_time = bpf_ktime_get_ns();
pid_t pid = bpf_get_current_pid_tgid();
u64 delay,start_time,syscallid;
Expand Down Expand Up @@ -89,27 +90,25 @@ static int trace_container_sys_exit(struct trace_event_raw_sys_exit *args,void *
if (!syscall_value) {
return 0;
}

//检查 syscallid 是否超出范围
//逻辑检查应该放到获取结构体之后的第一步操作,提前的检查让路径变得显式且安全,否则验证器可能无法通过
if (syscallid >= MAX_SYSCALL_NUM || syscallid < 0) {
return 0; // 如果超出范围,直接返回
}

// 读取 container_id
int ret = bpf_probe_read_kernel_str(syscall_value->container_id, sizeof(syscall_value->container_id), contain_id);
if (ret < 0) {
bpf_printk("Failed to read container_id from kernel space, error code: %d\n", ret);
return 0;
}

// 打印读取的 container_id
bpf_printk("container_id: %s\n", syscall_value->container_id);

// 获取进程名并存储
ret = bpf_get_current_comm(syscall_value->proc_name, sizeof(syscall_value->proc_name));
if (ret < 0) {
bpf_printk("Failed to read process name, error code: %d\n", ret);
return 0;
}
//检查 syscallid 是否超出范围
if (syscallid >= MAX_SYSCALL_NUM || syscallid < 0) {
return 0; // 如果超出范围,直接返回
}
syscall_value->syscall_total_delay[syscallid] += delay; // 加上 delay 的值
syscall_value->syscall_id_counts[syscallid] += 1; // 计数加 1
return 0;
Expand All @@ -118,4 +117,44 @@ static int trace_container_sys_exit(struct trace_event_raw_sys_exit *args,void *
struct data_t {
char nodename[MAX_NODENAME_LEN];
};
static bool is_container_task(const volatile char *hostname){
struct task_struct *task;
struct nsproxy *ns;
struct uts_namespace *uts;
struct data_t data = {};
// 获取当前任务的 task_struct
task = (struct task_struct *)bpf_get_current_task();

// 获取 nsproxy
bpf_probe_read_kernel(&ns, sizeof(ns), &task->nsproxy);
if (!ns) {
return false;
}

// 获取 uts_namespace
bpf_probe_read_kernel(&uts, sizeof(uts), &ns->uts_ns);
if (!uts) {
return false;
}
// 读取主机名
bpf_probe_read_kernel_str(&data.nodename, sizeof(data.nodename), uts->name.nodename);
// 打印主机名
bool is_equal = true;
for(int i = 0;i<MAX_NODENAME_LEN;i++){
if(data.nodename[i] != hostname[i]){
is_equal = false; //表明匹配失败了,该进程和需要监听的id不相等
break;
}
if(data.nodename[i]=='\0'||hostname[i]=='\0'){
break;
}
}
if (is_equal){ //表明匹配成功,该进程是需要监听的容器里的进程
pid_t pid = bpf_get_current_pid_tgid();
bpf_map_update_elem(&container_id_map,&pid,&data.nodename,BPF_ANY);
return true;
} else {
return false;
}
}
#endif /* __CONTAINER_H */
80 changes: 8 additions & 72 deletions eBPF_Supermarket/kvm_watcher/src/kvm_watcher.bpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -245,84 +245,20 @@ int BPF_KPROBE(kp_start_sw_timer, struct kvm_lapic *apic) {
CHECK_PID(vm_pid);
return trace_start_sw_timer(apic);
}

//采集容器的系统用调用信息
SEC("tracepoint/raw_syscalls/sys_enter")
int tp_container_sys_entry(struct trace_event_raw_sys_enter *args) {
//过滤进程
if (hostname == NULL || hostname[0] == '\0') {

return false; // 提前返回
}
struct task_struct *task;
struct nsproxy *ns;
struct uts_namespace *uts;
struct data_t data = {};
// 获取当前任务的 task_struct
task = (struct task_struct *)bpf_get_current_task();

// 获取 nsproxy
bpf_probe_read_kernel(&ns, sizeof(ns), &task->nsproxy);
if (!ns) {
return false;
}

// 获取 uts_namespace
bpf_probe_read_kernel(&uts, sizeof(uts), &ns->uts_ns);
if (!uts) {
return false;
}
// 读取主机名
bpf_probe_read_kernel_str(&data.nodename, sizeof(data.nodename), uts->name.nodename);
// 打印主机名

for(int i = 0;i<MAX_NODENAME_LEN;i++){
if(data.nodename[i] != hostname[i]){
return 0;
}
if(data.nodename[i]=='\0'||hostname[i]=='\0'){
break;
}
if(is_container_task(hostname)){
return trace_container_sys_entry(args);
}else{
return 0;
}
pid_t pid = bpf_get_current_pid_tgid();
bpf_map_update_elem(&container_id_map,&pid,&data.nodename,BPF_ANY);
return trace_container_sys_entry(args);
}
SEC("tracepoint/raw_syscalls/sys_exit")
int tracepoint__syscalls__sys_exit(struct trace_event_raw_sys_exit *args) {
//过滤进程
if (hostname == NULL || hostname[0] == '\0') {
return false;
}
struct task_struct *task;
struct nsproxy *ns;
struct uts_namespace *uts;
struct data_t data = {};
// 获取当前任务的 task_struct
task = (struct task_struct *)bpf_get_current_task();

// 获取 nsproxy
bpf_probe_read_kernel(&ns, sizeof(ns), &task->nsproxy);
if (!ns) {
return false;
}

// 获取 uts_namespace
bpf_probe_read_kernel(&uts, sizeof(uts), &ns->uts_ns);
if (!uts) {
return false;
}
// 读取主机名
bpf_probe_read_kernel_str(&data.nodename, sizeof(data.nodename), uts->name.nodename);
// 打印主机名

for(int i = 0;i<MAX_NODENAME_LEN;i++){
if(data.nodename[i] != hostname[i]){
return 0;
}
if(data.nodename[i]=='\0'||hostname[i]=='\0'){
break;
}
if(is_container_task(hostname)){
return trace_container_sys_exit(args);
}else{
return 0;
}
return trace_container_sys_exit(args, &rb, e);
}
Loading