Я пытаюсь написать несколько зондов bpf, которые сохраняют какое-то состояние, необходимое для проверки во время выполнения. Для этого я использую iovisor/BCC. Я создал закрепленную карту, чтобы это значение можно было использовать в нескольких программах bpf. Всякий раз, когда я читаю значение с карты state_store
, я получаю действительный указатель, значение которого я могу разыменовать и распечатать. Чтобы получить значение для состояния next
, я вызываю матричную функцию, представленную в automaton_s
.
#include <bcc/proto.h>
struct automaton_s {
int initial_state;
int function[4][4];
};
typedef struct automaton_s automaton_t;
BPF_STACK(automaton, automaton_t, 1);
BPF_TABLE_PINNED("hash", int, int, state_store, 1, "/sys/fs/bpf/state");
int trace_connect_v4_return(struct pt_regs *ctx)
{
int key = 0, init_val = 0;
int *curr_state;
curr_state = state_store.lookup_or_try_init(&key, &init_val);
if (!curr_state) {
bpf_trace_printk("State store is full");
return -1;
}
bpf_trace_printk("curr state: %d", *curr_state);
automaton_t aut;
if (automaton.peek(&aut) < 0) {
bpf_trace_printk("automaton init");
aut = (automaton_t) {
.initial_state = 0,
.function = {
{ 1, -1, -1, -1 },
{ -1, 2, -1, -1 },
{ -1, -1, 3, -1 },
{ -1, -1, -1, 0 }
}
};
automaton.push(&aut, BPF_EXIST);
}
int next = aut.function[*curr_state][0];
bpf_trace_printk("next val: %d", next);
state_store.update(&key, &next);
return 0;
}
Ошибка возникает всякий раз, когда я пытаюсь использовать это значение next
либо для печати, либо для обновления state_store
(см. последние две строки перед return 0;
). Я получаю ошибку math between fp pointer and register with unbounded min value is not allowed
. Комментирование этих двух строк заставляет программу как минимум компилироваться, но мне все равно нужно обновить файл state_store
.
Погуглив проблему, я пришел к выводу, что это какая-то ошибка смещения регистра, отклоненная верификатором.
Полное сообщение об ошибке:
bpf: Failed to load program: Invalid argument
0: (b7) r7 = 0
1: (63) *(u32 *)(r10 -4) = r7
last_idx 1 first_idx 0
regs=80 stack=0 before 0: (b7) r7 = 0
2: (63) *(u32 *)(r10 -8) = r7
3: (18) r1 = 0xffff98ec8a7dd800
5: (bf) r2 = r10
6: (07) r2 += -4
7: (85) call bpf_map_lookup_elem#1
8: (bf) r6 = r0
9: (55) if r6 != 0x0 goto pc+30
R0_w=inv0 R6_w=inv0 R7_w=invP0 R10=fp0 fp-8=mmmm0000
10: (18) r1 = 0xffff98ec8a7dd800
12: (bf) r6 = r10
13: (07) r6 += -4
14: (bf) r3 = r10
15: (07) r3 += -8
16: (bf) r2 = r6
17: (b7) r4 = 1
18: (85) call bpf_map_update_elem#2
19: (18) r1 = 0xffff98ec8a7dd800
21: (bf) r2 = r6
22: (85) call bpf_map_lookup_elem#1
23: (bf) r6 = r0
24: (55) if r6 != 0x0 goto pc+15
from 24 to 40: R0_w=map_value(id=0,off=0,ks=4,vs=4,imm=0) R6_w=map_value(id=0,off=0,ks=4,vs=4,imm=0) R7=invP0 R10=fp0 fp-8=mmmmmmmm
40: (73) *(u8 *)(r10 -66) = r7
41: (b7) r1 = 25637
42: (6b) *(u16 *)(r10 -68) = r1
43: (b7) r1 = 540697972
44: (63) *(u32 *)(r10 -72) = r1
45: (18) r1 = 0x6174732072727563
47: (7b) *(u64 *)(r10 -80) = r1
48: (61) r3 = *(u32 *)(r6 +0)
R0_w=map_value(id=0,off=0,ks=4,vs=4,imm=0) R1_w=inv7022364302173697379 R6_w=map_value(id=0,off=0,ks=4,vs=4,imm=0) R7=invP0 R10=fp0 fp-8=mmmmmmmm fp-72=?0mmmmmm fp-80_w=inv7022364302173697379
49: (bf) r1 = r10
50: (07) r1 += -80
51: (b7) r2 = 15
52: (85) call bpf_trace_printk#6
last_idx 52 first_idx 19
regs=4 stack=0 before 51: (b7) r2 = 15
53: (18) r1 = 0xffff98ed35b5b000
55: (bf) r2 = r10
56: (07) r2 += -80
57: (85) call bpf_map_peek_elem#89
58: (67) r0 <<= 32
59: (c7) r0 s>>= 32
60: (65) if r0 s> 0xffffffff goto pc+41
R0_w=inv(id=0,umin_value=18446744071562067968,var_off=(0xffffffff80000000; 0x7fffffff),u32_min_value=-2147483648) R6=map_value(id=0,off=0,ks=4,vs=4,imm=0) R7=invP0 R10=fp0 fp-8=mmmmmmmm fp-16=????mmmm fp-24=mmmmmmmm fp-32=mmmmmmmm fp-40=mmmmmmmm fp-48=mmmmmmmm fp-56=mmmmmmmm fp-64=mmmmmmmm fp-72=mmmmmmmm fp-80=mmmmmmmm
61: (b7) r1 = 29801
62: (6b) *(u16 *)(r10 -84) = r1
63: (b7) r1 = 1852383342
64: (63) *(u32 *)(r10 -88) = r1
65: (18) r1 = 0x6f74616d6f747561
67: (7b) *(u64 *)(r10 -96) = r1
68: (b7) r7 = 0
69: (73) *(u8 *)(r10 -82) = r7
last_idx 69 first_idx 53
regs=80 stack=0 before 68: (b7) r7 = 0
70: (bf) r1 = r10
71: (07) r1 += -96
72: (b7) r2 = 15
73: (85) call bpf_trace_printk#6
last_idx 73 first_idx 53
regs=4 stack=0 before 72: (b7) r2 = 15
74: (18) r1 = 0xffffffff
76: (63) *(u32 *)(r10 -72) = r1
77: (b7) r2 = 1
78: (63) *(u32 *)(r10 -76) = r2
79: (63) *(u32 *)(r10 -64) = r1
80: (63) *(u32 *)(r10 -68) = r1
81: (b7) r2 = 2
82: (63) *(u32 *)(r10 -56) = r2
83: (63) *(u32 *)(r10 -60) = r1
84: (63) *(u32 *)(r10 -48) = r1
85: (63) *(u32 *)(r10 -52) = r1
86: (63) *(u32 *)(r10 -40) = r1
87: (63) *(u32 *)(r10 -44) = r1
88: (63) *(u32 *)(r10 -32) = r1
89: (b7) r2 = 3
90: (63) *(u32 *)(r10 -36) = r2
91: (63) *(u32 *)(r10 -24) = r1
92: (63) *(u32 *)(r10 -28) = r1
93: (63) *(u32 *)(r10 -16) = r7
94: (63) *(u32 *)(r10 -20) = r1
95: (63) *(u32 *)(r10 -80) = r7
96: (18) r1 = 0xffff98ed35b5b000
98: (bf) r2 = r10
99: (07) r2 += -80
100: (b7) r3 = 2
101: (85) call bpf_map_push_elem#87
102: (61) r1 = *(u32 *)(r6 +0)
R0_w=inv(id=0) R6=map_value(id=0,off=0,ks=4,vs=4,imm=0) R7=invP0 R10=fp0 fp-8=mmmmmmmm fp-16=????mmmm fp-24=mmmmmmmm fp-32=mmmmmmmm fp-40=mmmmmmmm fp-48=mmmmmmmm fp-56=mmmmmmmm fp-64=mmmmmmmm fp-72=mmmmmmmm fp-80=mmmmmmmm fp-88=?mmmmmmm fp-96=mmmmmmmm
103: (67) r1 <<= 32
104: (c7) r1 s>>= 32
105: (67) r1 <<= 4
106: (bf) r2 = r10
107: (07) r2 += -80
108: (0f) r2 += r1
last_idx 108 first_idx 74
regs=2 stack=0 before 107: (07) r2 += -80
regs=2 stack=0 before 106: (bf) r2 = r10
regs=2 stack=0 before 105: (67) r1 <<= 4
regs=2 stack=0 before 104: (c7) r1 s>>= 32
regs=2 stack=0 before 103: (67) r1 <<= 32
regs=2 stack=0 before 102: (61) r1 = *(u32 *)(r6 +0)
math between fp pointer and register with unbounded min value is not allowed
processed 100 insns (limit 1000000) max_states_per_insn 0 total_states 4 peak_states 4 mark_read 2
Я пробовал тестировать минимальные и максимальные значения как *curr_state
, так и next
, например:
if (!next || next > 3 || next < -1) return -1;
Но это кажется наивным и не решает вопроса. Я понятия не имею, как действовать дальше, любая помощь очень ценится.
Итак, я нашел решение. Кажется, я неправильно проверил границы *curr_state
. Таким образом, решение состоит в том, чтобы просто добавить следующий фрагмент перед индексацией aut.function
.
if (*curr_state < 0 || *curr_state >= 4)
return -1;