eBPF Araclar ve Kavramlar
Verifier ve BTF/CO-RE
BPF Verifier güvenlik mekanizması ve BTF/CO-RE ile program taşınabilirliği.
Verifier
Lab: eBPF Verifier
Bu lab’da öğrenecekleriniz:
- License kontrolleri (GPL gereksinimi)
- Zorunlu NULL pointer kontrolleri
- Bounds checking
- Complexity limit
Verifier Kuralları
Bu kurallara eBPFHub egzersizlerinde karşılaşacaksınız:
| Kural | Hata Mesajı |
|---|---|
| Map lookup sonrası NULL check | R0 invalid mem access 'map_value_or_null' |
| Stack buffer sabit boyut | variable stack access var_off |
| Loop bounds derleme zamanı | back-edge from insn X to Y |
| Pointer arithmetic kısıtlı | R1 pointer arithmetic prohibited |
Verifier Güvenlik Garantileri
- Termination: Sabit loop bounds, maksimum complexity limit
- Memory Safety: Rastgele pointer yok, helper function kullanımı zorunlu
- Bounds Check: Her array erişiminde sınır kontrolü
- NULL Check: Map lookup sonucu her zaman kontrol edilmeli
Yaygın Hatalar ve Çözümleri
1. Map lookup sonrası NULL check eksik:
// HATALI — verifier reddeder
char *val = bpf_map_lookup_elem(&my_map, &key);
bpf_printk("value: %s", val); // R0 NULL olabilir!
// DOĞRU
char *val = bpf_map_lookup_elem(&my_map, &key);
if (!val) return 0; // NULL check zorunlu
bpf_printk("value: %s", val);
2. Sınırsız döngü:
// HATALI — verifier reddeder: "back-edge from insn X to Y"
for (int i = 0; i < len; i++) { // 'len' runtime değer
buf[i] = 0;
}
// DOĞRU — derleme zamanı sabit sınır
#pragma unroll
for (int i = 0; i < 64; i++) { // sabit sınır
if (i >= len) break;
buf[i] = 0;
}
3. Paket erişiminde sınır kontrolü eksik (XDP):
// HATALI — verifier reddeder: "invalid access to packet"
struct iphdr *ip = data + sizeof(struct ethhdr);
__u32 src = ip->saddr; // sınır kontrolü yok!
// DOĞRU — her zaman erişmeden önce kontrol et
struct iphdr *ip = data + sizeof(struct ethhdr);
if ((void *)(ip + 1) > data_end)
return XDP_PASS;
__u32 src = ip->saddr; // sınır kontrolünden sonra güvenli
Pratik: Kasıtlı olarak bir verifier hatası tetikleyin, mesajı anlayın ve düzeltin.
Araç: ebpf-cover - VS Code extension, verifier log’larından code coverage görselleştirmesi.
BTF ve CO-RE (Taşınabilirlik)
Lab 1: Portable eBPF Programs
Bu lab’da öğrenecekleriniz:
- Programların neden farklı kernel’larda çalışmayabileceği
vmlinux.hnedirBPF_CORE_READmacro- BTF (BPF Type Format)
vmlinux.h Oluşturma
bpftool btf dump file /sys/kernel/btf/vmlinux format c > vmlinux.h
Bu tek header dosyası, kernel header’larını kurmadan tüm kernel type’larına erişim sağlar.
BPF_CORE_READ
Farklı kernel versiyonlarında iç içe struct field’larını okuma:
#include "vmlinux.h"
#include <bpf/bpf_core_read.h>
SEC("kprobe/tcp_connect")
int trace(struct pt_regs *ctx) {
struct sock *sk = (void *)PT_REGS_PARM1(ctx);
// CO-RE OLMADAN — struct layout kernel'lar arasında değişirse bozulur
// __u16 port = sk->__sk_common.skc_dport;
// CO-RE İLE — kernel versiyonları arasında çalışır
__u16 port = BPF_CORE_READ(sk, __sk_common.skc_dport);
return 0;
}
BPF_CORE_READ relocatable okuma üretir — loader, çalışan kernel’ın BTF bilgisine göre field offset’lerini yükleme zamanında ayarlar.
Lab 2: Truly Portable eBPF
Bu lab’da öğrenecekleriniz:
- BTFHub kullanımı
- Minimal BTF oluşturma
- BTF olmayan kernel’larda çalıştırma
Not: Go + bpf2go kullanırken çoğu şey otomatiktir. Ama işlerin neden bu şekilde çalıştığını anlayın.