Comment by SideburnsOfDoom
5 years ago
This is modelled on "Reflections on Trusting Trust" by Ken Thompson, 1984
https://www.cs.cmu.edu/~rdriley/487/papers/Thompson_1984_Ref...
5 years ago
This is modelled on "Reflections on Trusting Trust" by Ken Thompson, 1984
https://www.cs.cmu.edu/~rdriley/487/papers/Thompson_1984_Ref...
That's what I was thinking while reading this article, +1!
In short, the premise of the talk is: if you add a self replicating change to any self-hosted compiler:
- You can 'teach' the compiler to do things that are never explicitly stated in their source code, like, in this article, making the compiler modify programs that meet specific predicates.
- You can not trust that your compiler hasn't been modified without bootstrapping it yourself. You can't trust a program without trusting its compiler; and since compilers are programs, well it's turtles all the way down.
To build a trusted compiler, you have to bootstrap one yourself from some trusted manner, usually from hand-written assembly. In C, this would be akin to writing a small C compiler in assembly, using that to compile tcc, using that to compile a slightly larger C compiler, and that to compile clang or gcc.
But in other more complex languages, such as Rust, bootstrapping is not as clear cut. There's the Reproducible Builds project, but afaict there exists no minimal small Rust compiler you can bootstrap the latest one from: You have to go back the the original OCaml one and compile up from there, or just trust that the publicly available build is secure (which it most likely is).
I guess the lesson is that it's possible to inject hidden self-replicating behavior into any significantly complex system.
You can use mrustc to not have to go back to the original OCaml.
Hmm, that's an interesting project! You'd still have to bootstrap a cpp compiler first, though
1 reply →
An assembler can also do this same attack. You have to hand-assemble your basic assembler to machine code. In theory a sophisticated-enough hex editor could also be subverted, silently adding in code when it's used to edit executable-looking files. The system dynamic linker can be compromised to subvert any executable. Etc.
If a machine is compromised, it can't be recovered without access to a known-good machine.
https://github.com/certik/bcompiler/ is an effort to do this very bootstrapping.
I get the theory here, but never having written a compiler myself, I’m curious how easy/difficult it would be to come up with those predicates in practice?
See 'Reflections on Rusting Trust' by Manish Goregaokar (In Pursuit of Laziness).
https://manishearth.github.io/blog/2016/12/02/reflections-on...
He modifies rustc with a predicate that replaces the string 'hello world' with something else. The method used to replicate the change is basically a self-modifying quine.
Coincidentally, Computerphile just posted this today:
https://www.youtube.com/watch?v=SJ7lOus1FzQ