Can I just say that putting a JIT into a kernel is a really bad idea? That putting /any/ executable code in a trusted environment that isn't utterly static, cryptographically signed, and well armored, is just going to end badly, over and over again?
We have enough trouble with user-space code generation, and with return-oriented-programming. Actual code generation at the driver level seems utterly wrong.
That's the interesting thing about a post like this; it starts to form an argument about a principle like "no dynamic native code generation in the kernel", which clearly isn't an accepted principle today.
I'm not sure what I think about that principle, because native code generation is exotic today, but probably won't be 10 years from now.
But either way: your statement is exactly the point the post is trying to make. It's not "Linux is insecure", or "SMEP is worthless". It's "how does native code generation interact with the roadmap of security features OS developers and hardware manufacturers are planning"? Also, of course, it's "JIT spraying is cool and fun to implement, and here's a new place to try it."
Actual code generation at the driver level seems utterly wrong.
"Utterly wrong" is a pretty black-and-white judgement. A JIT in the kernel has costs and benefits. You could as easily say that the ability to load modules dynamically into the kernel is "utterly wrong," since it opens up a code-injection vector that makes rootkits and other malware much easier to write. In some ways dynamically-loadable modules could be seen as even more risky than a JIT, because a JIT can only generate a subset of all possible machine code. It would be pretty hard to write a rootkit as a Berkeley Packet Filter program.
However, it wouldn't be impossible. I am quite sure (although I don't have a proof) that the BPF bytecode can be made turing complete, so an arbitrary program (maybe a rootkit, much more likely patches to a few kernel structures) could be implemented in it. Examples of things that are very unintendedly turing complete include HTML5 without JS(the clicky rule 110), ELF relocations (you can write a program to be interpreted by the loader in a few symbols and relocations without changing code, see elf-bf-tools on GitHub) and the Intel interrupt handling mechanism(unreleased, see talk at 29c3).
elf-bf-tools is an impressive hack, thanks for the link! To add to your list, you might want to mention that simply parsing C++ is turing-complete; see http://yosefk.com/c++fqa/web-vs-c++.html#misfeature-3 . The short of it is that you have to perform full template instantiation in some cases just to parse code that uses those templates!
As to your point about /dev/kmem, to me that is just another argument against the idea of banning JITs from the kernel. There are already lots of vectors for getting attack payloads into the kernel; the JIT angle only helps an attack if you somehow can make the kernel jump to a specified address but don't have root.