Hi Kostya, I’m also curious to know where Nuno is going with this, and the
details of his design. I’m worried he might be reinventing the wheel. I’m
also worried that he may be inventing a square wheel 
I believe Nuno’s goal is to prevent run-time exploitation of software.
If that’s the goal, the solution is likely to be wrong.
The proposed bounds-checking will cover a tiny portion of buffer overflows and will not cover use-after-free or stack corruption at all.
While I agree that you’re probably correct about the bounds checking covering a tiny portion of buffer overflows, I don’t think we really know that for certain. An experiment to find the percentage of pointer arithmetic operations that can be checked in this way would be interesting.
If the documentation will say something like “it prevents run-time exploitation”, users may get a false sense of safety which will make matter worse.
I agree that any future documentation on any added security attack mitigation features should be clear on which attacks are prevented and which are not.
Having a security solution that prevents some attacks but not others is okay. Defeating all memory safety attacks with acceptable performance is still an open research question. What I think is important is knowing which attacks a technique defeats and at what cost; you essentially want to know what you’re buying and for how much.
My concern with Nuno’s approach is that it is not clear which exploits it will prevent and which it will not. Alternatively, if we implemented CFI, we know exactly which types of attacks are prevented and which are not (and, I think, we’d mitigate a large number of attacks). I also suspect that the overhead of CFI may actually be lower than Nuno’s proposed solution, although we’ll need some experiments to be sure.
Note that asan does not claim to “prevent run-time exploitation”, because in general case it does not.
If we want full prevention, we need to use another kind of sandbox (e.g. Native Client).
Actually, Native Client is a sandboxing technique: it ensures that a plugin does not accidentally or intentionally read or write data from a program’s “core” (the “thing” that the plugin plugs into). Native Client doesn’t prevent attackers from taking over and controlling the behavior of the plugin, and it doesn’t prevent direct attacks on the core. Some of the techniques used in Native Client (and PNaCL in particular) could be of interest, though.
There are some memory safety techniques (or combinations of techniques) that could provide what I guess you would call full memory safety. However, they all either rely upon garbage collection (which is conservative for C) or dangling pointer detection (which is too expensive at run-time) (2).
I think the next best thing is SAFECode with its automatic pool allocation technique(1). With automatic pool allocation, SAFECode can optimize away type-safe loads and stores while ensuring that danging pointer dereferences through type-safe pointers do not violate the memory safety guarantees. It even gets you sound points-to analysis results, which I don’t think any other technique (except those I listed above) gives you.
The challenge is that the automatic pool allocation transform and its prerequisite points-to analysis and type-inference analysis are relatively sophisticated pieces of code. While I think the benefit is great, the required investment to make these pieces of code robust is not insignificant.
While I’d like LLVM to someday have a very strong memory safety attack mitigation feature, I also think that having a simpler mitigation technique that is fast and easier to implement is also valuable (as long as it’s effective). CFI appears to be a good candidate for these reasons.
– John T.
(1) (2) One of these solutions is SoftBound + CETS which has been built into the SAFECode Clang compiler.