Skip to content

Commit

Permalink
Merge pull request #952 from Monkey857/develop
Browse files Browse the repository at this point in the history
kvm_watcher:添加通过容器号来监测指定容器的系统调用功能
  • Loading branch information
nanshuaibo authored Dec 16, 2024
2 parents 25a0289 + 8ec6974 commit ae8fcc2
Show file tree
Hide file tree
Showing 4 changed files with 229 additions and 77 deletions.
93 changes: 39 additions & 54 deletions eBPF_Supermarket/kvm_watcher/include/bpf/container.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_core_read.h>
#include <bpf/bpf_tracing.h>
#define MAX_NODENAME_LEN 64
#define MAX_NODENAME_LEN 13
struct {
__uint(type,BPF_MAP_TYPE_HASH);
__uint(max_entries, 8192);
Expand All @@ -46,6 +46,12 @@ struct {
__type(value,struct container_id);
}container_id_map SEC(".maps");

struct {
__uint(type,BPF_MAP_TYPE_HASH);
__uint(max_entries, 80);
__type(key, pid_t);
__type(value,struct syscall_value); //记录容器ID、进程名、系统调用号、每个调用号的次数、单位时间内的总延迟
}proc_syscall_info SEC(".maps");

static int trace_container_sys_entry(struct trace_event_raw_sys_enter *args){
u64 st = bpf_ktime_get_ns();
Expand All @@ -62,8 +68,8 @@ static int trace_container_sys_exit(struct trace_event_raw_sys_exit *args,void *
u64 *st = bpf_map_lookup_elem(&time_info,&pid);
if( st !=0){
start_time = *st;
delay = (exit_time - start_time)/1000;
bpf_map_delete_elem(&time_info, &pid);
delay = (exit_time - start_time)/1000;
bpf_map_delete_elem(&time_info, &pid);
}else{
return 0;
}
Expand All @@ -72,65 +78,44 @@ static int trace_container_sys_exit(struct trace_event_raw_sys_exit *args,void *
syscallid = *sc_id;
bpf_map_delete_elem(&id, &pid);
}else{
return 0;
return 0;
}
const void *contain_id = bpf_map_lookup_elem(&container_id_map,&pid);
if(contain_id != NULL){
bpf_printk("hostname=%s\n",contain_id);
}else{
if(contain_id == NULL){
return 0;
}
//用指针去获取用户定义好的结构体,不然结构体过大会导致栈溢出
struct syscall_value *syscall_value = bpf_map_lookup_elem(&proc_syscall_info, &pid);
if (!syscall_value) {
return 0;
}
RESERVE_RINGBUF_ENTRY(rb, e);
e->syscall_data.delay = delay;
bpf_get_current_comm(&e->syscall_data.comm, sizeof(e->syscall_data.comm));
e->syscall_data.pid = pid;
bpf_probe_read_kernel_str(&(e->syscall_data.container_id),sizeof(e->syscall_data.container_id),contain_id);
e->syscall_data.syscall_id = syscallid;
bpf_ringbuf_submit(e, 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;
}

struct data_t {
char nodename[MAX_NODENAME_LEN];
};
static bool is_container_task(const volatile char hostname[MAX_NODENAME_LEN]){
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]){
pid_t pid = bpf_get_current_pid_tgid();
bpf_map_update_elem(&container_id_map,&pid,&data.nodename,BPF_ANY);
is_equal = false;
break;
}
if(data.nodename[i]=='\0'||hostname[i]=='\0'){
break;
}
}
if (is_equal){
return false;
} else {
return true;
}
}
#endif /* __CONTAINER_H */
8 changes: 8 additions & 0 deletions eBPF_Supermarket/kvm_watcher/include/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,14 @@ struct exit_value {
struct container_id{
char container_id[20];
};
//记录进程系统调用的详细信息
#define MAX_SYSCALL_NUM 462
struct syscall_value{
char container_id[20]; //容器ID
char proc_name[20]; //进程名
__u32 syscall_id_counts[MAX_SYSCALL_NUM];
__u64 syscall_total_delay[MAX_SYSCALL_NUM];
};
struct dirty_page_info {
__u64 gfn;
__u64 rel_gfn;
Expand Down
81 changes: 70 additions & 11 deletions eBPF_Supermarket/kvm_watcher/src/kvm_watcher.bpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
char LICENSE[] SEC("license") = "Dual BSD/GPL";

const volatile pid_t vm_pid = -1;
const volatile char hostname[64] = "";
const volatile char hostname[13] = "";
static struct common_event *e;

// 定义环形缓冲区maps
Expand Down Expand Up @@ -250,20 +250,79 @@ int BPF_KPROBE(kp_start_sw_timer, struct kvm_lapic *apic) {
SEC("tracepoint/raw_syscalls/sys_enter")
int tp_container_sys_entry(struct trace_event_raw_sys_enter *args) {
//过滤进程
bool is_container = is_container_task(hostname);
if (is_container) {
return trace_container_sys_entry(args);
} else {
return 0;
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;
}
}
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) {
//过滤进程
bool is_container = is_container_task(hostname);
if (is_container) {
return trace_container_sys_exit(args, &rb, e);
} else {
return 0;
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;
}
}
return trace_container_sys_exit(args, &rb, e);
}
Loading

0 comments on commit ae8fcc2

Please sign in to comment.