Complete reference for eBPF helper functions, data structures, and APIs used in this project.
Signature: u64 bpf_get_current_pid_tgid(void)
Returns: Combined PID/TGID value (upper 32 bits: TGID, lower 32 bits: PID)
Available since: Linux 3.19
u64 pid_tgid = bpf_get_current_pid_tgid();
u32 pid = pid_tgid & 0xFFFFFFFF; // Process ID
u32 tgid = pid_tgid >> 32; // Thread Group IDSignature: u64 bpf_get_current_uid_gid(void)
Returns: Combined UID/GID value (upper 32 bits: GID, lower 32 bits: UID)
Available since: Linux 4.2
u64 uid_gid = bpf_get_current_uid_gid();
u32 uid = uid_gid & 0xFFFFFFFF; // User ID
u32 gid = uid_gid >> 32; // Group IDSignature: long bpf_get_current_comm(void *buf, u32 size_of_buf)
Parameters:
buf: Buffer to store command namesize_of_buf: Size of buffer (typically 16)
Returns: 0 on success, negative on error
Available since: Linux 3.19
char comm[16];
if (bpf_get_current_comm(&comm, sizeof(comm)) == 0) {
// comm now contains process name
}Signature: u64 bpf_get_current_task(void)
Returns: Pointer to current task_struct
Available since: Linux 4.8
struct task_struct *task = (struct task_struct *)bpf_get_current_task();
// Use with bpf_probe_read_kernel() to access fields safelySignature: long bpf_probe_read_kernel(void *dst, u32 size, const void *unsafe_ptr)
Parameters:
dst: Destination buffersize: Number of bytes to readunsafe_ptr: Source kernel pointer
Returns: 0 on success, negative on error
Available since: Linux 5.5
struct task_struct *task = (struct task_struct *)bpf_get_current_task();
u32 pid;
if (bpf_probe_read_kernel(&pid, sizeof(pid), &task->pid) == 0) {
// pid is now safely read from kernel memory
}Signature: long bpf_probe_read_user(void *dst, u32 size, const void *unsafe_ptr)
Parameters:
dst: Destination buffersize: Number of bytes to readunsafe_ptr: Source user pointer
Returns: 0 on success, negative on error
Available since: Linux 5.5
char user_buffer[256];
char *user_ptr = (char *)ctx->args[1];
if (bpf_probe_read_user(&user_buffer, sizeof(user_buffer), user_ptr) == 0) {
// user_buffer contains data from user space
}Signature: long bpf_probe_read_user_str(void *dst, u32 size, const void *unsafe_ptr)
Parameters:
dst: Destination buffersize: Maximum bytes to readunsafe_ptr: Source user string pointer
Returns: String length on success (including null terminator), negative on error
Available since: Linux 4.11
char filename[256];
char *user_filename = (char *)ctx->args[1];
long len = bpf_probe_read_user_str(&filename, sizeof(filename), user_filename);
if (len > 0) {
// filename contains null-terminated string
}Signature: u64 bpf_ktime_get_ns(void)
Returns: Current kernel time in nanoseconds since boot
Available since: Linux 4.1
u64 timestamp = bpf_ktime_get_ns();
// timestamp contains nanoseconds since bootSignature: u64 bpf_ktime_get_boot_ns(void)
Returns: Current time in nanoseconds since boot (including suspend time)
Available since: Linux 5.8
u64 boot_time = bpf_ktime_get_boot_ns();
// Includes time spent in suspendSignature: void *bpf_map_lookup_elem(void *map, const void *key)
Parameters:
map: Map to lookup inkey: Key to search for
Returns: Pointer to value if found, NULL if not found
Available since: Linux 3.19
struct {
__uint(type, BPF_MAP_TYPE_HASH);
__type(key, u32);
__type(value, u64);
__uint(max_entries, 1024);
} counters SEC(".maps");
u32 pid = 1234;
u64 *counter = bpf_map_lookup_elem(&counters, &pid);
if (counter) {
(*counter)++;
}Signature: long bpf_map_update_elem(void *map, const void *key, const void *value, u64 flags)
Parameters:
map: Map to updatekey: Key to updatevalue: New valueflags: Update flags (BPF_ANY, BPF_NOEXIST, BPF_EXIST)
Returns: 0 on success, negative on error
Available since: Linux 3.19
u32 pid = 1234;
u64 count = 1;
long ret = bpf_map_update_elem(&counters, &pid, &count, BPF_ANY);
if (ret == 0) {
// Update successful
}Signature: long bpf_map_delete_elem(void *map, const void *key)
Parameters:
map: Map to delete fromkey: Key to delete
Returns: 0 on success, negative on error
Available since: Linux 3.19
u32 pid = 1234;
long ret = bpf_map_delete_elem(&counters, &pid);
if (ret == 0) {
// Key deleted successfully
}Signature: void *bpf_ringbuf_reserve(void *ringbuf, u64 size, u64 flags)
Parameters:
ringbuf: Ring buffer mapsize: Size to reserveflags: Reservation flags (usually 0)
Returns: Pointer to reserved space, NULL on failure
Available since: Linux 5.8
struct {
__uint(type, BPF_MAP_TYPE_RINGBUF);
__uint(max_entries, 1 << 24);
} events SEC(".maps");
struct event_data *data = bpf_ringbuf_reserve(&events, sizeof(*data), 0);
if (data) {
// Fill data structure
data->pid = bpf_get_current_pid_tgid() & 0xFFFFFFFF;
// Must call bpf_ringbuf_submit() or bpf_ringbuf_discard()
}Signature: void bpf_ringbuf_submit(void *data, u64 flags)
Parameters:
data: Data pointer from bpf_ringbuf_reserve()flags: Submission flags (usually 0)
Available since: Linux 5.8
// After filling reserved data
bpf_ringbuf_submit(data, 0);
// Data is now available to userspaceSignature: void bpf_ringbuf_discard(void *data, u64 flags)
Parameters:
data: Data pointer from bpf_ringbuf_reserve()flags: Discard flags (usually 0)
Available since: Linux 5.8
// If you decide not to submit the reserved data
bpf_ringbuf_discard(data, 0);
// Reserved space is freed without sending to userspaceSignature: u32 bpf_get_smp_processor_id(void)
Returns: Current CPU number
Available since: Linux 4.1
u32 cpu = bpf_get_smp_processor_id();
// cpu contains current CPU number (0-based)Signature: long bpf_trace_printk(const char *fmt, u32 fmt_size, ...)
Parameters:
fmt: Format stringfmt_size: Length of format string...: Arguments
Returns: Number of bytes written, negative on error
Available since: Linux 4.1
Note: For debugging only, not for production
bpf_trace_printk("Process %d opened file\n", 25, pid);
// Output appears in /sys/kernel/debug/tracing/trace_pipestruct process_event {
u32 pid; // Process ID
u32 ppid; // Parent process ID
u32 uid; // User ID
u32 gid; // Group ID
char comm[16]; // Process name (kernel limit)
u64 timestamp; // Event timestamp (nanoseconds)
} __attribute__((packed));struct file_event {
u32 pid; // Process ID performing operation
u32 fd; // File descriptor (if applicable)
u32 flags; // Open flags
char comm[16]; // Process name
char filename[256]; // File path
u64 timestamp; // Event timestamp
} __attribute__((packed));struct network_event {
u32 pid; // Process ID
u32 src_ip; // Source IP (network byte order)
u32 dst_ip; // Destination IP (network byte order)
u16 src_port; // Source port (network byte order)
u16 dst_port; // Destination port (network byte order)
u8 protocol; // Protocol (TCP=6, UDP=17)
char comm[16]; // Process name
u64 timestamp; // Event timestamp
} __attribute__((packed));struct {
__uint(type, BPF_MAP_TYPE_HASH);
__type(key, u32); // Key type
__type(value, struct counter); // Value type
__uint(max_entries, 10000); // Maximum entries
__uint(map_flags, BPF_F_NO_PREALLOC); // Optional flags
} process_counters SEC(".maps");struct {
__uint(type, BPF_MAP_TYPE_ARRAY);
__type(key, u32); // Index (0 to max_entries-1)
__type(value, u64); // Value type
__uint(max_entries, 256); // Array size
} statistics SEC(".maps");struct {
__uint(type, BPF_MAP_TYPE_RINGBUF);
__uint(max_entries, 1 << 24); // 16MB buffer
} events SEC(".maps");struct {
__uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
__type(key, u32);
__type(value, u64);
__uint(max_entries, 1); // One entry per CPU
} per_cpu_stats SEC(".maps");SEC("tracepoint/syscalls/sys_enter_openat") // System call entry
SEC("tracepoint/syscalls/sys_exit_openat") // System call exit
SEC("tracepoint/sched/sched_process_exec") // Process execution
SEC("tracepoint/sched/sched_process_exit") // Process exit
SEC("tracepoint/ext4/ext4_free_inode") // Filesystem eventsSEC("kprobe/do_sys_openat2") // Kernel function entry
SEC("kretprobe/do_sys_openat2") // Kernel function return
SEC("kprobe/vfs_open") // VFS layer functionSEC("xdp") // XDP program
SEC("tc") // Traffic control
SEC("socket") // Socket filter
SEC("sk_msg") // Socket message//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -target native program ../bpf/program.c
func loadProgram() error {
objs := programObjects{}
if err := loadProgramObjects(&objs, nil); err != nil {
return fmt.Errorf("loading eBPF objects: %w", err)
}
defer objs.Close()
// Use objs.ProgramName and objs.MapName
return nil
}func loadProgramWithOptions() error {
spec, err := loadProgramSpecs()
if err != nil {
return err
}
// Customize before loading
spec.Maps["events"].MaxEntries = 32 * 1024 * 1024 // 32MB ring buffer
coll, err := ebpf.NewCollection(spec)
if err != nil {
return err
}
defer coll.Close()
return nil
}func readFromMap(m *ebpf.Map) error {
var key uint32 = 1234
var value uint64
if err := m.Lookup(key, &value); err != nil {
if errors.Is(err, ebpf.ErrKeyNotExist) {
// Key doesn't exist
return nil
}
return fmt.Errorf("map lookup: %w", err)
}
fmt.Printf("Value for key %d: %d\n", key, value)
return nil
}func writeToMap(m *ebpf.Map) error {
var key uint32 = 1234
var value uint64 = 5678
if err := m.Update(key, value, ebpf.UpdateAny); err != nil {
return fmt.Errorf("map update: %w", err)
}
return nil
}func iterateMap(m *ebpf.Map) error {
var key uint32
var value uint64
iter := m.Iterate()
for iter.Next(&key, &value) {
fmt.Printf("Key: %d, Value: %d\n", key, value)
}
return iter.Err()
}func readRingBuffer(rb *ebpf.Map) error {
reader, err := ringbuf.NewReader(rb)
if err != nil {
return err
}
defer reader.Close()
for {
record, err := reader.Read()
if err != nil {
if errors.Is(err, ringbuf.ErrClosed) {
break
}
return err
}
// Process record.RawSample
var event ProcessEvent
if err := binary.Read(bytes.NewReader(record.RawSample),
binary.LittleEndian, &event); err != nil {
continue
}
fmt.Printf("Event: PID=%d, Comm=%s\n",
event.PID, nullTerminatedString(event.Comm[:]))
}
return nil
}func attachTracepoint(prog *ebpf.Program) error {
l, err := link.Tracepoint("syscalls", "sys_enter_openat", prog, nil)
if err != nil {
return fmt.Errorf("attaching tracepoint: %w", err)
}
defer l.Close()
// Keep program running
return nil
}func attachKprobe(prog *ebpf.Program) error {
l, err := link.Kprobe("do_sys_openat2", prog, nil)
if err != nil {
return fmt.Errorf("attaching kprobe: %w", err)
}
defer l.Close()
return nil
}// Convert null-terminated byte array to Go string
func nullTerminatedString(b []byte) string {
for i, c := range b {
if c == 0 {
return string(b[:i])
}
}
return string(b)
}
// Convert Go string to fixed-size byte array
func stringToBytes(s string, size int) []byte {
b := make([]byte, size)
copy(b, s)
return b
}// Convert eBPF timestamp (nanoseconds since boot) to Go time
func ebpfTimeToGoTime(ns uint64) time.Time {
// This is approximate - real implementation would need boot time
return time.Unix(0, int64(ns))
}
// Get current timestamp in eBPF format
func currentEBPFTime() uint64 {
return uint64(time.Now().UnixNano())
}// Convert network byte order to host byte order
func ntohl(n uint32) uint32 {
return binary.BigEndian.Uint32((*[4]byte)(unsafe.Pointer(&n))[:])
}
func ntohs(n uint16) uint16 {
return binary.BigEndian.Uint16((*[2]byte)(unsafe.Pointer(&n))[:])
}
// Convert host byte order to network byte order
func htonl(h uint32) uint32 {
b := make([]byte, 4)
binary.BigEndian.PutUint32(b, h)
return *(*uint32)(unsafe.Pointer(&b[0]))
}
func htons(h uint16) uint16 {
b := make([]byte, 2)
binary.BigEndian.PutUint16(b, h)
return *(*uint16)(unsafe.Pointer(&b[0]))
}| Error Code | Description | Common Causes |
|---|---|---|
-EACCES |
Permission denied | Missing capabilities, wrong program type |
-EINVAL |
Invalid argument | Invalid program, map type mismatch |
-E2BIG |
Program too large | Exceeds instruction or complexity limits |
-ENOENT |
No such entry | Map key doesn't exist, attachment point invalid |
-EEXIST |
Entry exists | BPF_NOEXIST flag with existing key |
-ENOMEM |
Out of memory | Map full, ring buffer full |
-EPERM |
Operation not permitted | Insufficient privileges |
- R1 invalid mem access: Direct memory access without helper
- invalid indirect read from stack: Uninitialized stack access
- back-edge from insn X to Y: Unbounded loop detected
- unreachable insn: Dead code after terminating instruction
# List programs and maps
sudo bpftool prog list
sudo bpftool map list
# Show program details
sudo bpftool prog show id <id>
sudo bpftool map show id <id>
# Dump program instructions
sudo bpftool prog dump xlated id <id>
sudo bpftool prog dump jited id <id>
# Dump map contents
sudo bpftool map dump id <id>
# Program statistics
sudo bpftool prog show id <id> --json | jq '.run_cnt, .run_time_ns'# View debug prints
sudo cat /sys/kernel/debug/tracing/trace_pipe
# Clear trace buffer
echo > /sys/kernel/debug/tracing/trace
# Enable/disable tracing
echo 1 > /sys/kernel/debug/tracing/tracing_on
echo 0 > /sys/kernel/debug/tracing/tracing_onThis API reference provides comprehensive documentation for all the key functions and data structures used in eBPF development. Use it as a quick reference when building your own eBPF tools! π