Enhancing C++ Code Security: A Look at Two Powerful Techniques
0:00:02 Introduction: Presenters Louie and Constantine from Apple introduce their work on lib C++, the C++ standard library, and their focus on improving C++ code security.
0:00:40 The Importance of Software Security: They emphasize the financial, infrastructural, and physical threats posed by security vulnerabilities.
0:02:04 Memory Unsafety: Memory unsafety accounts for approximately 70% of high-severity security issues.
0:02:36 C++ and Memory Safety: C++ is inherently memory-unsafe, as it was not designed with this property in mind.
0:03:01 The White House Recommendation: The White House recommends using memory-safe languages for critical software, highlighting the urgency of the situation.
0:03:32 Alternatives to C++: While memory-safe alternatives exist, migration is not always feasible.
0:03:54 Can We Make C++ Better?: The presenters believe C++ can and must improve its safety and security.
0:04:38 A Moral Imperative: They argue that there's a moral imperative to improve the current situation, particularly given the prevalence of C++ in critical systems.
0:05:10 Attitude Problem: Historically, C++ has prioritized performance over ease of use, leading to an "expert-friendly" language with a philosophy that often blames the user for errors.
0:06:00 Changing Mindset: A growing awareness of security issues is driving a shift in the C++ community, with the establishment of a Safety and Security study group.
0:06:46 Challenges of Implementing Solutions: Implementing and deploying security solutions across a vast and diverse C++ ecosystem is complex.
0:07:23 Concrete Techniques: The presenters focus on two specific techniques deployed in lib C++ to enhance memory safety.
0:07:40 Five Pillars of Memory Safety: Overview of spatial memory safety, temporal memory safety, type safety, guaranteed initialization, and thread safety.
0:07:56 Spatial Memory Safety: Ensuring memory accesses are within the bounds of allocated memory.
0:08:13 Spatial Memory Safety Example: A demonstration of how an out-of-bounds access can lead to security exploits by manipulating program state.
0:10:18 Temporal Memory Safety: Ensuring memory accesses occur only during an object's lifetime.
0:10:38 Type Safety: Ensuring memory is interpreted according to its allocated type.
0:11:15 Temporal Memory Safety and Type Confusion Example: An illustration of how a use-after-free bug combined with type confusion can allow attackers to hijack program control flow.
0:12:57 Library Undefined Behavior: Introduction to the concept of undefined behavior in the C++ standard and its classification.
0:14:13 Language vs. Library Undefined Behavior: Distinction between undefined behavior caused by the compiler and that caused by the standard library.
0:14:44 Library Undefined Behavior is Easier to Check: Most instances of library undefined behavior are explicitly stated in the standard and have an upper bound.
0:15:58 Classifying Library Undefined Behavior by Severity and Triviality: A method for prioritizing which undefined behaviors to address, focusing on those that are both security-critical and easy to check.
0:18:21 Hardening in lib C++: Turning select undefined behaviors into guaranteed traps to prevent exploitation and enhance security.
0:18:56 Hardening Modes: Four modes (none, fast, extensive, debug) with varying levels of checks and performance overhead, allowing users to choose the best trade-off for their needs.
0:20:54 Hardening in Practice Example: A demonstration of how a simple program with a potential out-of-bounds access is protected by hardening, causing a trap instead of undefined behavior.
0:23:39 Hardening is Not Just for Debugging: Emphasizing that hardening is intended for production use to provide continuous security benefits.
0:24:53 Design Priorities: Balancing security and performance, prioritizing adoption, and focusing on high-impact changes.
0:26:55 Implementation Details: Grouping checks into categories based on the type of undefined behavior they address.
0:28:22 Valid Element Access Check: An example of a check that ensures container accesses are within bounds.
0:28:58 Mapping Categories to Modes: How different categories of checks are enabled in each hardening mode.
0:29:56 Enabling Hardening: Currently done via a macro, with plans for a compiler flag in the future.
0:30:33 Per-Translation Unit Hardening: Allowing different hardening modes to be used in different parts of a project.
0:30:49 Behavior on Check Failure: Production modes (fast, extensive) trigger an immediate trap, while the debug mode prints an error message and calls abort.
0:31:54 ABI Considerations: Hardening modes are orthogonal to ABI, meaning they don't require ABI changes and can be enabled independently of ABI choices.
0:33:28 Bounded Iterators: An example of an ABI configuration that can enable additional hardening checks.
0:34:31 Array Cookies: A technique for storing the size of an array allocation without an ABI break, used to implement bounds checking for unique_ptr over dynamically allocated arrays.
0:36:20 Deployment Experience: Hardening is used in major projects like WebKit and the Darwin kernel, with positive results.
0:37:36 Caveats: Hardening primarily applies to the standard library, may require code adaptation, and has a non-zero performance cost.
0:38:40 Standardization Path: A proposal (P2757) to standardize a subset of hardening features, making them a portable guarantee across implementations.
0:41:38 Typed Memory Operations: A technique to isolate allocations by type, making temporal memory safety violations harder to exploit.
0:42:45 How Typed Memory Allocation Works: Allocating objects of different types in separate memory pools to prevent type confusion exploits.
0:43:53 Implementation in the Darwin Kernel: Typed memory allocation has been successfully deployed in the Darwin kernel.
0:45:03 Proposed Standardization Path: A proposal (P279) to add a new form of operator new that takes a type descriptor, enabling user-defined typed allocation schemes.
0:52:06 Conclusion: A call for focusing on simple, high-impact changes to improve C++ security, prioritizing ease of adoption and emphasizing the importance of pragmatic technology choices.
0:57:45 Q&A: Addressing questions about real-world usage, performance impact, compatibility with older C++ standards, and potential workarounds for projects that cannot modify the standard library.