今天遇到个不常见的问题:在往内核装载 bpf 程序时,bpf verifier 报告错误:

1
failed to load bpf with bitmap size 8: failed to load bpf obj and bpf maps: field Acl: program acl: load program: no space left on device: 578: R0=map_value(id=0,off=0,ks=8,vs=64,imm=0) R1_w=map_ptr(id=0,off=0,ks=4,vs=4,imm=0) R2_w=fp-4 R3_w=invP1 R4=invP(id=69 (3524 line(s) omitted)

觉得奇怪的地方是,bpf verifier 怎么会报告空间不足的错误呢?

bpf verifier

好吧,直接搜索 verifier.c 源代码,看看有哪些地方会返回 -ENOSPC

Emm,有且仅有一个地方:

1
2
3
4
5
6
7
8
// $KERNEL/kernel/bpf/verifier.c

    if (log->level && bpf_verifier_log_full(log))
        ret = -ENOSPC;
    if (log->level && !log->ubuf) {
        ret = -EFAULT;
        goto err_release_maps;
    }

这段代码的意思是,用于保存 bpf verifier 日志的地方满了,无法保存更多的 bpf verifier 日志了。

解决办法

解决办法有 2 个:

  1. 提供更大的 bpf verifier 日志空间。
  2. 不去获取 bpf verifier 日志。

使用 cilium/ebpf 的时候,通过以下选项来控制 bpf verifier 日志。

1
2
3
4
5
6
7
    opts := ebpf.CollectionOptions{
        Programs: ebpf.ProgramOptions{
            LogLevel: ebpf.LogLevelBranch|ebpf.LogLevelInstruction,
            LogSize: ebpf.DefaultVerifierLogSize*10,
            LogDisabled: false,
        },
    }

解决办法 1 就是调大 LogSize,解决办法 2 就是将 LogDisabled 设置为 true