【问题标题】: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
【解决方案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 程序不得导致尝试使用更多字节的可执行文件。
列出了其他允许或需要了解的项目。我只能鼓励你潜入其中!