【问题标题】:What is not allowed in restricted C for ebpf?ebpf 的受限 C 中不允许什么?
【发布时间】:2020-01-01 10:36:02
【问题描述】:

来自 bpf 手册页:

eBPF 程序可以用经过编译的受限 C 语言编写 (使用 clang 编译器)转换为 eBPF 字节码。各种功能是 从这个受限制的 C 中省略,例如循环、全局变量、 可变参数函数、浮点数和传递结构为 函数参数。

AFAIK 未更新的手册页。我想知道在使用受限 C 编写 eBPF 程序时究竟禁止了什么?手册页所说的仍然正确吗?

【问题讨论】:

    标签: c linux-kernel manpage bpf ebpf


    【解决方案1】:

    让我们来看看这些:

    • 可变参数函数、浮点数和传递结构作为函数参数仍然是不可能的。据我所知,没有正在进行的工作来支持这些。
    • 全局变量应该在 >=5.2 的内核中得到支持,感谢 recent patchset by Daniel Borkmann
    • 无限循环仍然不受支持。有limited support for bounded loops in kernels >=5.3。我在这里使用“有限”,因为如果循环太大,一个小程序仍然可能被拒绝。

    了解最新版本的 Linux 允许什么的最佳方式是阅读the verifier's code 和/或关注the bpf mailing list(您可能还想关注 netdev 邮件列表,因为某些补丁集可能仍然在那里)。我还发现检查 patchwork 非常有效,因为它更清楚地概述了每个补丁集的状态。

    【讨论】:

      【解决方案2】:

      这并不是 ELF 文件本身“允许”什么的问题。这句话意味着一旦编译成 eBPF 指令,你的 C 代码可能会产生会被验证者拒绝的代码。例如,BPF 程序中的循环长期以来一直在 BPF 程序中被拒绝,因为无法保证它们会终止(唯一的解决方法是在编译时展开它们)。

      因此,您基本上可以在 C 语言中使用几乎任何您想要的东西并成功生成 ELF 目标文件。但是你希望它通过验证者。哪些组件肯定会导致验证者抱怨?让我们看一下手册页中的列表:

      • 循环:Linux 5.3 版引入了对有界循环的支持,因此循环现在可以在一定程度上起作用。 “有界循环”是指验证者有办法告诉它们最终将完成的循环:通常,for (i = 0; i < CONSTANT; i++) 种类循环应该可以工作(假设 i 未在块中修改)。

      • 全局变量:最近有一些工作支持全局变量,但是它们以特定的方式处理(作为单条目映射)并且我没有真正尝试过它们,所以我不知道这是多么透明,如果您可以简单地在程序中定义全局变量。随意尝试:)。

      • 可变参数函数:很确定这不受支持,我目前不知道在 eBPF 中会如何转换。

      • 浮点数:仍然不支持。

      • 将结构作为函数参数传递:不支持,尽管我认为传递指向结构的指针应该可行。

      如果你对这个级别的细节感兴趣,你真的应该看看Cilium's documentation on BPF。它不是完全最新的(仅缺少非常新的功能),但比手册页更完整和准确。特别是,the LLVM section 有一个项目列表,这些项目应该或不应该在编译为 eBPF 的 C 程序中工作。除了上述项目外,他们还引用了:

      • (所有函数都需要内联,没有函数调用)->这个已经过时了,BPF有函数调用。

      • 没有共享库调用:这是真的。您不能调用标准库中的函数或其他 BPF 程序中定义的函数。您只能调用在相同 BPF 程序中定义的函数,或在内核中实现的 BPF 助手,或执行“尾调用”。

      • 例外:memset()/memcpy()/memmove()/memcmp() 的 LLVM 内置函数可用(我认为它们几乎是您可以调用的唯一函数,除了 BPF 助手和你的其他 BPF 函数)。

      • 不允许使用 const 字符串或数组(因为它们在 ELF 文件中的处理方式):我认为这在今天仍然有效?

      • BPF 程序堆栈限制为 512 字节,因此您的 C 程序不得导致尝试使用更多字节的可执行文件。

      列出了其他允许或需要了解的项目。我只能鼓励你潜入其中!

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-10-01
        • 1970-01-01
        • 2012-01-17
        • 2013-06-12
        • 2017-01-11
        • 1970-01-01
        • 2018-07-27
        • 1970-01-01
        相关资源
        最近更新 更多