I honestly would've expected it to be more than that.
> runtime code generation
The proposal sounds like an excellent operating system for attackers. I'd rather use a slow and boring system with high syscall overhead in exchange for full W^X in kernel code.
@niconiconi @akkartik Linux already implements dynamic code generation (BPF filters). It also supports loadable modules, which requires the kernel code to copy data from disk buffers (data space) into executable space. Dynamic code generation from a Turing-incomplete source description (e.g., implementing the precise semantics of open()) does not increase the attack surface any more than kernel modules do.
@niconiconi @akkartik That said, after reading the article, the whole thing is an outstanding and shining example for image-based VMs, such as that found on OS/400 or Smalltalk. The whole kernel and its associated runtime can be privilege DE-escalated if the backing VM is the only trusted code base in the system.
Looks like Dr. Kay and IBM were right. Again.
> implements dynamic code generation (BPF filters).
Yes. But I can/have disabled BPF and BPF-JIT unconditionally on all my boxes, and practically almost no applications is affected, except for decreased performance for low-level network things. I recommend everyone to do it if they don't need it.
> It also supports loadable modules
Yes, But this can be disabled as well with minimum functionality loss. I did it on my server. Also, digital signature can be enforced for kernel modules.
> from a Turing-incomplete source description does not increase the attack surface
This is interesting, have never thought about it, so it's not as dangerous as it seems.
BTW, I believe BPF is Turing-complete, is it?
I don't mind dynamic code generation, but it really bothers me when it's drawn from a Turing-complete source. As long as it's not Turing complete, you can statically prove useful properties of the generated code (see, e.g., how MIT's exokernel project implements disk management using dynamically synthesized code safely). As soon as Turing completeness is realized, all those guarantees go out the window.
@neko @akkartik @niconiconi There is no way for the semantics of open() to crash the kernel or violate another process' memory space. That is guaranteed behavior. The code generated from it, which implements a file-descriptor-specific implementation of read()/write()/seek()/close()/..etc. unique to the filesystem resource you specify in the call to open(), can be completely statically proven never to fail or violate security guarantees. It can do this because it's not Turing complete.
@neko @akkartik @niconiconi Another example is bit-blit operations, prior to the widespread use of GPUs. Frequently, these would be synthesized into code which consists of several tight inner loops. Nonetheless, because the semantics of the blit is finite, you can statically compute both how many instructions will execute to complete the function, and because of that, which memory locations will be touched. In other words, the halting problem is solved for non-TC programs.
@neko @akkartik @niconiconi As long as the *generator* was also trusted, yes. If you don't trust the generator, then a valid and correct wildcard spec can potentially cause the wrong code to be compiled.
The reason why non-TC is important is because proving non-TC semantics is much easier than proving TC semantics. (Interestingly, proving that a language is non-TC turns out to be pretty hard, though. See http://beza1e1.tuxen.de/articles/accidentally_turing_complete.html )
@vertigo @neko @akkartik The dynamic code generation in bitblit is an absolute classic. If it's unfamiliar to you, there is an complete description in Chapter 8, page 128 of the book Beautiful Code: Leading Programmers Explain How They Think. You can grab a copy from LibGen. http://booksdescr.org/item/index.php?md5=5F5EB341ED17C6C9CB3D12B9EFADC132
@niconiconi @cstanhope @akkartik This is interesting; this is a class of attack I wasn't aware of. After reading up on it, it appears that this exploits a buggy JIT compiler, not a bug in the language it compiles.
When I google'd for BFP, eBFP, and JIT spraying, though, nothing comes up. Do you have specific links I can read more on?
BPF-JIT also enables the easiest Spectre exploits: https://googleprojectzero.blogspot.com/2018/01/reading-privileged-memory-with-side.html
Also, if the JIT compiler is buggy...
Privilege escalation via eBPF in Linux 4.9 and beyond: https://lwn.net/Articles/742170/
Server run by the main developers of the project It is not focused on any particular niche interest - everyone is welcome as long as you follow our code of conduct!