oh goody another attack vector
I'll be back to say I told you so in a couple of months/years
The Linux Plumbers Conference in Dublin ends today and some of the talks have revealed interesting new uses for the eBPF functionality. Several different teams presented tools that all use a part of the kernel originally intended to control packet filtering for new and totally different purposes. Google's ghOSt allows for …
If a driver is capable of receiving configs via ebpf, it may as well have been written in the first place to also accept parameters via ioctl(). Ebpf doesn't magically mean all drivers are now infinitely tweakable, they still have to be (re)written and the kernel recompiled.
The point made is that allowing nearly arbitrary code to run inside the kernel to tweak io devices is madness, when a far safer interface has existed forever.
as it clearly is almost, but not quite, entirely unlike the BPF.
It's literally an in kernel VM, implemented with no common syntax, and with a totally different scope of operation.
and literally nothing to do with Berkeley.
and designed and built in conjunction with Lennart Poettering, who when asked about the security implications was pretty clear he DNGAF and insisted if anything could load code into an eBPF vm it could hose the system anyway. To which someone pointed out that a rootkit could park a pretty dangerous payload there and not a single piece of security software on the planet was looking there for it. And so by building whole new class of attack vectors and not providing good visibility or guidance he had just forced a bunch of their teams to essentially invent and implement a fix for his mistakes. Because Lennart.
Guy needs a lifetime ban from the kernel, or at least a full time permanent minder with veto power.
Because the BPF could run arbitrary code to analyze network packets?
"[T]he kernel statically analyzes the programs before loading them,[sic] in order to ensure that they cannot harm the running system."
(From man bpf, commas akimbo, mayhap bugs likewise.)
We can find the detailed description of the analysis (https://docs.kernel.org/bpf/verifier.html); the kernel won't, of itself, crash or visit 1 infinite loop when it runs the code. Unlike classic BPF it apparently spots code that has unreachable instructions (i.e. it doesn't allow code which has secret extra code that can't, actually, be executed.)
This is all fine; it's just messing with packets. What I don't get is why someone would allow it to mess with scheduling (like, I've brought down machines by giving the wrong process real time priority).
It is, of course, bad enough to be able to comment on a packet. Well, here's the answer:
https://docs.kernel.org/bpf/kfuncs.html
So if you want eBBF to be able to say, encrypt a disk drive, you have to persuade Linus to take a kernel patch as well; a kernel patch that exposes the Linux internal ransomware implementation to the eBPF engine.
Not that I am saying this is good because it is in the hands of the god. I've always been against Turing, except in real animals. Exposing even one API to eBPF seems to be a certain recipe for disaster:
"When an existing function in the kernel is fit for consumption by BPF programs,[sic] it can be directly registered with the BPF subsystem. However,[sic] care must still be taken to review the context in which it will be invoked by the BPF program and whether it is safe to do so."
(From my previous reference.)
Too much rope and too many commas.
Whilst agreeing with the sentiment, in fairness I feel I must point out that, from what I've read, ebpf programs are checked to see if they trivially complete, rather than lurk indefinitely.
I do not know how long one can run for, and indeed it may not have to run for very long to be dangerous, or perhaps one can be persisted some other way (respawned). All in all its a glob of code in the most sensitive place, and it need be only ever so slightly wrong and it is a disaster. It'll take about 10 years at least of complete stability before I'd guess most people would think of it as "routinely OK".
I think the real answer why it's called BPF or eBPF is that it's a technology created by a bunch of kernel engineers with no involvement from professional tech marketing, who would have given it a better name long ago. I'm not a marketing professional, but sure, it would be better called the "Kernel Execution Environment" (KEE). Wait, it can be user space too. How about the "BPF Execution Environment" or BEE for short. We already have a bee as the mascot! And the "BPF" part is a name and not an acronym. I'm joking as what it really needs not a kernel engineer to come up with a better name. :-)
It does come from BPF, which was implemented using a VM. eBPF extended it.
What's your source about it being designed and built with Lennart? I've been involved in eBPF from the beginning (2014) and have not run into him regarding BPF at all. However, I'm sure by now (2022) he's commented on it, since it's taking over Linux and everyone has run into it by now.
Doesn't he work for Microsoft now? That, somehow, seems like pouring salt on an open wound...
So are we now on the "Extend" portion of the tour, having successfully completed "Embrace"? Perhaps Poettering is the matchstick man put in place to burn the whole thing down once it comes time to Extinguish.
This could be trouble in the making. Apparently, programs are run in a sandbox; this is only partly reassuring. From the sounds of it, the sandbox is pretty large anyway; if ebpf can start tweaking the scheduler, dump config into device drivers, mess around with networking, what isn't in the sandbox?!
One of the slightly odd things is that as part of loading up a ebpf program, it is "verified", part of which means determining whether or not the program will terminate. The slightly odd thing is that predicting running to completion was a key part of Turing's maths behind Turing engines; effectively, the only way a Turing engine can determine whether another Turing engine will run to completion is to emulate it and run it, and see if it does indeed execute to completion (except in trivial cases). It sounds like that, for the moment, the ebpf verifier is insisting on trivial cases (e.g. the docs point to bounded loops being allowed, and unbounded loops being disqualified) so as to give a strong degree of confidence. And, fair enough, that's likely pretty good.
However, we all know where this will go. Extensions will be proposed, adopted, and the verifier will at some point become more "complex". Then the Turing engine that matters won't be the ebpf one, it'll be the verifier (that will have become one in order to do the verifying) that is required to test whether the ebpf is "safe" (i.e. still runs to completion), and that will be subject to attack.
What's interesting about some of the use cases is that, really, they're solving "problems" the wrong way. One of the major issues for network throughput in Linux is that network stacks are in the kernel, not in user space (indeed, some major content distributors bypass the Linux kernel entirely to do their networking in their applications). Rather than permitting arbitrary code into the kernel where it can "do networking better", it's probably better to move the stack out to user land and do more stuff there where it's a whole lot safer (like basically every other OS on the planet does).
It also seems to assume that ebpf loaded up by root is going to be safer that ebpf loaded up by a user. I'm not convinced by that. There's nothing about the root user that means that their ebpf is "safe".
"USB-HID is a very old standard, dating back to Windows 95..."
I mean, it's not entirely incorrect, but it also feels very lazy.
14-07-1995 - Windows 95 released
30-01-1996 - v1.0 of the USB HID was released
27-08-1997 - Windows 95 v4.03.1212 released (gained USB support).
31-12-2001 - Windows 95 extended support ended.
It's only a 6.5 year period I guess, but still.
Also, making references to MS OS' within the article (there's more than just this one) doesn't make it feel balanced, more like the writer leans a certain way.
this thing runs with a (small) register set and instruction set.
And of course once you a Turing complete processor....
There have been some work on "language security" and it's pretty amazing what you can coopt into running a program once you find something is Turning complete.
Unfortunately :-(