Как распечатать путь к файлу из открытого системного вызова с помощью ebpf python?

Я использую bpf из модуля python bcc, и я хочу, чтобы моя функция probe печатала путь к текущему файлу (своего рода пользовательский упрощенный opensnoop). Как я могу это сделать?

Это то, что у меня есть до сих пор:

b = BPF(text="""
#include <linux/ptrace.h>      
#include<linux/sched.h>

BPF_HASH(last);      

int trace_entry(struct pt_regs *ctx)      
{
    char fileName[200] = {0};
    bpf_probe_read(fileName, sizeof(fileName), &PT_REGS_PARM1(ctx));  
    bpf_trace_printk("File Opened<%s>\\n", fileName);      
    return 0;
}
""")

print("Tracing for open... Ctrl-C to end")
b.attach_kprobe(event="do_sys_open", fn_name="trace_entry")
#b.attach_kprobe(event=b.get_syscall_fnname("open"), fn_name='funcky')
b.trace_print()

person Liroshka    schedule 01.03.2020    source источник
comment
Что вы пробовали? Пожалуйста, прочтите документацию для bcc и/или попробуйте создать свою программу из существующего opensnoop, это не похоже на то, что здесь должна быть какая-то особая ловушка.   -  person Qeole    schedule 02.03.2020
comment
Я отредактировал то, что сделал до сих пор. по какой-то причине это не работает должным образом - я получаю сообщение об открытии файла‹› без пути к файлам.   -  person Liroshka    schedule 03.03.2020
comment
Я предполагаю, что вызов bpf_probe_read() терпит неудачу, потому что вы пытаетесь прочитать слишком много данных (200 байт, но имя файла может быть не таким длинным), и это выглядит небезопасно! В примере opensnoop от bcc есть способ получить длину имени файла и прочитать только то, что необходимо. В качестве альтернативы, я думаю, вы могли бы попытаться заменить этот вызов на bpf_probe_read_user_str(), поэтому вам не нужно заботиться о фактической длине имени файла.   -  person Qeole    schedule 04.03.2020
comment
(Я забыл упомянуть, что bpf_probe_read_user_str() доступен только в последних ядрах, начиная с 5.5. В более старых ядрах теперь доступен устаревший bpf_probe_read_str(). См. обоснование.)   -  person Qeole    schedule 04.03.2020


Ответы (1)


Просто:
Вставьте это в код ядра:

// Nicer way to call bpf_trace_printk()
#define bpf_custom_printk(fmt, ...)                     \
        ({                                              \
            char ____fmt[] = fmt;                       \
            bpf_trace_printk(____fmt, sizeof(____fmt),  \
                    ##__VA_ARGS__);                     \
        })
struct pair {
    uint32_t lip; // local IP
    uint32_t rip; // remote IP
};

и в коде ядра вставьте распечатанный код. Этот вызов функции работает точно так же, как printf со всеми форматами и заполнителями...

bpf_custom_printk("This year is %d\n", 2020);

Вывод на печать:

sudo cat /sys/kernel/debug/tracing/trace_pipe
person tuilagio    schedule 11.03.2020
comment
Я думаю, что нашел способ сделать это без изменения кода ядра. Я позабочусь о том, чтобы это работало, и обновлю пост. - person Liroshka; 11.03.2020
comment
@Liroshka, какое твое окончательное решение? - person DEls; 07.04.2021