Stateful eBPF

Maps and multiple programs

So far, each exercise has used a single eBPF program. But what if we need to correlate information across different events?

For example: When a process starts, we know its name. When it exits, we know its exit code. What if we want to know the name of processes that exit with a specific code?

Multiple eBPF programs

You can define multiple programs in one file, each hooking into different events.

Each program is independent and runs when its own event triggers.

A common case that requires multiple programs is the entry+exit event pair.

At entry, we have the input (arguments, process info).

SEC("tracepoint/sched/sched_process_exec")
int on_process_start(struct trace_event_raw_sched_process_exec *ctx) {
    // When the process starts execution
}

At exit, we have the output (return values, exit codes).

SEC("tracepoint/syscalls/sys_enter_exit")
int on_process_exit(struct trace_event_raw_sys_enter *ctx) {
    // When the process calls exit (program termination)
    // ctx->args[0] contains the exit code
}

To correlate both events, we need to persist data between program invocations.

Persisting state

Maps are data structures that persist between eBPF program invocations.

In eBPF, there are many kinds of maps. For this exercise, we’ll use hash maps (key-value store).

Map usage is straightforward. First, declare a struct with these __uint/__type macros.

struct {
    __uint(type, BPF_MAP_TYPE_HASH);
    __uint(max_entries, 1024);
    __type(key, u64);         // What you use to look up
    __type(value, char[16]);  // What you store
} my_map SEC(".maps");

To store, you pass a pointer to the data, which will be copied:

u64 key = 12345;
char value[16] = "hello";
bpf_map_update_elem(&my_map, &key, value, BPF_ANY);

To retrieve a pointer to the value:

char *stored = bpf_map_lookup_elem(&my_map, &key);
if (!stored) { // Key not found
    return 0;
}
// Use `stored` (it's a pointer to the char[16] array)

To delete an entry from the map:

bpf_map_delete_elem(&my_map, &key);

The challenge

A program named exit_with_code will run and exit. Submit its exit code using SUBMIT_NUM(code).

The starter code has most of the logic already, this is an introduction chapter after all.

Your task

Check if the process name matches "exit_with_code", and if so, submit the exit code.

Quick reference
Compare two strings for equality
Function bpf_strncmp Full documentation
Args:
char* bufdynamic buffer to compare
u32 buf_szlength of dynamic buffer
const char* buf2literal string to compare against
Returns 0 if strings match, non-zero if they differ
Run your code to see execution events here