Re: Reading Pinned maps in eBPF Programs


Ian
 

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

Join iovisor-dev@lists.iovisor.org to automatically receive all group messages.