如何在eBPF的XDP钩子中将数据包载荷复制到自定义缓冲区?
eBPF/XDP数据包载荷存储到自定义缓冲区的BPF验证器问题
我希望在eBPF & XDP钩子中将数据包的载荷存储到自定义缓冲区,但无法通过BPF验证器。对比他人代码未发现差异。
代码中已检查载荷长度应小于MTU(代码中设为1500),缓冲区大小为(1<<20),远大于MTU。
内核代码(.kern)
#define BUFFER_SIZE (1<<20) #define MTU 1500 struct my_buffer { __u32 len; char buf[BUFFER_SIZE + 5]; }; struct bpf_map_def SEC("maps") map_my_buffer = { .type = BPF_MAP_TYPE_ARRAY, .key_size = sizeof(unsigned int), .value_size = sizeof(struct my_buffer), .max_entries = 1, }; SEC("WriteBuffer") int WriteBuffer_main(struct xdp_md *ctx) { void *data_end = (void *)(long)ctx->data_end; void *data = (void *)(long)ctx->data; char *payload = data + sizeof(struct ethhdr) + sizeof(struct iphdr) + sizeof(struct udphdr); if (payload >= data_end) return XDP_PASS; unsigned int zero = 0; struct my_buffer *fd = bpf_map_lookup_elem(&map_my_buffer, &zero); if (!fd) return XDP_PASS; // can't find the context... __u32 data_len = data_end - (void *)payload; if (data_len > MTU) return XDP_PASS; for (__u32 i = 0; i < MTU && payload + i + 1 <= data_end; i++) { fd -> buf[i] = payload[i]; } return XDP_DROP; }
BPF验证器错误信息
67: (bf) r2 = r5 68: (57) r2 &= 4064 69: (0f) r9 += r2 70: (bf) r5 = r2 71: (71) r1 = *(u8 *)(r4 -16) 72: (7b) *(u64 *)(r10 -16) = r1 73: (71) r1 = *(u8 *)(r4 -15) invalid access to packet, off=120 size=1, R4(id=0,off=135,r=120) R4 offset is outside of the packet processed 60 insns (limit 1000000) max_states_per_insn 0 total_states 5 peak_states 5 mark_read 4
更新
按照pchaigno的指导,我将循环修改为:
for (__u32 i = 0; i <= MTU && i < data_len && payload + i + 1 <= data_end; ++i) { fd -> buf[i] = payload[i]; }
之后通过了验证...但我认为这三个条件存在冗余,不太合理。
内容的提问来源于stack exchange,提问作者Zezhou Wang
相关产品推荐
相关产品推荐

