Conversation

GrapheneOS used to implement a local-init sanitizer for Clang to zero uninitialized variables in C and C++. In the development branch, this feature is once again globally enabled for Vanadium and the GrapheneOS kernel/userspace via Clang's new -ftrivial-auto-var-init=zero switch.
2
31
Zero initialization is hidden behind -enable-trivial-auto-var-init-zero-knowing-it-will-be-removed-from-clang. We consider it part of the stable API regardless and depend on the feature. If it's removed, it will break compatibility with GrapheneOS and we'll just fork Clang again.
2
9
The existence of this switch is due to hostility by LLVM developers towards making existing C and C++ code safer. The desire for zeroing was misrepresented as being solely about performance. They're in denial about the unsafety of real world C and C++ code including within LLVM.
2
8
Performance was the only way I saw to convince folks that zero was useful: I’m sure it yield better performance. I also agree with security concerns, with some caveats (patterns easier to detect…), but know this is contentious and folks are worried about language semantics 🤷‍♂️
2
Pattern initialization is great for debug builds. We've encountered multiple real world bugs in the Android Open Source Project and device support code where non-zero turns an inert bug into a potentially exploitable vulnerability. It's often not caught by running test suites.
2
8
I think android.googlesource.com/platform/frame is twitter.com/DanielMicay/st as one example. We've seen various cases like this where non-zero filling (compiler-based initialization, malloc junk-on-free/junk-on-init, malloc canaries) creates values that aren't safe sentinels and makes bugs worse.
Quote Tweet
Replying to @DanielMicay @stephen_r_hines and 2 others
We used to use fully random heap canaries. We encountered a scary set of bugs in the Android media frameworks where canaries would fill all of the padding from size class rounding in the allocation for a C string, and the code relied on that padding to provide the NUL terminator.
This is exploitable either way, but it's a lot easier to dump data with a C string read overflow if malloc is doing non-zero filling on free/init and/or filling padding with fully random canaries. We've seen cases with C strings where non-zero filling would make it exploitable.
1
3
Same thing applies to the stack. If the compiler is filling everything with non-zero including padding, that's potentially making C string overflows worse. There are other cases where zero is a safe sentinel. It's easy for code to accidentally depend on uninit == zero already.
2