Можно ли также использовать perf_submit () eBPF в программе socket_filter? - PullRequest
0 голосов
/ 07 января 2020

Итак, я пытался отправить некоторые данные из космической программы ядра в пользовательскую космическую программу, используя perf_submit.

Я провел некоторые исследования и здесь (https://github.com/iovisor/bcc/issues/2423), yonghong-song ответил (последний комментарий), что программа socket_filter не может получить доступ к помощнику bpf_perf_event_output и, следовательно, его можно использовать только для отслеживания типов программ.

Однако на B CC ссылочный сайт (https://github.com/iovisor/bcc/blob/master/docs/reference_guide.md#2 -bpf_perf_output ), если вы ctrl + f и ищете: 3. perf_submit (), в пятой строке говорится, что «для программ SOCKET_FILTER вместо этого должна использоваться структура __sk_buff * skb». Я полагаю, что из этого следует, что perf_submit () можно использовать и для программ socket_filter?

Так что мне трудно понять, действительно ли perf_submit () можно использовать для программы фильтрации сокетов. Может быть, некоторые функции были добавлены после того, как Yonghong-song ответил на вопрос выше?

Я проверяю, будет ли perf_submit () работать с фильтром сокета, и на самом деле нет строки кода, которая захватывает вывод данных через perf_submit потому что просто addint perf_submit () в программе ядра уже пропустил ошибку.

Вот код моей программы:

from bcc import BPF

# Network interface to be monoitored
INTERFACE = "br-netrome"

bpf_text = """

#include <uapi/linux/ptrace.h>
#include <net/sock.h>
#include <bcc/proto.h>
#include <linux/bpf.h>

#define IP_TCP 6
#define IP_UDP 17
#define IP_ICMP 1
#define ETH_HLEN 14

BPF_PERF_OUTPUT(events);    // has to be delcared outside any function

int packet_monitor(struct __sk_buff *skb) {
    u8 *cursor = 0;
    u64 saddr;
    u64 daddr;
    u64 ttl;
    u64 hchecksum;

    struct ethernet_t *ethernet = cursor_advance(cursor, sizeof(*ethernet));
    if (!(ethernet -> type == 0x0800)) {
        return 0; // drop
    }

    struct ip_t *ip = cursor_advance(cursor, sizeof(*ip));
    /*
    if (ip->nextp != IP_TCP) 
    {
        if (ip -> nextp != IP_UDP) 
        {
            if (ip -> nextp != IP_ICMP) 
                return 0; 
        }
    }
    */

    saddr = ip -> src;
    daddr = ip -> dst;
    ttl = ip -> ttl;
    hchecksum = ip -> hchecksum;

    events.perf_submit(skb, &saddr, sizeof(saddr));

//    bpf_trace_printk("saddr = %llu, daddr = %llu, ttl = %llu", saddr, daddr, ttl); // only three arguments can be passed using printk

//    bpf_trace_printk("Incoming packet!!\\n");
    return -1;
}

, а вот код ошибки:

 R0=inv2048 R6=ctx(id=0,off=0,imm=0) R7=inv0 R10=fp0,call_-1
4: (20) r0 = *(u32 *)skb[26]
5: (7b) *(u64 *)(r10 -8) = r0
6: (18) r2 = 0xffff9bde204ffa00
8: (18) r7 = 0xffffffff
10: (bf) r4 = r10
11: (07) r4 += -8
12: (bf) r1 = r6
13: (18) r3 = 0xffffffff
15: (b7) r5 = 8
16: (85) call bpf_perf_event_output#25
unknown func bpf_perf_event_output#25

Traceback (most recent call last):
  File "packet_monitor.py", line 68, in <module>
    function_skb_matching = bpf.load_func("packet_monitor", BPF.SOCKET_FILTER)
  File "/usr/lib/python2.7/dist-packages/bcc/__init__.py", line 397, in load_func
    (func_name, errstr))

1 Ответ

2 голосов
/ 07 января 2020

TL; DR. Программы BPF типа BPF_PROG_TYPE_SOCKET_FILTER могут использовать bpf_perf_event_output только , начиная с Linux 5.4 .


К каким помощникам данная программа BPF имеет доступ, определяется get_func_proto членом объектов struct bpf_verifier_ops. Вы можете найти, какой bpf_verifier_ops объект соответствует какому типу программы, прочитав функцию find_prog_type() и файл bpf_types.h. В случае BPF_PROG_TYPE_SOCKET_FILTER соответствующая функция будет sk_filter_func_proto().

Если вы git blame эту функцию в последних источниках ядра, вы получите что-то как показано ниже (вы можете сделать то же самое с функцией обвинения GitHub):

$ git blame net/core/filter.c
[...]
2492d3b867043 (Daniel Borkmann          2017-01-24 01:06:27 +0100 6080) static const struct bpf_func_proto *
5e43f899b03a3 (Andrey Ignatov           2018-03-30 15:08:00 -0700 6081) sk_filter_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
2492d3b867043 (Daniel Borkmann          2017-01-24 01:06:27 +0100 6082) {
2492d3b867043 (Daniel Borkmann          2017-01-24 01:06:27 +0100 6083)         switch (func_id) {
2492d3b867043 (Daniel Borkmann          2017-01-24 01:06:27 +0100 6084)         case BPF_FUNC_skb_load_bytes:
2492d3b867043 (Daniel Borkmann          2017-01-24 01:06:27 +0100 6085)                 return &bpf_skb_load_bytes_proto;
4e1ec56cdc597 (Daniel Borkmann          2018-05-04 01:08:15 +0200 6086)         case BPF_FUNC_skb_load_bytes_relative:
4e1ec56cdc597 (Daniel Borkmann          2018-05-04 01:08:15 +0200 6087)                 return &bpf_skb_load_bytes_relative_proto;
91b8270f2a4d1 (Chenbo Feng              2017-03-22 17:27:34 -0700 6088)         case BPF_FUNC_get_socket_cookie:
91b8270f2a4d1 (Chenbo Feng              2017-03-22 17:27:34 -0700 6089)                 return &bpf_get_socket_cookie_proto;
6acc5c2910689 (Chenbo Feng              2017-03-22 17:27:35 -0700 6090)         case BPF_FUNC_get_socket_uid:
6acc5c2910689 (Chenbo Feng              2017-03-22 17:27:35 -0700 6091)                 return &bpf_get_socket_uid_proto;
7c4b90d79d0f4 (Allan Zhang              2019-07-23 17:07:24 -0700 6092)         case BPF_FUNC_perf_event_output:
7c4b90d79d0f4 (Allan Zhang              2019-07-23 17:07:24 -0700 6093)                 return &bpf_skb_event_output_proto;
2492d3b867043 (Daniel Borkmann          2017-01-24 01:06:27 +0100 6094)         default:
2492d3b867043 (Daniel Borkmann          2017-01-24 01:06:27 +0100 6095)                 return bpf_base_func_proto(func_id);
2492d3b867043 (Daniel Borkmann          2017-01-24 01:06:27 +0100 6096)         }
2492d3b867043 (Daniel Borkmann          2017-01-24 01:06:27 +0100 6097) }
[...]

Как видите, BPF_FUNC_perf_event_output был добавлен только недавно в список помощников, которые могут вызывать эти программы BPF. Коммит, который добавил эту поддержку, 7c4b90d79d0f4, был объединен в Linux v5.4:

$ git describe --contains 7c4b90d79d0f4
v5.4-rc1~131^2~248^2~20
...