Topik wawancara representatif

Wawancara Umum: Bagaimana Anda Menjelaskan eBPF Verifier dan Portabilitas?

UmumSulit
Tim Redaksi Offer.ccDipublikasikan Diperbarui

Pertanyaan

Bagaimana Anda akan men-deploy program observabilitas eBPF di berbagai distribusi Linux dan versi kernel? Jelaskan apa yang dilindungi oleh verifier, cara Anda men-debug kegagalan pemuatan (load), dan cara Anda membangun matriks kompatibilitas yang dapat diuji.

Perintah dan konteks

Bagaimana Anda akan men-deploy program observabilitas eBPF di berbagai distribusi Linux dan versi kernel? Jelaskan apa yang dilindungi oleh verifier, cara Anda men-debug kegagalan pemuatan (load), dan cara Anda membangun matriks kompatibilitas yang dapat diuji.

Ini cocok untuk wawancara platform, Linux, SRE, keamanan, dan sistem. Topik ini menguji batasan kernel, verifikasi statis, siklus hidup loader user-space, dan disiplin rilis. Program eBPF melewati verifier sebelum di-attach ke hook kernel. Lolos verifikasi tidak membuktikan kebenaran logika bisnis atau kompatibilitas dengan setiap kernel, set izin, helper, map, atau lingkungan BTF.

Hal yang dinilai oleh pewawancara

  • Memisahkan batasan keamanan verifier dari kebenaran hasil bisnis.
  • Memahami tipe register, batas pointer, stack yang diinisialisasi, loop, dan pemeriksaan helper.
  • Menjelaskan siklus hidup libbpf: open, load, attach, dan teardown.
  • Menggunakan BTF, CO-RE, deteksi fitur, dan matriks kernel untuk menangani perbedaan versi.
  • Memberikan alur debugging untuk log verifier, izin, sumber daya map, dan kegagalan attach.
  • Mengetahui bahwa eBPF tetap tunduk pada bug kernel, semantik helper, dan biaya observasi.

Jawaban 30 detik

“Verifier melakukan pemeriksaan statis sebelum eksekusi: ia membuktikan akses memori yang berbatas dan status register serta pointer yang valid, membatasi helper, dan menolak jalur yang tidak dapat dibuktikan aman. Verifier tidak dapat membuktikan apakah metrik saya memiliki arti yang benar. Saya akan membuat proses open, load, verify, attach, dan teardown objek dapat diobservasi serta menggunakan log verifier untuk debugging. BTF, CO-RE, deteksi fitur, dan matriks CI yang mencakup kernel, arsitektur, izin, dan hook akan membangun kompatibilitas. Jika target tidak dapat memuat program, layanan mempertahankan fallback ke user-space atau metrik yang ada daripada melewati pemeriksaan tersebut.”

Solusi langkah demi langkah

Langkah 1: Tentukan batas keamanan eBPF

Program eBPF berjalan di lingkungan eksekusi yang dikendalikan oleh kernel; program ini tidak dapat membaca memori kernel secara sembarangan atau memanggil fungsi yang tidak sah. Verifier mengikuti alur kontrol sambil melacak register, stack, pointer map, dan pointer paket, lalu menolak jalur yang keamanannya tidak dapat dibuktikan. Verifier adalah gerbang pengaman, bukan bukti formal yang lengkap, dan tidak meninjau arti sampling, privasi, atau biaya sumber daya.

Mulailah dengan tipe program dan hook: tracepoint, kprobe, cgroup, XDP, dan lainnya memiliki input, helper, serta batasan nilai kembali yang berbeda. Kode sumber yang sama dapat gagal saat dipindahkan ke tipe program lain karena konteks dan kapabilitasnya berubah.

Langkah 2: Kenali kegagalan umum verifier

Register yang belum diinisialisasi, akses stack di luar batas (out-of-bounds), pointer nullable yang tidak diperiksa, batas paket yang tidak memadai, loop yang tidak dapat dibuktikan, argumen helper yang tidak valid, dan aritmetika pointer yang tidak valid semuanya dapat menyebabkan penolakan. Baca kegagalan status pertama di dalam log daripada hanya memperbaiki pesan terakhir.

c
/* Pseudocode: check bounds before reading packet fields */
if (cursor + sizeof(struct header) > data_end)
    return DROP;
struct header *h = cursor;
return handle(h->kind);

Jaga agar jalur tetap sederhana, letakkan pemeriksaan batas tepat di samping operasi pembacaan, dan bagi penguraian yang kompleks menjadi fungsi-fungsi kecil yang dapat diverifikasi. Batasi loop secara eksplisit, periksa hasil lookup map, dan gunakan konversi pointer yang diizinkan oleh konteks saat ini.

Langkah 3: Jelaskan siklus hidup libbpf

Loader di user-space membuka objek BPF dan mendeteksi program, map, serta variabel global. Pemuatan (loading) membuat map, menyelesaikan relokasi, dan meminta verifier kernel untuk memeriksa dan memuat program. Tahap attach menghubungkan program ke hook; teardown melepaskan kaitan dan membebaskan sumber daya. Catat nama objek, tipe program, versi kernel, kode kesalahan, dan log verifier di setiap fase.

Pemuatan yang sukses tidak menjamin keberhasilan attach. Izin, batas locked-memory, BTF yang hilang, hook yang tidak ada, batas map, dan sumber daya ring-buffer dapat gagal di fase yang berbeda. Peluncur harus menampilkan fase mana yang gagal dan menyatakan kapabilitas apa yang tersisa ketika hanya sebagian program yang berhasil dimuat.

Langkah 4: Rancang map, event, dan batas sumber daya

Map menyediakan shared state utama antara kernel dan user-space. Pilih tipe map hash, array, per-CPU, atau ring-buffer berdasarkan key, value, konkurensi pembaruan, siklus hidup, dan kapasitas. Event berfrekuensi tinggi memerlukan sampling, batching, dan penghitung kehilangan (loss counter); observasi tidak boleh menghabiskan sumber daya kernel.

Minimalkan field sensitif di kernel dan kirimkan hash, kategori, atau jumlah jika memungkinkan. Konsumen di user-space harus menangani overflow ring-buffer, restart, dan perubahan versi. Event yang hilang adalah ketidakpastian yang eksplisit, bukan nol observasi.

Langkah 5: Tangani BTF, CO-RE, dan kompatibilitas

BTF menyediakan metadata tipe sehingga loader dan alat bantu dapat memahami program, map, dan simbol kernel. CO-RE melakukan relokasi berdasarkan tipe dan mengurangi kebutuhan kompilasi ulang untuk setiap kernel, tetapi tidak menghilangkan semua perbedaan. Helper, kfuncs, tipe program, arsitektur, compiler, dan izin masih memerlukan pemeriksaan fitur.

Matriks kompatibilitas harus mencakup distribusi, versi kernel, arsitektur, keberadaan BTF, feature flag, izin kontainer, dan hook target. CI harus menjalankan compile, pemuatan verifier, attach, replay event, dan teardown pada kernel nyata atau virtual. Kompilasi saja bukanlah bukti kompatibilitas.

Langkah 6: Bangun alur debugging, fallback, dan rilis

Lakukan debugging dengan urutan ini: konfirmasikan kernel dan izin; periksa tipe program dan hook; tangkap log verifier secara lengkap; periksa BTF dan helper; lalu periksa sumber daya map dan konsumsi user-space. Klasifikasikan kegagalan sebagai keamanan kode sumber, kapabilitas yang hilang, izin, sumber daya runtime, atau logika bisnis agar perbaikannya sesuai dengan penyebabnya.

Rilis terlebih dahulu di node bayangan (shadow nodes) atau canary host kecil. Pantau CPU, memori, event yang hilang, penolakan verifier, log kernel, dan sinyal target. Jika pemuatan gagal, layanan user-space mempertahankan metrik atau log yang ada. Simpan objek sebelumnya dan operasi detach sehingga rollback tidak bergantung pada program baru.

Peningkatan informasi dan batasan

Manfaat utama eBPF adalah kemampuan pemrograman kernel yang dibatasi melalui jalur pemuatan yang dapat diverifikasi dan diobservasi. Verifier membuktikan serangkaian properti keamanan, bukan niat program; CO-RE meningkatkan portabilitas tetapi tidak menjamin keberhasilan lintas versi. Jawaban yang kuat mencakup keamanan, kompatibilitas, sumber daya, dan kebenaran logika bisnis secara bersamaan.

Jawaban model

“Saya akan mulai dengan tipe program dan hook karena konteks tersebut menentukan input, nilai kembali, dan kapabilitas helper. Sebelum eksekusi, verifier melacak register, stack, map, dan pointer paket serta menolak register yang belum diinisialisasi, akses di luar batas, null yang tidak diperiksa, loop tak berbatas, dan argumen helper yang tidak valid. Lolosnya verifikasi membuktikan bahwa jalur tersebut aman untuk dieksekusi; ini tidak membuktikan bahwa sampling atau metrik bisnis sudah benar.

Loader user-space menggunakan libbpf untuk membuat proses open, load, attach, dan teardown dapat diobservasi. Saat terjadi kegagalan pemuatan, saya menyimpan log verifier secara lengkap dan membedakan antara keamanan kode sumber, helper yang hilang, BTF, izin, dan sumber daya. BTF dan CO-RE mengurangi kompilasi ulang, tetapi saya tetap menguji matriks nyata dari distribusi, kernel, arsitektur, hook, izin, dan fitur di seluruh tahap compile, load, attach, replay, dan teardown.

Saya membatasi kapasitas map dan laju event, mencatat kehilangan, serta meminimalkan field sensitif di kernel. Produksi dimulai dengan node bayangan dan canary kecil, memantau CPU, memori, event yang hilang, dan log kernel. Pemuatan yang gagal akan mempertahankan metrik atau jalur log yang ada dan melakukan rollback ke objek sebelumnya dengan detach. Pendekatan ini memanfaatkan eBPF tanpa salah mengartikan verifier atau CO-RE sebagai keamanan mutlak atau jaminan kompatibilitas penuh.”

Kesalahan umum

  • Menganggap verifier sebagai bukti kebenaran bisnis → verifier tidak memeriksa arti metrik atau privasi → tambahkan replay, sampling, dan audit data.
  • Hanya memeriksa kompilasi → proses load, attach, izin, dan BTF masih bisa gagal → uji seluruh siklus hidup pada matriks kernel.
  • Memperbaiki baris log terakhir → akar penyebabnya sering kali merupakan kegagalan status sebelumnya → mulai dari error register atau batas yang pertama.
  • Menulis map dan event tanpa batas → observasi dapat menghabiskan sumber daya kernel → batasi kapasitas, lakukan sampling, dan hitung kehilangan.
  • Mengasumsikan CO-RE menghilangkan perbedaan versi → helper, hook, izin, dan arsitektur tetap bervariasi → lakukan deteksi fitur dan lakukan degradasi secara terencana.
  • Tidak memiliki fallback di user-space → pemuatan yang gagal dapat memengaruhi layanan utama → pertahankan metrik, log, dan jalur detach.

Pertanyaan lanjutan

Bagaimana cara memperbaiki error verifier terkait pointer yang berpotensi null?

Periksa secara eksplisit pada setiap jalur alur kontrol sebelum melakukan dereferensi, letakkan pemeriksaan tersebut dekat dengan operasi pembacaan. Jika percabangannya kompleks, bagi fungsinya dan periksa kembali status verifier daripada menyembunyikan masalah dengan type casting yang tidak aman.

Bagaimana jika program yang sama berhasil dimuat di satu kernel tetapi gagal di kernel lain?

Bandingkan tipe program, helper, kfuncs, BTF, arsitektur, konfigurasi, izin, dan log verifier, bukan hanya membandingkan nomor versi. Lakukan deteksi fitur untuk menemukan alternatif dan catat hasilnya dalam matriks kompatibilitas serta release gate.

Bagaimana cara mencegah event yang hilang agar tidak terlihat normal?

Hitung kehilangan, overflow ring-buffer, dan restart konsumen baik di kernel maupun user-space. Publikasikan sample rate, tingkat kehilangan (loss rate), dan cakupan. Dasbor harus menampilkan ketidakpastian ketika data event tidak lengkap, bukan menampilkannya sebagai nol.

Apakah tinjauan keamanan masih diperlukan setelah disetujui oleh verifier?

Ya. Tinjau izin program, minimalisasi data, loader user-space, upgrade dan rollback, eksposur kernel, dan batas sumber daya. Verifier memang penting, tetapi tidak menggantikan pemodelan ancaman (threat modeling) atau pemantauan runtime.

Sumber publik

Pertanyaan terkait