4 ms·
eBPF isn't safe to load without root privilege. This means no containers and no users process. From what I saw so far, there is fear that letting Turing complet
by Elv13 7y ago
eBPF isn't safe to load without root privilege. This means no containers and no users process. From what I saw so far, there is fear that letting Turing complete programs in the kernel would make some future CPU/hardware vulnerabilities more dangerous. While the compiler makes sure the program return, it cannot make sure it isn't nefarious.
ref: https://lwn.net/Articles/808048/ https://lwn.net/Articles/808048/
- loeg 7y agoOne can easily imagine a restricted subset of eBPF that is not turing complete and could be safe for unprivileged users to use.
- amscanne 7y agoThat’s what BPF is already. It’s not Turing complete. Unbounded loops and backward branching is not allowed. The problem isn’t Turing completeness. It’s that there’s are too many micro-architectural side channels and unknowns.
- monocasa 7y agoThey currently go out of their way to remove microarchitectural side channels. Yes, there's almost certainly others, but it's pretty clear that the end goal is to allow non root creation of bpf programs.
- nickodell 7y agoIs it really possible to remove the side channels? Even if you formally prove that it does not access memory outside of authorized regions, that doesn't prevent it from speculatively accessing unauthorized memory. We've seen Spectre exploits through sandboxed Javascript. Unless you separated the eBPF VM address space from the kernel address space, I suspect you would have the exact same problems that browsers have had. But if you did put them in separate address spaces, then why bother with eBPF? You could run a normal userspace program.
- monocasa 7y agoeBPF right now issues fence instructions before computed address loads, in order to manually shutdown speculative instructions. They also do a cute trick to compute the address with a mask so that if a speculative access does happen, the speculatively computed offset is still in the valid range.
- nickodell 7y agoThat's a very good point, and thank you for correcting me.
- deleted 7y ago[deleted]
- geofft 7y agoeBPF isn't fundamentally unsafe (and, in particular, it's not Turing-complete, precisely because it's guaranteed that all eBPF programs terminate). It's just very ambitious and it exposes too much attack surface for people to feel comfortable making it available to unprivileged users. However, we do have a similar system exposed to unprivileged users - classic BPF. You could imagine writing classic BPF programs to chain multiple system calls with just one context switch.
- Elv13 7y ago> it's not Turing-complete On their own, but there is more than 1 way to insert BPF programs. If there is a key learning from ROP style exploits, is that you can assemble surprising constructs out of thin air. Linux 5.6 adds way for eBPF programs to write vtables. That one alone is an exploit waiting to happen. You just have to connect the calls just right and poof, eBPF programs calling each other: Turing completeness achieved.
- monocasa 7y ago> On their own, but there is more than 1 way to insert BPF programs. And the recursion, even tail recursion, in BPF is limited for that very reason. All eBPF programs have a statically verifiable worst case execution time.
- Elv13 7y agoMy point is that this limitation can be bypassed if you are smart enough. The Linux kernel is more complex than any single BPF program, it has side effects. For example, let say that I am an attacker who which to execute a loop to brute force a key using a new side channel from kernel space. eBPF programs are now available to userspace with "insert new shiny here". I add one as a performance tracepoint, then one in the packet filter, then one modifying a vtable somewhere. Now, I manage to make them oscillate and call each other while never leaving kernel space. I now "deadlock" the kernel with my small BPF programs until I manage to extract what I am after, then let the "deadlock" go away. It take only 1 bug to make this happen. Each BFP program individually return, but only to be called again. If you let users put these in the kernel, this will happen eventually. This kind of tricks has been used over and over with other technologies.