C Fundamentals

BPF C Specifics

BPF-specific C features and pitfalls - __attribute__ syntax, const/volatile restrictions, offsetof, and a summary of BPF C pitfalls.

1.13 __attribute__ Syntax (GCC/Clang Extensions)

Commonly used compiler attributes in BPF code:

// Mandatory inlining (required in BPF)
static __always_inline int foo(void) { }

// Compile even if unused (part of the SEC macro)
__attribute__((section("xdp"), used))

// Remove struct padding
__attribute__((packed))

// Force alignment
__attribute__((aligned(8)))

How the SEC() macro works:

#define SEC(NAME) __attribute__((section(NAME), used))

SEC("xdp")
int xdp_prog(struct xdp_md *ctx) { ... }

SEC() examples used in eBPFHub:

  • SEC("tp/sched/sched_process_exec") -> tracepoint
  • SEC("tracepoint/syscalls/sys_enter_read") -> syscall entry
  • SEC("kprobe/tcp_finish_connect") -> kprobe

1.14 const, volatile, and restrict

  • const -> immutable
  • volatile -> tells the optimizer “this may change”
  • restrict -> pointer aliasing hint

Restrictions in BPF:

  • const can cause issues in BPF (verifier)
  • volatile is sometimes needed for map access
  • Global const string/array is FORBIDDEN (relocation issue)
// WRONG (does not work in BPF)
const char *msg = "hello";

// CORRECT
char msg[] = "hello";  // on the stack

1.15 offsetof Macro

Calculate the offset of a struct member at compile time:

#include <stddef.h>

struct iphdr {
    // ...
    __be32 saddr;  // offset: 12
    __be32 daddr;  // offset: 16
};

size_t off = offsetof(struct iphdr, saddr);  // = 12

Usage in BPF:

bpf_skb_store_bytes(skb,
    l3_off + offsetof(struct iphdr, saddr),
    &new_saddr, 4, 0);

1.16 BPF C Pitfalls Summary

RuleReason
Every function must be static __always_inlineNo normal calls in BPF (except kernel 4.16+ bpf-to-bpf)
NO global variablesRelocation issue
NO const stringsRelocation issue
NO unbounded loopsVerifier rejects them
Use __builtin_* for memset/memcpyNo standard library
Watch out for struct paddingVerifier stack check
Pointer bounds check is MANDATORYif (ptr + 1 > data_end)

eBPFHub: In all exercises, these rules come up in practice - especially NULL checks, bounded loops, and stack buffer sizes.

Exercise: Write a simple BPF program, apply these rules, and pass the verifier.