Introducing Spanification

361 views
Skip to first unread message

danakj

unread,
Jun 28, 2024, 2:31:24 PMJun 28
to chromium-dev, Tom Sepez

Dear Chromiumies,


As we know, out-of-bounds errors are a top source of security bugs in Chrome. Generally speaking, each time we deconstruct a container into a pointer or an iterator, we create opportunities for security vulnerabilities to creep into the product when exposed to hostile input. We want to make these harder to write and harder to exploit, in the same way that MiraclePtr and DanglingPointerDetector have done for use-after-free bugs.


The security team has been busy building and beta-testing better bounds-safety in Chrome’s C++ code during H1 2024. Since the wrinkles have been ironed out, it is time to share the techniques we are using.


The larger goal is to enable the compiler to deduce size information wherever possible without the need for any developer intervention. We do this by replacing pointers and iterators with containers and view types that know the size of the buffer to which they point. A lot of our code already does this, as std::vector (for example) knows its bounds and checks that the program stays within them. One part of this is Spanification, which focuses on code that works with array pointers, and converts each of these pointers into base::span, std::vector, and base::HeapArray.


There is a new compiler warning -Wunsafe-buffer-usage which we have enabled globally in Chromium, but then opted-out the majority of the codebase. The warning fires when doing any sort of pointer operation that ought to be replaced by using a container (such as pointer arithmetic). Our task is to remove paths from the opt-out list and fix the resulting warnings. As we do so, we eliminate opportunities for out-of-bounds security bugs in our code.


We have documentation in //docs/unsafe_buffers.md that describe the ecosystem of types and functions for working with spans and common recipes for converting from pointers to containers.


Rangification of C++


C++ is moving progressively towards “ranges” in C++20 and C++23 (and beyond), and base::span is part of that same direction. What this means for us writing C++ code:

  • Working with containers and view types that know their start and end, instead of working with pointers or iterator pairs explicitly.

  • Using range-based for loops instead of indexes.

  • Using functions that work with a range instead of pointers or iterators, such as the std::ranges algorithms, and we have more functions to help, like base::ToVector, base::Extend, and span::copy_from.


Applying containers and spans to the codebase must be done incrementally. And there exist many C APIs (looking at you, third-party code) which can not be converted to containers. So it is possible to construct a span from a pointer and size, instead of from a container, for these cases. This can be used for incrementally rolling out the use of base::span to an area of code in order to prevent a single change from becoming too viral. Such constructor calls need to be enclosed in an UNSAFE_BUFFERS() macro, which is described in much detail in its comment, and is meant to be scary and rare, outside of temporary usage during incremental spanification.


Base layer


The security team has been driving the spanification of APIs in //base and //net, and then changing callers to those APIs across the codebase. This may have caused you to already bump into spans in your daily work. Our goal is that new code is able to work with spans without friction when using these core API layers. And we’re continuing this effort.


There are also explorations under way to see how much of our C++ code we can mechanically spanify.

Joining the Spanification


If you’re interested in better bounds safety in your area of the codebase, turn on the warning there, file a bug for writing TODOs against, and suppress any existing issues with the #pragma. Then start working through the warnings file by file by removing the #pragma. When you’re unsure how to approach a piece of code with spans, hit up the docs, or reach out by email or on Slack.


Happy spanning,

danakj@ and tsepez@ for the Spanification Crew

Reply all
Reply to author
Forward
0 new messages