BPF Map'ler ve State Yonetimi
Reading syscall buffers
Önceki alıştırmada, birden fazla eBPF programı arasında veri paylaşmak için map’leri nasıl kullanacağımızı öğrendik.
Şimdi bunu syscall buffer’larından veri yakalamak için uygulayalım. Syscall’ların iki tracepoint event’i vardır: enter (başlamadan önce) ve exit (tamamlandıktan sonra). Her ikisi arasındaki veriyi ilişkilendirmemiz gerekecek.
read syscall
read syscall’a bakalım:
ssize_t read(int fd, void *buf, size_t count);
sys_enter_read ve sys_exit_read’e hook olursak:
- Entry noktasında: argument’lere erişimimiz var, ancak buffer hala boş.
- Exit noktasında: buffer veriyle dolmuş durumda, ancak yalnızca return value’ya erişimimiz var.
Her ikisini ilişkilendirmek için, entry noktasında buffer pointer’ı bir map kullanarak yakalayıp, exit noktasında doldurulmuş buffer’ı okuyoruz.
Entry noktasında buffer adresini saklama
Öncelikle, syscall başladığında buffer pointer’ı kaydetmemiz gerekiyor. Buffer adresi ctx->args[1] içindedir.
Bu adresi, daha sonra arayabilmemiz için PID’yi key olarak kullanarak bir map’te saklayacağız:
u64 buf_addr = ctx->args[1];
bpf_map_update_elem(&read_buffers, &pid, &buf_addr, BPF_ANY);
Buffer adresini u64 value olarak sakladığımıza dikkat edin.
Exit noktasında buffer’ı okuma
Şimdi exit programında, syscall tarafından doldurulan buffer’ı alıp okumamız gerekiyor.
Önce read işleminin başarılı olup olmadığını kontrol edin:
size_t count = ctx->ret;
if (count <= 0) return 0;
Return value ctx->ret, kaç byte okunduğunu söyler.
Ardından, PID’yi key olarak kullanarak kayıtlı buffer adresini bulun:
u64 *buf_ptr = bpf_map_lookup_elem(&read_buffers, &pid);
if (!buf_ptr) return 0;
Bu, saklanan value’ya (u64*) bir pointer döndürür.
Buffer’ı okumak için yerel bir buffer oluşturun ve bpf_probe_read_user kullanın. Gerçek buffer adresini elde etmek için buf_ptr’ı dereference etmeniz gerekecek:
char local_buf[32];
if (count > 32) count = 32;
bpf_probe_read_user(local_buf, count, (void *)*buf_ptr);
*buf_ptr ifadesine dikkat edin, daha önce sakladığımız buffer adresini elde etmek için pointer’ı dereference ediyoruz.
Görev
Bir program, parola içeren bir dosyayı okuyor. Dosyanın tüm içeriğini SUBMIT_STR_LEN ile gönderin.
Yapmanız gereken
Buffer içeriğini yakalamak ve göndermek için hem entry hem de exit programlarını tamamlayın.
Compare two strings for equality
- Args:
char* bufdynamic buffer to compareu32 buf_szlength of dynamic bufferconst char* buf2literal string to compare against
Read string from user space into kernel buffer
- Args:
void* dstkernel buffer to read intou32 sizemaximum bytes to readconst void* srcuser space pointer to string
Read bytes from user space into kernel buffer
- Args:
void* dstkernel buffer to read intou32 sizebytes to readconst void* srcuser space pointer