Как загрузить программу eBPF, которая проверяет функцию NFS?Linux

Ответить
Anonymous
 Как загрузить программу eBPF, которая проверяет функцию NFS?

Сообщение Anonymous »

Я пытаюсь воспроизвести поведение скрипта bpftrace, который я недавно создал (я считаю, что сам код bpftrace не очень важен, но тот факт, что он работает, доказывает, что eBPF и NFSDv4 правильно настроены на моей машине с Linux 5.14):

Код: Выделить всё

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;

printf("UID: %u, Write to Inode: %lu, Filename: %s/%s\n",
$uid,
$ino,
str($dentry->d_parent->d_name.name),
str($dentry->d_name.name),
);
}
Я переписываю его с помощью ebpf-go. Тем не менее, я продолжаю получать сообщение Загрузка объектов eBPF: поле WriteOps: программа write_ops: загрузка программы: разрешение отклонено: 0: (bf) r3 = r2: R2 !read_ok (3 строки опущены), что я интерпретирую как верификатор, не принимающий мою программу. Например, R2 !read_ok означает, что он не смог проверить безопасность чтения из второго аргумента?
Ниже приведен скелет кода 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, то он загружается без проблем, хотя при ближайшем рассмотрении я могу получить мусорные значения (?). Например, верификатор не жалуется на присоединение с помощью этого кода в write_ops

    Код: Выделить всё

    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 ошибка (или подобные ошибки). Например, я попробовал использовать функцию write_ops:

    Код: Выделить всё

    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)
}
Что касается того, что происходит не так, я предполагаю, что это связано с тем, как загружается nfsd-btf.h (поскольку именно там живут nfsd4_compound_state и nfsd4_op_u) или с тем, что ядро ​​не распознает BTF в аргументах. Это причина? Я попытался удалить «nfsd-btf.h», но потом жалуется на команду «Generate». Есть ли обычный способ загрузки программ, которые присоединяются к функциям, когда структуры аргументов функции отсутствуют в vmlinux.h?


Подробнее здесь: https://stackoverflow.com/questions/798 ... s-function
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Linux»