You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 18:57:49