What is not allowed in restricted C for ebpf?

别来无恙 提交于 2021-01-27 21:16:19

问题


From bpf man page:

eBPF programs can be written in a restricted C that is compiled (using the clang compiler) into eBPF bytecode. Various features are omitted from this restricted C, such as loops, global variables, variadic functions, floating-point numbers, and passing structures as function arguments.

AFAIK the man page it's not updated. I'd like to know what is exactly forbidden when using restricted C to write an eBPF program? Is what the man page says still true?


回答1:


It is not really a matter of what is “allowed” in the ELF file itself. This sentence means that once compiled into eBPF instructions, your C code may produce code that would be rejected by the verifier. For example, loops in BPF programs have long been rejected in BPF programs, because there was no guaranty that they would terminate (the only workaround was to unroll them at compile time).

So you can basically use pretty much whatever you want in C and produce successfully an ELF object file. But then you want it to pass the verifier. What components will surely result in the verifier complaining? Let's have a look at the list from man page:

  • Loops: Linux version 5.3 introduces support for bounded loops, so loops now work to some extent. “Bounded loops” means loops for which the verifier has a way to tell they will eventually finish: typically, a for (i = 0; i < CONSTANT; i++) kind loop should work (assuming i is not modified in the block).

  • Global variables: There has been some work recently to support global variables, but they are processed in a specific way (as single-entry maps) and I have not really experimented with them, so I don't know how transparent this is and if you can simply have global variables defined in your program. Feel free to experiment :).

  • Variadic functions: Pretty sure this is not supported, I don't see how that would translate in eBPF at the moment.

  • Floating point numbers: Still not supported.

  • Passing structure as function arguments: Not supported, although passing pointers to structs should work I think.

If you are interested in this level of details, you should really have a look at Cilium's documentation on BPF. It is not completely up-to-date (only the very new features are missing), but much more complete and accurate than the man page. In particular, the LLVM section has a list of items that should or should not work in C programs compiled to eBPF. In addition to the aforedmentioned items, they cite:

  • (All function needing to be inlined, no function calls) -> This one is outdated, BPF has function calls.

  • No shared library calls: This is true. You cannot call functions from standard libraries, or functions defined in other BPF programs. You can only call into functions defined in the same BPF programs, or BPF helpers implemented in the kernel, or perform “tail calls”.

  • Exception: LLVM built-in functions for memset()/memcpy()/memmove()/memcmp() are available (I think they're pretty much the only functions you can call, other than BPF helpers and your other BPF functions).

  • No const string or arrays allowed (because of how they are handled in the ELF file): I think this is still valid today?

  • BPF program stack is limited to 512 bytes, so your C program must not result in an executable that attempts to use more.

Additional allowed or good-to-know items are listed. I can only encourage you to dive into it!




回答2:


Let's go over these:

  • Variadic functions, floating-point numbers and passing structures as function arguments are still not possible. As far as I know, there is no ongoing work to support these.
  • Global variables should be supported in kernels >=5.2, thanks to a recent patchset by Daniel Borkmann.
  • Loops are still unsupported, although there should be a limited support for bounded loops in kernels >=5.3. I'm using "limited" here because a small program may still be rejected if the loop is too large.

The best way to know what the last versions of Linux allow is to read the verifier's code and/or to follow the bpf mailing list (you might also want to follow the netdev mailing list as some patchsets may still land there). I've also found checking patchwork to be quite efficient as it more clearly outlines the state of each patchset.



来源:https://stackoverflow.com/questions/57688344/what-is-not-allowed-in-restricted-c-for-ebpf

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!