Как изменить память пользовательского пространства с помощью eBPF?

Я пытаюсь написать образец кода и посмотреть, как он работает на практике.

Как сказано здесь и обсуждается здесь.

Если все правильно, вывод должен быть:

$ cat foo1
this is foo1 content
$ cat foo2
this is foo2 content
$ sudo bcc_mangle_open.py &
[1] 63453
$ cat foo1
this is foo2 content

Я написал образец в BCC, который выглядит так:

from bcc import BPF

# define BPF program
prog = """
#include <uapi/linux/ptrace.h>
#include <linux/sched.h>
int trace_entry(struct pt_regs *ctx)
{
    char buf[10];
    char foo2[] = "foo2";
    char *fname = (char *) PT_REGS_PARM1(ctx);

    bpf_probe_read_str(buf, sizeof(buf), fname);
    if (buf[0] != 'f' || buf[1] != 'o' || buf[2] != 'o' || buf[3] != '1') {
        return 0;
    }

    bpf_probe_write_user(fname, foo2, sizeof(foo2));

    return 0;
};
"""

# load BPF program
b = BPF(text=prog)

b.attach_kprobe("do_sys_open", fn_name="trace_entry")

Содержание foo1 должно измениться, но этого не происходит.

И я пытался напечатать fname и даже buf с помощью bpf_trace_printk(), но на моем экране ничего не отображается.

Есть идеи, почему контент не меняется?

обновление-1

По предложению @Queole

.Это сработало.. Так что мы должны дать (char *) PT_REGS_PARM2(ctx) вместо того (char *) PT_REGS_PARM1(ctx). Я получил результат, но немного странно. через 3-4cat foo1, содержание меняется.

$ cat foo1
this is foo1 content
$ cat foo1
this is foo1 content
$ cat foo1
this is foo2 content
$ cat foo1
this is foo1 content
$ cat foo1
this is foo1 content
$ cat foo1
this is foo1 content
$ cat foo1
this is foo1 content
$ cat foo1
this is foo1 content
$ cat foo1
this is foo1 content
$ cat foo1
this is foo1 content
$ cat foo1
this is foo1 content
$ cat foo1
this is foo1 content
$ cat foo1
this is foo1 content
$ cat foo1
this is foo1 content
$ cat foo1
this is foo1 content
$ cat foo1
this is foo2 content

В чем причина такого поведения?

2 ответа

В последнее время меня очень заинтересовал ebpf. И я провел ваш эксперимент на Ubuntu 18.04 (5.4.0) и получил тот же результат. Исходный код кота я не смотрел. Но я написал простую кошачью программу, например:

      #include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main()
{
    char c = '\0';
    int fd;
    char file_name[16];
    memcpy(file_name, "foo1", 4);
    fd = open(file_name, O_RDONLY);
    if(fd < 0)
        return 0;
    while (read(fd, &c, 1) == 1)
    {
        printf("%c", c);
    }
    close(fd);

    return 0;
}

Я получил то, что хотел. Если я изменюсь" fd = open("file_name", O_RDONLY);" к " fd = open("foo1", O_RDONLY);", то эксперимент провалится.

У меня тоже была проблема. Я обнаружил, что адрес параметра r--p. Возможно, параметр находится в .rodata и .data, что означает, что его нельзя записать. Вы можете попытаться выделить некоторую память, скопировать параметр в эту область, а затем отправить эту область в func.

Другие вопросы по тегам