fentry:nfsd:nfsd4_write {
$dentry = args->cstate->current_fh.fh_dentry;
$ino = $dentry->d_inode->i_ino;
$uid = args->rqstp->rq_cred.cr_uid.val;
$p = args->cstate->current_fh.fh_export->ex_path;
$export_name = str($p.dentry->d_name.name);
printf("UID: %u, Write to Inode: %lu, Filename: %s/%s, Export: %s, Filepath: %s\n",
$uid,
$ino,
str($dentry->d_parent->d_name.name),
str($dentry->d_name.name),
$export_name,
@paths[$ino]
);
}
Я использую ebpf-go. Тем не менее, я продолжаю получать сообщение Загрузка объектов eBPF: поле WriteOps: программа write_ops: загрузка программы: разрешение отклонено: 0: (bf) r3 = r2: R2 !read_ok (3 строки опущены), что я интерпретирую как верификатор, не принимающий мою программу.
Ниже приведен скелет кода C, который я пытаюсь использовать, и я опишу странное поведение, которое я наблюдаю.
#include "nfsd-btf.h"
#include "vmlinux.h"
#include
#include
SEC("fentry/nfsd4_write")
int write_ops(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
union nfsd4_op_u *u) {
....
}
Примечание: я генерирую vmlinux.h через файл дампа bpftool btf /sys/kernel/btf/vmlinux в формате c > vmlinux.h и генерирую nfsd-btf.h через файл дампа bpftool btf /sys/kernel/btf/nfsd в формате c > nfsd-btf.h
Вот что я наблюдаю:
- Если я ничего не делаю с аргументами, то он загружается без проблем.
- Если я пытаюсь получить доступ к rqstp, то он загружается без проблем, хотя при ближайшем рассмотрении я могу получить мусорные значения (?). Например, я могу сделать
bpf_printk("nfs write %u\n", BPF_CORE_READ(rqstp, rq_cred.cr_uid.val));
но напечатанное значение не является моим фактическим uid (оно дает мне 3243852586, независимо от пользователя или даже root) - Если я попытаюсь получить доступ к cstate, я получаю отказ в разрешении: 0: (bf) r3 = r2: R2 !read_ok ошибка (или подобные ошибки). Например, я попробовал (весь остальной код закомментировал)
struct dentry *dentry_ptr = BPF_CORE_READ(cstate, current_fh.fh_dentry);
bpf_printk("%p\n", cstate);
if (!cstate) {
bpf_printk("cstate NULL");
return 0;
} else {
bpf_printk("cstate valid");
}
Для справки: это программа main.go
import (
"log"
"time"
"github.com/cilium/ebpf/link"
)
func main() {
// Load eBPF objects to the objs struct (not the kernel yet!)
var objs collectorObjects
if err := loadCollectorObjects(&objs, nil); err != nil {
log.Fatal("Loading eBPF objects:", err)
}
defer objs.Close()
link, err := link.AttachTracing(link.TracingOptions{
Program: objs.WriteOps,
})
if err != nil {
log.Fatal("Attaching Fentry:", err)
}
defer link.Close()
log.Printf("Program Loaded!\n")
time.Sleep(10*time.Seconds)
}
Подробнее здесь: https://stackoverflow.com/questions/798 ... s-function
Мобильная версия