Tüm eğitimler
TEKNİK REHBER GÖMÜLÜ LİNUX EBPF 2026

eBPF
Kernel Gözlemlenebilirlik

kernel'ı yeniden derlemeden tracing, ağ analizi ve güvenlik politikaları — BPF virtual machine, verifier ve JIT compiler.

00 eBPF nedir

eBPF (extended Berkeley Packet Filter), Linux kernel'ını yeniden derlemek veya modül yazmak zorunda kalmadan kernel içinde güvenli program çalıştırmayı sağlayan devrimsel bir altyapıdır.

Temel fikir

Geleneksel yaklaşımda kernel davranışını değiştirmek için ya kernel modülü yazılır (güvenlik riski, karmaşıklık) ya da kernel kaynak kodu değiştirilerek yeniden derlenir (uzun süre, dağıtım bağımlılığı). eBPF bunların hiçbirini gerektirmez: kullanıcı alanında yazılan küçük programlar kernel'a yüklenir, doğrulanır (verifier) ve JIT derleme ile native makine koduna çevrilir. Kernel belirli noktalarda (hook) bu programları çalıştırır.

eBPF C kodu → LLVM/Clang → BPF bytecode → kernel verifier → JIT compiler → native kod → hook noktasında çalışır

BPF sanal makinesi

BPF sanal makinesi 64-bit RISC mimarisiyle modellenmiştir. 11 adet 64-bit genel amaçlı kayıt (r0–r10), 512 byte'lık stack ve sınırlı sayıda instruction set içerir. Bu kısıtlamalar kasıtlıdır: verifier programın sonlanacağını (döngü yokluğu), bellek sınırlarını aşmadığını ve güvenli helper'lar dışında kernel fonksiyon çağırmadığını ispat etmek için bu kısıtları kullanır.

BileşenGörev
BPF VerifierProgramın güvenli olduğunu statik analiz ile kanıtlar — sonsuz döngü yok, OOB erişim yok
JIT CompilerBPF bytecode → x86-64 / ARM64 / RISC-V native kod; %0 interpreter overhead
BPF MapsKernel-userspace arası paylaşılan veri yapıları — hash, array, ring buffer
BPF HelpersKernel'ın güvenli API'si — bpf_ktime_get_ns(), bpf_map_lookup_elem() vb.
BTF (BPF Type Format)Kernel veri yapısı tip bilgisi — CO-RE (Compile Once Run Everywhere) için temel

Güvenlik garantileri

Sonlanma garantisiVerifier DAG analizi ile programın mutlaka sonlanacağını ispatlar — kernel askıya alınamaz
Bellek güvenliğiHer pointer erişimi null kontrolü ve sınır doğrulaması gerektirir — buffer overflow imkansız
Ayrıcalık gerektirmeCAP_BPF veya CAP_SYS_ADMIN gerekli — rastgele kullanıcı kod çalıştıramaz
Kısıtlı APIYalnızca onaylı BPF helper fonksiyonlar çağrılabilir — keyfi kernel fonksiyon erişimi yok

Kullanım senaryoları

AlanÖrnekAraç
Tracing / ProfilingHangi fonksiyon ne kadar sürüyor, CPU hotspotbpftrace, BCC, perf
DDoS mitigation, load balancing, paket filtrelemeXDP, TC, Cilium
GüvenlikSyscall filtreleme, LSM politikası, sandboxSeccomp-BPF, BPF-LSM
GözlemlenebilirlikService mesh telemetry, container ağ izlemeCilium, Pixie, Falco
PerformansDisk I/O latency, scheduler analiziBCC biolatency, runqlat
NOT

eBPF, kernel 3.18'de temel özelliklerle tanıtıldı. Modern eBPF özellikleri (BPF ringbuf, CO-RE, BPF LSM, BPF iterator) kernel 5.8+ gerektirir. Üretim sistemleri için kernel 5.15 LTS veya üzeri önerilir. Kernel versiyonunu doğrulamak için: uname -r.

Bu bölümde

  • eBPF = kernel modülü gücü + verifier güvenliği — yeniden derleme gerekmez
  • BPF VM → verifier (güvenlik) → JIT (performans) → hook noktasında çalışır
  • Tracing, ağ, güvenlik, gözlemlenebilirlik — tek altyapı, çok kullanım
  • Kernel 5.15+ LTS önerilir; modern CO-RE için BTF desteği gerekli

01 eBPF program türleri

Her eBPF program türü farklı bir kernel hook noktasına bağlanır — doğru türü seçmek hem çalışma garantisi hem de erişilebilecek veri için belirleyicidir.

Program türleri tablosu

TürHook noktasıTetiklenmeKullanım
kprobeKernel fonksiyon girişiHerhangi kernel fonksiyon çağrıldığındaKernel davranışı izleme, argüman okuma
kretprobeKernel fonksiyon dönüşüFonksiyon return ettiğindeReturn değeri okuma, latency ölçüm
tracepointStatik kernel tracepointKernel önceden tanımlanmış noktaStabil API, kernel güncellemelerinde kırılmaz
uprobeUserspace fonksiyon girişiBelirtilen process fonksiyon çağırırUygulama tracing, Python/Go runtime izleme
uretprobeUserspace fonksiyon dönüşüUserspace fonksiyon returnUygulama latency ölçümü
XDPNIC sürücüsü (skb öncesi)Her gelen paketYüksek hızlı paket filtreleme, DDoS
TC (Traffic Control)Network stack ingress/egressHer paketPaket manipülasyon, QoS, NAT
socket filterSocket seviyesiSocket üzerinden geçen paketSeccomp-BPF, özel paket filtreleme
LSM (BPF-LSM)Linux Security Module hookGüvenlik kararı gerektiğindePolitika zorlama, sandboxing (kernel 5.7+)
perf_eventDonanım/yazılım sayacıPMU event veya timerCPU profiling, hardware counter okuma
cgroupCgroup hook noktalarıProcess cgroup geçişleriContainer ağ politikası
fentry/fexitKernel fonksiyon (BTF ile)Fonksiyon giriş/çıkışkprobe gibi ama daha hızlı, CO-RE uyumlu

kprobe vs tracepoint — hangisini seç

kprobeHerhangi kernel fonksiyona bağlanabilir — güçlü ama kernel güncellemelerinde fonksiyon imzası değişebilir
tracepointKernel geliştiricilerinin kasıtlı koyduğu stabil nokta — ABI garantisi var, kernel versiyonları arası taşınabilir
fentry/fexitBTF destekli kprobe alternatifi — daha düşük overhead, tip bilgisi mevcut, CO-RE uyumlu
uprobeKullanıcı alanı binary'lerine — process PID veya binary yolu ile bağlanır, dlopen ile yüklenen kütüphaneleri de yakalar

Mevcut tracepoint'leri listeleme

bash — tracepoint keşfi
# Tüm tracepoint kategorileri
ls /sys/kernel/debug/tracing/events/
# block  ext4  irq  kmem  net  sched  signal  skb  sock  syscalls  task  ...

# Syscall tracepoint'leri
ls /sys/kernel/debug/tracing/events/syscalls/ | grep open
# sys_enter_open  sys_exit_open  sys_enter_openat  sys_exit_openat

# Tracepoint format bilgisi
cat /sys/kernel/debug/tracing/events/syscalls/sys_enter_openat/format
# name: sys_enter_openat
# ID: 612
# format:
#   field:int __syscall_nr;  offset:8; size:4;
#   field:int dfd;           offset:16; size:8;
#   field:const char * filename; offset:24; size:8;
#   field:int flags;         offset:32; size:8;

# bpftrace ile tracepoint listesi
bpftrace -l 'tracepoint:syscalls:*open*'

Bu bölümde

  • kprobe: herhangi kernel fonksiyon — güçlü ama kararsız ABI
  • tracepoint: stabil API, kernel versiyonları arası taşınabilir — tercih edilmeli
  • XDP: NIC sürücüsünde paket işleme — en yüksek performanslı ağ hook
  • fentry/fexit: BTF tabanlı modern kprobe alternatifi, CO-RE uyumlu

02 bpftrace — tek satır tracing

bpftrace, AWK benzeri bir dil ile kernel ve uygulama davranışını anlık olarak incelemenizi sağlayan yüksek seviyeli eBPF ön yüzüdür.

Kurulum

bash — bpftrace kurulumu
# Ubuntu 22.04+
sudo apt-get install -y bpftrace

# Versiyon kontrolü
bpftrace --version
# bpftrace v0.20.4

# Kernel BTF desteğini doğrula
ls /sys/kernel/btf/vmlinux
# /sys/kernel/btf/vmlinux

# Kernel debug FS monte edilmeli
sudo mount -t debugfs none /sys/kernel/debug

Temel sözdizimi

bpftrace — sözdizimi
# Genel form: probe /filtre/ { aksiyon }
# probe: kprobe:fonksiyon, tracepoint:kategori:olay, interval:s:N

# Açılan dosyaları yazdır
sudo bpftrace -e 'kprobe:do_sys_openat2 { printf("%s\n", str(arg1)); }'

# Tracepoint ile (daha stabil)
sudo bpftrace -e '
  tracepoint:syscalls:sys_enter_openat {
    printf("pid=%d comm=%s file=%s\n",
      pid, comm, str(args->filename));
  }
'

# Belirli prosesi izle
sudo bpftrace -e '
  tracepoint:syscalls:sys_enter_openat
  /comm == "nginx"/ {
    printf("%s\n", str(args->filename));
  }
'

Yararlı yerleşik değişkenler

DeğişkenTipAçıklama
pidintProcess ID
tidintThread ID
commstringProcess adı (ilk 16 karakter)
uidintUser ID
cpuintCPU numarası
nsecsuint64Boot'tan bu yana nanosaniye
elapseduint64Program başlangıcından bu yana ns
argsstructTracepoint argümanları (BTF ile tipli)
retvalint64Fonksiyon return değeri (kretprobe)
curtasktask_struct*Mevcut task_struct pointer

Probe sözdizimi örnekleri

bpftrace — probe örnekleri
# kprobe: kernel fonksiyon girişi
sudo bpftrace -e 'kprobe:tcp_connect { printf("TCP connect: pid=%d\n", pid); }'

# kretprobe: return değeri oku
sudo bpftrace -e 'kretprobe:sys_read { printf("read() = %d\n", retval); }'

# tracepoint: stabil API
sudo bpftrace -e 'tracepoint:sched:sched_process_exec { printf("%s exec\n", str(args->filename)); }'

# uprobe: kullanıcı alanı fonksiyon
sudo bpftrace -e 'uprobe:/usr/lib/x86_64-linux-gnu/libssl.so.3:SSL_write { printf("SSL write: pid=%d\n", pid); }'

# interval: periyodik yazdırma
sudo bpftrace -e 'interval:s:1 { printf("--- 1 saniye ---\n"); }'

# BEGIN/END: başlangıç ve bitiş hook'ları
sudo bpftrace -e '
  BEGIN { printf("Tracing başladı\n"); }
  END   { printf("Tracing bitti\n"); }
  kprobe:do_nanosleep { printf("sleep: pid=%d\n", pid); }
'

# Probe listesi — eşleşen probe'ları listele
sudo bpftrace -l 'kprobe:tcp_*'
sudo bpftrace -l 'tracepoint:net:*'

Map (toplama) kullanımı

bpftrace — histogram ve count
# Syscall sayısı — process başına
sudo bpftrace -e '
  tracepoint:raw_syscalls:sys_enter {
    @syscalls[comm] = count();
  }
  interval:s:5 { print(@syscalls); clear(@syscalls); }
'

# read() latency histogramı
sudo bpftrace -e '
  kprobe:vfs_read   { @start[tid] = nsecs; }
  kretprobe:vfs_read
  /@start[tid]/ {
    @lat_us = hist((nsecs - @start[tid]) / 1000);
    delete(@start[tid]);
  }
  interval:s:5 { print(@lat_us); }
'

# Stack trace ile CPU hotspot
sudo bpftrace -e '
  profile:hz:99 {
    @[kstack] = count();
  }
  interval:s:10 { print(@); exit(); }
'

Bu bölümde

  • bpftrace -e 'kprobe:func { printf(...); }': tek satır kernel tracing
  • Yerleşik değişkenler: pid, comm, nsecs, args, retval
  • @map[key] = count(), hist(): bpftrace içi aggregation map
  • bpftrace -l 'kprobe:tcp_*': eşleşen probe noktalarını listele

03 bpftrace araçları

BCC ve bpftrace ile gelen hazır araçlar — sistem davranışını anında görüntüleme için kullanıma hazır one-liner'lar ve araçlar.

opensnoop — dosya açma izleme

bash — opensnoop
# opensnoop.bt — tüm dosya açma işlemlerini izle
sudo bpftrace -e '
  tracepoint:syscalls:sys_enter_openat {
    printf("%-6d %-16s %s\n", pid, comm, str(args->filename));
  }
'

# Örnek çıktı:
# PID    COMM             FILE
# 1234   nginx            /etc/nginx/nginx.conf
# 1235   python3          /usr/lib/python3.11/re.py
# 1236   bash             /proc/1236/stat

# BCC sürümü (daha zengin çıktı)
sudo /usr/share/bcc/tools/opensnoop

execsnoop — process çalıştırma izleme

bash — execsnoop
# Her exec() çağrısını yakala
sudo bpftrace -e '
  tracepoint:syscalls:sys_enter_execve {
    printf("%-6d %-16s %s\n", pid, comm, str(args->filename));
  }
'

# Örnek çıktı:
# PID    COMM             EXE
# 4521   bash             /usr/bin/ls
# 4522   ls               /usr/bin/ls
# 4523   make             /usr/bin/gcc

tcpconnect — TCP bağlantı izleme

bash — tcpconnect
# Tüm yeni TCP bağlantıları
sudo bpftrace -e '
  kprobe:tcp_connect {
    $sk = (struct sock *)arg0;
    printf("%-6d %-16s → %s:%d\n",
      pid, comm,
      ntop(AF_INET, $sk->__sk_common.skc_daddr),
      $sk->__sk_common.skc_dport);
  }
'

# Örnek çıktı:
# PID    COMM             DST              PORT
# 8901   curl             93.184.216.34    80
# 8902   apt              91.189.91.38     80

biolatency — disk I/O latency histogramı

bash — biolatency
# Disk I/O gecikme dağılımı (10 saniye)
sudo bpftrace -e '
  tracepoint:block:block_rq_issue   { @start[args->sector] = nsecs; }
  tracepoint:block:block_rq_complete
  /@start[args->sector]/ {
    @latency_us = hist((nsecs - @start[args->sector]) / 1000);
    delete(@start[args->sector]);
  }
  interval:s:10 { print(@latency_us); exit(); }
'

# Örnek çıktı:
# @latency_us:
# [8, 16)              245 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@
# [16, 32)             512 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
# [32, 64)              97 |@@@@@@@@@@
# [64, 128)             12 |@

runqlat — scheduler gecikme ölçümü

bash — run queue latency
# Process'in CPU'ya ne kadar bekleyeceğini ölç
sudo bpftrace -e '
  tracepoint:sched:sched_wakeup,
  tracepoint:sched:sched_wakeup_new {
    @qtime[args->pid] = nsecs;
  }
  tracepoint:sched:sched_switch {
    if (args->prev_state == TASK_RUNNING) {
      @qtime[args->prev_pid] = nsecs;
    }
    $ns = @qtime[args->next_pid];
    if ($ns) {
      @runqlat_us = hist((nsecs - $ns) / 1000);
      delete(@qtime[args->next_pid]);
    }
  }
  interval:s:5 { print(@runqlat_us); exit(); }
'

Bu bölümde

  • opensnoop: tüm dosya açma işlemlerini gerçek zamanlı göster
  • execsnoop: her yeni process başlatmayı yakala
  • tcpconnect: yeni TCP bağlantılarını izle — hedef IP + port
  • biolatency: disk I/O gecikme histogramı; runqlat: scheduler gecikme dağılımı

04 BCC — BPF Compiler Collection

BCC, Python ön yüzüyle C BPF programı yazmayı kolaylaştıran bir çerçevedir — kprobe bağlama, histogram toplama ve kullanıcı alanına veri gönderme.

Kurulum

bash — BCC kurulumu
# Ubuntu 22.04
sudo apt-get install -y bpfcc-tools python3-bpfcc linux-headers-$(uname -r)

# BCC Python modülü
python3 -c "from bcc import BPF; print('BCC OK')"

# Hazır BCC araçları
ls /usr/share/bcc/tools/
# biolatency  execsnoop  opensnoop  tcpconnect  tcptop  profile  ...

İlk BCC programı — syscall sayacı

Python — syscall_count.py
#!/usr/bin/env python3
from bcc import BPF
import time

# BPF C programı (string olarak)
bpf_program = """
#include <uapi/linux/ptrace.h>

BPF_HASH(syscall_count, u32, u64);

TRACEPOINT_PROBE(raw_syscalls, sys_enter) {
    u32 pid = bpf_get_current_pid_tgid() >> 32;
    u64 *count = syscall_count.lookup(&pid);
    if (count) {
        (*count)++;
    } else {
        u64 init = 1;
        syscall_count.update(&pid, &init);
    }
    return 0;
}
"""

# BPF programını derle ve yükle
b = BPF(text=bpf_program)

print("Syscall sayılıyor... (Ctrl+C ile dur)")
time.sleep(5)

# Sonuçları oku ve yazdır
print(f"{'PID':<8} {'Syscall Sayısı'}")
for pid, count in sorted(b["syscall_count"].items(),
                         key=lambda x: x[1].value, reverse=True)[:10]:
    print(f"{pid.value:<8} {count.value}")

kprobe bağlama ve perf buffer

Python — open_tracer.py
#!/usr/bin/env python3
from bcc import BPF
import ctypes

bpf_text = """
#include <uapi/linux/ptrace.h>
#include <linux/sched.h>

struct event_t {
    u32  pid;
    char comm[TASK_COMM_LEN];
    char fname[256];
};

BPF_PERF_OUTPUT(events);

int trace_openat(struct pt_regs *ctx, int dfd,
                 const char __user *filename, int flags) {
    struct event_t ev = {};
    ev.pid = bpf_get_current_pid_tgid() >> 32;
    bpf_get_current_comm(&ev.comm, sizeof(ev.comm));
    bpf_probe_read_user_str(&ev.fname, sizeof(ev.fname), filename);
    events.perf_submit(ctx, &ev, sizeof(ev));
    return 0;
}
"""

b = BPF(text=bpf_text)
b.attach_kprobe(event="do_sys_openat2", fn_name="trace_openat")

class Event(ctypes.Structure):
    _fields_ = [
        ("pid",  ctypes.c_uint),
        ("comm", ctypes.c_char * 16),
        ("fname", ctypes.c_char * 256),
    ]

def print_event(cpu, data, size):
    ev = ctypes.cast(data, ctypes.POINTER(Event)).contents
    print(f"{ev.pid:<8} {ev.comm.decode():<16} {ev.fname.decode()}")

b["events"].open_perf_buffer(print_event)
print("Dosya açma izleniyor...")
while True:
    b.perf_buffer_poll()

BPF_HISTOGRAM ile latency ölçümü

Python — read_latency.py (BPF_HISTOGRAM)
#!/usr/bin/env python3
from bcc import BPF
import time

bpf_text = """
#include <uapi/linux/ptrace.h>

BPF_HASH(start, u32, u64);
BPF_HISTOGRAM(dist, u64);

int kprobe__vfs_read(struct pt_regs *ctx) {
    u32 tid = bpf_get_current_pid_tgid();
    u64 ts = bpf_ktime_get_ns();
    start.update(&tid, &ts);
    return 0;
}

int kretprobe__vfs_read(struct pt_regs *ctx) {
    u32 tid = bpf_get_current_pid_tgid();
    u64 *tsp = start.lookup(&tid);
    if (tsp) {
        u64 delta_us = (bpf_ktime_get_ns() - *tsp) / 1000;
        dist.increment(bpf_log2l(delta_us));
        start.delete(&tid);
    }
    return 0;
}
"""

b = BPF(text=bpf_text)
print("vfs_read() latency ölçülüyor (10 sn)...")
time.sleep(10)
b["dist"].print_log2_hist("usecs")

Bu bölümde

  • BCC = Python ön yüzü + C BPF kodu — hızlı geliştirme, dinamik derleme
  • BPF_HASH, BPF_PERF_OUTPUT, BPF_HISTOGRAM: built-in BCC map makroları
  • b.attach_kprobe(): Python'dan kernel fonksiyona kprobe bağlama
  • perf_buffer_poll(): kernel → userspace olay akışı (düşük overhead)

05 libbpf ve CO-RE

libbpf ve CO-RE (Compile Once — Run Everywhere) ile kernel versiyonundan bağımsız taşınabilir eBPF programları yazma.

CO-RE neden gerekli

BCC her çalıştırmada kernel'a özgü header dosyaları ile BPF kodunu dinamik olarak derler — bu üretim sistemlerinde hem yavaş hem de risklidir (clang/llvm hedef sistemde kurulu olmalı). CO-RE ise geliştirme makinesinde bir kez derlenen BPF programını farklı kernel versiyonlarında çalıştırır. Bu, BTF (BPF Type Format) ile mümkün olur: kernel, veri yapısı tip bilgisini BTF formatında expose eder; libbpf bu bilgiyle binary'deki field offset'lerini çalışma anında ayarlar.

BPF C + BTF annotations → Clang (geliştirme makinesinde) → .o (BTF dahil) → hedef kernel libbpf CO-RE relocate → yükle

Kurulum

bash — libbpf + bpftool kurulumu
# libbpf geliştirme kütüphanesi
sudo apt-get install -y \
  libbpf-dev \
  clang \
  llvm \
  linux-headers-$(uname -r)

# bpftool — BPF program / map yönetimi + skeleton üretimi
sudo apt-get install -y linux-tools-$(uname -r)

# Versiyon
bpftool version
# bpftool v7.3.0

# Sistem BTF desteğini doğrula
bpftool btf dump file /sys/kernel/btf/vmlinux format raw | head -2
# [1] INT int size=4 bits_offset=0 nr_bits=32 encoding=SIGNED

CO-RE BPF programı

C — openat_tracer.bpf.c
// SPDX-License-Identifier: GPL-2.0
#include "vmlinux.h"          // bpftool ile üretilir: bpftool btf dump file vmlinux
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>
#include <bpf/bpf_core_read.h>

struct event {
    __u32  pid;
    __u32  uid;
    char   comm[16];
    char   fname[256];
};

// Ring buffer map — düşük overhead, büyük event akışı için
struct {
    __uint(type, BPF_MAP_TYPE_RINGBUF);
    __uint(max_entries, 256 * 1024);  // 256 KB ring buffer
} events SEC(".maps");

SEC("tracepoint/syscalls/sys_enter_openat")
int trace_openat(struct trace_event_raw_sys_enter *ctx)
{
    struct event *e;
    const char *fname_ptr;

    e = bpf_ringbuf_reserve(&events, sizeof(*e), 0);
    if (!e)
        return 0;

    e->pid = bpf_get_current_pid_tgid() >> 32;
    e->uid = bpf_get_current_uid_gid() & 0xFFFFFFFF;
    bpf_get_current_comm(&e->comm, sizeof(e->comm));

    // ctx->args[1] = filename pointer
    fname_ptr = (const char *)BPF_CORE_READ(ctx, args[1]);
    bpf_probe_read_user_str(e->fname, sizeof(e->fname), fname_ptr);

    bpf_ringbuf_submit(e, 0);
    return 0;
}

char LICENSE[] SEC("license") = "GPL";

Skeleton üretimi ve userspace yükleyici

bash — derleme ve skeleton
# vmlinux.h üret (bir kez, kernel başına)
bpftool btf dump file /sys/kernel/btf/vmlinux format c > vmlinux.h

# BPF programını derle
clang -g -O2 -target bpf \
  -D__TARGET_ARCH_x86 \
  -I/usr/include/bpf \
  -c openat_tracer.bpf.c \
  -o openat_tracer.bpf.o

# Skeleton oluştur (C header)
bpftool gen skeleton openat_tracer.bpf.o > openat_tracer.skel.h

# Skeleton içeriği (otomatik üretilen fonksiyonlar):
# openat_tracer_bpf__open()   → BPF obje aç
# openat_tracer_bpf__load()   → kernel'a yükle
# openat_tracer_bpf__attach() → hook noktasına bağla
# openat_tracer_bpf__destroy() → temizle
C — openat_tracer.c (userspace loader)
#include <stdio.h>
#include <signal.h>
#include <bpf/libbpf.h>
#include "openat_tracer.skel.h"

static volatile bool running = true;

static int handle_event(void *ctx, void *data, size_t sz)
{
    struct event *e = data;
    printf("pid=%-6u uid=%-6u comm=%-16s file=%s\n",
           e->pid, e->uid, e->comm, e->fname);
    return 0;
}

int main(void)
{
    struct openat_tracer_bpf *skel;
    struct ring_buffer *rb;
    int err;

    /* Skeleton aç, yükle, bağla */
    skel = openat_tracer_bpf__open_and_load();
    if (!skel) { fprintf(stderr, "load failed\n"); return 1; }

    err = openat_tracer_bpf__attach(skel);
    if (err) { fprintf(stderr, "attach failed\n"); goto cleanup; }

    /* Ring buffer consumer */
    rb = ring_buffer__new(bpf_map__fd(skel->maps.events), handle_event, NULL, NULL);
    if (!rb) { err = -1; goto cleanup; }

    printf("Tracing openat()... Ctrl+C ile dur\n");
    while (running)
        ring_buffer__poll(rb, 100);

    ring_buffer__free(rb);
cleanup:
    openat_tracer_bpf__destroy(skel);
    return err;
}

Bu bölümde

  • CO-RE: geliştirme makinesinde derle, farklı kernel'larda çalıştır — BTF ile field offset yeniden konumlandırma
  • bpftool btf dump → vmlinux.h: tüm kernel tipleri tek header
  • bpftool gen skeleton: otomatik open/load/attach/destroy C API üretir
  • BPF_MAP_TYPE_RINGBUF: yüksek throughput event akışı için modern alternatif

06 BPF Maps

BPF map'leri, kernel BPF programları ile kullanıcı alanı arasındaki paylaşılan veri yapılarıdır — sayaç, histogram, event akışı ve durum takibi için.

Map türleri

TürAçıklamaKullanım
BPF_MAP_TYPE_HASHHash tablosu — key/value çiftiPID bazlı timestamp, sayaç
BPF_MAP_TYPE_ARRAYSabit boyutlu dizi, indeks = keyCPU başına sayaç, konfigürasyon
BPF_MAP_TYPE_PERCPU_HASHCPU başına hash — kilit gerektirmezYüksek performanslı sayaç
BPF_MAP_TYPE_PERCPU_ARRAYCPU başına diziPer-CPU istatistik
BPF_MAP_TYPE_LRU_HASHLRU tahliyeli hashBağlantı takibi, sınırlı bellek
BPF_MAP_TYPE_PERF_EVENT_ARRAYPerf ring bufferEvent streaming (eski yöntem)
BPF_MAP_TYPE_RINGBUFPaylaşımlı ring buffer (kernel 5.8+)Yüksek throughput event akışı
BPF_MAP_TYPE_STACK_TRACEStack iz depolamaCPU profiling, flame graph
BPF_MAP_TYPE_PROG_ARRAYBPF program referans dizisitail call — program zincirleme

Hash map kullanımı (kernel tarafı)

C — BPF hash map (kernel)
#include "vmlinux.h"
#include <bpf/bpf_helpers.h>

// pid → u64 sayaç hash map
struct {
    __uint(type,        BPF_MAP_TYPE_HASH);
    __uint(max_entries, 4096);
    __type(key,   __u32);   // PID
    __type(value, __u64);   // syscall sayısı
} pid_syscall_count SEC(".maps");

SEC("tracepoint/raw_syscalls/sys_enter")
int count_syscalls(struct trace_event_raw_sys_enter *ctx)
{
    __u32 pid = bpf_get_current_pid_tgid() >> 32;
    __u64 *count = bpf_map_lookup_elem(&pid_syscall_count, &pid);

    if (count) {
        __sync_fetch_and_add(count, 1);
    } else {
        __u64 init = 1;
        bpf_map_update_elem(&pid_syscall_count, &pid, &init, BPF_ANY);
    }
    return 0;
}

char LICENSE[] SEC("license") = "GPL";

Map okuma (kullanıcı alanı)

C — map okuma (userspace)
#include <bpf/libbpf.h>
#include <bpf/bpf.h>
#include "syscall_count.skel.h"

/* ... skel yükleme ve attach sonrası ... */

int map_fd = bpf_map__fd(skel->maps.pid_syscall_count);
__u32 pid = 0, next_pid;
__u64 count;

/* Hash map'i iterate et */
while (bpf_map_get_next_key(map_fd, &pid, &next_pid) == 0) {
    if (bpf_map_lookup_elem(map_fd, &next_pid, &count) == 0) {
        printf("pid=%u count=%llu\n", next_pid, count);
    }
    pid = next_pid;
}

/* Belirli key için değer oku */
__u32 target_pid = 1234;
if (bpf_map_lookup_elem(map_fd, &target_pid, &count) == 0)
    printf("pid %u: %llu syscall\n", target_pid, count);

/* Key sil */
bpf_map_delete_elem(map_fd, &target_pid);

Ring buffer — yüksek throughput event akışı

C — ring buffer (kernel + userspace)
/* === Kernel tarafı === */
struct {
    __uint(type, BPF_MAP_TYPE_RINGBUF);
    __uint(max_entries, 1 << 24);  /* 16 MB */
} rb SEC(".maps");

/* Event gönder */
struct my_event *e = bpf_ringbuf_reserve(&rb, sizeof(*e), 0);
if (e) {
    e->pid = bpf_get_current_pid_tgid() >> 32;
    bpf_ringbuf_submit(e, 0);   /* veya bpf_ringbuf_discard(e, 0) */
}

/* === Userspace tarafı === */
static int handle_event(void *ctx, void *data, size_t sz) {
    struct my_event *e = data;
    printf("event: pid=%u\n", e->pid);
    return 0;
}

struct ring_buffer *rb_consumer = ring_buffer__new(
    bpf_map__fd(skel->maps.rb),
    handle_event, NULL, NULL
);

while (running)
    ring_buffer__poll(rb_consumer, 100 /* timeout ms */);

Bu bölümde

  • HASH: key/value genel amaçlı depolama; ARRAY: indeks bazlı sabit boyut
  • PERCPU_HASH/ARRAY: atomik olmadan yüksek hızlı sayaç — per-CPU güncelleme
  • RINGBUF (kernel 5.8+): yüksek throughput event akışı — PERF_EVENT_ARRAY'in modern halefi
  • bpf_map_get_next_key(): userspace'den map iterate etme — tüm kayıtları okuma

07 XDP — eXpress Data Path

XDP, ağ paketlerini kernel ağ yığınına girmeden önce NIC sürücüsü seviyesinde işleme alır — saniyede 10+ milyon paket işleyebilen en yüksek performanslı Linux ağ hook'u.

XDP aksiyon kararları

AksiyonDeğerSonuç
XDP_ABORTED0Program hatası — paketi düşür, tracepoint tetikle
XDP_DROP1Paketi düşür — DDoS mitigation için en hızlı yol
XDP_PASS2Paketi kernel ağ yığınına ilet — normal işlem
XDP_TX3Paketi aynı ağ kartından geri gönder
XDP_REDIRECT4Paketi başka bir ağ arabirimine yönlendir

XDP paket sayacı — temel örnek

C — xdp_counter.bpf.c
#include "vmlinux.h"
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_endian.h>

struct {
    __uint(type, BPF_MAP_TYPE_PERCPU_ARRAY);
    __uint(max_entries, 1);
    __type(key,   __u32);
    __type(value, __u64);
} pkt_count SEC(".maps");

SEC("xdp")
int xdp_counter(struct xdp_md *ctx)
{
    void *data     = (void *)(long)ctx->data;
    void *data_end = (void *)(long)ctx->data_end;

    /* Ethernet başlığı sınır kontrolü */
    struct ethhdr *eth = data;
    if (((void *)eth + sizeof(*eth)) > data_end)
        return XDP_ABORTED;

    /* Paketi say */
    __u32 key = 0;
    __u64 *count = bpf_map_lookup_elem(&pkt_count, &key);
    if (count)
        (*count)++;

    return XDP_PASS;
}

char LICENSE[] SEC("license") = "GPL";

XDP ile basit DDoS mitigation (kaynak IP engelle)

C — xdp_block.bpf.c
#include "vmlinux.h"
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_endian.h>

/* Engellenen IP'ler seti */
struct {
    __uint(type, BPF_MAP_TYPE_LRU_HASH);
    __uint(max_entries, 1024);
    __type(key,   __u32);   /* src IP (network byte order) */
    __type(value, __u8);    /* 1 = engelle */
} blocklist SEC(".maps");

SEC("xdp")
int xdp_block_ip(struct xdp_md *ctx)
{
    void *data     = (void *)(long)ctx->data;
    void *data_end = (void *)(long)ctx->data_end;

    struct ethhdr *eth = data;
    if (((void *)eth + sizeof(*eth)) > data_end)
        return XDP_ABORTED;

    /* Yalnızca IPv4 paketlerine bak */
    if (bpf_ntohs(eth->h_proto) != ETH_P_IP)
        return XDP_PASS;

    struct iphdr *iph = (struct iphdr *)(eth + 1);
    if (((void *)iph + sizeof(*iph)) > data_end)
        return XDP_ABORTED;

    __u32 src_ip = iph->saddr;
    __u8 *blocked = bpf_map_lookup_elem(&blocklist, &src_ip);
    if (blocked && *blocked == 1)
        return XDP_DROP;

    return XDP_PASS;
}

char LICENSE[] SEC("license") = "GPL";

XDP programını yükleme ve yönetme

bash — XDP yükleme
# ip link ile XDP programı yükle
sudo ip link set eth0 xdp obj xdp_block.bpf.o sec xdp

# Yüklü XDP programını görüntüle
ip link show eth0
# 2: eth0: <BROADCAST,MULTICAST,UP> ...
#    link/ether ... brd ...
#    prog/xdp id 42 tag ab12cd34ef56 jited

# XDP programını kaldır
sudo ip link set eth0 xdp off

# bpftool ile XDP yükle (daha detaylı kontrol)
sudo bpftool prog load xdp_block.bpf.o /sys/fs/bpf/xdp_block
sudo bpftool net attach xdp id $(bpftool prog show name xdp_block_ip | awk '/^[0-9]/{print $1}') dev eth0

# IP engelle (map'e ekle)
sudo bpftool map update name blocklist \
  key hex c0 a8 01 64 \   # 192.168.1.100 (network byte order)
  value hex 01

# Map içeriğini görüntüle
sudo bpftool map dump name blocklist
UYARI

XDP programı yanlış yazıldığında tüm ağ bağlantısı kesilebilir. Geliştirme aşamasında XDP_PASS varsayılan aksiyonu kullanın ve gerçek donanım yerine QEMU veya veth (virtual ethernet) çiftleri üzerinde test edin. Üretim sistemine yüklemeden önce ip link set eth0 xdpgeneric (generic/slower) modda test edin.

Bu bölümde

  • XDP_DROP: NIC seviyesinde paket düşürme — DDoS için en hızlı yol
  • Sınır kontrolü zorunlu: verifier her pointer erişiminde data_end kontrolü ister
  • ip link set eth0 xdp obj prog.o sec xdp: XDP yükleme komutu
  • LRU_HASH map: sınırlı bellekte büyük bağlantı/IP takibi

08 eBPF güvenlik

Seccomp-BPF, BPF-LSM ve capability gereksinimleri — eBPF'i güvenlik için kullanma ve eBPF'i güvenli çalıştırma.

Capability gereksinimleri

Capabilityİzin verilen işlemNe zaman gerekli
CAP_BPFPrivileged BPF programları yükle, map oluşturKernel 5.8+ — bpftool, libbpf için
CAP_PERFMONPerf event monitörü, kprobe/tracepoint bağlamaKernel 5.8+ — tracing programlar
CAP_NET_ADMINXDP, TC BPF program yüklemeAğ BPF programları
CAP_SYS_ADMINHer şey dahil — eski yöntemKernel < 5.8 veya root benzeri erişim

Seccomp-BPF — syscall sandboxing

Seccomp-BPF, process'in hangi syscall'ları çağırabileceğini BPF programıyla kısıtlar. Her syscall çağrısında BPF programı çalışır ve izin verir, reddeder veya sinyal gönderir.

C — seccomp BPF filtresi
#include <seccomp.h>
#include <unistd.h>
#include <stdio.h>

int main(void)
{
    /* libseccomp ile BPF filtresi oluştur */
    scmp_filter_ctx ctx = seccomp_init(SCMP_ACT_KILL_PROCESS);

    /* İzin verilen syscall'lar — whitelist */
    seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(read),   0);
    seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write),  0);
    seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(close),  0);
    seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(exit_group), 0);
    seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mmap),   0);
    seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(brk),    0);

    /* Filtreyi uygula */
    seccomp_load(ctx);
    seccomp_release(ctx);

    /* Artık yalnızca izin verilen syscall'lar çağrılabilir */
    write(STDOUT_FILENO, "Sandbox aktif\n", 14);

    /* Bu satır SIGKILL ile öldürür (execve izinde değil) */
    /* execve("/bin/sh", NULL, NULL); */

    return 0;
}
/* Derleme: gcc -o sandbox sandbox.c -lseccomp */

BPF-LSM — Linux Security Module hook

C — bpf_lsm_file_open.bpf.c
#include "vmlinux.h"
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>

/* Kernel config: CONFIG_BPF_LSM=y ve security= ayarında "bpf" olmalı */

SEC("lsm/file_open")
int BPF_PROG(restrict_file_open, struct file *file)
{
    struct inode *inode = BPF_CORE_READ(file, f_inode);
    umode_t mode = BPF_CORE_READ(inode, i_mode);

    /* Set-UID binary açılmasını logla */
    if (mode & S_ISUID) {
        bpf_printk("LSM: SUID file open pid=%d\n",
                   bpf_get_current_pid_tgid() >> 32);
    }

    return 0; /* 0 = izin ver; -EPERM = reddet */
}

char LICENSE[] SEC("license") = "GPL";

Unprivileged BPF kısıtlama

bash — kernel BPF güvenlik ayarları
# Unprivileged BPF'i tamamen kapat
sudo sysctl -w kernel.unprivileged_bpf_disabled=1
# kernel.unprivileged_bpf_disabled = 1
# Kalıcı yapmak için: /etc/sysctl.d/99-bpf.conf

# JIT hardening (spectre mitigations)
sudo sysctl -w net.core.bpf_jit_harden=2
# 0 = hardening yok
# 1 = ayrıcalıksız kullanıcılar için hardening
# 2 = tüm kullanıcılar için hardening

# Yüklü BPF programlarını listele
sudo bpftool prog show
# 42: xdp  name xdp_block_ip  tag ab12cd34ef56  jited
#     loaded_at 2026-01-15T14:30:00+0300  uid 0
#     xlated 1024B  jited 576B  memlock 4096B  map_ids 5

# Program bytecode + JIT disassembly
sudo bpftool prog dump jited name xdp_block_ip

Bu bölümde

  • Kernel 5.8+: CAP_BPF + CAP_PERFMON — root olmadan güvenli BPF
  • Seccomp-BPF: process'e syscall whitelist — container ve uygulama sandboxing
  • BPF-LSM: Linux güvenlik kararlarına hook — kernel module gerektirmeden politika
  • kernel.unprivileged_bpf_disabled=1: üretim sistemlerinde BPF'i kısıtla

09 Pratik: HTTP latency tracker

tcp_sendmsg ve tcp_recvmsg arasındaki süreyi kprobe ile ölçme — bpftrace one-liner'dan libbpf CO-RE C programına evrim.

Strateji

tcp_sendmsg() çağrıldı → zaman damgası kaydet → tcp_recvmsg() döndü → delta hesapla → histograma ekle

Adım 1: bpftrace one-liner ile kavram kanıtı

bash — bpftrace HTTP latency (one-liner)
# TCP send → recv arası süreyi ölç
sudo bpftrace -e '
  kprobe:tcp_sendmsg {
    @send_ts[tid] = nsecs;
  }

  kretprobe:tcp_recvmsg
  /@send_ts[tid]/ {
    $delta_us = (nsecs - @send_ts[tid]) / 1000;
    @latency_us = hist($delta_us);
    delete(@send_ts[tid]);
  }

  interval:s:5 {
    print(@latency_us);
    clear(@latency_us);
  }
'

# Örnek çıktı (5 saniyede bir):
# @latency_us:
# [32, 64)              3 |@
# [64, 128)            47 |@@@@@@@@@@@@@@@@@@
# [128, 256)          112 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
# [256, 512)           23 |@@@@@@@@@
# [512, 1K)             4 |@

Adım 2: BCC Python ile process filtreli versiyon

Python — http_latency_bcc.py
#!/usr/bin/env python3
from bcc import BPF
import argparse, time

parser = argparse.ArgumentParser()
parser.add_argument("--pid", type=int, default=0, help="Filter by PID")
args = parser.parse_args()

bpf_text = """
#include <uapi/linux/ptrace.h>
#include <net/sock.h>

BPF_HASH(start_ts, u32, u64);   // tid → send timestamp
BPF_HISTOGRAM(dist, u64);       // latency histogram (log2 us)

int kprobe__tcp_sendmsg(struct pt_regs *ctx, struct sock *sk,
                        struct msghdr *msg, size_t size) {
    u32 tid = bpf_get_current_pid_tgid();
    FILTER_PID
    u64 ts = bpf_ktime_get_ns();
    start_ts.update(&tid, &ts);
    return 0;
}

int kretprobe__tcp_recvmsg(struct pt_regs *ctx) {
    u32 tid = bpf_get_current_pid_tgid();
    u64 *tsp = start_ts.lookup(&tid);
    if (tsp == 0) return 0;
    u64 delta_us = (bpf_ktime_get_ns() - *tsp) / 1000;
    dist.increment(bpf_log2l(delta_us));
    start_ts.delete(&tid);
    return 0;
}
"""

pid_filter = ""
if args.pid:
    pid_filter = f"""
    u32 pid = bpf_get_current_pid_tgid() >> 32;
    if (pid != {args.pid}) return 0;
    """

bpf_text = bpf_text.replace("FILTER_PID", pid_filter)
b = BPF(text=bpf_text)

print(f"HTTP latency izleniyor"
      + (f" (pid={args.pid})" if args.pid else "")
      + "... Ctrl+C")

try:
    while True:
        time.sleep(5)
        print("\n--- Son 5 saniye ---")
        b["dist"].print_log2_hist("usecs")
        b["dist"].clear()
except KeyboardInterrupt:
    pass

Adım 3: libbpf CO-RE C programı

C — http_latency.bpf.c (kernel)
#include "vmlinux.h"
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>

#define MAX_ENTRIES 8192
#define HIST_SLOTS  26    /* log2(usec) = 0..25 (1 ns .. ~33 s) */

struct {
    __uint(type, BPF_MAP_TYPE_HASH);
    __uint(max_entries, MAX_ENTRIES);
    __type(key,   __u32);   /* tid */
    __type(value, __u64);   /* send timestamp (ns) */
} start SEC(".maps");

struct {
    __uint(type, BPF_MAP_TYPE_ARRAY);
    __uint(max_entries, HIST_SLOTS);
    __type(key,   __u32);
    __type(value, __u64);
} latency_hist SEC(".maps");

static inline __u32 log2(__u64 v)
{
    __u32 r = 0;
    if (v > 0xFFFFFFFF) { v >>= 32; r += 32; }
    if (v > 0x0000FFFF) { v >>= 16; r += 16; }
    if (v > 0x000000FF) { v >>=  8; r +=  8; }
    if (v > 0x0000000F) { v >>=  4; r +=  4; }
    if (v > 0x00000003) { v >>=  2; r +=  2; }
    if (v > 0x00000001) {           r +=  1; }
    return r;
}

SEC("kprobe/tcp_sendmsg")
int BPF_KPROBE(tcp_sendmsg_entry)
{
    __u32 tid = bpf_get_current_pid_tgid();
    __u64 ts  = bpf_ktime_get_ns();
    bpf_map_update_elem(&start, &tid, &ts, BPF_ANY);
    return 0;
}

SEC("kretprobe/tcp_recvmsg")
int BPF_KRETPROBE(tcp_recvmsg_exit)
{
    __u32 tid  = bpf_get_current_pid_tgid();
    __u64 *tsp = bpf_map_lookup_elem(&start, &tid);
    if (!tsp)
        return 0;

    __u64 delta_us = (bpf_ktime_get_ns() - *tsp) / 1000;
    bpf_map_delete_elem(&start, &tid);

    __u32 slot = log2(delta_us);
    if (slot >= HIST_SLOTS)
        slot = HIST_SLOTS - 1;

    __u64 *cnt = bpf_map_lookup_elem(&latency_hist, &slot);
    if (cnt)
        __sync_fetch_and_add(cnt, 1);

    return 0;
}

char LICENSE[] SEC("license") = "GPL";

Userspace yükleyici ve histogram yazdırma

C — http_latency.c (userspace)
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <math.h>
#include <bpf/libbpf.h>
#include <bpf/bpf.h>
#include "http_latency.skel.h"

#define HIST_SLOTS 26

static volatile bool running = true;

static void print_hist(int map_fd)
{
    __u32 key;
    __u64 val, max_val = 0;
    __u64 vals[HIST_SLOTS] = {};

    for (key = 0; key < HIST_SLOTS; key++) {
        if (!bpf_map_lookup_elem(map_fd, &key, &val))
            vals[key] = val;
        if (vals[key] > max_val) max_val = vals[key];
    }

    printf("\n%-20s %10s %-40s\n", "usecs", "count", "distribution");
    for (key = 0; key < HIST_SLOTS; key++) {
        if (!vals[key]) continue;
        __u64 lo = (key == 0) ? 0 : (1ULL << (key-1));
        __u64 hi = (1ULL << key) - 1;
        int  stars = max_val ? (vals[key] * 40 / max_val) : 0;
        printf("[%8llu, %8llu) %10llu |", lo, hi, vals[key]);
        for (int i = 0; i < stars; i++) putchar('@');
        putchar('\n');
    }

    /* Temizle */
    __u64 zero = 0;
    for (key = 0; key < HIST_SLOTS; key++)
        bpf_map_update_elem(map_fd, &key, &zero, BPF_ANY);
}

int main(void)
{
    struct http_latency_bpf *skel;

    skel = http_latency_bpf__open_and_load();
    if (!skel) { fprintf(stderr, "load failed\n"); return 1; }
    if (http_latency_bpf__attach(skel)) {
        fprintf(stderr, "attach failed\n"); goto cleanup;
    }

    printf("HTTP latency izleniyor (5 sn)...\n");
    while (running) {
        sleep(5);
        print_hist(bpf_map__fd(skel->maps.latency_hist));
    }

cleanup:
    http_latency_bpf__destroy(skel);
    return 0;
}

Derleme ve çalıştırma

Makefile — http_latency
CLANG := clang
CC    := gcc
ARCH  := $(shell uname -m | sed 's/x86_64/x86/')

CFLAGS := -g -Wall -I/usr/include/bpf
LDFLAGS := -lbpf -lelf -lz

all: vmlinux.h http_latency.skel.h http_latency

vmlinux.h:
	bpftool btf dump file /sys/kernel/btf/vmlinux format c > vmlinux.h

http_latency.bpf.o: http_latency.bpf.c vmlinux.h
	$(CLANG) -g -O2 -target bpf -D__TARGET_ARCH_$(ARCH) \
	  -I/usr/include/bpf -c $< -o $@

http_latency.skel.h: http_latency.bpf.o
	bpftool gen skeleton $< > $@

http_latency: http_latency.c http_latency.skel.h
	$(CC) $(CFLAGS) -o $@ $< $(LDFLAGS) -lm

clean:
	rm -f vmlinux.h *.o *.skel.h http_latency

# Derleme
# make
# sudo ./http_latency
NOT

Bu örnekte tcp_sendmsg → tcp_recvmsg latency, aynı thread'deki bir HTTP istek-yanıt döngüsünü ölçer. Gerçek HTTP latency için uprobe ile kullanıcı alanı HTTP kütüphanesinin gönder/al fonksiyonlarını izlemek daha doğru sonuç verir. bpftrace -l 'uprobe:/usr/lib/*/libcurl.so*:curl_*' ile libcurl fonksiyonlarını keşfedebilirsiniz.

UYARI

tcp_sendmsg ve tcp_recvmsg kernel fonksiyon isimleri kernel versiyonları arasında değişebilir (örneğin tcp_sendmsg_locked). Kprobe bağlamadan önce bpftrace -l 'kprobe:tcp_send*' ile mevcut sembol adlarını doğrulayın. Stabil alternatif: tracepoint:tcp:tcp_probe veya tracepoint:sock:inet_sock_set_state.

Bu bölümde

  • Adım 1 bpftrace one-liner: kavram kanıtı, 5 dakikada histogram çıktısı
  • Adım 2 BCC Python: process filtresi, dinamik derleme, iteratif geliştirme
  • Adım 3 libbpf CO-RE: üretim kalitesi, kernel bağımsız, clang runtime gerektirmez
  • Evrim: one-liner → BCC → libbpf CO-RE — karmaşıklık gerektikçe geçiş yap