Skip to content

Commit

Permalink
proc_image&kvm_watcher:添加采集容器进程的系统调用信息 (#854)
Browse files Browse the repository at this point in the history
* container

* container proc

* kvm_container_syscall

* mod_pr
  • Loading branch information
Monkey857 authored Jul 10, 2024
1 parent 9faff7b commit 26f90f8
Show file tree
Hide file tree
Showing 8 changed files with 293 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,9 @@
#include "proc_image.h"

char LICENSE[] SEC("license") = "Dual BSD/GPL";

#define MAX_NODENAME_LEN 64
const volatile pid_t ignore_tgid = -1;
const volatile char hostname[MAX_NODENAME_LEN] = "";
const int key = 0;
pid_t pre_target_pid = -1;//上一个监测的进程;
int pre_target_tgid = -1;//上一个监测的进程组;
Expand All @@ -48,14 +49,69 @@ struct {
__uint(max_entries,256 * 10240);
} syscall_rb SEC(".maps");

struct {
__uint(type,BPF_MAP_TYPE_HASH);
__uint(max_entries, 8192);
__type(key, pid_t);
__type(value,struct container_id);
}container_id_map SEC(".maps");

struct container_id{
char container_id[20];
};

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;
}
}
SEC("tracepoint/raw_syscalls/sys_enter")
int sys_enter(struct trace_event_raw_sys_enter *args)
{
struct sc_ctrl *sc_ctrl;
sc_ctrl = bpf_map_lookup_elem(&sc_ctrl_map,&key);
if(!sc_ctrl || !sc_ctrl->sc_func)
if(!sc_ctrl || !sc_ctrl->sc_func)
return 0;

if(sc_ctrl->is_container)
if(!is_container_task(hostname))
return 0;
pid_t pid = bpf_get_current_pid_tgid();
int tgid = bpf_get_current_pid_tgid() >> 32;

Expand Down Expand Up @@ -104,7 +160,9 @@ int sys_exit(struct trace_event_raw_sys_exit *args)
sc_ctrl = bpf_map_lookup_elem(&sc_ctrl_map,&key);
if(!sc_ctrl || !sc_ctrl->sc_func)
return 0;

if(sc_ctrl->is_container)
if(!is_container_task(hostname))
return 0;
pid_t pid = bpf_get_current_pid_tgid();
int tgid = bpf_get_current_pid_tgid() >> 32;

Expand Down
10 changes: 8 additions & 2 deletions eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/controller.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ static struct env {
bool enable_lock;
bool enable_syscall;
bool enable_schedule;
bool is_container;
} env = {
.usemode = 0,
.pid = -1,
Expand All @@ -68,6 +69,7 @@ static struct env {
.enable_lock = false,
.enable_syscall = false,
.enable_schedule = false,
.is_container = false,
};

const char argp_program_doc[] ="Trace process to get process image.\n";
Expand All @@ -78,6 +80,7 @@ static const struct argp_option opts[] = {
{ "finish", 'f', NULL, 0, "Finish to run eBPF tool" },
{ "pid", 'p', "PID", 0, "Process ID to trace" },
{ "tgid", 'P', "TGID", 0, "Thread group to trace" },
{ "containerproc", 'o', NULL, 0, "Thread of containerproc to trace" },
{ "cpuid", 'c', "CPUID", 0, "Set For Tracing per-CPU Process(other processes don't need to set this parameter)" },
{ "time", 't', "TIME-SEC", 0, "Max Running Time(0 for infinite)" },
{ "myproc", 'm', NULL, 0, "Trace the process of the tool itself (not tracked by default)" },
Expand Down Expand Up @@ -143,6 +146,9 @@ static error_t parse_arg(int key, char *arg, struct argp_state *state)
case 'm':
env.enable_myproc = true;
break;
case 'o':
env.is_container = true;
break;
case 'r':
env.enable_resource = true;
break;
Expand Down Expand Up @@ -201,7 +207,7 @@ int deactivate_mode(){
}

if(env.enable_syscall){
struct sc_ctrl sc_ctrl = {false,false,-1,-1,0};
struct sc_ctrl sc_ctrl = {false,false,false,-1,-1,0};
err = update_sc_ctrl_map(sc_ctrl);
if(err < 0) return err;
}
Expand Down Expand Up @@ -257,7 +263,7 @@ int main(int argc, char **argv)
}

if(env.enable_syscall){
struct sc_ctrl sc_ctrl = {true,env.enable_myproc,env.pid,env.tgid,env.syscalls};
struct sc_ctrl sc_ctrl = {true,env.enable_myproc, env.is_container,env.pid,env.tgid,env.syscalls};
err = update_sc_ctrl_map(sc_ctrl);
if(err < 0) return err;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ struct total_rsc{
struct sc_ctrl {
bool sc_func;
bool enable_myproc;
bool is_container;
pid_t target_pid;
pid_t target_tgid;
int syscalls;
Expand Down
16 changes: 15 additions & 1 deletion eBPF_Supermarket/CPU_Subsystem/eBPF_proc_image/proc_image.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ static struct env {
int lock_prev_tgid;
int sched_prev_tgid;
int sc_prev_tgid;
char hostname[64];
} env = {
.output_resourse = false,
.output_schedule = false,
Expand All @@ -88,6 +89,7 @@ static struct env {
.lock_prev_tgid = 0,
.sched_prev_tgid = 0,
.sc_prev_tgid = 0,
.hostname = "",
};

struct hashmap *map = NULL;
Expand Down Expand Up @@ -723,6 +725,16 @@ static void sig_handler(int signo)
exiting = true;
}

void get_hostname() {
char hostname[64];
int result = gethostname(hostname, sizeof(hostname));
if (result == 0) {
strcpy(env.hostname,hostname);
} else {
perror("gethostname");
}
}

int main(int argc, char **argv)
{
struct resource_image_bpf *resource_skel = NULL;
Expand Down Expand Up @@ -802,7 +814,9 @@ int main(int argc, char **argv)
}

syscall_skel->rodata->ignore_tgid = env.ignore_tgid;

get_hostname();
strcpy(syscall_skel->rodata->hostname,env.hostname);

err = syscall_image_bpf__load(syscall_skel);
if (err) {
fprintf(stderr, "Failed to load and verify BPF syscall skeleton\n");
Expand Down
136 changes: 136 additions & 0 deletions eBPF_Supermarket/kvm_watcher/include/bpf/container.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
// Copyright 2023 The LMP Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://github.com/linuxkerneltravel/lmp/blob/develop/LICENSE
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// author: [email protected]
//
// Kernel space BPF program used for counting container sys_entry/sys_exit info.

#ifndef __CONTAINER_H
#define __CONTAINER_H

#include "common.h"
#include "vmlinux.h"
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_core_read.h>
#include <bpf/bpf_tracing.h>
#define MAX_NODENAME_LEN 64
struct {
__uint(type,BPF_MAP_TYPE_HASH);
__uint(max_entries, 8192);
__type(key, pid_t);
__type(value, u64);
}time_info SEC(".maps");

struct {
__uint(type,BPF_MAP_TYPE_HASH);
__uint(max_entries, 8192);
__type(key, pid_t);
__type(value, u64);
}id SEC(".maps");

struct {
__uint(type,BPF_MAP_TYPE_HASH);
__uint(max_entries, 8192);
__type(key, pid_t);
__type(value,struct container_id);
}container_id_map SEC(".maps");


static int trace_container_sys_entry(struct trace_event_raw_sys_enter *args){
u64 st = bpf_ktime_get_ns();
pid_t pid = bpf_get_current_pid_tgid();
u64 syscall_id = (u64)args->id;
bpf_map_update_elem(&time_info,&pid,&st,BPF_ANY);
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){
u64 exit_time = bpf_ktime_get_ns();
pid_t pid = bpf_get_current_pid_tgid();
u64 delay,start_time,syscallid;
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);
}else{
return 0;
}
u64 *sc_id = bpf_map_lookup_elem(&id,&pid);
if( sc_id != 0){
syscallid = *sc_id;
bpf_map_delete_elem(&id, &pid);
}else{
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{
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);
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 */
15 changes: 14 additions & 1 deletion eBPF_Supermarket/kvm_watcher/include/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ static const char binary_path[] = "/bin/qemu-system-x86_64";

#define PFERR_RSVD_MASK (1UL << 3) // mmio


// 定时器模式
#define APIC_LVT_TIMER_ONESHOT (0 << 17) // 单次触发
#define APIC_LVT_TIMER_PERIODIC (1 << 17) // 周期性触发模式
Expand Down Expand Up @@ -190,7 +191,9 @@ struct exit_value {
__u32 count;
__u32 pad;
};

struct container_id{
char container_id[20];
};
struct dirty_page_info {
__u64 gfn;
__u64 rel_gfn;
Expand Down Expand Up @@ -232,6 +235,7 @@ struct process {
char comm[TASK_COMM_LEN];
};


enum EventType {
NONE_TYPE,
VCPU_WAKEUP,
Expand All @@ -244,6 +248,7 @@ enum EventType {
IRQ_INJECT,
HYPERCALL,
IOCTL,
CONTAINER_SYSCALL,
TIMER,
} event_type;

Expand Down Expand Up @@ -342,6 +347,14 @@ struct common_event {
__u32 vcpu_id;
// HYPERCALL 特有成员
} hypercall_data;

struct{
__u64 pid;
__u64 syscall_id;
__u64 delay;
char comm[20];
char container_id[20];
} syscall_data;
};
};

Expand Down
Loading

0 comments on commit 26f90f8

Please sign in to comment.