ERASAN: Efficient Rust Address Sanitizer
Jiun Min, Dongyeon Yu, Seongyun Jeong, Dokyung Song, Yuseok Jeon
IEEE Symposium on Security and Privacy 2024 · Day 3 · Continental Ballroom 4
Overview
Rust has rapidly gained traction in systems programming due to its powerful memory safety guarantees, enforced through mechanisms like ownership, borrow checking, lifetime inference, and bound checking. These features are designed to prevent common memory-related vulnerabilities that plague languages like C and C++. However, Rust provides an escape hatch: unsafe blocks. These blocks allow developers to perform low-level operations that bypass Rust's strict safety rules, which are sometimes necessary for specific functionalities or performance optimizations. Unfortunately, this flexibility comes at a cost, as unsafe Rust is susceptible to the very memory bugs that Rust aims to eliminate. The Rust security database has reported 581 memory bugs in Rust programs over the past seven years, highlighting a critical gap in its otherwise robust security posture.

Key moments
- 0:50 Unsafe Rust: A source of memory bugs
- 2:50 Existing ASan's substantial overhead on Rust
- 3:30 Redundant ASan checks on Rust's safe code
- 4:50 Low pointers and aliases are root causes of Rust bugs
- 6:15 ERASAN: An efficient Rust Address Sanitizer overview
- 7:30 Preserving low pointer information from MIR to LLVM IR
- 8:45 Identifying alias pointers via backward points-to analysis
- 9:40 Refining unsafe access sites based on bug types
ERASAN: Efficient Rust Address Sanitizer
Speakers: Jiun Min, Researcher, UNIST; Dongyeon Yu; Seongyun Jeong; Dokyung Song; Yuseok Jeon, Advisor, UNIST
Conference: IEEE S&P
YouTube: https://www.youtube.com/watch?v=r_a5zJg5jeE
Overview
Rust has rapidly gained traction in systems programming due to its powerful memory safety guarantees, enforced through mechanisms like ownership, borrow checking, lifetime inference, and bound checking. These features are designed to prevent common memory-related vulnerabilities that plague languages like C and C++. However, Rust provides an escape hatch: unsafe blocks. These blocks allow developers to perform low-level operations that bypass Rust's strict safety rules, which are sometimes necessary for specific functionalities or performance optimizations. Unfortunately, this flexibility comes at a cost, as unsafe Rust is susceptible to the very memory bugs that Rust aims to eliminate. The Rust security database has reported 581 memory bugs in Rust programs over the past seven years, highlighting a critical gap in its otherwise robust security posture.
To address these vulnerabilities, security tools like Address Sanitizer (ASan) are commonly employed. While ASan is highly effective in detecting memory errors in C/C++ programs, its direct application to Rust programs introduces significant runtime overhead. This inefficiency stems from ASan's indiscriminate instrumentation of all memory accesses, even those already protected by Rust's compiler-enforced safety rules. The talk "ERASAN: Efficient Rust Address Sanitizer," presented by Jiun Min from UNIST, details a novel approach to adapt ASan for Rust, making it dramatically more efficient without sacrificing its detection capabilities.
ERASAN, developed by Jiun Min, Dongyeon Yu, Seongyun Jeong, Dokyung Song, and Yuseok Jeon in collaboration with Yonsei University, re-engineers ASan to specifically target the memory unsafe parts of Rust code. By leveraging Rust's unique compiler internals and understanding the root causes of memory bugs in unsafe contexts, ERASAN achieves substantial performance improvements and a significant reduction in redundant checks. This work is crucial for maintaining the memory safety promise of Rust in projects that inevitably rely on unsafe operations, providing a practical tool for developers and security engineers to harden their Rust applications against critical vulnerabilities.
Background
▶ Watch: Unsafe Rust: A source of memory bugs (0:50)
Rust's reputation for memory safety is built upon a sophisticated type system and a set of compiler-enforced rules. The ownership system dictates how memory is managed, ensuring that each piece of data has a clear owner. Borrow checking prevents data races by enforcing rules around shared and mutable access to data. Lifetime inference tracks the validity of references, preventing use-after-free errors. Finally, bound checking ensures that array and slice accesses remain within their allocated memory regions, averting buffer overflows. These mechanisms collectively eliminate a vast category of memory bugs prevalent in other low-level languages.
Despite these strong guarantees, certain advanced programming patterns or interactions with low-level hardware require direct memory manipulation that bypasses Rust's strict checks. For instance, implementing complex data structures like a truly double-linked list or interfacing with foreign function interfaces (FFI) often necessitates the use of unsafe Rust. Within an unsafe block, developers can perform operations like dereferencing raw pointers, calling unsafe functions, or accessing static mut variables, effectively opting out of Rust's compile-time safety guarantees. This is where memory bugs can creep back into Rust programs. As noted in the talk, the Rust security database has documented 581 memory bugs in Rust programs over the past seven years, indicating that the unsafe portions of Rust code are indeed a significant attack surface.
To detect these post-compilation memory errors, Address Sanitizer (ASan) is a widely adopted dynamic analysis tool. ASan works by instrumenting program binaries with checks for common memory errors such as buffer overflows, use-after-free, and double-free. It achieves this by inserting red zones around memory allocations and maintaining a shadow memory that tracks the validity of each byte in the program's address space. During execution, every memory access is checked against this shadow memory to ensure it's valid. While highly effective, ASan was originally designed for C and C++, languages where memory safety is not a compiler-guaranteed feature. When applied directly to Rust, ASan instruments all memory access sites, including those already rigorously checked by the Rust compiler's safety rules. This results in redundant checks and substantial runtime overhead, making its adoption impractical for many performance-sensitive Rust applications. The core problem is that "ASan cannot identify which memory accesses are protected by R safety rules," leading to a double-checking of memory-safe code. This inefficiency presented a clear opportunity for optimization: selectively applying ASan to only the truly unsafe parts of Rust programs.
Key Findings
▶ Watch: Redundant ASan checks on Rust's safe code (3:30)
The ERASAN project began with a critical investigation into the nature of memory bugs found in Rust programs. The researchers meticulously analyzed 131 reproducible memory bugs reported over the past seven years from the total of 581. These analyzed bugs encompassed common categories such as buffer overflows, use-after-free, and double-free errors. The findings from this in-depth analysis were pivotal in shaping ERASAN's design.
The most significant discovery was that all identified memory bugs were directly related to incorrect memory access through a raw pointer (referred to as "low pointer" in the talk) or its aliases. A raw pointer in Rust is a fundamental type that can point to any memory location without the strict safety rules applied to references. Unlike Rust references, raw pointers are not subject to ownership, borrow checking, or lifetime rules, making them powerful but inherently dangerous if misused.
Based on this comprehensive analysis, the researchers identified two primary root causes for memory bugs in Rust programs:
- Temporal and Spatial Memory Safety Violations by Raw Pointers: Raw pointers, by their nature, can bypass Rust's built-in bound checks and lifetime rules. This allows them to access memory outside allocated buffers (spatial violations) or access memory after it has been freed (temporal violations).
- Temporal Memory Safety Violations Triggered by Pointers Aliased with Raw Pointers: Even if a pointer itself is a "safe" Rust reference, if it becomes an alias to a raw pointer, it can indirectly participate in temporal memory safety violations. This occurs because the raw pointer can free the underlying memory, leaving the aliased safe pointer pointing to invalid memory, which can then be used after free.
These findings led to a crucial insight: instead of instrumenting all memory accesses, as traditional ASan does, performance overhead could be significantly reduced by focusing instrumentation only on memory accesses made through raw pointers and their aliases. The researchers also observed that the proportion of Rust source code involving raw pointers and their aliases is substantially smaller compared to the entire unsafe Rust code base. This indicated that a targeted approach focusing on raw pointers would yield much lower overhead than even an unsafe block-based dynamic detection strategy. These two key findings form the bedrock of ERASAN's design, enabling it to fully leverage Rust's security guarantees and memory bug patterns for efficient and effective sanitization.
Technical Deep Dive
▶ Watch: ERASAN: An efficient Rust Address Sanitizer overview (6:15)
ERASAN's architecture is built upon three interconnected modules that work in concert to identify and selectively instrument memory unsafe code in Rust programs. This modular design allows ERASAN to precisely target vulnerabilities without incurring the overhead of traditional ASan.
1. Raw Pointer Identification and Annotation
The first challenge in building ERASAN was accurately identifying raw pointers. In the standard Rust compilation pipeline, raw pointer information, which is unique to Rust's Mid-level Intermediate Representation (MIR), is lost when translated to the LLVM Intermediate Representation (LLVM IR). At the LLVM IR level, raw pointers are transformed into generic pointers, indistinguishable from pointers derived from safe references (which are governed by Rust's safety rules). This makes it impossible for LLVM-level static analysis to differentiate between safe and unsafe pointer origins.
To overcome this, ERASAN modifies the Rust compiler to operate at the MIR level. MIR is a high-level, structured intermediate representation that still retains Rust-specific semantic information, including the explicit notion of raw pointers. ERASAN identifies all raw pointers at this stage. Once identified, this critical raw pointer information is then annotated as metadata onto the corresponding LLVM instructions. This annotation allows ERASAN to preserve the distinct identity of raw pointers throughout the compilation process, making it accessible for subsequent static analysis phases at the LLVM IR level. This step is fundamental, as it provides the necessary foundation for ERASAN to precisely track the propagation of raw pointer influence.
2. Unsafe Memory Access Site Identification and Optimization
With raw pointer information preserved, the next module focuses on identifying all memory access sites that are potentially unsafe due to their relationship with raw pointers. This process involves two main stages: identifying all aliases and then optimizing the set of identified sites based on the type of memory bug.
Alias Identification via Points-to Analysis
ERASAN employs points-to analysis at the LLVM IR level to discover all pointers that have an alias relationship with raw pointers. The process begins by identifying the initial declaration sites of raw pointers. From these sites, a backward points-to analysis is conducted. This analysis traces back through the program's data flow to determine all possible memory allocation sites that could be pointed to by the initial raw pointers. Once these allocation sites are identified, ERASAN then tracks all subsequent memory access sites (reads and writes) that operate on these allocated regions or through pointers derived from them. All such memory access sites are provisionally marked as "unsafe memory access sites," as they might be influenced by raw pointers and thus potentially trigger memory bugs. This conservative approach ensures that no potentially vulnerable access is missed.
Optimization Based on Memory Bug Types
The initial alias identification step is conservative, meaning it might mark some accesses as unsafe even if they are ultimately protected by other Rust mechanisms. To further refine the set of truly unsafe sites and reduce redundant checks, ERASAN introduces optimizations that differentiate between spatial and temporal memory bugs.
- Spatial Memory Bugs (e.g., Buffer Overflow): Rust's compiler typically prevents buffer overflows for safe pointers (references) through robust bound checking. Therefore, memory access sites involving safe references generally do not require additional ASan checks for spatial safety. However, raw pointers are capable of bypassing these bound checks entirely, allowing them to access memory outside their designated bounds. Consequently, for spatial memory safety violations, ERASAN needs to consider only memory accesses made directly through raw pointers. It does not instrument accesses through aliased safe pointers for spatial checks, as those are already covered by Rust's native bound checks.
- Temporal Memory Bugs (e.g., Use-after-Free, Double-Free): Temporal memory bugs are more complex because they can be triggered by both raw pointers and their aliases. Rust's lifetime safety rules are designed to prevent use-after-free, but these rules do not apply to raw pointers or their aliases. When a raw pointer frees memory, any aliased safe pointer can become dangling, leading to a temporal violation if dereferenced later. A key insight here is that temporal memory violations can only occur after the memory has been freed. This allows for significant optimization: ERASAN can avoid instrumenting memory accesses that occur before the memory is freed. The optimization strategy varies based on memory type:
- Heap Objects: For memory allocated on the heap, the Rust compiler automatically inserts a
dropfunction, which is responsible for deallocating the object's resources. Temporal memory bugs related to heap objects can only occur after thisdropfunction has executed. Therefore, ERASAN only instruments memory access sites that occur after thedropfunction call for aliased pointers. Accesses beforedropare considered safe from temporal violations in this context. - Stack Objects: Similarly, for memory allocated on the stack, temporal memory bugs can only occur after the stack frame has been cleaned up and the memory is no longer valid. ERASAN applies similar logic, ensuring instrumentation for stack-allocated objects only after their scope has ended and the memory is effectively "freed."
3. Selective Instrumentation
The final module of ERASAN leverages the precisely identified and optimized list of unsafe memory access sites. Instead of instrumenting every memory operation, ERASAN selectively injects ASan checks only into those specific LLVM IR instructions that have been determined to be potentially vulnerable through raw pointers or their aliases. This highly targeted approach ensures that ASan's powerful detection capabilities are maintained for the critical unsafe portions of Rust code, while drastically reducing the overall instrumentation overhead. By doing so, ERASAN successfully integrates Rust's compiler-based security guarantees with ASan's dynamic detection, achieving a balance between safety and performance.
Demo / Proof of Concept
▶ Watch: Preserving low pointer information from MIR to LLVM IR (7:30)
While the talk did not feature a live, interactive demo of ERASAN in action, the researchers provided comprehensive evaluation results that serve as a robust proof of concept for its effectiveness and efficiency. This evaluation involved a rigorous comparison against several baselines using 23 benchmark tests and 28 reproducible CVEs.
The evaluation measured ERASAN's performance across five key aspects:
- Reduction in Static Checks: ERASAN was shown to remove approximately 90% of the unnecessary ASan checks compared to the unmodified ASan. This significant reduction is attributed to ERASAN's ability to precisely identify and avoid instrumenting memory accesses unrelated to raw pointers or their aliases, which are already protected by Rust's safety rules.
- Runtime Overhead: ERASAN demonstrated a remarkable performance improvement, reducing runtime overhead by approximately 240% compared to the original ASan. This substantial gain highlights the efficiency of ERASAN's focused approach, which prioritizes memory accesses involving raw pointers and their aliases. The evaluation also showed ERASAN outperforming an
unsafeblock-based approach and benefiting from its specific optimizations fordropaccess on object types. - Detection Capabilities: Crucially, ERASAN maintained full detection capabilities, successfully identifying all 28 reproducible CVEs that the original ASan could detect. This confirms that ERASAN's optimizations do not compromise its ability to find real-world memory safety vulnerabilities.
- Comparison with State-of-the-Art: ERASAN was compared against
ASan--, a known state-of-the-art technique for reducing ASan overhead. ERASAN proved to be more efficient, removing 56.8% of checks thatASan--could not, by leveraging its deeper understanding of the Rust environment and more precise identification of redundant checks.
These results unequivocally demonstrate that ERASAN is an efficient and effective solution for sanitizing Rust programs, achieving significant performance gains without sacrificing its ability to detect critical memory bugs.
Defensive Implications
▶ Watch: Refining unsafe access sites based on bug types (9:40)
The ERASAN project offers profound defensive implications for Rust developers, security engineers, and organizations building systems with Rust, particularly those that utilize unsafe blocks.
First and foremost, ERASAN serves as a critical reminder that while Rust provides strong memory safety guarantees by default, these guarantees do not extend into unsafe code. The presence of 581 reported memory bugs underscores the fact that unsafe Rust is a potential source of vulnerabilities, akin to memory errors in C/C++. Developers should approach unsafe blocks with extreme caution and treat them as security-critical components requiring rigorous testing and scrutiny.
For projects that necessitate the use of unsafe Rust, integrating ERASAN into the development and testing pipeline becomes a highly recommended practice. By leveraging ERASAN, teams can dynamically detect memory bugs in their unsafe code with significantly lower performance overhead than traditional ASan. This makes it feasible to run ASan-like checks in continuous integration (CI/CD) environments, during development, or even in certain staging environments, without prohibitive performance penalties. Such integration can catch critical vulnerabilities before they reach production, enhancing the overall security posture of Rust applications.
The specific findings of ERASAN also provide actionable insights for code review and development practices. The discovery that all memory bugs stem from raw pointers and their aliases highlights these constructs as primary targets for security review. Developers should:
- Minimize Raw Pointer Usage: Strive to use safe Rust constructs wherever possible. If raw pointers are indispensable, encapsulate them within safe abstractions (e.g.,
Arc,Box,Vec) to limit the scope ofunsafeoperations. - Scrutinize Raw Pointer Operations: During code reviews, pay extra attention to the creation, dereferencing, and manipulation of raw pointers. Verify that their usage aligns with the intended memory safety invariants.
- Understand Aliasing Risks: Be acutely aware of how raw pointers can alias with other pointers, even "safe" Rust references. The temporal bug analysis in ERASAN emphasizes that even safe references can become dangerous if they point to memory freed by an aliased raw pointer. Ensure that memory management (allocation and deallocation) involving raw pointers is meticulously handled to prevent use-after-free scenarios for any aliased pointers.
- Consider Memory Types: The optimizations based on heap vs. stack objects and the timing of
dropfunctions provide a mental model for where temporal vulnerabilities are most likely to occur. Developers can use this to focus their testing and reasoning about memory safety around object lifetimes and deallocation points.
Ultimately, ERASAN empowers defenders by providing a practical tool to bridge the security gap introduced by unsafe Rust. It ensures that the robust memory safety promise of Rust can be extended to its low-level components, fostering greater confidence in the security of Rust-based systems across critical infrastructure and applications.
Key Takeaways
- Rust's
unsafeblocks, while necessary for low-level operations, bypass its strict memory safety rules and introduce memory vulnerabilities, with 581 bugs reported over 7 years. - Traditional Address Sanitizer (ASan) is inefficient for Rust programs, performing redundant checks on memory accesses already protected by Rust's compiler, leading to substantial runtime overhead.
- ERASAN identifies that virtually all Rust memory bugs (buffer overflow, use-after-free, double-free) are caused by raw pointers and their aliases, which circumvent Rust's safety guarantees.
- ERASAN leverages Rust's Mid-level IR (MIR) to precisely track raw pointer information and employs points-to analysis to identify all potentially unsafe memory access sites.
- Through optimizations distinguishing between spatial and temporal memory bugs, and considering object lifetimes (e.g.,
dropfunctions for heap objects), ERASAN drastically reduces unnecessary ASan checks. - ERASAN achieves a 90% reduction in unnecessary ASan checks and a 240% performance improvement over standard ASan, while retaining full detection capabilities for all 28 reproducible CVEs.
About the Speaker(s)
The research presented in "ERASAN: Efficient Rust Address Sanitizer" was a collaborative effort. The primary presenter was Jiun Min, a researcher from UNIST (Ulsan National Institute of Science and Technology). Jiun Min was an equal contributor to this work. The project was advised by Yuseok Jeon, also from UNIST. Additional equal contributors to the research include Dongyeon Yu, Seongyun Jeong, and Dokyung Song. This work was conducted as a joint effort with Yonsei University.
Reviews
Dr. Zero (Offensive Security Researcher) — MUST SEE
This talk introduces ERASAN, a highly efficient Address Sanitizer for Rust that targets memory bugs specifically within unsafe code. By leveraging MIR-level analysis to track raw pointers and their aliases, ERASAN drastically reduces instrumentation overhead while maintaining full detection capabilities for critical vulnerabilities. This is a crucial advancement for hardening Rust applications.
Heather Calloway (CISO) — STRONG ACCEPT
This research directly addresses a critical blind spot in Rust's security narrative, clearly demonstrating that unsafe blocks are a significant source of memory vulnerabilities. ERASAN provides a highly efficient and effective solution for dynamically detecting these bugs, making robust sanitization practical for production systems. It offers actionable insights for securing critical infrastructure reliant on unsafe Rust.
→ Top-rated talks at IEEE Symposium on Security and Privacy 2024