Подключите байт-код eBPF к сокету SOCK_STREAM - PullRequest
0 голосов
/ 20 ноября 2018

Я использую https://elixir.bootlin.com/linux/v4.9.137/source/samples/bpf/sockex3_kern.c в этом примере, но вместо сокета RAW я использую обычные AF_INET6 / SOCK_STREAM и BPF_PROG_TYPE_SOCKET_FILTER.

Я не могу понять, почему load_half используется для чтения прото.Первые 32 бита - это поле длины:

SEC("socket/0")
int bpf_prog(struct __sk_buff *skb)
{
    __u32 proto = load_half(skb, 12);

    char fmt[] = "PROTO %x\n";
    bpf_trace_printk(fmt, sizeof(fmt), proto);
}

Или, если я попытаюсь сделать это:

SEC("socket/0")
int bpf_prog(struct __sk_buff *skb)
{
    u64 proto = load_half(skb, 12);
    char fmt[] = "PROTO %x %u\n";
    void *data = (void *)(long)skb->data;
    struct ethhdr *eth = data;
    void *data_end = (void *)(long)skb->data_end;
    ...
}

Я получил ошибку «недопустимый доступ bpf_context off = 80 size = 4».Как я понимаю, я должен прочитать все данные из поля «данные» здесь.

Итак, может быть, кто-то может сказать мне, где были обрезаны первые 34 байта (заголовок eth + ip) для текущего sk_buff?Где-нибудь в tcp_v4_rcv?

Можно ли получить доступ к полям заголовка IP с сокетом SOCK_STREAM?

UPD : похоже, что нет прямого доступа к данным из фильтра:

https://elixir.bootlin.com/linux/v4.9.137/source/net/core/filter.c#L2647

switch (off) {
case offsetof(struct __sk_buff, tc_classid):
case offsetof(struct __sk_buff, data):
case offsetof(struct __sk_buff, data_end):
    return false;
}

1 Ответ

0 голосов
/ 20 ноября 2018

Согласно последним источникам ядра, протокол имеет 16-байтовое смещение, а не 12!

https://elixir.bootlin.com/linux/latest/source/include/uapi/linux/bpf.h#L2305

...