eBPF程序编译报错:BPF栈限制超出问题咨询
eBPF栈溢出问题解答
问题代码
#include <stdio.h> #include <string.h> #include <linux/bpf.h> #include <sys/socket.h> #include <bpf/bpf_helpers.h> char LICENSE[] SEC("license") = "GPL"; // msg_data_map carries a key-value pair of (msg_id, msg_length), and can record // upto 65535 messages at once. #define MAX_MSG_LEN 128 struct { __uint(type, BPF_MAP_TYPE_HASH); __uint(max_entries, 65535); __type(key, int); __type(value, char[MAX_MSG_LEN]); } msg_data_map SEC(".maps"); SEC("sk_msg") int msg_prog(struct sk_msg_md *msg) { long len = (long)msg->data_end - (long)msg->data; void *data_end = (void *)(long) msg->data_end; void *data = (void *)(long) msg->data; // Bounds check to make verifier happy if (data + MAX_MSG_LEN > data_end) { return SK_PASS; } char buf[MAX_MSG_LEN] = {0}; if (len > MAX_MSG_LEN) { __builtin_memcpy(buf, data, MAX_MSG_LEN); } else { __builtin_memcpy(buf, data, len); } // Update in map int index = 0; bpf_map_update_elem(&msg_data_map, &index, &buf, BPF_ANY); return SK_PASS; }
编译错误信息
Looks like the BPF stack limit of 512 bytes is exceeded. Please move large on stack variables into BPF per-cpu array map.
问题1:128字节的buf为何触发栈溢出?
BPF验证器计算栈使用量时,并非只统计显式定义的局部变量大小,还会包含helper函数调用带来的隐式栈开销:
- 显式定义的
buf占128字节,加上其他局部变量(len、data_end、data、index)的开销,总和远小于512字节; - 但调用
bpf_map_update_elem将栈上的buf写入哈希表时,内核需要完成从栈到map元素的数据拷贝,验证器会将这个拷贝操作所需的临时缓冲区(大小等于value的128字节)也计入栈使用量; - 再加上helper函数调用的栈帧开销、内存对齐的额外占用,总栈使用量就会超过512字节的限制,触发报错。
问题2:注释掉map更新代码即可正常编译的原因?
当注释掉bpf_map_update_elem调用后:
- 编译器优化器会发现
buf内的数据没有被后续读取使用(仅执行写入操作但无输出),可能直接优化掉buf的栈分配; - 即使编译器未做优化,验证器也不再需要计算
bpf_map_update_elem调用带来的隐式栈开销,总栈使用量会降到512字节以下,因此程序可以正常通过验证和编译。
内容的提问来源于stack exchange,提问作者diviquery
相关产品推荐
相关产品推荐

