// Programa BPF del experimento §9.5.1 de SDD 25: un iterador `task` que emite // un registro BINARIO por proceso, para comparar contra el barrido de texto de /proc. // // No usa vmlinux.h a propósito (haría falta bpftool, que no está en la máquina ni // en el store): declara a mano el mínimo de tipos con `preserve_access_index`, que // es lo que hace CO-RE reubicar los offsets contra el BTF del kernel en carga. #include #include #include char LICENSE[] SEC("license") = "GPL"; typedef unsigned int u32; typedef unsigned long long u64; struct bpf_iter_meta { struct seq_file *seq; u64 session_id; u64 seq_num; } __attribute__((preserve_access_index)); struct task_struct { unsigned int __state; int pid; int tgid; struct task_struct *real_parent; char comm[16]; u64 utime; u64 stime; } __attribute__((preserve_access_index)); struct bpf_iter__task { struct bpf_iter_meta *meta; struct task_struct *task; } __attribute__((preserve_access_index)); // El mismo puñado de campos que sandokan saca hoy de /proc//stat. struct registro { int pid; int ppid; u32 estado; u32 _pad; u64 utime; u64 stime; char comm[16]; }; SEC("iter/task") int barrido(struct bpf_iter__task *ctx) { struct task_struct *t = ctx->task; struct registro r = {}; if (!t) return 0; // El iterador `task` recorre HILOS. sandokan cuenta procesos ⇒ sólo los // líderes de grupo, que es exactamente lo que hay bajo /proc/. r.pid = BPF_CORE_READ(t, pid); r.ppid = BPF_CORE_READ(t, tgid); if (r.pid != r.ppid) return 0; r.ppid = BPF_CORE_READ(t, real_parent, tgid); r.estado = BPF_CORE_READ(t, __state); r.utime = BPF_CORE_READ(t, utime); r.stime = BPF_CORE_READ(t, stime); BPF_CORE_READ_INTO(&r.comm, t, comm); bpf_seq_write(ctx->meta->seq, &r, sizeof(r)); return 0; }