Hello! Sorry for the wait, I just started back at uni and things are a little bit crazy around here!
Anyways, this is the source code for my version of open snoop. Which is what I have been testing with. This does not contain the changes for map reading. My goal is to have this open snoop file open/read a map with one element after it gets the PID to compare them. It is also worth noting that I am tracking both open and openat within the same file.
#include <linux/bpf.h> // BPF asm file that ships with the OS
#include "bpf_helpers.h" // bpf_helper functions
#include <linux/version.h>
// For navigating the task struct
#include <linux/sched.h>
#include <linux/nsproxy.h>
#include <linux/pid_namespace.h>
#include <linux/ns_common.h>
#define MAX_CPUS 4
/**
* Struct to pass data to the perf buffer
*/
#pragma pack(1)
struct opensnoop_data_t {
u32 pid;
u32 tgid;
char program_name[16]; // max comm length is 16
char file[255];
u32 namespace;
u64 time;
};
struct sys_enter_openat_args {
long long pad;
long __syscall_nr;
long dfd;
const char *filename;
long flags;
long mode;
};
struct sys_enter_open_args {
long long pad;
long __syscall_nr;
const char *filename;
long flags;
long mode;
};
/**
* Using the magic macro SEC this struct declares
* and creates a new bpf map of a type PERF that we
* can use to pass data to userspace
*/
struct bpf_map_def SEC("maps") opensnoop_events = {
.type = BPF_MAP_TYPE_PERF_EVENT_ARRAY,
.key_size = sizeof(int),
.value_size = sizeof(u32),
.max_entries = MAX_CPUS,
};
SEC("tracepoint/syscalls/sys_enter_openat")
int bpf_prog(struct sys_enter_openat_args *ctx) {
struct opensnoop_data_t data = {};
data.pid = bpf_get_current_pid_tgid() >> 32; // use fn from libbpf.h to get pid_tgid
data.tgid = bpf_get_current_pid_tgid(); // first 32 bits are tgid
data.time = bpf_ktime_get_ns();
bpf_get_current_comm(&data.program_name, sizeof(data.program_name)); // puts current comm into char array
int err = bpf_probe_read_str(data.file, sizeof(data.file), ctx->filename);
if (!err) {
char msg[] = "Err: %d\n";
bpf_trace_printk(msg, sizeof(msg), err);
}
struct task_struct *task = (struct task_struct *)bpf_get_current_task(); // sched.h
struct nsproxy *nsprox = 0; // nsproxy.h
struct pid_namespace *pidns = 0; // pid_namespace.h
struct ns_common *nsc = 0; // ns_common.h
struct ns_common n = {};
data.namespace = ({
typeof(unsigned int) _val;
__builtin_memset(&_val, 0, sizeof(_val)); // set bytes to 0
bpf_probe_read(&_val, sizeof(_val), &({
typeof(struct pid_namespace *) _val;
__builtin_memset(&_val, 0, sizeof(_val));
bpf_probe_read(&_val, sizeof(_val), &({
typeof(struct nsproxy *) _val;
__builtin_memset(&_val, 0, sizeof(_val));
bpf_probe_read(&_val, sizeof(_val), &task->nsproxy);
_val;
})->pid_ns_for_children);
_val;
})->ns.inum);
_val;
});
#ifdef DEBUG
char debug_msg[] = "Tracepoint on syscalls/sys_enter_openat was called for process %d\n";
bpf_trace_printk(debug_msg, sizeof(debug_msg), data.pid);
#endif
bpf_perf_event_output(ctx, &opensnoop_events, BPF_F_CURRENT_CPU /*run on current cpu*/, &data, sizeof(data));
return 0;
}
SEC("tracepoint/syscalls/sys_enter_open")
int sys_enter_open_prog(struct sys_enter_open_args *ctx) {
struct opensnoop_data_t data = {};
data.pid = bpf_get_current_pid_tgid() >> 32; // use fn from libbpf.h to get pid_tgid
data.tgid = bpf_get_current_pid_tgid(); // first 32 bits are tgid
data.time = bpf_ktime_get_ns();
bpf_get_current_comm(&data.program_name, sizeof(data.program_name)); // puts current comm into char array
int err = bpf_probe_read_str(data.file, sizeof(data.file), ctx->filename);
if (!err) {
char msg[] = "Err: %d\n";
bpf_trace_printk(msg, sizeof(msg), err);
}
#ifdef DEBUG
char debug_msg[] = "Tracepoint on syscalls/sys_enter_open was called for process %d\n";
bpf_trace_printk(debug_msg, sizeof(debug_msg), data.pid);
#endif
bpf_perf_event_output(ctx, &opensnoop_events, BPF_F_CURRENT_CPU /*run on current cpu*/, &data, sizeof(data));
return 0;
}
u32 _version SEC("version") = LINUX_VERSION_CODE;
char _license[] SEC("license") = "GPL"; // necessary to use types of kernel ABI's